* RE: [PATCH v9 0/6] Update MFC v4l2 driver to support MFC6.x
2012-10-02 14:55 [PATCH v9 0/6] Update MFC v4l2 driver to support MFC6.x Arun Kumar K
@ 2012-10-02 11:16 ` Kamil Debski
2012-10-02 17:10 ` Sylwester Nawrocki
2012-10-02 14:55 ` [PATCH v9 1/6] [media] v4l: Add fourcc definitions for new formats Arun Kumar K
` (5 subsequent siblings)
6 siblings, 1 reply; 15+ messages in thread
From: Kamil Debski @ 2012-10-02 11:16 UTC (permalink / raw)
To: 'Arun Kumar K', linux-media
Cc: jtp.park, janghyuck.kim, jaeryul.oh, ch.naveen, Marek Szyprowski,
Sylwester Nawrocki, hverkuil, kmpark, joshi
Hi Arun,
Thank you for your hard work with these patches.
I think that they are ready to be merged.
Best wishes,
--
Kamil Debski
Linux Platform Group
Samsung Poland R&D Center
> From: Arun Kumar K [mailto:arun.kk@samsung.com]
> Sent: 02 October 2012 16:56
>
> The patchset adds support for MFCv6 firmware in s5p-mfc driver.
> The patches are rebased to the latest media-tree.
>
> Changelog v9
> - Addressed review comments by Hans Verkuil
> http://www.mail-archive.com/linux-media@vger.kernel.org/msg53016.html
>
> Changelog v8
> - Addressed review comments by Sylwester Nawrocki
> http://www.mail-archive.com/linux-media@vger.kernel.org/msg52942.html
>
> Changelog v7
> - Removed unused macros from register files
>
> Changelog v6
> - Use s5p_mfc_hw_call macro to call all HW related ops and cmds
> - Rebased onto latest media-tree
> - Resending patches adding required v4l controls
> - Addressed review comments of Patch v5
>
> Changelog v5
> - Modified ops mechanism for macro based function call
> - Addressed all other review comments on Patch v4
>
> Changelog v4
> - Separate patch for callback based architecture.
> - Patches divided to enable incremental compilation.
> - Working MFCv6 encoder and decoder.
> - Addressed review comments given for v3 patchset.
>
> Changelog v3
> - Supports MFCv5 and v6 co-existence.
> - Tested for encoding & decoding in MFCv5.
> - Supports only decoding in MFCv6 now.
> - Can be compiled with kernel image and as module.
> - Config macros for MFC version selection removed.
> - All previous review comments addressed.
>
> Changelog v2
> - Addressed review comments received
>
http://comments.gmane.org/gmane.linux.drivers.video-input-infrastructure/45189
>
> Changelog v1
> - Fixed crash issue in Exynos4 SoCs running MFC 5.1
> - Encoder not tested
>
> Arun Kumar K (4):
> [media] v4l: Add fourcc definitions for new formats
> [media] v4l: Add control definitions for new H264 encoder features
> [media] s5p-mfc: Update MFCv5 driver for callback based architecture
> [media] s5p-mfc: Add MFC variant data to device context
>
> Jeongtae Park (2):
> [media] s5p-mfc: MFCv6 register definitions
> [media] s5p-mfc: Update MFC v4l2 driver to support MFC6.x
>
> Documentation/DocBook/media/v4l/controls.xml | 268 +++-
> Documentation/DocBook/media/v4l/pixfmt-nv12m.xml | 17 +-
> Documentation/DocBook/media/v4l/pixfmt.xml | 10 +
> drivers/media/platform/Kconfig | 4 +-
> drivers/media/platform/s5p-mfc/Makefile | 7 +-
> drivers/media/platform/s5p-mfc/regs-mfc-v6.h | 408 +++++
> drivers/media/platform/s5p-mfc/regs-mfc.h | 41 +
> drivers/media/platform/s5p-mfc/s5p_mfc.c | 296 +++--
> drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c | 109 +--
> drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h | 15 +-
> drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c | 166 ++
> drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h | 20 +
> drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c | 156 ++
> drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h | 20 +
> drivers/media/platform/s5p-mfc/s5p_mfc_common.h | 191 ++-
> drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c | 194 ++-
> drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h | 1 +
> drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 258 ++-
> drivers/media/platform/s5p-mfc/s5p_mfc_dec.h | 1 +
> drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | 239 ++--
> drivers/media/platform/s5p-mfc/s5p_mfc_enc.h | 1 +
> drivers/media/platform/s5p-mfc/s5p_mfc_intr.c | 11 +-
> drivers/media/platform/s5p-mfc/s5p_mfc_opr.c | 1386 +---------------
> drivers/media/platform/s5p-mfc/s5p_mfc_opr.h | 133 +-
> drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c | 1763 +++++++++++++++++++
> drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.h | 85 +
> drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c | 1956
++++++++++++++++++++++
> drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h | 50 +
> drivers/media/platform/s5p-mfc/s5p_mfc_pm.c | 3 +-
> drivers/media/platform/s5p-mfc/s5p_mfc_shm.c | 47 -
> drivers/media/platform/s5p-mfc/s5p_mfc_shm.h | 90 -
> drivers/media/v4l2-core/v4l2-ctrls.c | 42 +
> include/linux/v4l2-controls.h | 41 +
> include/linux/videodev2.h | 4 +
> 34 files changed, 5940 insertions(+), 2093 deletions(-)
> create mode 100644 drivers/media/platform/s5p-mfc/regs-mfc-v6.h
> create mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
> create mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h
> create mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c
> create mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h
> create mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
> create mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.h
> create mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
> create mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h
> delete mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_shm.c
> delete mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_shm.h
^ permalink raw reply [flat|nested] 15+ messages in thread
* RE: [PATCH v9 1/6] [media] v4l: Add fourcc definitions for new formats
2012-10-02 14:55 ` [PATCH v9 1/6] [media] v4l: Add fourcc definitions for new formats Arun Kumar K
@ 2012-10-02 11:16 ` Kamil Debski
0 siblings, 0 replies; 15+ messages in thread
From: Kamil Debski @ 2012-10-02 11:16 UTC (permalink / raw)
To: 'Arun Kumar K', linux-media
Cc: jtp.park, janghyuck.kim, jaeryul.oh, ch.naveen, Marek Szyprowski,
Sylwester Nawrocki, hverkuil, kmpark, joshi
> From: Arun Kumar K [mailto:arun.kk@samsung.com]
> Sent: 02 October 2012 16:56
>
> Adds the following new fourcc definitions.
> For multiplanar YCbCr
> - V4L2_PIX_FMT_NV21M
> - V4L2_PIX_FMT_NV12MT_16X16
> and compressed formats
> - V4L2_PIX_FMT_H264_MVC
> - V4L2_PIX_FMT_VP8
>
> Signed-off-by: Jeongtae Park <jtp.park@samsung.com>
> Signed-off-by: Naveen Krishna Chatradhi <ch.naveen@samsung.com>
> Signed-off-by: Arun Kumar K <arun.kk@samsung.com>
Acked-by: Kamil Debski <k.debski@samsung.com>
> ---
> Documentation/DocBook/media/v4l/pixfmt-nv12m.xml | 17 ++++++++++++-----
> Documentation/DocBook/media/v4l/pixfmt.xml | 10 ++++++++++
> include/linux/videodev2.h | 4 ++++
> 3 files changed, 26 insertions(+), 5 deletions(-)
>
> diff --git a/Documentation/DocBook/media/v4l/pixfmt-nv12m.xml
> b/Documentation/DocBook/media/v4l/pixfmt-nv12m.xml
> index 5274c24..a990b34 100644
> --- a/Documentation/DocBook/media/v4l/pixfmt-nv12m.xml
> +++ b/Documentation/DocBook/media/v4l/pixfmt-nv12m.xml
> @@ -1,11 +1,13 @@
> - <refentry id="V4L2-PIX-FMT-NV12M">
> + <refentry>
> <refmeta>
> - <refentrytitle>V4L2_PIX_FMT_NV12M ('NM12')</refentrytitle>
> + <refentrytitle>V4L2_PIX_FMT_NV12M ('NM12'), V4L2_PIX_FMT_NV21M
('NM21'),
> V4L2_PIX_FMT_NV12MT_16X16</refentrytitle>
> &manvol;
> </refmeta>
> <refnamediv>
> - <refname> <constant>V4L2_PIX_FMT_NV12M</constant></refname>
> - <refpurpose>Variation of <constant>V4L2_PIX_FMT_NV12</constant> with
> planes
> + <refname id="V4L2-PIX-FMT-
> NV12M"><constant>V4L2_PIX_FMT_NV12M</constant></refname>
> + <refname id="V4L2-PIX-FMT-
> NV21M"><constant>V4L2_PIX_FMT_NV21M</constant></refname>
> + <refname id="V4L2-PIX-FMT-
> NV12MT_16X16"><constant>V4L2_PIX_FMT_NV12MT_16X16</constant></refname>
> + <refpurpose>Variation of <constant>V4L2_PIX_FMT_NV12</constant> and
> <constant>V4L2_PIX_FMT_NV21</constant> with planes
> non contiguous in memory. </refpurpose>
> </refnamediv>
> <refsect1>
> @@ -22,7 +24,12 @@ The CbCr plane is the same width, in bytes, as the Y
plane
> (and of the image),
> but is half as tall in pixels. Each CbCr pair belongs to four pixels. For
> example,
> Cb<subscript>0</subscript>/Cr<subscript>0</subscript> belongs to
> Y'<subscript>00</subscript>, Y'<subscript>01</subscript>,
> -Y'<subscript>10</subscript>, Y'<subscript>11</subscript>. </para>
> +Y'<subscript>10</subscript>, Y'<subscript>11</subscript>.
> +<constant>V4L2_PIX_FMT_NV12MT_16X16</constant> is the tiled version of
> +<constant>V4L2_PIX_FMT_NV12M</constant> with 16x16 macroblock tiles. Here
> pixels
> +are arranged in 16x16 2D tiles and tiles are arranged in linear order in
memory.
> +<constant>V4L2_PIX_FMT_NV21M</constant> is the same as
> <constant>V4L2_PIX_FMT_NV12M</constant>
> +except the Cb and Cr bytes are swapped, the CrCb plane starts with a Cr
> byte.</para>
>
> <para><constant>V4L2_PIX_FMT_NV12M</constant> is intended to be
> used only in drivers and applications that support the multi-planar API,
> diff --git a/Documentation/DocBook/media/v4l/pixfmt.xml
> b/Documentation/DocBook/media/v4l/pixfmt.xml
> index 1ddbfab..6ca0be4 100644
> --- a/Documentation/DocBook/media/v4l/pixfmt.xml
> +++ b/Documentation/DocBook/media/v4l/pixfmt.xml
> @@ -758,6 +758,11 @@ extended control
> <constant>V4L2_CID_MPEG_STREAM_TYPE</constant>, see
> <entry>'AVC1'</entry>
> <entry>H264 video elementary stream without start
codes.</entry>
> </row>
> + <row id="V4L2-PIX-FMT-H264-MVC">
> + <entry><constant>V4L2_PIX_FMT_H264_MVC</constant></entry>
> + <entry>'MVC'</entry>
> + <entry>H264 MVC video elementary stream.</entry>
> + </row>
> <row id="V4L2-PIX-FMT-H263">
> <entry><constant>V4L2_PIX_FMT_H263</constant></entry>
> <entry>'H263'</entry>
> @@ -793,6 +798,11 @@ extended control
> <constant>V4L2_CID_MPEG_STREAM_TYPE</constant>, see
> <entry>'VC1L'</entry>
> <entry>VC1, SMPTE 421M Annex L compliant stream.</entry>
> </row>
> + <row id="V4L2-PIX-FMT-VP8">
> + <entry><constant>V4L2_PIX_FMT_VP8</constant></entry>
> + <entry>'VP8'</entry>
> + <entry>VP8 video elementary stream.</entry>
> + </row>
> </tbody>
> </tgroup>
> </table>
> diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
> index 61395ef..16e6ab0 100644
> --- a/include/linux/videodev2.h
> +++ b/include/linux/videodev2.h
> @@ -366,7 +366,9 @@ struct v4l2_pix_format {
>
> /* two non contiguous planes - one Y, one Cr + Cb interleaved */
> #define V4L2_PIX_FMT_NV12M v4l2_fourcc('N', 'M', '1', '2') /* 12 Y/CbCr
> 4:2:0 */
> +#define V4L2_PIX_FMT_NV21M v4l2_fourcc('N', 'M', '2', '1') /* 21 Y/CrCb
> 4:2:0 */
> #define V4L2_PIX_FMT_NV12MT v4l2_fourcc('T', 'M', '1', '2') /* 12 Y/CbCr
> 4:2:0 64x32 macroblocks */
> +#define V4L2_PIX_FMT_NV12MT_16X16 v4l2_fourcc('V', 'M', '1', '2') /* 12
Y/CbCr
> 4:2:0 16x16 macroblocks */
>
> /* three non contiguous planes - Y, Cb, Cr */
> #define V4L2_PIX_FMT_YUV420M v4l2_fourcc('Y', 'M', '1', '2') /* 12 YUV420
> planar */
> @@ -403,6 +405,7 @@ struct v4l2_pix_format {
> #define V4L2_PIX_FMT_MPEG v4l2_fourcc('M', 'P', 'E', 'G') /* MPEG-1/2/4
> Multiplexed */
> #define V4L2_PIX_FMT_H264 v4l2_fourcc('H', '2', '6', '4') /* H264 with
> start codes */
> #define V4L2_PIX_FMT_H264_NO_SC v4l2_fourcc('A', 'V', 'C', '1') /* H264
without
> start codes */
> +#define V4L2_PIX_FMT_H264_MVC v4l2_fourcc('M', '2', '6', '4') /* H264 MVC
*/
> #define V4L2_PIX_FMT_H263 v4l2_fourcc('H', '2', '6', '3') /* H263
> */
> #define V4L2_PIX_FMT_MPEG1 v4l2_fourcc('M', 'P', 'G', '1') /* MPEG-1 ES
> */
> #define V4L2_PIX_FMT_MPEG2 v4l2_fourcc('M', 'P', 'G', '2') /* MPEG-2 ES
> */
> @@ -410,6 +413,7 @@ struct v4l2_pix_format {
> #define V4L2_PIX_FMT_XVID v4l2_fourcc('X', 'V', 'I', 'D') /* Xvid
> */
> #define V4L2_PIX_FMT_VC1_ANNEX_G v4l2_fourcc('V', 'C', '1', 'G') /* SMPTE
421M
> Annex G compliant stream */
> #define V4L2_PIX_FMT_VC1_ANNEX_L v4l2_fourcc('V', 'C', '1', 'L') /* SMPTE
421M
> Annex L compliant stream */
> +#define V4L2_PIX_FMT_VP8 v4l2_fourcc('V', 'P', '8', '0') /* VP8 */
>
> /* Vendor-specific formats */
> #define V4L2_PIX_FMT_CPIA1 v4l2_fourcc('C', 'P', 'I', 'A') /* cpia1 YUV
*/
> --
> 1.7.0.4
^ permalink raw reply [flat|nested] 15+ messages in thread
* RE: [PATCH v9 2/6] [media] v4l: Add control definitions for new H264 encoder features
2012-10-02 14:55 ` [PATCH v9 2/6] [media] v4l: Add control definitions for new H264 encoder features Arun Kumar K
@ 2012-10-02 11:16 ` Kamil Debski
0 siblings, 0 replies; 15+ messages in thread
From: Kamil Debski @ 2012-10-02 11:16 UTC (permalink / raw)
To: 'Arun Kumar K', linux-media
Cc: jtp.park, janghyuck.kim, jaeryul.oh, ch.naveen, Marek Szyprowski,
Sylwester Nawrocki, hverkuil, kmpark, joshi
> From: Arun Kumar K [mailto:arun.kk@samsung.com]
> Sent: 02 October 2012 16:56
>
> New controls are added for supporting H264 encoding features like
> - MVC frame packing
> - Flexible macroblock ordering
> - Arbitrary slice ordering
> - Hierarchical coding
>
> Signed-off-by: Jeongtae Park <jtp.park@samsung.com>
> Signed-off-by: Naveen Krishna Chatradhi <ch.naveen@samsung.com>
> Signed-off-by: Arun Kumar K <arun.kk@samsung.com>
Acked-by: Kamil Debski <k.debski@samsung.com>
> ---
> Documentation/DocBook/media/v4l/controls.xml | 268
+++++++++++++++++++++++++-
> drivers/media/v4l2-core/v4l2-ctrls.c | 42 ++++
> include/linux/v4l2-controls.h | 41 ++++
> 3 files changed, 350 insertions(+), 1 deletions(-)
>
> diff --git a/Documentation/DocBook/media/v4l/controls.xml
> b/Documentation/DocBook/media/v4l/controls.xml
> index 272a5f7..09e09bd 100644
> --- a/Documentation/DocBook/media/v4l/controls.xml
> +++ b/Documentation/DocBook/media/v4l/controls.xml
> @@ -1586,7 +1586,6 @@ frame counter of the frame that is currently displayed
> (decoded). This value is
> the decoder is started.</entry>
> </row>
>
> -
> <row><entry></entry></row>
> <row>
> <entry
>
spanname="id"><constant>V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE</constant>
&n
> bsp;</entry>
> @@ -2270,6 +2269,14 @@ Applicable to the MPEG1, MPEG2, MPEG4
encoders.</entry>
> </row>
>
> <row><entry></entry></row>
> + <row id="v4l2-mpeg-video-vbv-delay">
> + <entry
>
spanname="id"><constant>V4L2_CID_MPEG_VIDEO_VBV_DELAY</constant> </entry>
> + <entry>integer</entry>
> + </row><row><entry spanname="descr">Sets the initial delay in
> milliseconds for
> +VBV buffer control.</entry>
> + </row>
> +
> + <row><entry></entry></row>
> <row>
> <entry
>
spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE</constant> </en
tr
> y>
> <entry>integer</entry>
> @@ -2334,6 +2341,265 @@ Applicable to the MPEG4 decoder.</entry>
> </row><row><entry spanname="descr">vop_time_increment value for
> MPEG4. Applicable to the MPEG4 encoder.</entry>
> </row>
>
> + <row><entry></entry></row>
> + <row>
> + <entry
>
spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING</constant>&
nb
> sp;</entry>
> + <entry>boolean</entry>
> + </row>
> + <row><entry spanname="descr">Enable generation of frame packing
> supplemental enhancement information in the encoded bitstream.
> +The frame packing SEI message contains the arrangement of L and R planes
for 3D
> viewing. Applicable to the H264 encoder.</entry>
> + </row>
> +
> + <row><entry></entry></row>
> + <row>
> + <entry
>
spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_SEI_FP_CURRENT_FRAME_0</const
an
> t> </entry>
> + <entry>boolean</entry>
> + </row>
> + <row><entry spanname="descr">Sets current frame as frame0 in
frame
> packing SEI.
> +Applicable to the H264 encoder.</entry>
> + </row>
> +
> + <row><entry></entry></row>
> + <row id="v4l2-mpeg-video-h264-sei-fp-arrangement-type">
> + <entry
>
spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE</cons
ta
> nt> </entry>
> +
> <entry>enum v4l2_mpeg_video_h264_sei_fp_arrangement_type</entry>
> + </row>
> + <row><entry spanname="descr">Frame packing arrangement type for
H264
> SEI.
> +Applicable to the H264 encoder.
> +Possible values are:</entry>
> + </row>
> + <row>
> + <entrytbl spanname="descr" cols="2">
> + <tbody valign="top">
> + <row>
> +
>
<entry><constant>V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_CHEKERBOARD</con
st
> ant> </entry>
> + <entry>Pixels are alternatively from L and R.</entry>
> + </row>
> + <row>
> +
>
<entry><constant>V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_COLUMN</constant
>&
> nbsp;</entry>
> + <entry>L and R are interlaced by column.</entry>
> + </row>
> + <row>
> +
>
<entry><constant>V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_ROW</constant>&n
bs
> p;</entry>
> + <entry>L and R are interlaced by row.</entry>
> + </row>
> + <row>
> +
>
<entry><constant>V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_SIDE_BY_SIDE</co
ns
> tant> </entry>
> + <entry>L is on the left, R on the right.</entry>
> + </row>
> + <row>
> +
>
<entry><constant>V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_TOP_BOTTOM</cons
ta
> nt> </entry>
> + <entry>L is on top, R on bottom.</entry>
> + </row>
> + <row>
> +
>
<entry><constant>V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_TEMPORAL</consta
nt
> > </entry>
> + <entry>One view per frame.</entry>
> + </row>
> + </tbody>
> + </entrytbl>
> + </row>
> +
> + <row><entry></entry></row>
> + <row>
> + <entry
>
spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_FMO</constant> </entry>
> + <entry>boolean</entry>
> + </row>
> + <row><entry spanname="descr">Enables flexible macroblock
ordering in
> the encoded bitstream. It is a technique
> +used for restructuring the ordering of macroblocks in pictures. Applicable
to
> the H264 encoder.</entry>
> + </row>
> +
> + <row><entry></entry></row>
> + <row id="v4l2-mpeg-video-h264-fmo-map-type">
> + <entry
>
spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE</constant>
</
> entry>
> + <entry>enum v4l2_mpeg_video_h264_fmo_map_type</entry>
> + </row>
> + <row><entry spanname="descr">When using FMO, the map type
divides
> the image in different scan patterns of macroblocks.
> +Applicable to the H264 encoder.
> +Possible values are:</entry>
> + </row>
> + <row>
> + <entrytbl spanname="descr" cols="2">
> + <tbody valign="top">
> + <row>
> +
>
<entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES</constan
t>
> </entry>
> + <entry>Slices are interleaved one after other with
> macroblocks in run length order.</entry>
> + </row>
> + <row>
> +
>
<entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_SCATTERED_SLICES</constant>
&n
> bsp;</entry>
> + <entry>Scatters the macroblocks based on a mathematical
> function known to both encoder and decoder.</entry>
> + </row>
> + <row>
> +
>
<entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_FOREGROUND_WITH_LEFT_OVER</
co
> nstant> </entry>
> + <entry>Macroblocks arranged in rectangular areas or
regions
> of interest.</entry>
> + </row>
> + <row>
> +
>
<entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_BOX_OUT</constant> </e
nt
> ry>
> + <entry>Slice groups grow in a cyclic way from centre to
> outwards.</entry>
> + </row>
> + <row>
> +
>
<entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_RASTER_SCAN</constant> 
;<
> /entry>
> + <entry>Slice groups grow in raster scan pattern from
left to
> right.</entry>
> + </row>
> + <row>
> +
>
<entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_WIPE_SCAN</constant> <
/e
> ntry>
> + <entry>Slice groups grow in wipe scan pattern from top
to
> bottom.</entry>
> + </row>
> + <row>
> +
>
<entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_EXPLICIT</constant> </
en
> try>
> + <entry>User defined map type.</entry>
> + </row>
> + </tbody>
> + </entrytbl>
> + </row>
> +
> + <row><entry></entry></row>
> + <row>
> + <entry
>
spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_FMO_SLICE_GROUP</constant>&nb
sp
> ;</entry>
> + <entry>integer</entry>
> + </row>
> + <row><entry spanname="descr">Number of slice groups in FMO.
> +Applicable to the H264 encoder.</entry>
> + </row>
> +
> + <row><entry></entry></row>
> + <row id="v4l2-mpeg-video-h264-fmo-change-direction">
> + <entry
>
spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_DIRECTION</constan
t>
> </entry>
> + <entry>enum v4l2_mpeg_video_h264_fmo_change_dir</entry>
> + </row>
> + <row><entry spanname="descr">Specifies a direction of the slice
> group change for raster and wipe maps.
> +Applicable to the H264 encoder.
> +Possible values are:</entry>
> + </row>
> + <row>
> + <entrytbl spanname="descr" cols="2">
> + <tbody valign="top">
> + <row>
> +
>
<entry><constant>V4L2_MPEG_VIDEO_H264_FMO_CHANGE_DIR_RIGHT</constant> </e
nt
> ry>
> + <entry>Raster scan or wipe right.</entry>
> + </row>
> + <row>
> +
>
<entry><constant>V4L2_MPEG_VIDEO_H264_FMO_CHANGE_DIR_LEFT</constant> </en
tr
> y>
> + <entry>Reverse raster scan or wipe left.</entry>
> + </row>
> + </tbody>
> + </entrytbl>
> + </row>
> +
> + <row><entry></entry></row>
> + <row>
> + <entry
>
spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_RATE</constant>&nb
sp
> ;</entry>
> + <entry>integer</entry>
> + </row>
> + <row><entry spanname="descr">Specifies the size of the first
slice
> group for raster and wipe map.
> +Applicable to the H264 encoder.</entry>
> + </row>
> +
> + <row><entry></entry></row>
> + <row>
> + <entry
>
spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH</constant>&nbs
p;
> </entry>
> + <entry>integer</entry>
> + </row>
> + <row><entry spanname="descr">Specifies the number of consecutive
> macroblocks for the interleaved map.
> +Applicable to the H264 encoder.</entry>
> + </row>
> +
> + <row><entry></entry></row>
> + <row>
> + <entry
>
spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_ASO</constant> </entry>
> + <entry>boolean</entry>
> + </row>
> + <row><entry spanname="descr">Enables arbitrary slice ordering in
> encoded bitstream.
> +Applicable to the H264 encoder.</entry>
> + </row>
> +
> + <row><entry></entry></row>
> + <row>
> + <entry
>
spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_ASO_SLICE_ORDER</constant>&nb
sp
> ;</entry>
> + <entry>integer</entry>
> + </row><row><entry spanname="descr">Specifies the slice order in
ASO.
> Applicable to the H264 encoder.
> +The supplied 32-bit integer is interpreted as follows (bit
> +0 = least significant bit):</entry>
> + </row>
> + <row>
> + <entrytbl spanname="descr" cols="2">
> + <tbody valign="top">
> + <row>
> + <entry>Bit 0:15</entry>
> + <entry>Slice ID</entry>
> + </row>
> + <row>
> + <entry>Bit 16:32</entry>
> + <entry>Slice position or order</entry>
> + </row>
> + </tbody>
> + </entrytbl>
> + </row>
> +
> + <row><entry></entry></row>
> + <row>
> + <entry
>
spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING</constant
>&
> nbsp;</entry>
> + <entry>boolean</entry>
> + </row>
> + <row><entry spanname="descr">Enables H264 hierarchical coding.
> +Applicable to the H264 encoder.</entry>
> + </row>
> +
> + <row><entry></entry></row>
> + <row id="v4l2-mpeg-video-h264-hierarchical-coding-type">
> + <entry
>
spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE</con
st
> ant> </entry>
> +
> <entry>enum v4l2_mpeg_video_h264_hierarchical_coding_type</entry>
> + </row>
> + <row><entry spanname="descr">Specifies the hierarchical coding
type.
> +Applicable to the H264 encoder.
> +Possible values are:</entry>
> + </row>
> + <row>
> + <entrytbl spanname="descr" cols="2">
> + <tbody valign="top">
> + <row>
> +
>
<entry><constant>V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B</constant> </
en
> try>
> + <entry>Hierarchical B coding.</entry>
> + </row>
> + <row>
> +
>
<entry><constant>V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P</constant> </
en
> try>
> + <entry>Hierarchical P coding.</entry>
> + </row>
> + </tbody>
> + </entrytbl>
> + </row>
> +
> + <row><entry></entry></row>
> + <row>
> + <entry
>
spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER</co
ns
> tant> </entry>
> + <entry>integer</entry>
> + </row>
> + <row><entry spanname="descr">Specifies the number of
hierarchical
> coding layers.
> +Applicable to the H264 encoder.</entry>
> + </row>
> +
> + <row><entry></entry></row>
> + <row>
> + <entry
>
spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP<
/c
> onstant> </entry>
> + <entry>integer</entry>
> + </row><row><entry spanname="descr">Specifies a user defined QP
for
> each layer. Applicable to the H264 encoder.
> +The supplied 32-bit integer is interpreted as follows (bit
> +0 = least significant bit):</entry>
> + </row>
> + <row>
> + <entrytbl spanname="descr" cols="2">
> + <tbody valign="top">
> + <row>
> + <entry>Bit 0:15</entry>
> + <entry>QP value</entry>
> + </row>
> + <row>
> + <entry>Bit 16:32</entry>
> + <entry>Layer number</entry>
> + </row>
> + </tbody>
> + </entrytbl>
> + </row>
> +
> </tbody>
> </tgroup>
> </table>
> diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-
> core/v4l2-ctrls.c
> index f400035..fb986ec 100644
> --- a/drivers/media/v4l2-core/v4l2-ctrls.c
> +++ b/drivers/media/v4l2-core/v4l2-ctrls.c
> @@ -384,6 +384,25 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
> "Extended SAR",
> NULL,
> };
> + static const char * const h264_fp_arrangement_type[] = {
> + "Checkerboard",
> + "Column",
> + "Row",
> + "Side by Side",
> + "Top Bottom",
> + "Temporal",
> + NULL,
> + };
> + static const char * const h264_fmo_map_type[] = {
> + "Interleaved Slices",
> + "Scattered Slices",
> + "Foreground with Leftover",
> + "Box Out",
> + "Raster Scan",
> + "Wipe Scan",
> + "Explicit",
> + NULL,
> + };
> static const char * const mpeg_mpeg4_level[] = {
> "0",
> "0b",
> @@ -508,6 +527,10 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
> return h264_profile;
> case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC:
> return vui_sar_idc;
> + case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE:
> + return h264_fp_arrangement_type;
> + case V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE:
> + return h264_fmo_map_type;
> case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
> return mpeg_mpeg4_level;
> case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
> @@ -643,6 +666,22 @@ const char *v4l2_ctrl_get_name(u32 id)
> case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH: return
"Horizontal
> Size of SAR";
> case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE: return "Aspect
Ratio
> VUI Enable";
> case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC: return "VUI
Aspect
> Ratio IDC";
> + case V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING: return "H264
Enable
> Frame Packing SEI";
> + case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_CURRENT_FRAME_0: return "H264
> Set Curr. Frame as Frame0";
> + case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE: return "H264
> FP Arrangement Type";
> + case V4L2_CID_MPEG_VIDEO_H264_FMO: return "H264
Flexible
> MB Ordering";
> + case V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE: return "H264
Map Type
> for FMO";
> + case V4L2_CID_MPEG_VIDEO_H264_FMO_SLICE_GROUP: return "H264
FMO
> Number of Slice Groups";
> + case V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_DIRECTION: return "H264
FMO
> Direction of Change";
> + case V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_RATE: return "H264
FMO Size
> of 1st Slice Grp";
> + case V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH: return "H264
FMO No.
> of Consecutive MBs";
> + case V4L2_CID_MPEG_VIDEO_H264_ASO: return "H264
> Arbitrary Slice Ordering";
> + case V4L2_CID_MPEG_VIDEO_H264_ASO_SLICE_ORDER: return "H264
ASO
> Slice Order";
> + case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING: return "Enable
H264
> Hierarchical Coding";
> + case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE: return "H264
> Hierarchical Coding Type";
> + case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER:return "H264
> Number of HC Layers";
> + case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP:
> + return "H264
Set QP Value
> for HC Layers";
> case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP: return "MPEG4
I-Frame
> QP Value";
> case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP: return "MPEG4
P-Frame
> QP Value";
> case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP: return "MPEG4
B-Frame
> QP Value";
> @@ -657,6 +696,7 @@ const char *v4l2_ctrl_get_name(u32 id)
> case V4L2_CID_MPEG_VIDEO_VBV_SIZE: return "VBV
Buffer
> Size";
> case V4L2_CID_MPEG_VIDEO_DEC_PTS: return "Video
Decoder
> PTS";
> case V4L2_CID_MPEG_VIDEO_DEC_FRAME: return "Video
Decoder
> Frame Count";
> + case V4L2_CID_MPEG_VIDEO_VBV_DELAY: return
"Initial Delay
> for VBV Control";
>
> /* CAMERA controls */
> /* Keep the order of the 'case's the same as in videodev2.h! */
> @@ -853,6 +893,8 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum
> v4l2_ctrl_type *type,
> case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:
> case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
> case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC:
> + case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE:
> + case V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE:
> case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
> case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
> case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
> diff --git a/include/linux/v4l2-controls.h b/include/linux/v4l2-controls.h
> index 421d24c..1c4d0c9 100644
> --- a/include/linux/v4l2-controls.h
> +++ b/include/linux/v4l2-controls.h
> @@ -349,6 +349,7 @@ enum v4l2_mpeg_video_multi_slice_mode {
> #define V4L2_CID_MPEG_VIDEO_VBV_SIZE
(V4L2_CID_MPEG_BASE+222)
> #define V4L2_CID_MPEG_VIDEO_DEC_PTS
(V4L2_CID_MPEG_BASE+223)
> #define V4L2_CID_MPEG_VIDEO_DEC_FRAME
(V4L2_CID_MPEG_BASE+224)
> +#define V4L2_CID_MPEG_VIDEO_VBV_DELAY
(V4L2_CID_MPEG_BASE+225)
>
> #define V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP
(V4L2_CID_MPEG_BASE+300)
> #define V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP
(V4L2_CID_MPEG_BASE+301)
> @@ -439,6 +440,46 @@ enum v4l2_mpeg_video_h264_vui_sar_idc {
> V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_2x1 = 16,
> V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED = 17,
> };
> +#define V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING
> (V4L2_CID_MPEG_BASE+368)
> +#define V4L2_CID_MPEG_VIDEO_H264_SEI_FP_CURRENT_FRAME_0
> (V4L2_CID_MPEG_BASE+369)
> +#define V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE
> (V4L2_CID_MPEG_BASE+370)
> +enum v4l2_mpeg_video_h264_sei_fp_arrangement_type {
> + V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_CHECKERBOARD = 0,
> + V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_COLUMN = 1,
> + V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_ROW = 2,
> + V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_SIDE_BY_SIDE = 3,
> + V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_TOP_BOTTOM = 4,
> + V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_TEMPORAL = 5,
> +};
> +#define V4L2_CID_MPEG_VIDEO_H264_FMO
(V4L2_CID_MPEG_BASE+371)
> +#define V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE
(V4L2_CID_MPEG_BASE+372)
> +enum v4l2_mpeg_video_h264_fmo_map_type {
> + V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES = 0,
> + V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_SCATTERED_SLICES = 1,
> + V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_FOREGROUND_WITH_LEFT_OVER = 2,
> + V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_BOX_OUT = 3,
> + V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_RASTER_SCAN = 4,
> + V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_WIPE_SCAN = 5,
> + V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_EXPLICIT = 6,
> +};
> +#define V4L2_CID_MPEG_VIDEO_H264_FMO_SLICE_GROUP
(V4L2_CID_MPEG_BASE+373)
> +#define V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_DIRECTION
> (V4L2_CID_MPEG_BASE+374)
> +enum v4l2_mpeg_video_h264_fmo_change_dir {
> + V4L2_MPEG_VIDEO_H264_FMO_CHANGE_DIR_RIGHT = 0,
> + V4L2_MPEG_VIDEO_H264_FMO_CHANGE_DIR_LEFT = 1,
> +};
> +#define V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_RATE
(V4L2_CID_MPEG_BASE+375)
> +#define V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH
> (V4L2_CID_MPEG_BASE+376)
> +#define V4L2_CID_MPEG_VIDEO_H264_ASO
(V4L2_CID_MPEG_BASE+377)
> +#define V4L2_CID_MPEG_VIDEO_H264_ASO_SLICE_ORDER
(V4L2_CID_MPEG_BASE+378)
> +#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING
> (V4L2_CID_MPEG_BASE+379)
> +#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE
> (V4L2_CID_MPEG_BASE+380)
> +enum v4l2_mpeg_video_h264_hierarchical_coding_type {
> + V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B = 0,
> + V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P = 1,
> +};
> +#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER
> (V4L2_CID_MPEG_BASE+381)
> +#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP
> (V4L2_CID_MPEG_BASE+382)
> #define V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP (V4L2_CID_MPEG_BASE+400)
> #define V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP (V4L2_CID_MPEG_BASE+401)
> #define V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP (V4L2_CID_MPEG_BASE+402)
> --
> 1.7.0.4
^ permalink raw reply [flat|nested] 15+ messages in thread
* RE: [PATCH v9 3/6] [media] s5p-mfc: Update MFCv5 driver for callback based architecture
2012-10-02 14:55 ` [PATCH v9 3/6] [media] s5p-mfc: Update MFCv5 driver for callback based architecture Arun Kumar K
@ 2012-10-02 11:16 ` Kamil Debski
0 siblings, 0 replies; 15+ messages in thread
From: Kamil Debski @ 2012-10-02 11:16 UTC (permalink / raw)
To: 'Arun Kumar K', linux-media
Cc: jtp.park, janghyuck.kim, jaeryul.oh, ch.naveen, Marek Szyprowski,
Sylwester Nawrocki, hverkuil, kmpark, joshi
> From: Arun Kumar K [mailto:arun.kk@samsung.com]
> Sent: 02 October 2012 16:56
>
> Modifies the driver to use a callback based architecture
> for hardware dependent calls. This architecture is suitable
> for supporting co-existence with newer versions of MFC hardware.
>
> Signed-off-by: Arun Kumar K <arun.kk@samsung.com>
> Signed-off-by: Naveen Krishna Chatradhi <ch.naveen@samsung.com>
Acked-by: Kamil Debski <k.debski@samsung.com>
> ---
> drivers/media/platform/s5p-mfc/Makefile | 3 +-
> drivers/media/platform/s5p-mfc/s5p_mfc.c | 154 ++-
> drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c | 106 +--
> drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h | 15 +-
> drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c | 166 +++
> drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h | 20 +
> drivers/media/platform/s5p-mfc/s5p_mfc_common.h | 45 +-
> drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c | 33 +-
> drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h | 1 +
> drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 85 +-
> drivers/media/platform/s5p-mfc/s5p_mfc_dec.h | 1 +
> drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | 68 +-
> drivers/media/platform/s5p-mfc/s5p_mfc_enc.h | 1 +
> drivers/media/platform/s5p-mfc/s5p_mfc_intr.c | 11 +-
> drivers/media/platform/s5p-mfc/s5p_mfc_opr.c | 1384 +------------------
> drivers/media/platform/s5p-mfc/s5p_mfc_opr.h | 133 +-
> drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c | 1698
+++++++++++++++++++++++
> drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.h | 85 ++
> drivers/media/platform/s5p-mfc/s5p_mfc_shm.c | 47 -
> drivers/media/platform/s5p-mfc/s5p_mfc_shm.h | 90 --
> 20 files changed, 2312 insertions(+), 1834 deletions(-)
> create mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
> create mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h
> create mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
> create mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.h
> delete mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_shm.c
> delete mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_shm.h
>
> diff --git a/drivers/media/platform/s5p-mfc/Makefile
> b/drivers/media/platform/s5p-mfc/Makefile
> index d066340..cfb9ee9 100644
> --- a/drivers/media/platform/s5p-mfc/Makefile
> +++ b/drivers/media/platform/s5p-mfc/Makefile
> @@ -2,4 +2,5 @@ obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) := s5p-mfc.o
> s5p-mfc-y += s5p_mfc.o s5p_mfc_intr.o s5p_mfc_opr.o
> s5p-mfc-y += s5p_mfc_dec.o s5p_mfc_enc.o
> s5p-mfc-y += s5p_mfc_ctrl.o s5p_mfc_cmd.o
> -s5p-mfc-y += s5p_mfc_pm.o s5p_mfc_shm.o
> +s5p-mfc-y += s5p_mfc_pm.o
> +s5p-mfc-y += s5p_mfc_opr_v5.o s5p_mfc_cmd_v5.o
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c
> b/drivers/media/platform/s5p-mfc/s5p_mfc.c
> index 0476be4..3319410 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
> @@ -21,15 +21,15 @@
> #include <linux/videodev2.h>
> #include <linux/workqueue.h>
> #include <media/videobuf2-core.h>
> -#include "regs-mfc.h"
> +#include "s5p_mfc_common.h"
> #include "s5p_mfc_ctrl.h"
> #include "s5p_mfc_debug.h"
> #include "s5p_mfc_dec.h"
> #include "s5p_mfc_enc.h"
> #include "s5p_mfc_intr.h"
> #include "s5p_mfc_opr.h"
> +#include "s5p_mfc_cmd.h"
> #include "s5p_mfc_pm.h"
> -#include "s5p_mfc_shm.h"
>
> #define S5P_MFC_NAME "s5p-mfc"
> #define S5P_MFC_DEC_NAME "s5p-mfc-dec"
> @@ -115,10 +115,12 @@ static void s5p_mfc_watchdog_worker(struct work_struct
> *work)
> if (!ctx)
> continue;
> ctx->state = MFCINST_ERROR;
> - s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
> - s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
> + s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue,
> + &ctx->vq_dst);
> + s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue,
> + &ctx->vq_src);
> clear_work_bit(ctx);
> - wake_up_ctx(ctx, S5P_FIMV_R2H_CMD_ERR_RET, 0);
> + wake_up_ctx(ctx, S5P_MFC_R2H_CMD_ERR_RET, 0);
> }
> clear_bit(0, &dev->hw_lock);
> spin_unlock_irqrestore(&dev->irqlock, flags);
> @@ -155,16 +157,10 @@ static enum s5p_mfc_node_type
s5p_mfc_get_node_type(struct
> file *file)
> return MFCNODE_INVALID;
> }
>
> -static void s5p_mfc_clear_int_flags(struct s5p_mfc_dev *dev)
> -{
> - mfc_write(dev, 0, S5P_FIMV_RISC_HOST_INT);
> - mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
> - mfc_write(dev, 0xffff, S5P_FIMV_SI_RTN_CHID);
> -}
> -
> static void s5p_mfc_handle_frame_all_extracted(struct s5p_mfc_ctx *ctx)
> {
> struct s5p_mfc_buf *dst_buf;
> + struct s5p_mfc_dev *dev = ctx->dev;
>
> ctx->state = MFCINST_FINISHED;
> ctx->sequence++;
> @@ -179,8 +175,8 @@ static void s5p_mfc_handle_frame_all_extracted(struct
> s5p_mfc_ctx *ctx)
> ctx->dst_queue_cnt--;
> dst_buf->b->v4l2_buf.sequence = (ctx->sequence++);
>
> - if (s5p_mfc_read_shm(ctx, PIC_TIME_TOP) ==
> - s5p_mfc_read_shm(ctx, PIC_TIME_BOT))
> + if (s5p_mfc_hw_call(dev->mfc_ops, get_pic_type_top, ctx) ==
> + s5p_mfc_hw_call(dev->mfc_ops, get_pic_type_bot, ctx))
> dst_buf->b->v4l2_buf.field = V4L2_FIELD_NONE;
> else
> dst_buf->b->v4l2_buf.field = V4L2_FIELD_INTERLACED;
> @@ -194,8 +190,11 @@ static void s5p_mfc_handle_frame_copy_time(struct
> s5p_mfc_ctx *ctx)
> {
> struct s5p_mfc_dev *dev = ctx->dev;
> struct s5p_mfc_buf *dst_buf, *src_buf;
> - size_t dec_y_addr = s5p_mfc_get_dec_y_adr();
> - unsigned int frame_type = s5p_mfc_get_frame_type();
> + size_t dec_y_addr;
> + unsigned int frame_type;
> +
> + dec_y_addr = s5p_mfc_hw_call(dev->mfc_ops, get_dec_y_adr, dev);
> + frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_dec_frame_type, dev);
>
> /* Copy timestamp / timecode from decoded src to dst and set
> appropraite flags */
> @@ -231,10 +230,13 @@ static void s5p_mfc_handle_frame_new(struct
s5p_mfc_ctx
> *ctx, unsigned int err)
> {
> struct s5p_mfc_dev *dev = ctx->dev;
> struct s5p_mfc_buf *dst_buf;
> - size_t dspl_y_addr = s5p_mfc_get_dspl_y_adr();
> - unsigned int frame_type = s5p_mfc_get_frame_type();
> + size_t dspl_y_addr;
> + unsigned int frame_type;
> unsigned int index;
>
> + dspl_y_addr = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_y_adr, dev);
> + frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_dec_frame_type, dev);
> +
> /* If frame is same as previous then skip and do not dequeue */
> if (frame_type == S5P_FIMV_DECODE_FRAME_SKIPPED) {
> if (!ctx->after_packed_pb)
> @@ -251,8 +253,10 @@ static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx
> *ctx, unsigned int err)
> list_del(&dst_buf->list);
> ctx->dst_queue_cnt--;
> dst_buf->b->v4l2_buf.sequence = ctx->sequence;
> - if (s5p_mfc_read_shm(ctx, PIC_TIME_TOP) ==
> - s5p_mfc_read_shm(ctx, PIC_TIME_BOT))
> + if (s5p_mfc_hw_call(dev->mfc_ops,
> + get_pic_type_top, ctx) ==
> + s5p_mfc_hw_call(dev->mfc_ops,
> + get_pic_type_bot, ctx))
> dst_buf->b->v4l2_buf.field = V4L2_FIELD_NONE;
> else
> dst_buf->b->v4l2_buf.field =
> @@ -283,21 +287,21 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx
*ctx,
>
> unsigned int index;
>
> - dst_frame_status = s5p_mfc_get_dspl_status()
> + dst_frame_status = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev)
> & S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK;
> - res_change = s5p_mfc_get_dspl_status()
> + res_change = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev)
> & S5P_FIMV_DEC_STATUS_RESOLUTION_MASK;
> mfc_debug(2, "Frame Status: %x\n", dst_frame_status);
> if (ctx->state == MFCINST_RES_CHANGE_INIT)
> ctx->state = MFCINST_RES_CHANGE_FLUSH;
> if (res_change) {
> ctx->state = MFCINST_RES_CHANGE_INIT;
> - s5p_mfc_clear_int_flags(dev);
> + s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
> wake_up_ctx(ctx, reason, err);
> if (test_and_clear_bit(0, &dev->hw_lock) == 0)
> BUG();
> s5p_mfc_clock_off();
> - s5p_mfc_try_run(dev);
> + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
> return;
> }
> if (ctx->dpb_flush_flag)
> @@ -331,9 +335,12 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx
*ctx,
> && !list_empty(&ctx->src_queue)) {
> src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf,
> list);
> - ctx->consumed_stream += s5p_mfc_get_consumed_stream();
> - if (ctx->codec_mode != S5P_FIMV_CODEC_H264_DEC &&
> - s5p_mfc_get_frame_type() ==
S5P_FIMV_DECODE_FRAME_P_FRAME
> + ctx->consumed_stream += s5p_mfc_hw_call(dev->mfc_ops,
> + get_consumed_stream, dev);
> + if (ctx->codec_mode != S5P_MFC_CODEC_H264_DEC &&
> + s5p_mfc_hw_call(dev->mfc_ops,
> + get_dec_frame_type, dev) ==
> + S5P_FIMV_DECODE_FRAME_P_FRAME
> && ctx->consumed_stream + STUFF_BYTE <
> src_buf->b->v4l2_planes[0].bytesused)
{
> /* Run MFC again on the same buffer */
> @@ -345,7 +352,7 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx
*ctx,
> ctx->consumed_stream = 0;
> list_del(&src_buf->list);
> ctx->src_queue_cnt--;
> - if (s5p_mfc_err_dec(err) > 0)
> + if (s5p_mfc_hw_call(dev->mfc_ops, err_dec, err) > 0)
> vb2_buffer_done(src_buf->b,
VB2_BUF_STATE_ERROR);
> else
> vb2_buffer_done(src_buf->b,
VB2_BUF_STATE_DONE);
> @@ -356,12 +363,12 @@ leave_handle_frame:
> if ((ctx->src_queue_cnt == 0 && ctx->state != MFCINST_FINISHING)
> || ctx->dst_queue_cnt < ctx->dpb_count)
> clear_work_bit(ctx);
> - s5p_mfc_clear_int_flags(dev);
> + s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
> wake_up_ctx(ctx, reason, err);
> if (test_and_clear_bit(0, &dev->hw_lock) == 0)
> BUG();
> s5p_mfc_clock_off();
> - s5p_mfc_try_run(dev);
> + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
> }
>
> /* Error handling for interrupt */
> @@ -378,7 +385,7 @@ static void s5p_mfc_handle_error(struct s5p_mfc_ctx
*ctx,
>
> dev = ctx->dev;
> mfc_err("Interrupt Error: %08x\n", err);
> - s5p_mfc_clear_int_flags(dev);
> + s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
> wake_up_dev(dev, reason, err);
>
> /* Error recovery is dependent on the state of context */
> @@ -407,9 +414,11 @@ static void s5p_mfc_handle_error(struct s5p_mfc_ctx
*ctx,
> ctx->state = MFCINST_ERROR;
> /* Mark all dst buffers as having an error */
> spin_lock_irqsave(&dev->irqlock, flags);
> - s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
> + s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue,
> + &ctx->vq_dst);
> /* Mark all src buffers as having an error */
> - s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
> + s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue,
> + &ctx->vq_src);
> spin_unlock_irqrestore(&dev->irqlock, flags);
> if (test_and_clear_bit(0, &dev->hw_lock) == 0)
> BUG();
> @@ -436,8 +445,10 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx
*ctx,
> if (ctx->c_ops->post_seq_start(ctx))
> mfc_err("post_seq_start() failed\n");
> } else {
> - ctx->img_width = s5p_mfc_get_img_width();
> - ctx->img_height = s5p_mfc_get_img_height();
> + ctx->img_width = s5p_mfc_hw_call(dev->mfc_ops, get_img_width,
> + dev);
> + ctx->img_height = s5p_mfc_hw_call(dev->mfc_ops,
get_img_height,
> + dev);
>
> ctx->buf_width = ALIGN(ctx->img_width,
> S5P_FIMV_NV12MT_HALIGN);
> @@ -473,18 +484,19 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx
> *ctx,
> guard_height, S5P_FIMV_DEC_BUF_ALIGN);
> ctx->mv_size = 0;
> }
> - ctx->dpb_count = s5p_mfc_get_dpb_count();
> + ctx->dpb_count = s5p_mfc_hw_call(dev->mfc_ops, get_dpb_count,
> + dev);
> if (ctx->img_width == 0 || ctx->img_height == 0)
> ctx->state = MFCINST_ERROR;
> else
> ctx->state = MFCINST_HEAD_PARSED;
> }
> - s5p_mfc_clear_int_flags(dev);
> + s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
> clear_work_bit(ctx);
> if (test_and_clear_bit(0, &dev->hw_lock) == 0)
> BUG();
> s5p_mfc_clock_off();
> - s5p_mfc_try_run(dev);
> + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
> wake_up_ctx(ctx, reason, err);
> }
>
> @@ -499,7 +511,7 @@ static void s5p_mfc_handle_init_buffers(struct
s5p_mfc_ctx
> *ctx,
> if (ctx == NULL)
> return;
> dev = ctx->dev;
> - s5p_mfc_clear_int_flags(dev);
> + s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
> ctx->int_type = reason;
> ctx->int_err = err;
> ctx->int_cond = 1;
> @@ -528,7 +540,7 @@ static void s5p_mfc_handle_init_buffers(struct
s5p_mfc_ctx
> *ctx,
> s5p_mfc_clock_off();
>
> wake_up(&ctx->queue);
> - s5p_mfc_try_run(dev);
> + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
> } else {
> if (test_and_clear_bit(0, &dev->hw_lock) == 0)
> BUG();
> @@ -552,76 +564,78 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
> atomic_set(&dev->watchdog_cnt, 0);
> ctx = dev->ctx[dev->curr_ctx];
> /* Get the reason of interrupt and the error code */
> - reason = s5p_mfc_get_int_reason();
> - err = s5p_mfc_get_int_err();
> + reason = s5p_mfc_hw_call(dev->mfc_ops, get_int_reason, dev);
> + err = s5p_mfc_hw_call(dev->mfc_ops, get_int_err, dev);
> mfc_debug(1, "Int reason: %d (err: %08x)\n", reason, err);
> switch (reason) {
> - case S5P_FIMV_R2H_CMD_ERR_RET:
> + case S5P_MFC_R2H_CMD_ERR_RET:
> /* An error has occured */
> if (ctx->state == MFCINST_RUNNING &&
> - s5p_mfc_err_dec(err) >= S5P_FIMV_ERR_WARNINGS_START)
> + s5p_mfc_hw_call(dev->mfc_ops, err_dec, err) >=
> + dev->warn_start)
> s5p_mfc_handle_frame(ctx, reason, err);
> else
> s5p_mfc_handle_error(ctx, reason, err);
> clear_bit(0, &dev->enter_suspend);
> break;
>
> - case S5P_FIMV_R2H_CMD_SLICE_DONE_RET:
> - case S5P_FIMV_R2H_CMD_FRAME_DONE_RET:
> + case S5P_MFC_R2H_CMD_SLICE_DONE_RET:
> + case S5P_MFC_R2H_CMD_FIELD_DONE_RET:
> + case S5P_MFC_R2H_CMD_FRAME_DONE_RET:
> if (ctx->c_ops->post_frame_start) {
> if (ctx->c_ops->post_frame_start(ctx))
> mfc_err("post_frame_start() failed\n");
> - s5p_mfc_clear_int_flags(dev);
> + s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
> wake_up_ctx(ctx, reason, err);
> if (test_and_clear_bit(0, &dev->hw_lock) == 0)
> BUG();
> s5p_mfc_clock_off();
> - s5p_mfc_try_run(dev);
> + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
> } else {
> s5p_mfc_handle_frame(ctx, reason, err);
> }
> break;
>
> - case S5P_FIMV_R2H_CMD_SEQ_DONE_RET:
> + case S5P_MFC_R2H_CMD_SEQ_DONE_RET:
> s5p_mfc_handle_seq_done(ctx, reason, err);
> break;
>
> - case S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET:
> - ctx->inst_no = s5p_mfc_get_inst_no();
> + case S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET:
> + ctx->inst_no = s5p_mfc_hw_call(dev->mfc_ops, get_inst_no,
dev);
> ctx->state = MFCINST_GOT_INST;
> clear_work_bit(ctx);
> wake_up(&ctx->queue);
> goto irq_cleanup_hw;
>
> - case S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET:
> + case S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET:
> clear_work_bit(ctx);
> ctx->state = MFCINST_FREE;
> wake_up(&ctx->queue);
> goto irq_cleanup_hw;
>
> - case S5P_FIMV_R2H_CMD_SYS_INIT_RET:
> - case S5P_FIMV_R2H_CMD_FW_STATUS_RET:
> - case S5P_FIMV_R2H_CMD_SLEEP_RET:
> - case S5P_FIMV_R2H_CMD_WAKEUP_RET:
> + case S5P_MFC_R2H_CMD_SYS_INIT_RET:
> + case S5P_MFC_R2H_CMD_FW_STATUS_RET:
> + case S5P_MFC_R2H_CMD_SLEEP_RET:
> + case S5P_MFC_R2H_CMD_WAKEUP_RET:
> if (ctx)
> clear_work_bit(ctx);
> - s5p_mfc_clear_int_flags(dev);
> + s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
> wake_up_dev(dev, reason, err);
> clear_bit(0, &dev->hw_lock);
> clear_bit(0, &dev->enter_suspend);
> break;
>
> - case S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET:
> + case S5P_MFC_R2H_CMD_INIT_BUFFERS_RET:
> s5p_mfc_handle_init_buffers(ctx, reason, err);
> break;
> default:
> mfc_debug(2, "Unknown int reason\n");
> - s5p_mfc_clear_int_flags(dev);
> + s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
> }
> mfc_debug_leave();
> return IRQ_HANDLED;
> irq_cleanup_hw:
> - s5p_mfc_clear_int_flags(dev);
> + s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
> ctx->int_type = reason;
> ctx->int_err = err;
> ctx->int_cond = 1;
> @@ -630,7 +644,7 @@ irq_cleanup_hw:
>
> s5p_mfc_clock_off();
>
> - s5p_mfc_try_run(dev);
> + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
> mfc_debug(2, "Exit via irq_cleanup_hw\n");
> return IRQ_HANDLED;
> }
> @@ -681,6 +695,7 @@ static int s5p_mfc_open(struct file *file)
> if (s5p_mfc_get_node_type(file) == MFCNODE_DECODER) {
> ctx->type = MFCINST_DECODER;
> ctx->c_ops = get_dec_codec_ops();
> + s5p_mfc_dec_init(ctx);
> /* Setup ctrl handler */
> ret = s5p_mfc_dec_ctrls_setup(ctx);
> if (ret) {
> @@ -693,6 +708,7 @@ static int s5p_mfc_open(struct file *file)
> /* only for encoder */
> INIT_LIST_HEAD(&ctx->ref_queue);
> ctx->ref_queue_cnt = 0;
> + s5p_mfc_enc_init(ctx);
> /* Setup ctrl handler */
> ret = s5p_mfc_enc_ctrls_setup(ctx);
> if (ret) {
> @@ -823,19 +839,20 @@ static int s5p_mfc_release(struct file *file)
> set_bit(ctx->num, &dev->ctx_work_bits);
> spin_unlock_irqrestore(&dev->condlock, flags);
> s5p_mfc_clean_ctx_int_flags(ctx);
> - s5p_mfc_try_run(dev);
> + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
> /* Wait until instance is returned or timeout occured */
> if (s5p_mfc_wait_for_done_ctx
> - (ctx, S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET, 0)) {
> + (ctx, S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET, 0)) {
> s5p_mfc_clock_off();
> mfc_err("Err returning instance\n");
> }
> mfc_debug(2, "After free instance\n");
> /* Free resources */
> - s5p_mfc_release_codec_buffers(ctx);
> - s5p_mfc_release_instance_buffer(ctx);
> + s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers, ctx);
> + s5p_mfc_hw_call(dev->mfc_ops, release_instance_buffer, ctx);
> if (ctx->type == MFCINST_DECODER)
> - s5p_mfc_release_dec_desc_buffer(ctx);
> + s5p_mfc_hw_call(dev->mfc_ops, release_dec_desc_buffer,
> + ctx);
>
> ctx->inst_no = MFC_NO_INSTANCE_SET;
> }
> @@ -847,6 +864,7 @@ static int s5p_mfc_release(struct file *file)
> mfc_debug(2, "Last instance - release firmware\n");
> /* reset <-> F/W release */
> s5p_mfc_reset(dev);
> + s5p_mfc_deinit_hw(dev);
> s5p_mfc_release_firmware(dev);
> del_timer_sync(&dev->watchdog_timer);
> if (s5p_mfc_power_off() < 0)
> @@ -1094,6 +1112,10 @@ static int s5p_mfc_probe(struct platform_device
*pdev)
> dev->watchdog_timer.data = (unsigned long)dev;
> dev->watchdog_timer.function = s5p_mfc_watchdog;
>
> + /* Initialize HW ops and commands based on MFC version */
> + s5p_mfc_init_hw_ops(dev);
> + s5p_mfc_init_hw_cmds(dev);
> +
> pr_debug("%s--\n", __func__);
> return 0;
>
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c
> b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c
> index 91a4155..47b956d 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c
> @@ -10,111 +10,15 @@
> * (at your option) any later version.
> */
>
> -#include "regs-mfc.h"
> #include "s5p_mfc_cmd.h"
> #include "s5p_mfc_common.h"
> #include "s5p_mfc_debug.h"
> +#include "s5p_mfc_cmd_v5.h"
>
> -/* This function is used to send a command to the MFC */
> -static int s5p_mfc_cmd_host2risc(struct s5p_mfc_dev *dev, int cmd,
> - struct s5p_mfc_cmd_args *args)
> -{
> - int cur_cmd;
> - unsigned long timeout;
> -
> - timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
> - /* wait until host to risc command register becomes 'H2R_CMD_EMPTY' */
> - do {
> - if (time_after(jiffies, timeout)) {
> - mfc_err("Timeout while waiting for hardware\n");
> - return -EIO;
> - }
> - cur_cmd = mfc_read(dev, S5P_FIMV_HOST2RISC_CMD);
> - } while (cur_cmd != S5P_FIMV_H2R_CMD_EMPTY);
> - mfc_write(dev, args->arg[0], S5P_FIMV_HOST2RISC_ARG1);
> - mfc_write(dev, args->arg[1], S5P_FIMV_HOST2RISC_ARG2);
> - mfc_write(dev, args->arg[2], S5P_FIMV_HOST2RISC_ARG3);
> - mfc_write(dev, args->arg[3], S5P_FIMV_HOST2RISC_ARG4);
> - /* Issue the command */
> - mfc_write(dev, cmd, S5P_FIMV_HOST2RISC_CMD);
> - return 0;
> -}
> -
> -/* Initialize the MFC */
> -int s5p_mfc_sys_init_cmd(struct s5p_mfc_dev *dev)
> -{
> - struct s5p_mfc_cmd_args h2r_args;
> -
> - memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
> - h2r_args.arg[0] = dev->fw_size;
> - return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SYS_INIT,
&h2r_args);
> -}
> -
> -/* Suspend the MFC hardware */
> -int s5p_mfc_sleep_cmd(struct s5p_mfc_dev *dev)
> -{
> - struct s5p_mfc_cmd_args h2r_args;
> -
> - memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
> - return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SLEEP, &h2r_args);
> -}
> +static struct s5p_mfc_hw_cmds *s5p_mfc_cmds;
>
> -/* Wake up the MFC hardware */
> -int s5p_mfc_wakeup_cmd(struct s5p_mfc_dev *dev)
> +void s5p_mfc_init_hw_cmds(struct s5p_mfc_dev *dev)
> {
> - struct s5p_mfc_cmd_args h2r_args;
> -
> - memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
> - return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_WAKEUP, &h2r_args);
> -}
> -
> -
> -int s5p_mfc_open_inst_cmd(struct s5p_mfc_ctx *ctx)
> -{
> - struct s5p_mfc_dev *dev = ctx->dev;
> - struct s5p_mfc_cmd_args h2r_args;
> - int ret;
> -
> - /* Preparing decoding - getting instance number */
> - mfc_debug(2, "Getting instance number (codec: %d)\n",
ctx->codec_mode);
> - dev->curr_ctx = ctx->num;
> - memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
> - h2r_args.arg[0] = ctx->codec_mode;
> - h2r_args.arg[1] = 0; /* no crc & no pixelcache */
> - h2r_args.arg[2] = ctx->ctx_ofs;
> - h2r_args.arg[3] = ctx->ctx_size;
> - ret = s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE,
> - &h2r_args);
> - if (ret) {
> - mfc_err("Failed to create a new instance\n");
> - ctx->state = MFCINST_ERROR;
> - }
> - return ret;
> + s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v5();
> + dev->mfc_cmds = s5p_mfc_cmds;
> }
> -
> -int s5p_mfc_close_inst_cmd(struct s5p_mfc_ctx *ctx)
> -{
> - struct s5p_mfc_dev *dev = ctx->dev;
> - struct s5p_mfc_cmd_args h2r_args;
> - int ret;
> -
> - if (ctx->state == MFCINST_FREE) {
> - mfc_err("Instance already returned\n");
> - ctx->state = MFCINST_ERROR;
> - return -EINVAL;
> - }
> - /* Closing decoding instance */
> - mfc_debug(2, "Returning instance number %d\n", ctx->inst_no);
> - dev->curr_ctx = ctx->num;
> - memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
> - h2r_args.arg[0] = ctx->inst_no;
> - ret = s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_CLOSE_INSTANCE,
> - &h2r_args);
> - if (ret) {
> - mfc_err("Failed to return an instance\n");
> - ctx->state = MFCINST_ERROR;
> - return -EINVAL;
> - }
> - return 0;
> -}
> -
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h
> b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h
> index 8b090d3..42dcd15 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h
> @@ -21,10 +21,15 @@ struct s5p_mfc_cmd_args {
> unsigned int arg[MAX_H2R_ARG];
> };
>
> -int s5p_mfc_sys_init_cmd(struct s5p_mfc_dev *dev);
> -int s5p_mfc_sleep_cmd(struct s5p_mfc_dev *dev);
> -int s5p_mfc_wakeup_cmd(struct s5p_mfc_dev *dev);
> -int s5p_mfc_open_inst_cmd(struct s5p_mfc_ctx *ctx);
> -int s5p_mfc_close_inst_cmd(struct s5p_mfc_ctx *ctx);
> +struct s5p_mfc_hw_cmds {
> + int (*cmd_host2risc)(struct s5p_mfc_dev *dev, int cmd,
> + struct s5p_mfc_cmd_args *args);
> + int (*sys_init_cmd)(struct s5p_mfc_dev *dev);
> + int (*sleep_cmd)(struct s5p_mfc_dev *dev);
> + int (*wakeup_cmd)(struct s5p_mfc_dev *dev);
> + int (*open_inst_cmd)(struct s5p_mfc_ctx *ctx);
> + int (*close_inst_cmd)(struct s5p_mfc_ctx *ctx);
> +};
>
> +void s5p_mfc_init_hw_cmds(struct s5p_mfc_dev *dev);
> #endif /* S5P_MFC_CMD_H_ */
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
> b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
> new file mode 100644
> index 0000000..f3d7874
> --- /dev/null
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
> @@ -0,0 +1,166 @@
> +/*
> + * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
> + *
> + * Copyright (C) 2012 Samsung Electronics Co., Ltd.
> + * http://www.samsung.com/
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include "regs-mfc.h"
> +#include "s5p_mfc_cmd.h"
> +#include "s5p_mfc_common.h"
> +#include "s5p_mfc_debug.h"
> +
> +/* This function is used to send a command to the MFC */
> +int s5p_mfc_cmd_host2risc_v5(struct s5p_mfc_dev *dev, int cmd,
> + struct s5p_mfc_cmd_args *args)
> +{
> + int cur_cmd;
> + unsigned long timeout;
> +
> + timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
> + /* wait until host to risc command register becomes 'H2R_CMD_EMPTY' */
> + do {
> + if (time_after(jiffies, timeout)) {
> + mfc_err("Timeout while waiting for hardware\n");
> + return -EIO;
> + }
> + cur_cmd = mfc_read(dev, S5P_FIMV_HOST2RISC_CMD);
> + } while (cur_cmd != S5P_FIMV_H2R_CMD_EMPTY);
> + mfc_write(dev, args->arg[0], S5P_FIMV_HOST2RISC_ARG1);
> + mfc_write(dev, args->arg[1], S5P_FIMV_HOST2RISC_ARG2);
> + mfc_write(dev, args->arg[2], S5P_FIMV_HOST2RISC_ARG3);
> + mfc_write(dev, args->arg[3], S5P_FIMV_HOST2RISC_ARG4);
> + /* Issue the command */
> + mfc_write(dev, cmd, S5P_FIMV_HOST2RISC_CMD);
> + return 0;
> +}
> +
> +/* Initialize the MFC */
> +int s5p_mfc_sys_init_cmd_v5(struct s5p_mfc_dev *dev)
> +{
> + struct s5p_mfc_cmd_args h2r_args;
> +
> + memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
> + h2r_args.arg[0] = dev->fw_size;
> + return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_SYS_INIT,
> + &h2r_args);
> +}
> +
> +/* Suspend the MFC hardware */
> +int s5p_mfc_sleep_cmd_v5(struct s5p_mfc_dev *dev)
> +{
> + struct s5p_mfc_cmd_args h2r_args;
> +
> + memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
> + return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_SLEEP,
&h2r_args);
> +}
> +
> +/* Wake up the MFC hardware */
> +int s5p_mfc_wakeup_cmd_v5(struct s5p_mfc_dev *dev)
> +{
> + struct s5p_mfc_cmd_args h2r_args;
> +
> + memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
> + return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_WAKEUP,
> + &h2r_args);
> +}
> +
> +
> +int s5p_mfc_open_inst_cmd_v5(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_cmd_args h2r_args;
> + int ret;
> +
> + /* Preparing decoding - getting instance number */
> + mfc_debug(2, "Getting instance number (codec: %d)\n",
ctx->codec_mode);
> + dev->curr_ctx = ctx->num;
> + memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
> + switch (ctx->codec_mode) {
> + case S5P_MFC_CODEC_H264_DEC:
> + h2r_args.arg[0] = S5P_FIMV_CODEC_H264_DEC;
> + break;
> + case S5P_MFC_CODEC_VC1_DEC:
> + h2r_args.arg[0] = S5P_FIMV_CODEC_VC1_DEC;
> + break;
> + case S5P_MFC_CODEC_MPEG4_DEC:
> + h2r_args.arg[0] = S5P_FIMV_CODEC_MPEG4_DEC;
> + break;
> + case S5P_MFC_CODEC_MPEG2_DEC:
> + h2r_args.arg[0] = S5P_FIMV_CODEC_MPEG2_DEC;
> + break;
> + case S5P_MFC_CODEC_H263_DEC:
> + h2r_args.arg[0] = S5P_FIMV_CODEC_H263_DEC;
> + break;
> + case S5P_MFC_CODEC_VC1RCV_DEC:
> + h2r_args.arg[0] = S5P_FIMV_CODEC_VC1RCV_DEC;
> + break;
> + case S5P_MFC_CODEC_H264_ENC:
> + h2r_args.arg[0] = S5P_FIMV_CODEC_H264_ENC;
> + break;
> + case S5P_MFC_CODEC_MPEG4_ENC:
> + h2r_args.arg[0] = S5P_FIMV_CODEC_MPEG4_ENC;
> + break;
> + case S5P_MFC_CODEC_H263_ENC:
> + h2r_args.arg[0] = S5P_FIMV_CODEC_H263_ENC;
> + break;
> + default:
> + h2r_args.arg[0] = S5P_FIMV_CODEC_NONE;
> + };
> + h2r_args.arg[1] = 0; /* no crc & no pixelcache */
> + h2r_args.arg[2] = ctx->ctx_ofs;
> + h2r_args.arg[3] = ctx->ctx_size;
> + ret = s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE,
> + &h2r_args);
> + if (ret) {
> + mfc_err("Failed to create a new instance\n");
> + ctx->state = MFCINST_ERROR;
> + }
> + return ret;
> +}
> +
> +int s5p_mfc_close_inst_cmd_v5(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_cmd_args h2r_args;
> + int ret;
> +
> + if (ctx->state == MFCINST_FREE) {
> + mfc_err("Instance already returned\n");
> + ctx->state = MFCINST_ERROR;
> + return -EINVAL;
> + }
> + /* Closing decoding instance */
> + mfc_debug(2, "Returning instance number %d\n", ctx->inst_no);
> + dev->curr_ctx = ctx->num;
> + memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
> + h2r_args.arg[0] = ctx->inst_no;
> + ret = s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_CLOSE_INSTANCE,
> + &h2r_args);
> + if (ret) {
> + mfc_err("Failed to return an instance\n");
> + ctx->state = MFCINST_ERROR;
> + return -EINVAL;
> + }
> + return 0;
> +}
> +
> +/* Initialize cmd function pointers for MFC v5 */
> +static struct s5p_mfc_hw_cmds s5p_mfc_cmds_v5 = {
> + .cmd_host2risc = s5p_mfc_cmd_host2risc_v5,
> + .sys_init_cmd = s5p_mfc_sys_init_cmd_v5,
> + .sleep_cmd = s5p_mfc_sleep_cmd_v5,
> + .wakeup_cmd = s5p_mfc_wakeup_cmd_v5,
> + .open_inst_cmd = s5p_mfc_open_inst_cmd_v5,
> + .close_inst_cmd = s5p_mfc_close_inst_cmd_v5,
> +};
> +
> +struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v5(void)
> +{
> + return &s5p_mfc_cmds_v5;
> +}
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h
> b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h
> new file mode 100644
> index 0000000..6928a55
> --- /dev/null
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h
> @@ -0,0 +1,20 @@
> +/*
> + * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h
> + *
> + * Copyright (C) 2011 Samsung Electronics Co., Ltd.
> + * http://www.samsung.com/
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef S5P_MFC_CMD_V5_H_
> +#define S5P_MFC_CMD_V5_H_
> +
> +#include "s5p_mfc_common.h"
> +
> +struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v5(void);
> +
> +#endif /* S5P_MFC_CMD_H_ */
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
> b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
> index bd5706a..ccb59ac 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
> @@ -74,7 +74,40 @@ static inline dma_addr_t s5p_mfc_mem_cookie(void *a, void
*b)
> #define MFC_ENC_CAP_PLANE_COUNT 1
> #define MFC_ENC_OUT_PLANE_COUNT 2
> #define STUFF_BYTE 4
> -#define MFC_MAX_CTRLS 64
> +#define MFC_MAX_CTRLS 70
> +
> +#define S5P_MFC_CODEC_NONE -1
> +#define S5P_MFC_CODEC_H264_DEC 0
> +#define S5P_MFC_CODEC_H264_MVC_DEC 1
> +#define S5P_MFC_CODEC_VC1_DEC 2
> +#define S5P_MFC_CODEC_MPEG4_DEC 3
> +#define S5P_MFC_CODEC_MPEG2_DEC 4
> +#define S5P_MFC_CODEC_H263_DEC 5
> +#define S5P_MFC_CODEC_VC1RCV_DEC 6
> +#define S5P_MFC_CODEC_VP8_DEC 7
> +
> +#define S5P_MFC_CODEC_H264_ENC 20
> +#define S5P_MFC_CODEC_H264_MVC_ENC 21
> +#define S5P_MFC_CODEC_MPEG4_ENC 22
> +#define S5P_MFC_CODEC_H263_ENC 23
> +
> +#define S5P_MFC_R2H_CMD_EMPTY 0
> +#define S5P_MFC_R2H_CMD_SYS_INIT_RET 1
> +#define S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET 2
> +#define S5P_MFC_R2H_CMD_SEQ_DONE_RET 3
> +#define S5P_MFC_R2H_CMD_INIT_BUFFERS_RET 4
> +#define S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET 6
> +#define S5P_MFC_R2H_CMD_SLEEP_RET 7
> +#define S5P_MFC_R2H_CMD_WAKEUP_RET 8
> +#define S5P_MFC_R2H_CMD_COMPLETE_SEQ_RET 9
> +#define S5P_MFC_R2H_CMD_DPB_FLUSH_RET 10
> +#define S5P_MFC_R2H_CMD_NAL_ABORT_RET 11
> +#define S5P_MFC_R2H_CMD_FW_STATUS_RET 12
> +#define S5P_MFC_R2H_CMD_FRAME_DONE_RET 13
> +#define S5P_MFC_R2H_CMD_FIELD_DONE_RET 14
> +#define S5P_MFC_R2H_CMD_SLICE_DONE_RET 15
> +#define S5P_MFC_R2H_CMD_ENC_BUFFER_FUL_RET 16
> +#define S5P_MFC_R2H_CMD_ERR_RET 32
>
> #define mfc_read(dev, offset) readl(dev->regs_base +
(offset))
> #define mfc_write(dev, data, offset) writel((data), dev->regs_base + \
> @@ -209,6 +242,9 @@ struct s5p_mfc_pm {
> * @watchdog_work: worker for the watchdog
> * @alloc_ctx: videobuf2 allocator contexts for two memory
banks
> * @enter_suspend: flag set when entering suspend
> + * @warn_start: hardware error code from which warnings start
> + * @mfc_ops: ops structure holding HW operation function pointers
> + * @mfc_cmds: cmd structure holding HW commands function
pointers
> *
> */
> struct s5p_mfc_dev {
> @@ -245,6 +281,10 @@ struct s5p_mfc_dev {
> struct work_struct watchdog_work;
> void *alloc_ctx[2];
> unsigned long enter_suspend;
> +
> + int warn_start;
> + struct s5p_mfc_hw_ops *mfc_ops;
> + struct s5p_mfc_hw_cmds *mfc_cmds;
> };
>
> /**
> @@ -562,6 +602,9 @@ struct mfc_control {
> __u8 is_volatile;
> };
>
> +/* Macro for making hardware specific calls */
> +#define s5p_mfc_hw_call(f, op, args...) \
> + ((f && f->op) ? f->op(args) : -ENODEV)
>
> #define fh_to_ctx(__fh) container_of(__fh, struct s5p_mfc_ctx, fh)
> #define ctrl_to_ctx(__ctrl) \
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
> b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
> index 4d662f1..4a39e5e 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
> @@ -15,11 +15,11 @@
> #include <linux/firmware.h>
> #include <linux/jiffies.h>
> #include <linux/sched.h>
> -#include "regs-mfc.h"
> #include "s5p_mfc_cmd.h"
> #include "s5p_mfc_common.h"
> #include "s5p_mfc_debug.h"
> #include "s5p_mfc_intr.h"
> +#include "s5p_mfc_opr.h"
> #include "s5p_mfc_pm.h"
>
> static void *s5p_mfc_bitproc_buf;
> @@ -226,7 +226,7 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
> s5p_mfc_clean_dev_int_flags(dev);
> mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
> mfc_debug(2, "Will now wait for completion of firmware transfer\n");
> - if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_FW_STATUS_RET)) {
> + if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_FW_STATUS_RET)) {
> mfc_err("Failed to load firmware\n");
> s5p_mfc_reset(dev);
> s5p_mfc_clock_off();
> @@ -234,7 +234,7 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
> }
> s5p_mfc_clean_dev_int_flags(dev);
> /* 4. Initialize firmware */
> - ret = s5p_mfc_sys_init_cmd(dev);
> + ret = s5p_mfc_hw_call(dev->mfc_cmds, sys_init_cmd, dev);
> if (ret) {
> mfc_err("Failed to send command to MFC - timeout\n");
> s5p_mfc_reset(dev);
> @@ -242,7 +242,7 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
> return ret;
> }
> mfc_debug(2, "Ok, now will write a command to init the system\n");
> - if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_SYS_INIT_RET)) {
> + if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_SYS_INIT_RET)) {
> mfc_err("Failed to load firmware\n");
> s5p_mfc_reset(dev);
> s5p_mfc_clock_off();
> @@ -250,7 +250,7 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
> }
> dev->int_cond = 0;
> if (dev->int_err != 0 || dev->int_type !=
> - S5P_FIMV_R2H_CMD_SYS_INIT_RET) {
> + S5P_MFC_R2H_CMD_SYS_INIT_RET) {
> /* Failure. */
> mfc_err("Failed to init firmware - error: %d int: %d\n",
> dev->int_err, dev->int_type);
> @@ -267,6 +267,17 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
> }
>
>
> +/* Deinitialize hardware */
> +void s5p_mfc_deinit_hw(struct s5p_mfc_dev *dev)
> +{
> + s5p_mfc_clock_on();
> +
> + s5p_mfc_reset(dev);
> + s5p_mfc_hw_call(dev->mfc_ops, release_dev_context_buffer, dev);
> +
> + s5p_mfc_clock_off();
> +}
> +
> int s5p_mfc_sleep(struct s5p_mfc_dev *dev)
> {
> int ret;
> @@ -274,19 +285,19 @@ int s5p_mfc_sleep(struct s5p_mfc_dev *dev)
> mfc_debug_enter();
> s5p_mfc_clock_on();
> s5p_mfc_clean_dev_int_flags(dev);
> - ret = s5p_mfc_sleep_cmd(dev);
> + ret = s5p_mfc_hw_call(dev->mfc_cmds, sleep_cmd, dev);
> if (ret) {
> mfc_err("Failed to send command to MFC - timeout\n");
> return ret;
> }
> - if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_SLEEP_RET)) {
> + if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_SLEEP_RET)) {
> mfc_err("Failed to sleep\n");
> return -EIO;
> }
> s5p_mfc_clock_off();
> dev->int_cond = 0;
> if (dev->int_err != 0 || dev->int_type !=
> - S5P_FIMV_R2H_CMD_SLEEP_RET) {
> + S5P_MFC_R2H_CMD_SLEEP_RET) {
> /* Failure. */
> mfc_err("Failed to sleep - error: %d int: %d\n", dev->int_err,
>
dev->int_type);
> @@ -316,7 +327,7 @@ int s5p_mfc_wakeup(struct s5p_mfc_dev *dev)
> s5p_mfc_clear_cmds(dev);
> s5p_mfc_clean_dev_int_flags(dev);
> /* 3. Initialize firmware */
> - ret = s5p_mfc_wakeup_cmd(dev);
> + ret = s5p_mfc_hw_call(dev->mfc_cmds, wakeup_cmd, dev);
> if (ret) {
> mfc_err("Failed to send command to MFC - timeout\n");
> return ret;
> @@ -324,14 +335,14 @@ int s5p_mfc_wakeup(struct s5p_mfc_dev *dev)
> /* 4. Release reset signal to the RISC */
> mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
> mfc_debug(2, "Ok, now will write a command to wakeup the system\n");
> - if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_WAKEUP_RET)) {
> + if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_WAKEUP_RET)) {
> mfc_err("Failed to load firmware\n");
> return -EIO;
> }
> s5p_mfc_clock_off();
> dev->int_cond = 0;
> if (dev->int_err != 0 || dev->int_type !=
> - S5P_FIMV_R2H_CMD_WAKEUP_RET) {
> + S5P_MFC_R2H_CMD_WAKEUP_RET) {
> /* Failure. */
> mfc_err("Failed to wakeup - error: %d int: %d\n",
dev->int_err,
>
dev->int_type);
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h
> b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h
> index e1e0c54..90aa9b9 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h
> @@ -20,6 +20,7 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev
*dev);
> int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev);
>
> int s5p_mfc_init_hw(struct s5p_mfc_dev *dev);
> +void s5p_mfc_deinit_hw(struct s5p_mfc_dev *dev);
>
> int s5p_mfc_sleep(struct s5p_mfc_dev *dev);
> int s5p_mfc_wakeup(struct s5p_mfc_dev *dev);
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
> b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
> index 456f5df..8133a4c 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
> @@ -23,83 +23,84 @@
> #include <linux/workqueue.h>
> #include <media/v4l2-ctrls.h>
> #include <media/videobuf2-core.h>
> -#include "regs-mfc.h"
> #include "s5p_mfc_common.h"
> #include "s5p_mfc_debug.h"
> #include "s5p_mfc_dec.h"
> #include "s5p_mfc_intr.h"
> #include "s5p_mfc_opr.h"
> #include "s5p_mfc_pm.h"
> -#include "s5p_mfc_shm.h"
> +
> +#define DEF_SRC_FMT_DEC V4L2_PIX_FMT_H264
> +#define DEF_DST_FMT_DEC V4L2_PIX_FMT_NV12MT
>
> static struct s5p_mfc_fmt formats[] = {
> {
> .name = "4:2:0 2 Planes 64x32 Tiles",
> .fourcc = V4L2_PIX_FMT_NV12MT,
> - .codec_mode = S5P_FIMV_CODEC_NONE,
> + .codec_mode = S5P_MFC_CODEC_NONE,
> .type = MFC_FMT_RAW,
> .num_planes = 2,
> - },
> + },
> {
> .name = "4:2:0 2 Planes",
> .fourcc = V4L2_PIX_FMT_NV12M,
> - .codec_mode = S5P_FIMV_CODEC_NONE,
> + .codec_mode = S5P_MFC_CODEC_NONE,
> .type = MFC_FMT_RAW,
> .num_planes = 2,
> },
> {
> .name = "H264 Encoded Stream",
> .fourcc = V4L2_PIX_FMT_H264,
> - .codec_mode = S5P_FIMV_CODEC_H264_DEC,
> + .codec_mode = S5P_MFC_CODEC_H264_DEC,
> .type = MFC_FMT_DEC,
> .num_planes = 1,
> },
> {
> .name = "H263 Encoded Stream",
> .fourcc = V4L2_PIX_FMT_H263,
> - .codec_mode = S5P_FIMV_CODEC_H263_DEC,
> + .codec_mode = S5P_MFC_CODEC_H263_DEC,
> .type = MFC_FMT_DEC,
> .num_planes = 1,
> },
> {
> .name = "MPEG1 Encoded Stream",
> .fourcc = V4L2_PIX_FMT_MPEG1,
> - .codec_mode = S5P_FIMV_CODEC_MPEG2_DEC,
> + .codec_mode = S5P_MFC_CODEC_MPEG2_DEC,
> .type = MFC_FMT_DEC,
> .num_planes = 1,
> },
> {
> .name = "MPEG2 Encoded Stream",
> .fourcc = V4L2_PIX_FMT_MPEG2,
> - .codec_mode = S5P_FIMV_CODEC_MPEG2_DEC,
> + .codec_mode = S5P_MFC_CODEC_MPEG2_DEC,
> .type = MFC_FMT_DEC,
> .num_planes = 1,
> },
> {
> .name = "MPEG4 Encoded Stream",
> .fourcc = V4L2_PIX_FMT_MPEG4,
> - .codec_mode = S5P_FIMV_CODEC_MPEG4_DEC,
> + .codec_mode = S5P_MFC_CODEC_MPEG4_DEC,
> .type = MFC_FMT_DEC,
> .num_planes = 1,
> },
> {
> .name = "XviD Encoded Stream",
> .fourcc = V4L2_PIX_FMT_XVID,
> - .codec_mode = S5P_FIMV_CODEC_MPEG4_DEC,
> + .codec_mode = S5P_MFC_CODEC_MPEG4_DEC,
> .type = MFC_FMT_DEC,
> .num_planes = 1,
> },
> {
> .name = "VC1 Encoded Stream",
> .fourcc = V4L2_PIX_FMT_VC1_ANNEX_G,
> - .codec_mode = S5P_FIMV_CODEC_VC1_DEC,
> + .codec_mode = S5P_MFC_CODEC_VC1_DEC,
> .type = MFC_FMT_DEC,
> .num_planes = 1,
> },
> {
> .name = "VC1 RCV Encoded Stream",
> .fourcc = V4L2_PIX_FMT_VC1_ANNEX_L,
> - .codec_mode = S5P_FIMV_CODEC_VC1RCV_DEC,
> + .codec_mode = S5P_MFC_CODEC_VC1RCV_DEC,
> .type = MFC_FMT_DEC,
> .num_planes = 1,
> },
> @@ -297,7 +298,7 @@ static int vidioc_g_fmt(struct file *file, void *priv,
> struct v4l2_format *f)
> /* If the MFC is parsing the header,
> * so wait until it is finished */
> s5p_mfc_clean_ctx_int_flags(ctx);
> - s5p_mfc_wait_for_done_ctx(ctx, S5P_FIMV_R2H_CMD_SEQ_DONE_RET,
> + s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_SEQ_DONE_RET,
> 0);
> }
> if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
> @@ -380,7 +381,7 @@ static int vidioc_s_fmt(struct file *file, void *priv,
> struct v4l2_format *f)
> goto out;
> }
> fmt = find_format(f, MFC_FMT_DEC);
> - if (!fmt || fmt->codec_mode == S5P_FIMV_CODEC_NONE) {
> + if (!fmt || fmt->codec_mode == S5P_MFC_CODEC_NONE) {
> mfc_err("Unknown codec\n");
> ret = -EINVAL;
> goto out;
> @@ -477,7 +478,7 @@ static int vidioc_reqbufs(struct file *file, void *priv,
> return -ENOMEM;
> }
> ctx->total_dpb_count = reqbufs->count;
> - ret = s5p_mfc_alloc_codec_buffers(ctx);
> + ret = s5p_mfc_hw_call(dev->mfc_ops, alloc_codec_buffers, ctx);
> if (ret) {
> mfc_err("Failed to allocate decoding buffers\n");
> reqbufs->count = 0;
> @@ -493,7 +494,8 @@ static int vidioc_reqbufs(struct file *file, void *priv,
> reqbufs->count = 0;
> s5p_mfc_clock_on();
> ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
> - s5p_mfc_release_codec_buffers(ctx);
> + s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers,
> + ctx);
> s5p_mfc_clock_off();
> return -ENOMEM;
> }
> @@ -502,9 +504,9 @@ static int vidioc_reqbufs(struct file *file, void *priv,
> set_bit(ctx->num, &dev->ctx_work_bits);
> spin_unlock_irqrestore(&dev->condlock, flags);
> }
> - s5p_mfc_try_run(dev);
> + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
> s5p_mfc_wait_for_done_ctx(ctx,
> - S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET,
0);
> + S5P_MFC_R2H_CMD_INIT_BUFFERS_RET, 0);
> }
> return ret;
> }
> @@ -587,20 +589,24 @@ static int vidioc_streamon(struct file *file, void
*priv,
> ctx->src_bufs_cnt = 0;
> ctx->capture_state = QUEUE_FREE;
> ctx->output_state = QUEUE_FREE;
> - s5p_mfc_alloc_instance_buffer(ctx);
> - s5p_mfc_alloc_dec_temp_buffers(ctx);
> + s5p_mfc_hw_call(dev->mfc_ops, alloc_instance_buffer,
> + ctx);
> + s5p_mfc_hw_call(dev->mfc_ops, alloc_dec_temp_buffers,
> + ctx);
> spin_lock_irqsave(&dev->condlock, flags);
> set_bit(ctx->num, &dev->ctx_work_bits);
> spin_unlock_irqrestore(&dev->condlock, flags);
> s5p_mfc_clean_ctx_int_flags(ctx);
> - s5p_mfc_try_run(dev);
> + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
>
> if (s5p_mfc_wait_for_done_ctx(ctx,
> - S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET, 0)) {
> + S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET, 0)) {
> /* Error or timeout */
> mfc_err("Error getting instance from
hardware\n");
> - s5p_mfc_release_instance_buffer(ctx);
> - s5p_mfc_release_dec_desc_buffer(ctx);
> + s5p_mfc_hw_call(dev->mfc_ops,
> + release_instance_buffer, ctx);
> + s5p_mfc_hw_call(dev->mfc_ops,
> + release_dec_desc_buffer, ctx);
> return -EIO;
> }
> mfc_debug(2, "Got instance number: %d\n",
ctx->inst_no);
> @@ -669,7 +675,7 @@ static int s5p_mfc_dec_g_v_ctrl(struct v4l2_ctrl *ctrl)
> /* Should wait for the header to be parsed */
> s5p_mfc_clean_ctx_int_flags(ctx);
> s5p_mfc_wait_for_done_ctx(ctx,
> - S5P_FIMV_R2H_CMD_SEQ_DONE_RET, 0);
> + S5P_MFC_R2H_CMD_SEQ_DONE_RET, 0);
> if (ctx->state >= MFCINST_HEAD_PARSED &&
> ctx->state < MFCINST_ABORT) {
> ctrl->val = ctx->dpb_count;
> @@ -693,6 +699,7 @@ static int vidioc_g_crop(struct file *file, void *priv,
> struct v4l2_crop *cr)
> {
> struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
> + struct s5p_mfc_dev *dev = ctx->dev;
> u32 left, right, top, bottom;
>
> if (ctx->state != MFCINST_HEAD_PARSED &&
> @@ -702,10 +709,10 @@ static int vidioc_g_crop(struct file *file, void
*priv,
> return -EINVAL;
> }
> if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_H264) {
> - left = s5p_mfc_read_shm(ctx, CROP_INFO_H);
> + left = s5p_mfc_hw_call(dev->mfc_ops, get_crop_info_h, ctx);
> right = left >> S5P_FIMV_SHARED_CROP_RIGHT_SHIFT;
> left = left & S5P_FIMV_SHARED_CROP_LEFT_MASK;
> - top = s5p_mfc_read_shm(ctx, CROP_INFO_V);
> + top = s5p_mfc_hw_call(dev->mfc_ops, get_crop_info_v, ctx);
> bottom = top >> S5P_FIMV_SHARED_CROP_BOTTOM_SHIFT;
> top = top & S5P_FIMV_SHARED_CROP_TOP_MASK;
> cr->c.left = left;
> @@ -887,7 +894,7 @@ static int s5p_mfc_start_streaming(struct vb2_queue *q,
> unsigned int count)
> set_bit(ctx->num, &dev->ctx_work_bits);
> spin_unlock_irqrestore(&dev->condlock, flags);
> }
> - s5p_mfc_try_run(dev);
> + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
> return 0;
> }
>
> @@ -903,19 +910,21 @@ static int s5p_mfc_stop_streaming(struct vb2_queue *q)
> dev->curr_ctx == ctx->num && dev->hw_lock) {
> ctx->state = MFCINST_ABORT;
> s5p_mfc_wait_for_done_ctx(ctx,
> - S5P_FIMV_R2H_CMD_FRAME_DONE_RET, 0);
> + S5P_MFC_R2H_CMD_FRAME_DONE_RET, 0);
> aborted = 1;
> }
> spin_lock_irqsave(&dev->irqlock, flags);
> if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
> - s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
> + s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue,
> + &ctx->vq_dst);
> INIT_LIST_HEAD(&ctx->dst_queue);
> ctx->dst_queue_cnt = 0;
> ctx->dpb_flush_flag = 1;
> ctx->dec_dst_flag = 0;
> }
> if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
> - s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
> + s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue,
> + &ctx->vq_src);
> INIT_LIST_HEAD(&ctx->src_queue);
> ctx->src_queue_cnt = 0;
> }
> @@ -958,7 +967,7 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
> set_bit(ctx->num, &dev->ctx_work_bits);
> spin_unlock_irqrestore(&dev->condlock, flags);
> }
> - s5p_mfc_try_run(dev);
> + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
> }
>
> static struct vb2_ops s5p_mfc_dec_qops = {
> @@ -1042,3 +1051,13 @@ void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx
*ctx)
> ctx->ctrls[i] = NULL;
> }
>
> +void s5p_mfc_dec_init(struct s5p_mfc_ctx *ctx)
> +{
> + struct v4l2_format f;
> + f.fmt.pix_mp.pixelformat = DEF_SRC_FMT_DEC;
> + ctx->src_fmt = find_format(&f, MFC_FMT_DEC);
> + f.fmt.pix_mp.pixelformat = DEF_DST_FMT_DEC;
> + ctx->dst_fmt = find_format(&f, MFC_FMT_RAW);
> + mfc_debug(2, "Default src_fmt is %x, dest_fmt is %x\n",
> + (unsigned int)ctx->src_fmt, (unsigned
int)ctx->dst_fmt);
> +}
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.h
> b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.h
> index fdf1d99..d06a7ca 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.h
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.h
> @@ -19,5 +19,6 @@ const struct v4l2_ioctl_ops *get_dec_v4l2_ioctl_ops(void);
> struct s5p_mfc_fmt *get_dec_def_fmt(bool src);
> int s5p_mfc_dec_ctrls_setup(struct s5p_mfc_ctx *ctx);
> void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx *ctx);
> +void s5p_mfc_dec_init(struct s5p_mfc_ctx *ctx);
>
> #endif /* S5P_MFC_DEC_H_ */
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
> b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
> index fdeebb0..02e1a94 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
> @@ -24,46 +24,48 @@
> #include <linux/workqueue.h>
> #include <media/v4l2-ctrls.h>
> #include <media/videobuf2-core.h>
> -#include "regs-mfc.h"
> #include "s5p_mfc_common.h"
> #include "s5p_mfc_debug.h"
> #include "s5p_mfc_enc.h"
> #include "s5p_mfc_intr.h"
> #include "s5p_mfc_opr.h"
>
> +#define DEF_SRC_FMT_ENC V4L2_PIX_FMT_NV12MT
> +#define DEF_DST_FMT_ENC V4L2_PIX_FMT_H264
> +
> static struct s5p_mfc_fmt formats[] = {
> {
> .name = "4:2:0 2 Planes 64x32 Tiles",
> .fourcc = V4L2_PIX_FMT_NV12MT,
> - .codec_mode = S5P_FIMV_CODEC_NONE,
> + .codec_mode = S5P_MFC_CODEC_NONE,
> .type = MFC_FMT_RAW,
> .num_planes = 2,
> },
> {
> .name = "4:2:0 2 Planes",
> .fourcc = V4L2_PIX_FMT_NV12M,
> - .codec_mode = S5P_FIMV_CODEC_NONE,
> + .codec_mode = S5P_MFC_CODEC_NONE,
> .type = MFC_FMT_RAW,
> .num_planes = 2,
> },
> {
> .name = "H264 Encoded Stream",
> .fourcc = V4L2_PIX_FMT_H264,
> - .codec_mode = S5P_FIMV_CODEC_H264_ENC,
> + .codec_mode = S5P_MFC_CODEC_H264_ENC,
> .type = MFC_FMT_ENC,
> .num_planes = 1,
> },
> {
> .name = "MPEG4 Encoded Stream",
> .fourcc = V4L2_PIX_FMT_MPEG4,
> - .codec_mode = S5P_FIMV_CODEC_MPEG4_ENC,
> + .codec_mode = S5P_MFC_CODEC_MPEG4_ENC,
> .type = MFC_FMT_ENC,
> .num_planes = 1,
> },
> {
> .name = "H263 Encoded Stream",
> .fourcc = V4L2_PIX_FMT_H263,
> - .codec_mode = S5P_FIMV_CODEC_H263_ENC,
> + .codec_mode = S5P_MFC_CODEC_H263_ENC,
> .type = MFC_FMT_ENC,
> .num_planes = 1,
> },
> @@ -618,7 +620,8 @@ static int enc_pre_seq_start(struct s5p_mfc_ctx *ctx)
> dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
> dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
> dst_size = vb2_plane_size(dst_mb->b, 0);
> - s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
> + s5p_mfc_hw_call(dev->mfc_ops, set_enc_stream_buffer, ctx, dst_addr,
> + dst_size);
> spin_unlock_irqrestore(&dev->irqlock, flags);
> return 0;
> }
> @@ -637,7 +640,7 @@ static int enc_post_seq_start(struct s5p_mfc_ctx *ctx)
> list_del(&dst_mb->list);
> ctx->dst_queue_cnt--;
> vb2_set_plane_payload(dst_mb->b, 0,
> - s5p_mfc_get_enc_strm_size());
> + s5p_mfc_hw_call(dev->mfc_ops, get_enc_strm_size,
dev));
> vb2_buffer_done(dst_mb->b, VB2_BUF_STATE_DONE);
> spin_unlock_irqrestore(&dev->irqlock, flags);
> }
> @@ -647,7 +650,7 @@ static int enc_post_seq_start(struct s5p_mfc_ctx *ctx)
> set_bit(ctx->num, &dev->ctx_work_bits);
> spin_unlock_irqrestore(&dev->condlock, flags);
> }
> - s5p_mfc_try_run(dev);
> + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
> return 0;
> }
>
> @@ -664,14 +667,16 @@ static int enc_pre_frame_start(struct s5p_mfc_ctx
*ctx)
> src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
> src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 0);
> src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1);
> - s5p_mfc_set_enc_frame_buffer(ctx, src_y_addr, src_c_addr);
> + s5p_mfc_hw_call(dev->mfc_ops, set_enc_frame_buffer, ctx, src_y_addr,
> + src_c_addr);
> spin_unlock_irqrestore(&dev->irqlock, flags);
>
> spin_lock_irqsave(&dev->irqlock, flags);
> dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
> dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
> dst_size = vb2_plane_size(dst_mb->b, 0);
> - s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
> + s5p_mfc_hw_call(dev->mfc_ops, set_enc_stream_buffer, ctx, dst_addr,
> + dst_size);
> spin_unlock_irqrestore(&dev->irqlock, flags);
>
> return 0;
> @@ -687,15 +692,16 @@ static int enc_post_frame_start(struct s5p_mfc_ctx
*ctx)
> unsigned int strm_size;
> unsigned long flags;
>
> - slice_type = s5p_mfc_get_enc_slice_type();
> - strm_size = s5p_mfc_get_enc_strm_size();
> + slice_type = s5p_mfc_hw_call(dev->mfc_ops, get_enc_slice_type, dev);
> + strm_size = s5p_mfc_hw_call(dev->mfc_ops, get_enc_strm_size, dev);
> mfc_debug(2, "Encoded slice type: %d", slice_type);
> mfc_debug(2, "Encoded stream size: %d", strm_size);
> mfc_debug(2, "Display order: %d",
> mfc_read(dev, S5P_FIMV_ENC_SI_PIC_CNT));
> spin_lock_irqsave(&dev->irqlock, flags);
> if (slice_type >= 0) {
> - s5p_mfc_get_enc_frame_buffer(ctx, &enc_y_addr, &enc_c_addr);
> + s5p_mfc_hw_call(dev->mfc_ops, get_enc_frame_buffer, ctx,
> + &enc_y_addr, &enc_c_addr);
> list_for_each_entry(mb_entry, &ctx->src_queue, list) {
> mb_y_addr = vb2_dma_contig_plane_dma_addr(mb_entry->b,
0);
> mb_c_addr = vb2_dma_contig_plane_dma_addr(mb_entry->b,
1);
> @@ -945,17 +951,18 @@ static int vidioc_s_fmt(struct file *file, void *priv,
> struct v4l2_format *f)
> pix_fmt_mp->plane_fmt[0].bytesperline = 0;
> ctx->dst_bufs_cnt = 0;
> ctx->capture_state = QUEUE_FREE;
> - s5p_mfc_alloc_instance_buffer(ctx);
> + s5p_mfc_hw_call(dev->mfc_ops, alloc_instance_buffer, ctx);
> spin_lock_irqsave(&dev->condlock, flags);
> set_bit(ctx->num, &dev->ctx_work_bits);
> spin_unlock_irqrestore(&dev->condlock, flags);
> s5p_mfc_clean_ctx_int_flags(ctx);
> - s5p_mfc_try_run(dev);
> + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
> if (s5p_mfc_wait_for_done_ctx(ctx, \
> - S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET, 1)) {
> + S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET, 1)) {
> /* Error or timeout */
> mfc_err("Error getting instance from hardware\n");
> - s5p_mfc_release_instance_buffer(ctx);
> + s5p_mfc_hw_call(dev->mfc_ops, release_instance_buffer,
> + ctx);
> ret = -EIO;
> goto out;
> }
> @@ -1050,7 +1057,8 @@ static int vidioc_reqbufs(struct file *file, void
*priv,
> return ret;
> }
> ctx->capture_state = QUEUE_BUFS_REQUESTED;
> - ret = s5p_mfc_alloc_codec_buffers(ctx);
> + ret = s5p_mfc_hw_call(ctx->dev->mfc_ops, alloc_codec_buffers,
> + ctx);
> if (ret) {
> mfc_err("Failed to allocate encoding buffers\n");
> reqbufs->count = 0;
> @@ -1657,7 +1665,7 @@ static int s5p_mfc_start_streaming(struct vb2_queue
*q,
> unsigned int count)
> set_bit(ctx->num, &dev->ctx_work_bits);
> spin_unlock_irqrestore(&dev->condlock, flags);
> }
> - s5p_mfc_try_run(dev);
> + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
> return 0;
> }
>
> @@ -1671,19 +1679,21 @@ static int s5p_mfc_stop_streaming(struct vb2_queue
*q)
> ctx->state == MFCINST_RUNNING) &&
> dev->curr_ctx == ctx->num && dev->hw_lock) {
> ctx->state = MFCINST_ABORT;
> - s5p_mfc_wait_for_done_ctx(ctx,
S5P_FIMV_R2H_CMD_FRAME_DONE_RET,
> + s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_FRAME_DONE_RET,
> 0);
> }
> ctx->state = MFCINST_FINISHED;
> spin_lock_irqsave(&dev->irqlock, flags);
> if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
> - s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
> + s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue,
> + &ctx->vq_dst);
> INIT_LIST_HEAD(&ctx->dst_queue);
> ctx->dst_queue_cnt = 0;
> }
> if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
> cleanup_ref_queue(ctx);
> - s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
> + s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue,
> + &ctx->vq_src);
> INIT_LIST_HEAD(&ctx->src_queue);
> ctx->src_queue_cnt = 0;
> }
> @@ -1734,7 +1744,7 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
> set_bit(ctx->num, &dev->ctx_work_bits);
> spin_unlock_irqrestore(&dev->condlock, flags);
> }
> - s5p_mfc_try_run(dev);
> + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
> }
>
> static struct vb2_ops s5p_mfc_enc_qops = {
> @@ -1832,3 +1842,13 @@ void s5p_mfc_enc_ctrls_delete(struct s5p_mfc_ctx
*ctx)
> for (i = 0; i < NUM_CTRLS; i++)
> ctx->ctrls[i] = NULL;
> }
> +
> +void s5p_mfc_enc_init(struct s5p_mfc_ctx *ctx)
> +{
> + struct v4l2_format f;
> + f.fmt.pix_mp.pixelformat = DEF_SRC_FMT_ENC;
> + ctx->src_fmt = find_format(&f, MFC_FMT_RAW);
> + f.fmt.pix_mp.pixelformat = DEF_DST_FMT_ENC;
> + ctx->dst_fmt = find_format(&f, MFC_FMT_ENC);
> +}
> +
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.h
> b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.h
> index ca9fd66..5118d46 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.h
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.h
> @@ -19,5 +19,6 @@ const struct v4l2_ioctl_ops *get_enc_v4l2_ioctl_ops(void);
> struct s5p_mfc_fmt *get_enc_def_fmt(bool src);
> int s5p_mfc_enc_ctrls_setup(struct s5p_mfc_ctx *ctx);
> void s5p_mfc_enc_ctrls_delete(struct s5p_mfc_ctx *ctx);
> +void s5p_mfc_enc_init(struct s5p_mfc_ctx *ctx);
>
> #endif /* S5P_MFC_ENC_H_ */
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_intr.c
> b/drivers/media/platform/s5p-mfc/s5p_mfc_intr.c
> index 37860e2..5b8f0e0 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_intr.c
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_intr.c
> @@ -17,7 +17,6 @@
> #include <linux/io.h>
> #include <linux/sched.h>
> #include <linux/wait.h>
> -#include "regs-mfc.h"
> #include "s5p_mfc_common.h"
> #include "s5p_mfc_debug.h"
> #include "s5p_mfc_intr.h"
> @@ -28,7 +27,7 @@ int s5p_mfc_wait_for_done_dev(struct s5p_mfc_dev *dev, int
> command)
>
> ret = wait_event_interruptible_timeout(dev->queue,
> (dev->int_cond && (dev->int_type == command
> - || dev->int_type == S5P_FIMV_R2H_CMD_ERR_RET)),
> + || dev->int_type == S5P_MFC_R2H_CMD_ERR_RET)),
> msecs_to_jiffies(MFC_INT_TIMEOUT));
> if (ret == 0) {
> mfc_err("Interrupt (dev->int_type:%d, command:%d) timed
out\n",
> @@ -40,7 +39,7 @@ int s5p_mfc_wait_for_done_dev(struct s5p_mfc_dev *dev, int
> command)
> }
> mfc_debug(1, "Finished waiting (dev->int_type:%d, command: %d)\n",
> dev->int_type,
command);
> - if (dev->int_type == S5P_FIMV_R2H_CMD_ERR_RET)
> + if (dev->int_type == S5P_MFC_R2H_CMD_ERR_RET)
> return 1;
> return 0;
> }
> @@ -60,12 +59,12 @@ int s5p_mfc_wait_for_done_ctx(struct s5p_mfc_ctx *ctx,
> if (interrupt) {
> ret = wait_event_interruptible_timeout(ctx->queue,
> (ctx->int_cond && (ctx->int_type == command
> - || ctx->int_type == S5P_FIMV_R2H_CMD_ERR_RET)),
> + || ctx->int_type == S5P_MFC_R2H_CMD_ERR_RET)),
> msecs_to_jiffies(MFC_INT_TIMEOUT));
> } else {
> ret = wait_event_timeout(ctx->queue,
> (ctx->int_cond && (ctx->int_type == command
> - || ctx->int_type == S5P_FIMV_R2H_CMD_ERR_RET)),
> + || ctx->int_type == S5P_MFC_R2H_CMD_ERR_RET)),
> msecs_to_jiffies(MFC_INT_TIMEOUT));
> }
> if (ret == 0) {
> @@ -78,7 +77,7 @@ int s5p_mfc_wait_for_done_ctx(struct s5p_mfc_ctx *ctx,
> }
> mfc_debug(1, "Finished waiting (ctx->int_type:%d, command: %d)\n",
> ctx->int_type,
command);
> - if (ctx->int_type == S5P_FIMV_R2H_CMD_ERR_RET)
> + if (ctx->int_type == S5P_MFC_R2H_CMD_ERR_RET)
> return 1;
> return 0;
> }
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
> b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
> index b5fd3d4..ef8683e 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
> @@ -12,1386 +12,14 @@
> * published by the Free Software Foundation.
> */
>
> -#include "regs-mfc.h"
> -#include "s5p_mfc_cmd.h"
> -#include "s5p_mfc_common.h"
> -#include "s5p_mfc_ctrl.h"
> -#include "s5p_mfc_debug.h"
> -#include "s5p_mfc_intr.h"
> #include "s5p_mfc_opr.h"
> -#include "s5p_mfc_pm.h"
> -#include "s5p_mfc_shm.h"
> -#include <asm/cacheflush.h>
> -#include <linux/delay.h>
> -#include <linux/dma-mapping.h>
> -#include <linux/err.h>
> -#include <linux/firmware.h>
> -#include <linux/io.h>
> -#include <linux/jiffies.h>
> -#include <linux/mm.h>
> -#include <linux/sched.h>
> +#include "s5p_mfc_opr_v5.h"
>
> -#define OFFSETA(x) (((x) - dev->bank1) >> MFC_OFFSET_SHIFT)
> -#define OFFSETB(x) (((x) - dev->bank2) >> MFC_OFFSET_SHIFT)
> +static struct s5p_mfc_hw_ops *s5p_mfc_ops;
>
> -/* Allocate temporary buffers for decoding */
> -int s5p_mfc_alloc_dec_temp_buffers(struct s5p_mfc_ctx *ctx)
> +void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev)
> {
> - void *desc_virt;
> - struct s5p_mfc_dev *dev = ctx->dev;
> -
> - ctx->desc_buf = vb2_dma_contig_memops.alloc(
> - dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], DESC_BUF_SIZE);
> - if (IS_ERR_VALUE((int)ctx->desc_buf)) {
> - ctx->desc_buf = NULL;
> - mfc_err("Allocating DESC buffer failed\n");
> - return -ENOMEM;
> - }
> - ctx->desc_phys = s5p_mfc_mem_cookie(
> - dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->desc_buf);
> - BUG_ON(ctx->desc_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
> - desc_virt = vb2_dma_contig_memops.vaddr(ctx->desc_buf);
> - if (desc_virt == NULL) {
> - vb2_dma_contig_memops.put(ctx->desc_buf);
> - ctx->desc_phys = 0;
> - ctx->desc_buf = NULL;
> - mfc_err("Remapping DESC buffer failed\n");
> - return -ENOMEM;
> - }
> - memset(desc_virt, 0, DESC_BUF_SIZE);
> - wmb();
> - return 0;
> -}
> -
> -/* Release temporary buffers for decoding */
> -void s5p_mfc_release_dec_desc_buffer(struct s5p_mfc_ctx *ctx)
> -{
> - if (ctx->desc_phys) {
> - vb2_dma_contig_memops.put(ctx->desc_buf);
> - ctx->desc_phys = 0;
> - ctx->desc_buf = NULL;
> - }
> -}
> -
> -/* Allocate codec buffers */
> -int s5p_mfc_alloc_codec_buffers(struct s5p_mfc_ctx *ctx)
> -{
> - struct s5p_mfc_dev *dev = ctx->dev;
> - unsigned int enc_ref_y_size = 0;
> - unsigned int enc_ref_c_size = 0;
> - unsigned int guard_width, guard_height;
> -
> - if (ctx->type == MFCINST_DECODER) {
> - mfc_debug(2, "Luma size:%d Chroma size:%d MV size:%d\n",
> - ctx->luma_size, ctx->chroma_size, ctx->mv_size);
> - mfc_debug(2, "Totals bufs: %d\n", ctx->total_dpb_count);
> - } else if (ctx->type == MFCINST_ENCODER) {
> - enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
> - * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
> - enc_ref_y_size = ALIGN(enc_ref_y_size,
S5P_FIMV_NV12MT_SALIGN);
> -
> - if (ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC) {
> - enc_ref_c_size = ALIGN(ctx->img_width,
> - S5P_FIMV_NV12MT_HALIGN)
> - * ALIGN(ctx->img_height >> 1,
> - S5P_FIMV_NV12MT_VALIGN);
> - enc_ref_c_size = ALIGN(enc_ref_c_size,
> -
S5P_FIMV_NV12MT_SALIGN);
> - } else {
> - guard_width = ALIGN(ctx->img_width + 16,
> -
S5P_FIMV_NV12MT_HALIGN);
> - guard_height = ALIGN((ctx->img_height >> 1) + 4,
> -
S5P_FIMV_NV12MT_VALIGN);
> - enc_ref_c_size = ALIGN(guard_width * guard_height,
> - S5P_FIMV_NV12MT_SALIGN);
> - }
> - mfc_debug(2, "recon luma size: %d chroma size: %d\n",
> - enc_ref_y_size, enc_ref_c_size);
> - } else {
> - return -EINVAL;
> - }
> - /* Codecs have different memory requirements */
> - switch (ctx->codec_mode) {
> - case S5P_FIMV_CODEC_H264_DEC:
> - ctx->bank1_size =
> - ALIGN(S5P_FIMV_DEC_NB_IP_SIZE +
> - S5P_FIMV_DEC_VERT_NB_MV_SIZE,
> - S5P_FIMV_DEC_BUF_ALIGN);
> - ctx->bank2_size = ctx->total_dpb_count * ctx->mv_size;
> - break;
> - case S5P_FIMV_CODEC_MPEG4_DEC:
> - ctx->bank1_size =
> - ALIGN(S5P_FIMV_DEC_NB_DCAC_SIZE +
> - S5P_FIMV_DEC_UPNB_MV_SIZE +
> - S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
> - S5P_FIMV_DEC_STX_PARSER_SIZE +
> - S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE,
> - S5P_FIMV_DEC_BUF_ALIGN);
> - ctx->bank2_size = 0;
> - break;
> - case S5P_FIMV_CODEC_VC1RCV_DEC:
> - case S5P_FIMV_CODEC_VC1_DEC:
> - ctx->bank1_size =
> - ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE +
> - S5P_FIMV_DEC_UPNB_MV_SIZE +
> - S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
> - S5P_FIMV_DEC_NB_DCAC_SIZE +
> - 3 * S5P_FIMV_DEC_VC1_BITPLANE_SIZE,
> - S5P_FIMV_DEC_BUF_ALIGN);
> - ctx->bank2_size = 0;
> - break;
> - case S5P_FIMV_CODEC_MPEG2_DEC:
> - ctx->bank1_size = 0;
> - ctx->bank2_size = 0;
> - break;
> - case S5P_FIMV_CODEC_H263_DEC:
> - ctx->bank1_size =
> - ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE +
> - S5P_FIMV_DEC_UPNB_MV_SIZE +
> - S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
> - S5P_FIMV_DEC_NB_DCAC_SIZE,
> - S5P_FIMV_DEC_BUF_ALIGN);
> - ctx->bank2_size = 0;
> - break;
> - case S5P_FIMV_CODEC_H264_ENC:
> - ctx->bank1_size = (enc_ref_y_size * 2) +
> - S5P_FIMV_ENC_UPMV_SIZE +
> - S5P_FIMV_ENC_COLFLG_SIZE +
> - S5P_FIMV_ENC_INTRAMD_SIZE +
> - S5P_FIMV_ENC_NBORINFO_SIZE;
> - ctx->bank2_size = (enc_ref_y_size * 2) +
> - (enc_ref_c_size * 4) +
> - S5P_FIMV_ENC_INTRAPRED_SIZE;
> - break;
> - case S5P_FIMV_CODEC_MPEG4_ENC:
> - ctx->bank1_size = (enc_ref_y_size * 2) +
> - S5P_FIMV_ENC_UPMV_SIZE +
> - S5P_FIMV_ENC_COLFLG_SIZE +
> - S5P_FIMV_ENC_ACDCCOEF_SIZE;
> - ctx->bank2_size = (enc_ref_y_size * 2) +
> - (enc_ref_c_size * 4);
> - break;
> - case S5P_FIMV_CODEC_H263_ENC:
> - ctx->bank1_size = (enc_ref_y_size * 2) +
> - S5P_FIMV_ENC_UPMV_SIZE +
> - S5P_FIMV_ENC_ACDCCOEF_SIZE;
> - ctx->bank2_size = (enc_ref_y_size * 2) +
> - (enc_ref_c_size * 4);
> - break;
> - default:
> - break;
> - }
> - /* Allocate only if memory from bank 1 is necessary */
> - if (ctx->bank1_size > 0) {
> - ctx->bank1_buf = vb2_dma_contig_memops.alloc(
> - dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_size);
> - if (IS_ERR(ctx->bank1_buf)) {
> - ctx->bank1_buf = NULL;
> - printk(KERN_ERR
> - "Buf alloc for decoding failed (port A)\n");
> - return -ENOMEM;
> - }
> - ctx->bank1_phys = s5p_mfc_mem_cookie(
> - dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_buf);
> - BUG_ON(ctx->bank1_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
> - }
> - /* Allocate only if memory from bank 2 is necessary */
> - if (ctx->bank2_size > 0) {
> - ctx->bank2_buf = vb2_dma_contig_memops.alloc(
> - dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], ctx->bank2_size);
> - if (IS_ERR(ctx->bank2_buf)) {
> - ctx->bank2_buf = NULL;
> - mfc_err("Buf alloc for decoding failed (port B)\n");
> - return -ENOMEM;
> - }
> - ctx->bank2_phys = s5p_mfc_mem_cookie(
> - dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], ctx->bank2_buf);
> - BUG_ON(ctx->bank2_phys & ((1 << MFC_BANK2_ALIGN_ORDER) - 1));
> - }
> - return 0;
> -}
> -
> -/* Release buffers allocated for codec */
> -void s5p_mfc_release_codec_buffers(struct s5p_mfc_ctx *ctx)
> -{
> - if (ctx->bank1_buf) {
> - vb2_dma_contig_memops.put(ctx->bank1_buf);
> - ctx->bank1_buf = NULL;
> - ctx->bank1_phys = 0;
> - ctx->bank1_size = 0;
> - }
> - if (ctx->bank2_buf) {
> - vb2_dma_contig_memops.put(ctx->bank2_buf);
> - ctx->bank2_buf = NULL;
> - ctx->bank2_phys = 0;
> - ctx->bank2_size = 0;
> - }
> -}
> -
> -/* Allocate memory for instance data buffer */
> -int s5p_mfc_alloc_instance_buffer(struct s5p_mfc_ctx *ctx)
> -{
> - void *context_virt;
> - struct s5p_mfc_dev *dev = ctx->dev;
> -
> - if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC ||
> - ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC)
> - ctx->ctx_size = MFC_H264_CTX_BUF_SIZE;
> - else
> - ctx->ctx_size = MFC_CTX_BUF_SIZE;
> - ctx->ctx_buf = vb2_dma_contig_memops.alloc(
> - dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx_size);
> - if (IS_ERR(ctx->ctx_buf)) {
> - mfc_err("Allocating context buffer failed\n");
> - ctx->ctx_phys = 0;
> - ctx->ctx_buf = NULL;
> - return -ENOMEM;
> - }
> - ctx->ctx_phys = s5p_mfc_mem_cookie(
> - dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx_buf);
> - BUG_ON(ctx->ctx_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
> - ctx->ctx_ofs = OFFSETA(ctx->ctx_phys);
> - context_virt = vb2_dma_contig_memops.vaddr(ctx->ctx_buf);
> - if (context_virt == NULL) {
> - mfc_err("Remapping instance buffer failed\n");
> - vb2_dma_contig_memops.put(ctx->ctx_buf);
> - ctx->ctx_phys = 0;
> - ctx->ctx_buf = NULL;
> - return -ENOMEM;
> - }
> - /* Zero content of the allocated memory */
> - memset(context_virt, 0, ctx->ctx_size);
> - wmb();
> - if (s5p_mfc_init_shm(ctx) < 0) {
> - vb2_dma_contig_memops.put(ctx->ctx_buf);
> - ctx->ctx_phys = 0;
> - ctx->ctx_buf = NULL;
> - return -ENOMEM;
> - }
> - return 0;
> -}
> -
> -/* Release instance buffer */
> -void s5p_mfc_release_instance_buffer(struct s5p_mfc_ctx *ctx)
> -{
> - if (ctx->ctx_buf) {
> - vb2_dma_contig_memops.put(ctx->ctx_buf);
> - ctx->ctx_phys = 0;
> - ctx->ctx_buf = NULL;
> - }
> - if (ctx->shm_alloc) {
> - vb2_dma_contig_memops.put(ctx->shm_alloc);
> - ctx->shm_alloc = NULL;
> - ctx->shm = NULL;
> - }
> -}
> -
> -/* Set registers for decoding temporary buffers */
> -void s5p_mfc_set_dec_desc_buffer(struct s5p_mfc_ctx *ctx)
> -{
> - struct s5p_mfc_dev *dev = ctx->dev;
> -
> - mfc_write(dev, OFFSETA(ctx->desc_phys), S5P_FIMV_SI_CH0_DESC_ADR);
> - mfc_write(dev, DESC_BUF_SIZE, S5P_FIMV_SI_CH0_DESC_SIZE);
> -}
> -
> -/* Set registers for shared buffer */
> -static void s5p_mfc_set_shared_buffer(struct s5p_mfc_ctx *ctx)
> -{
> - struct s5p_mfc_dev *dev = ctx->dev;
> - mfc_write(dev, ctx->shm_ofs, S5P_FIMV_SI_CH0_HOST_WR_ADR);
> -}
> -
> -/* Set registers for decoding stream buffer */
> -int s5p_mfc_set_dec_stream_buffer(struct s5p_mfc_ctx *ctx, int buf_addr,
> - unsigned int start_num_byte, unsigned int buf_size)
> -{
> - struct s5p_mfc_dev *dev = ctx->dev;
> -
> - mfc_write(dev, OFFSETA(buf_addr), S5P_FIMV_SI_CH0_SB_ST_ADR);
> - mfc_write(dev, ctx->dec_src_buf_size, S5P_FIMV_SI_CH0_CPB_SIZE);
> - mfc_write(dev, buf_size, S5P_FIMV_SI_CH0_SB_FRM_SIZE);
> - s5p_mfc_write_shm(ctx, start_num_byte, START_BYTE_NUM);
> - return 0;
> -}
> -
> -/* Set decoding frame buffer */
> -int s5p_mfc_set_dec_frame_buffer(struct s5p_mfc_ctx *ctx)
> -{
> - unsigned int frame_size, i;
> - unsigned int frame_size_ch, frame_size_mv;
> - struct s5p_mfc_dev *dev = ctx->dev;
> - unsigned int dpb;
> - size_t buf_addr1, buf_addr2;
> - int buf_size1, buf_size2;
> -
> - buf_addr1 = ctx->bank1_phys;
> - buf_size1 = ctx->bank1_size;
> - buf_addr2 = ctx->bank2_phys;
> - buf_size2 = ctx->bank2_size;
> - dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) &
> - ~S5P_FIMV_DPB_COUNT_MASK;
> - mfc_write(dev, ctx->total_dpb_count | dpb,
> -
S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
> - s5p_mfc_set_shared_buffer(ctx);
> - switch (ctx->codec_mode) {
> - case S5P_FIMV_CODEC_H264_DEC:
> - mfc_write(dev, OFFSETA(buf_addr1),
> - S5P_FIMV_H264_VERT_NB_MV_ADR);
> - buf_addr1 += S5P_FIMV_DEC_VERT_NB_MV_SIZE;
> - buf_size1 -= S5P_FIMV_DEC_VERT_NB_MV_SIZE;
> - mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H264_NB_IP_ADR);
> - buf_addr1 += S5P_FIMV_DEC_NB_IP_SIZE;
> - buf_size1 -= S5P_FIMV_DEC_NB_IP_SIZE;
> - break;
> - case S5P_FIMV_CODEC_MPEG4_DEC:
> - mfc_write(dev, OFFSETA(buf_addr1),
S5P_FIMV_MPEG4_NB_DCAC_ADR);
> - buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
> - buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
> - mfc_write(dev, OFFSETA(buf_addr1),
S5P_FIMV_MPEG4_UP_NB_MV_ADR);
> - buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
> - buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
> - mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_SA_MV_ADR);
> - buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
> - buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
> - mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_SP_ADR);
> - buf_addr1 += S5P_FIMV_DEC_STX_PARSER_SIZE;
> - buf_size1 -= S5P_FIMV_DEC_STX_PARSER_SIZE;
> - mfc_write(dev, OFFSETA(buf_addr1),
S5P_FIMV_MPEG4_OT_LINE_ADR);
> - buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
> - buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
> - break;
> - case S5P_FIMV_CODEC_H263_DEC:
> - mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_OT_LINE_ADR);
> - buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
> - buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
> - mfc_write(dev, OFFSETA(buf_addr1),
S5P_FIMV_H263_UP_NB_MV_ADR);
> - buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
> - buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
> - mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_SA_MV_ADR);
> - buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
> - buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
> - mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_NB_DCAC_ADR);
> - buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
> - buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
> - break;
> - case S5P_FIMV_CODEC_VC1_DEC:
> - case S5P_FIMV_CODEC_VC1RCV_DEC:
> - mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_NB_DCAC_ADR);
> - buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
> - buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
> - mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_OT_LINE_ADR);
> - buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
> - buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
> - mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_UP_NB_MV_ADR);
> - buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
> - buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
> - mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_SA_MV_ADR);
> - buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
> - buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
> - mfc_write(dev, OFFSETA(buf_addr1),
S5P_FIMV_VC1_BITPLANE3_ADR);
> - buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
> - buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
> - mfc_write(dev, OFFSETA(buf_addr1),
S5P_FIMV_VC1_BITPLANE2_ADR);
> - buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
> - buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
> - mfc_write(dev, OFFSETA(buf_addr1),
S5P_FIMV_VC1_BITPLANE1_ADR);
> - buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
> - buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
> - break;
> - case S5P_FIMV_CODEC_MPEG2_DEC:
> - break;
> - default:
> - mfc_err("Unknown codec for decoding (%x)\n",
> - ctx->codec_mode);
> - return -EINVAL;
> - break;
> - }
> - frame_size = ctx->luma_size;
> - frame_size_ch = ctx->chroma_size;
> - frame_size_mv = ctx->mv_size;
> - mfc_debug(2, "Frm size: %d ch: %d mv: %d\n", frame_size,
frame_size_ch,
> -
frame_size_mv);
> - for (i = 0; i < ctx->total_dpb_count; i++) {
> - /* Bank2 */
> - mfc_debug(2, "Luma %d: %x\n", i,
> - ctx->dst_bufs[i].cookie.raw.luma);
> - mfc_write(dev, OFFSETB(ctx->dst_bufs[i].cookie.raw.luma),
> - S5P_FIMV_DEC_LUMA_ADR + i *
4);
> - mfc_debug(2, "\tChroma %d: %x\n", i,
> - ctx->dst_bufs[i].cookie.raw.chroma);
> - mfc_write(dev, OFFSETA(ctx->dst_bufs[i].cookie.raw.chroma),
> - S5P_FIMV_DEC_CHROMA_ADR + i *
4);
> - if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC) {
> - mfc_debug(2, "\tBuf2: %x, size: %d\n",
> - buf_addr2, buf_size2);
> - mfc_write(dev, OFFSETB(buf_addr2),
> - S5P_FIMV_H264_MV_ADR + i * 4);
> - buf_addr2 += frame_size_mv;
> - buf_size2 -= frame_size_mv;
> - }
> - }
> - mfc_debug(2, "Buf1: %u, buf_size1: %d\n", buf_addr1, buf_size1);
> - mfc_debug(2, "Buf 1/2 size after: %d/%d (frames %d)\n",
> - buf_size1, buf_size2, ctx->total_dpb_count);
> - if (buf_size1 < 0 || buf_size2 < 0) {
> - mfc_debug(2, "Not enough memory has been allocated\n");
> - return -ENOMEM;
> - }
> - s5p_mfc_write_shm(ctx, frame_size, ALLOC_LUMA_DPB_SIZE);
> - s5p_mfc_write_shm(ctx, frame_size_ch, ALLOC_CHROMA_DPB_SIZE);
> - if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC)
> - s5p_mfc_write_shm(ctx, frame_size_mv, ALLOC_MV_SIZE);
> - mfc_write(dev, ((S5P_FIMV_CH_INIT_BUFS & S5P_FIMV_CH_MASK)
> - << S5P_FIMV_CH_SHIFT) |
(ctx->inst_no),
> - S5P_FIMV_SI_CH0_INST_ID);
> - return 0;
> -}
> -
> -/* Set registers for encoding stream buffer */
> -int s5p_mfc_set_enc_stream_buffer(struct s5p_mfc_ctx *ctx,
> - unsigned long addr, unsigned int size)
> -{
> - struct s5p_mfc_dev *dev = ctx->dev;
> -
> - mfc_write(dev, OFFSETA(addr), S5P_FIMV_ENC_SI_CH0_SB_ADR);
> - mfc_write(dev, size, S5P_FIMV_ENC_SI_CH0_SB_SIZE);
> - return 0;
> -}
> -
> -void s5p_mfc_set_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
> - unsigned long y_addr, unsigned long c_addr)
> -{
> - struct s5p_mfc_dev *dev = ctx->dev;
> -
> - mfc_write(dev, OFFSETB(y_addr), S5P_FIMV_ENC_SI_CH0_CUR_Y_ADR);
> - mfc_write(dev, OFFSETB(c_addr), S5P_FIMV_ENC_SI_CH0_CUR_C_ADR);
> -}
> -
> -void s5p_mfc_get_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
> - unsigned long *y_addr, unsigned long *c_addr)
> -{
> - struct s5p_mfc_dev *dev = ctx->dev;
> -
> - *y_addr = dev->bank2 + (mfc_read(dev, S5P_FIMV_ENCODED_Y_ADDR)
> - << MFC_OFFSET_SHIFT);
> - *c_addr = dev->bank2 + (mfc_read(dev, S5P_FIMV_ENCODED_C_ADDR)
> - << MFC_OFFSET_SHIFT);
> -}
> -
> -/* Set encoding ref & codec buffer */
> -int s5p_mfc_set_enc_ref_buffer(struct s5p_mfc_ctx *ctx)
> -{
> - struct s5p_mfc_dev *dev = ctx->dev;
> - size_t buf_addr1, buf_addr2;
> - size_t buf_size1, buf_size2;
> - unsigned int enc_ref_y_size, enc_ref_c_size;
> - unsigned int guard_width, guard_height;
> - int i;
> -
> - buf_addr1 = ctx->bank1_phys;
> - buf_size1 = ctx->bank1_size;
> - buf_addr2 = ctx->bank2_phys;
> - buf_size2 = ctx->bank2_size;
> - enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
> - * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
> - enc_ref_y_size = ALIGN(enc_ref_y_size, S5P_FIMV_NV12MT_SALIGN);
> - if (ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC) {
> - enc_ref_c_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
> - * ALIGN((ctx->img_height >> 1),
S5P_FIMV_NV12MT_VALIGN);
> - enc_ref_c_size = ALIGN(enc_ref_c_size,
S5P_FIMV_NV12MT_SALIGN);
> - } else {
> - guard_width = ALIGN(ctx->img_width + 16,
> - S5P_FIMV_NV12MT_HALIGN);
> - guard_height = ALIGN((ctx->img_height >> 1) + 4,
> - S5P_FIMV_NV12MT_VALIGN);
> - enc_ref_c_size = ALIGN(guard_width * guard_height,
> - S5P_FIMV_NV12MT_SALIGN);
> - }
> - mfc_debug(2, "buf_size1: %d, buf_size2: %d\n", buf_size1, buf_size2);
> - switch (ctx->codec_mode) {
> - case S5P_FIMV_CODEC_H264_ENC:
> - for (i = 0; i < 2; i++) {
> - mfc_write(dev, OFFSETA(buf_addr1),
> - S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
> - buf_addr1 += enc_ref_y_size;
> - buf_size1 -= enc_ref_y_size;
> -
> - mfc_write(dev, OFFSETB(buf_addr2),
> - S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
> - buf_addr2 += enc_ref_y_size;
> - buf_size2 -= enc_ref_y_size;
> - }
> - for (i = 0; i < 4; i++) {
> - mfc_write(dev, OFFSETB(buf_addr2),
> - S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
> - buf_addr2 += enc_ref_c_size;
> - buf_size2 -= enc_ref_c_size;
> - }
> - mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H264_UP_MV_ADR);
> - buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
> - buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
> - mfc_write(dev, OFFSETA(buf_addr1),
> - S5P_FIMV_H264_COZERO_FLAG_ADR);
> - buf_addr1 += S5P_FIMV_ENC_COLFLG_SIZE;
> - buf_size1 -= S5P_FIMV_ENC_COLFLG_SIZE;
> - mfc_write(dev, OFFSETA(buf_addr1),
> - S5P_FIMV_H264_UP_INTRA_MD_ADR);
> - buf_addr1 += S5P_FIMV_ENC_INTRAMD_SIZE;
> - buf_size1 -= S5P_FIMV_ENC_INTRAMD_SIZE;
> - mfc_write(dev, OFFSETB(buf_addr2),
> - S5P_FIMV_H264_UP_INTRA_PRED_ADR);
> - buf_addr2 += S5P_FIMV_ENC_INTRAPRED_SIZE;
> - buf_size2 -= S5P_FIMV_ENC_INTRAPRED_SIZE;
> - mfc_write(dev, OFFSETA(buf_addr1),
> - S5P_FIMV_H264_NBOR_INFO_ADR);
> - buf_addr1 += S5P_FIMV_ENC_NBORINFO_SIZE;
> - buf_size1 -= S5P_FIMV_ENC_NBORINFO_SIZE;
> - mfc_debug(2, "buf_size1: %d, buf_size2: %d\n",
> - buf_size1, buf_size2);
> - break;
> - case S5P_FIMV_CODEC_MPEG4_ENC:
> - for (i = 0; i < 2; i++) {
> - mfc_write(dev, OFFSETA(buf_addr1),
> - S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
> - buf_addr1 += enc_ref_y_size;
> - buf_size1 -= enc_ref_y_size;
> - mfc_write(dev, OFFSETB(buf_addr2),
> - S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
> - buf_addr2 += enc_ref_y_size;
> - buf_size2 -= enc_ref_y_size;
> - }
> - for (i = 0; i < 4; i++) {
> - mfc_write(dev, OFFSETB(buf_addr2),
> - S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
> - buf_addr2 += enc_ref_c_size;
> - buf_size2 -= enc_ref_c_size;
> - }
> - mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_UP_MV_ADR);
> - buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
> - buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
> - mfc_write(dev, OFFSETA(buf_addr1),
> -
S5P_FIMV_MPEG4_COZERO_FLAG_ADR);
> - buf_addr1 += S5P_FIMV_ENC_COLFLG_SIZE;
> - buf_size1 -= S5P_FIMV_ENC_COLFLG_SIZE;
> - mfc_write(dev, OFFSETA(buf_addr1),
> - S5P_FIMV_MPEG4_ACDC_COEF_ADR);
> - buf_addr1 += S5P_FIMV_ENC_ACDCCOEF_SIZE;
> - buf_size1 -= S5P_FIMV_ENC_ACDCCOEF_SIZE;
> - mfc_debug(2, "buf_size1: %d, buf_size2: %d\n",
> - buf_size1, buf_size2);
> - break;
> - case S5P_FIMV_CODEC_H263_ENC:
> - for (i = 0; i < 2; i++) {
> - mfc_write(dev, OFFSETA(buf_addr1),
> - S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
> - buf_addr1 += enc_ref_y_size;
> - buf_size1 -= enc_ref_y_size;
> - mfc_write(dev, OFFSETB(buf_addr2),
> - S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
> - buf_addr2 += enc_ref_y_size;
> - buf_size2 -= enc_ref_y_size;
> - }
> - for (i = 0; i < 4; i++) {
> - mfc_write(dev, OFFSETB(buf_addr2),
> - S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
> - buf_addr2 += enc_ref_c_size;
> - buf_size2 -= enc_ref_c_size;
> - }
> - mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_UP_MV_ADR);
> - buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
> - buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
> - mfc_write(dev, OFFSETA(buf_addr1),
S5P_FIMV_H263_ACDC_COEF_ADR);
> - buf_addr1 += S5P_FIMV_ENC_ACDCCOEF_SIZE;
> - buf_size1 -= S5P_FIMV_ENC_ACDCCOEF_SIZE;
> - mfc_debug(2, "buf_size1: %d, buf_size2: %d\n",
> - buf_size1, buf_size2);
> - break;
> - default:
> - mfc_err("Unknown codec set for encoding: %d\n",
> - ctx->codec_mode);
> - return -EINVAL;
> - }
> - return 0;
> -}
> -
> -static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
> -{
> - struct s5p_mfc_dev *dev = ctx->dev;
> - struct s5p_mfc_enc_params *p = &ctx->enc_params;
> - unsigned int reg;
> - unsigned int shm;
> -
> - /* width */
> - mfc_write(dev, ctx->img_width, S5P_FIMV_ENC_HSIZE_PX);
> - /* height */
> - mfc_write(dev, ctx->img_height, S5P_FIMV_ENC_VSIZE_PX);
> - /* pictype : enable, IDR period */
> - reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
> - reg |= (1 << 18);
> - reg &= ~(0xFFFF);
> - reg |= p->gop_size;
> - mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
> - mfc_write(dev, 0, S5P_FIMV_ENC_B_RECON_WRITE_ON);
> - /* multi-slice control */
> - /* multi-slice MB number or bit size */
> - mfc_write(dev, p->slice_mode, S5P_FIMV_ENC_MSLICE_CTRL);
> - if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) {
> - mfc_write(dev, p->slice_mb, S5P_FIMV_ENC_MSLICE_MB);
> - } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES)
{
> - mfc_write(dev, p->slice_bit, S5P_FIMV_ENC_MSLICE_BIT);
> - } else {
> - mfc_write(dev, 0, S5P_FIMV_ENC_MSLICE_MB);
> - mfc_write(dev, 0, S5P_FIMV_ENC_MSLICE_BIT);
> - }
> - /* cyclic intra refresh */
> - mfc_write(dev, p->intra_refresh_mb, S5P_FIMV_ENC_CIR_CTRL);
> - /* memory structure cur. frame */
> - if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M)
> - mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR);
> - else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT)
> - mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR);
> - /* padding control & value */
> - reg = mfc_read(dev, S5P_FIMV_ENC_PADDING_CTRL);
> - if (p->pad) {
> - /** enable */
> - reg |= (1 << 31);
> - /** cr value */
> - reg &= ~(0xFF << 16);
> - reg |= (p->pad_cr << 16);
> - /** cb value */
> - reg &= ~(0xFF << 8);
> - reg |= (p->pad_cb << 8);
> - /** y value */
> - reg &= ~(0xFF);
> - reg |= (p->pad_luma);
> - } else {
> - /** disable & all value clear */
> - reg = 0;
> - }
> - mfc_write(dev, reg, S5P_FIMV_ENC_PADDING_CTRL);
> - /* rate control config. */
> - reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
> - /** frame-level rate control */
> - reg &= ~(0x1 << 9);
> - reg |= (p->rc_frame << 9);
> - mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
> - /* bit rate */
> - if (p->rc_frame)
> - mfc_write(dev, p->rc_bitrate,
> - S5P_FIMV_ENC_RC_BIT_RATE);
> - else
> - mfc_write(dev, 0, S5P_FIMV_ENC_RC_BIT_RATE);
> - /* reaction coefficient */
> - if (p->rc_frame)
> - mfc_write(dev, p->rc_reaction_coeff, S5P_FIMV_ENC_RC_RPARA);
> - shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
> - /* seq header ctrl */
> - shm &= ~(0x1 << 3);
> - shm |= (p->seq_hdr_mode << 3);
> - /* frame skip mode */
> - shm &= ~(0x3 << 1);
> - shm |= (p->frame_skip_mode << 1);
> - s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
> - /* fixed target bit */
> - s5p_mfc_write_shm(ctx, p->fixed_target_bit, RC_CONTROL_CONFIG);
> - return 0;
> -}
> -
> -static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
> -{
> - struct s5p_mfc_dev *dev = ctx->dev;
> - struct s5p_mfc_enc_params *p = &ctx->enc_params;
> - struct s5p_mfc_h264_enc_params *p_264 = &p->codec.h264;
> - unsigned int reg;
> - unsigned int shm;
> -
> - s5p_mfc_set_enc_params(ctx);
> - /* pictype : number of B */
> - reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
> - /* num_b_frame - 0 ~ 2 */
> - reg &= ~(0x3 << 16);
> - reg |= (p->num_b_frame << 16);
> - mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
> - /* profile & level */
> - reg = mfc_read(dev, S5P_FIMV_ENC_PROFILE);
> - /* level */
> - reg &= ~(0xFF << 8);
> - reg |= (p_264->level << 8);
> - /* profile - 0 ~ 2 */
> - reg &= ~(0x3F);
> - reg |= p_264->profile;
> - mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE);
> - /* interlace */
> - mfc_write(dev, p->interlace, S5P_FIMV_ENC_PIC_STRUCT);
> - /* height */
> - if (p->interlace)
> - mfc_write(dev, ctx->img_height >> 1, S5P_FIMV_ENC_VSIZE_PX);
> - /* loopfilter ctrl */
> - mfc_write(dev, p_264->loop_filter_mode, S5P_FIMV_ENC_LF_CTRL);
> - /* loopfilter alpha offset */
> - if (p_264->loop_filter_alpha < 0) {
> - reg = 0x10;
> - reg |= (0xFF - p_264->loop_filter_alpha) + 1;
> - } else {
> - reg = 0x00;
> - reg |= (p_264->loop_filter_alpha & 0xF);
> - }
> - mfc_write(dev, reg, S5P_FIMV_ENC_ALPHA_OFF);
> - /* loopfilter beta offset */
> - if (p_264->loop_filter_beta < 0) {
> - reg = 0x10;
> - reg |= (0xFF - p_264->loop_filter_beta) + 1;
> - } else {
> - reg = 0x00;
> - reg |= (p_264->loop_filter_beta & 0xF);
> - }
> - mfc_write(dev, reg, S5P_FIMV_ENC_BETA_OFF);
> - /* entropy coding mode */
> - if (p_264->entropy_mode == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC)
> - mfc_write(dev, 1, S5P_FIMV_ENC_H264_ENTROPY_MODE);
> - else
> - mfc_write(dev, 0, S5P_FIMV_ENC_H264_ENTROPY_MODE);
> - /* number of ref. picture */
> - reg = mfc_read(dev, S5P_FIMV_ENC_H264_NUM_OF_REF);
> - /* num of ref. pictures of P */
> - reg &= ~(0x3 << 5);
> - reg |= (p_264->num_ref_pic_4p << 5);
> - /* max number of ref. pictures */
> - reg &= ~(0x1F);
> - reg |= p_264->max_ref_pic;
> - mfc_write(dev, reg, S5P_FIMV_ENC_H264_NUM_OF_REF);
> - /* 8x8 transform enable */
> - mfc_write(dev, p_264->_8x8_transform, S5P_FIMV_ENC_H264_TRANS_FLAG);
> - /* rate control config. */
> - reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
> - /* macroblock level rate control */
> - reg &= ~(0x1 << 8);
> - reg |= (p_264->rc_mb << 8);
> - /* frame QP */
> - reg &= ~(0x3F);
> - reg |= p_264->rc_frame_qp;
> - mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
> - /* frame rate */
> - if (p->rc_frame && p->rc_framerate_denom)
> - mfc_write(dev, p->rc_framerate_num * 1000
> - / p->rc_framerate_denom, S5P_FIMV_ENC_RC_FRAME_RATE);
> - else
> - mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
> - /* max & min value of QP */
> - reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
> - /* max QP */
> - reg &= ~(0x3F << 8);
> - reg |= (p_264->rc_max_qp << 8);
> - /* min QP */
> - reg &= ~(0x3F);
> - reg |= p_264->rc_min_qp;
> - mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
> - /* macroblock adaptive scaling features */
> - if (p_264->rc_mb) {
> - reg = mfc_read(dev, S5P_FIMV_ENC_RC_MB_CTRL);
> - /* dark region */
> - reg &= ~(0x1 << 3);
> - reg |= (p_264->rc_mb_dark << 3);
> - /* smooth region */
> - reg &= ~(0x1 << 2);
> - reg |= (p_264->rc_mb_smooth << 2);
> - /* static region */
> - reg &= ~(0x1 << 1);
> - reg |= (p_264->rc_mb_static << 1);
> - /* high activity region */
> - reg &= ~(0x1);
> - reg |= p_264->rc_mb_activity;
> - mfc_write(dev, reg, S5P_FIMV_ENC_RC_MB_CTRL);
> - }
> - if (!p->rc_frame &&
> - !p_264->rc_mb) {
> - shm = s5p_mfc_read_shm(ctx, P_B_FRAME_QP);
> - shm &= ~(0xFFF);
> - shm |= ((p_264->rc_b_frame_qp & 0x3F) << 6);
> - shm |= (p_264->rc_p_frame_qp & 0x3F);
> - s5p_mfc_write_shm(ctx, shm, P_B_FRAME_QP);
> - }
> - /* extended encoder ctrl */
> - shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
> - /* AR VUI control */
> - shm &= ~(0x1 << 15);
> - shm |= (p_264->vui_sar << 1);
> - s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
> - if (p_264->vui_sar) {
> - /* aspect ration IDC */
> - shm = s5p_mfc_read_shm(ctx, SAMPLE_ASPECT_RATIO_IDC);
> - shm &= ~(0xFF);
> - shm |= p_264->vui_sar_idc;
> - s5p_mfc_write_shm(ctx, shm, SAMPLE_ASPECT_RATIO_IDC);
> - if (p_264->vui_sar_idc == 0xFF) {
> - /* sample AR info */
> - shm = s5p_mfc_read_shm(ctx, EXTENDED_SAR);
> - shm &= ~(0xFFFFFFFF);
> - shm |= p_264->vui_ext_sar_width << 16;
> - shm |= p_264->vui_ext_sar_height;
> - s5p_mfc_write_shm(ctx, shm, EXTENDED_SAR);
> - }
> - }
> - /* intra picture period for H.264 */
> - shm = s5p_mfc_read_shm(ctx, H264_I_PERIOD);
> - /* control */
> - shm &= ~(0x1 << 16);
> - shm |= (p_264->open_gop << 16);
> - /* value */
> - if (p_264->open_gop) {
> - shm &= ~(0xFFFF);
> - shm |= p_264->open_gop_size;
> - }
> - s5p_mfc_write_shm(ctx, shm, H264_I_PERIOD);
> - /* extended encoder ctrl */
> - shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
> - /* vbv buffer size */
> - if (p->frame_skip_mode ==
> - V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
> - shm &= ~(0xFFFF << 16);
> - shm |= (p_264->cpb_size << 16);
> - }
> - s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
> - return 0;
> -}
> -
> -static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
> -{
> - struct s5p_mfc_dev *dev = ctx->dev;
> - struct s5p_mfc_enc_params *p = &ctx->enc_params;
> - struct s5p_mfc_mpeg4_enc_params *p_mpeg4 = &p->codec.mpeg4;
> - unsigned int reg;
> - unsigned int shm;
> - unsigned int framerate;
> -
> - s5p_mfc_set_enc_params(ctx);
> - /* pictype : number of B */
> - reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
> - /* num_b_frame - 0 ~ 2 */
> - reg &= ~(0x3 << 16);
> - reg |= (p->num_b_frame << 16);
> - mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
> - /* profile & level */
> - reg = mfc_read(dev, S5P_FIMV_ENC_PROFILE);
> - /* level */
> - reg &= ~(0xFF << 8);
> - reg |= (p_mpeg4->level << 8);
> - /* profile - 0 ~ 2 */
> - reg &= ~(0x3F);
> - reg |= p_mpeg4->profile;
> - mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE);
> - /* quarter_pixel */
> - mfc_write(dev, p_mpeg4->quarter_pixel, S5P_FIMV_ENC_MPEG4_QUART_PXL);
> - /* qp */
> - if (!p->rc_frame) {
> - shm = s5p_mfc_read_shm(ctx, P_B_FRAME_QP);
> - shm &= ~(0xFFF);
> - shm |= ((p_mpeg4->rc_b_frame_qp & 0x3F) << 6);
> - shm |= (p_mpeg4->rc_p_frame_qp & 0x3F);
> - s5p_mfc_write_shm(ctx, shm, P_B_FRAME_QP);
> - }
> - /* frame rate */
> - if (p->rc_frame) {
> - if (p->rc_framerate_denom > 0) {
> - framerate = p->rc_framerate_num * 1000 /
> - p->rc_framerate_denom;
> - mfc_write(dev, framerate,
> - S5P_FIMV_ENC_RC_FRAME_RATE);
> - shm = s5p_mfc_read_shm(ctx, RC_VOP_TIMING);
> - shm &= ~(0xFFFFFFFF);
> - shm |= (1 << 31);
> - shm |= ((p->rc_framerate_num & 0x7FFF) << 16);
> - shm |= (p->rc_framerate_denom & 0xFFFF);
> - s5p_mfc_write_shm(ctx, shm, RC_VOP_TIMING);
> - }
> - } else {
> - mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
> - }
> - /* rate control config. */
> - reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
> - /* frame QP */
> - reg &= ~(0x3F);
> - reg |= p_mpeg4->rc_frame_qp;
> - mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
> - /* max & min value of QP */
> - reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
> - /* max QP */
> - reg &= ~(0x3F << 8);
> - reg |= (p_mpeg4->rc_max_qp << 8);
> - /* min QP */
> - reg &= ~(0x3F);
> - reg |= p_mpeg4->rc_min_qp;
> - mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
> - /* extended encoder ctrl */
> - shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
> - /* vbv buffer size */
> - if (p->frame_skip_mode ==
> - V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
> - shm &= ~(0xFFFF << 16);
> - shm |= (p->vbv_size << 16);
> - }
> - s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
> - return 0;
> + s5p_mfc_ops = s5p_mfc_init_hw_ops_v5();
> + dev->warn_start = S5P_FIMV_ERR_WARNINGS_START;
> + dev->mfc_ops = s5p_mfc_ops;
> }
> -
> -static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)
> -{
> - struct s5p_mfc_dev *dev = ctx->dev;
> - struct s5p_mfc_enc_params *p = &ctx->enc_params;
> - struct s5p_mfc_mpeg4_enc_params *p_h263 = &p->codec.mpeg4;
> - unsigned int reg;
> - unsigned int shm;
> -
> - s5p_mfc_set_enc_params(ctx);
> - /* qp */
> - if (!p->rc_frame) {
> - shm = s5p_mfc_read_shm(ctx, P_B_FRAME_QP);
> - shm &= ~(0xFFF);
> - shm |= (p_h263->rc_p_frame_qp & 0x3F);
> - s5p_mfc_write_shm(ctx, shm, P_B_FRAME_QP);
> - }
> - /* frame rate */
> - if (p->rc_frame && p->rc_framerate_denom)
> - mfc_write(dev, p->rc_framerate_num * 1000
> - / p->rc_framerate_denom, S5P_FIMV_ENC_RC_FRAME_RATE);
> - else
> - mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
> - /* rate control config. */
> - reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
> - /* frame QP */
> - reg &= ~(0x3F);
> - reg |= p_h263->rc_frame_qp;
> - mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
> - /* max & min value of QP */
> - reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
> - /* max QP */
> - reg &= ~(0x3F << 8);
> - reg |= (p_h263->rc_max_qp << 8);
> - /* min QP */
> - reg &= ~(0x3F);
> - reg |= p_h263->rc_min_qp;
> - mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
> - /* extended encoder ctrl */
> - shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
> - /* vbv buffer size */
> - if (p->frame_skip_mode ==
> - V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
> - shm &= ~(0xFFFF << 16);
> - shm |= (p->vbv_size << 16);
> - }
> - s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
> - return 0;
> -}
> -
> -/* Initialize decoding */
> -int s5p_mfc_init_decode(struct s5p_mfc_ctx *ctx)
> -{
> - struct s5p_mfc_dev *dev = ctx->dev;
> -
> - s5p_mfc_set_shared_buffer(ctx);
> - /* Setup loop filter, for decoding this is only valid for MPEG4 */
> - if (ctx->codec_mode == S5P_FIMV_CODEC_MPEG4_DEC)
> - mfc_write(dev, ctx->loop_filter_mpeg4, S5P_FIMV_ENC_LF_CTRL);
> - else
> - mfc_write(dev, 0, S5P_FIMV_ENC_LF_CTRL);
> - mfc_write(dev, ((ctx->slice_interface & S5P_FIMV_SLICE_INT_MASK) <<
> - S5P_FIMV_SLICE_INT_SHIFT) | (ctx->display_delay_enable <<
> - S5P_FIMV_DDELAY_ENA_SHIFT) | ((ctx->display_delay &
> - S5P_FIMV_DDELAY_VAL_MASK) << S5P_FIMV_DDELAY_VAL_SHIFT),
> - S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
> - mfc_write(dev,
> - ((S5P_FIMV_CH_SEQ_HEADER & S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT)
> - | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
> - return 0;
> -}
> -
> -static void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush)
> -{
> - struct s5p_mfc_dev *dev = ctx->dev;
> - unsigned int dpb;
> -
> - if (flush)
> - dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) | (
> - S5P_FIMV_DPB_FLUSH_MASK << S5P_FIMV_DPB_FLUSH_SHIFT);
> - else
> - dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) &
> - ~(S5P_FIMV_DPB_FLUSH_MASK <<
S5P_FIMV_DPB_FLUSH_SHIFT);
> - mfc_write(dev, dpb, S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
> -}
> -
> -/* Decode a single frame */
> -int s5p_mfc_decode_one_frame(struct s5p_mfc_ctx *ctx,
> - enum s5p_mfc_decode_arg last_frame)
> -{
> - struct s5p_mfc_dev *dev = ctx->dev;
> -
> - mfc_write(dev, ctx->dec_dst_flag, S5P_FIMV_SI_CH0_RELEASE_BUF);
> - s5p_mfc_set_shared_buffer(ctx);
> - s5p_mfc_set_flush(ctx, ctx->dpb_flush_flag);
> - /* Issue different commands to instance basing on whether it
> - * is the last frame or not. */
> - switch (last_frame) {
> - case MFC_DEC_FRAME:
> - mfc_write(dev, ((S5P_FIMV_CH_FRAME_START & S5P_FIMV_CH_MASK)
<<
> - S5P_FIMV_CH_SHIFT) | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
> - break;
> - case MFC_DEC_LAST_FRAME:
> - mfc_write(dev, ((S5P_FIMV_CH_LAST_FRAME & S5P_FIMV_CH_MASK) <<
> - S5P_FIMV_CH_SHIFT) | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
> - break;
> - case MFC_DEC_RES_CHANGE:
> - mfc_write(dev, ((S5P_FIMV_CH_FRAME_START_REALLOC &
> - S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT) | (ctx->inst_no),
> - S5P_FIMV_SI_CH0_INST_ID);
> - break;
> - }
> - mfc_debug(2, "Decoding a usual frame\n");
> - return 0;
> -}
> -
> -int s5p_mfc_init_encode(struct s5p_mfc_ctx *ctx)
> -{
> - struct s5p_mfc_dev *dev = ctx->dev;
> -
> - if (ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC)
> - s5p_mfc_set_enc_params_h264(ctx);
> - else if (ctx->codec_mode == S5P_FIMV_CODEC_MPEG4_ENC)
> - s5p_mfc_set_enc_params_mpeg4(ctx);
> - else if (ctx->codec_mode == S5P_FIMV_CODEC_H263_ENC)
> - s5p_mfc_set_enc_params_h263(ctx);
> - else {
> - mfc_err("Unknown codec for encoding (%x)\n",
> - ctx->codec_mode);
> - return -EINVAL;
> - }
> - s5p_mfc_set_shared_buffer(ctx);
> - mfc_write(dev, ((S5P_FIMV_CH_SEQ_HEADER << 16) & 0x70000) |
> - (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
> - return 0;
> -}
> -
> -/* Encode a single frame */
> -int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *ctx)
> -{
> - struct s5p_mfc_dev *dev = ctx->dev;
> - /* memory structure cur. frame */
> - if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M)
> - mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR);
> - else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT)
> - mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR);
> - s5p_mfc_set_shared_buffer(ctx);
> - mfc_write(dev, (S5P_FIMV_CH_FRAME_START << 16 & 0x70000) |
> - (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
> - return 0;
> -}
> -
> -static int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev)
> -{
> - unsigned long flags;
> - int new_ctx;
> - int cnt;
> -
> - spin_lock_irqsave(&dev->condlock, flags);
> - new_ctx = (dev->curr_ctx + 1) % MFC_NUM_CONTEXTS;
> - cnt = 0;
> - while (!test_bit(new_ctx, &dev->ctx_work_bits)) {
> - new_ctx = (new_ctx + 1) % MFC_NUM_CONTEXTS;
> - if (++cnt > MFC_NUM_CONTEXTS) {
> - /* No contexts to run */
> - spin_unlock_irqrestore(&dev->condlock, flags);
> - return -EAGAIN;
> - }
> - }
> - spin_unlock_irqrestore(&dev->condlock, flags);
> - return new_ctx;
> -}
> -
> -static void s5p_mfc_run_res_change(struct s5p_mfc_ctx *ctx)
> -{
> - struct s5p_mfc_dev *dev = ctx->dev;
> -
> - s5p_mfc_set_dec_stream_buffer(ctx, 0, 0, 0);
> - dev->curr_ctx = ctx->num;
> - s5p_mfc_clean_ctx_int_flags(ctx);
> - s5p_mfc_decode_one_frame(ctx, MFC_DEC_RES_CHANGE);
> -}
> -
> -static int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx, int last_frame)
> -{
> - struct s5p_mfc_dev *dev = ctx->dev;
> - struct s5p_mfc_buf *temp_vb;
> - unsigned long flags;
> - unsigned int index;
> -
> - spin_lock_irqsave(&dev->irqlock, flags);
> - /* Frames are being decoded */
> - if (list_empty(&ctx->src_queue)) {
> - mfc_debug(2, "No src buffers\n");
> - spin_unlock_irqrestore(&dev->irqlock, flags);
> - return -EAGAIN;
> - }
> - /* Get the next source buffer */
> - temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
> - temp_vb->used = 1;
> - s5p_mfc_set_dec_stream_buffer(ctx,
> - vb2_dma_contig_plane_dma_addr(temp_vb->b, 0),
ctx->consumed_stream,
> - temp_vb->b->v4l2_planes[0].bytesused);
> - spin_unlock_irqrestore(&dev->irqlock, flags);
> - index = temp_vb->b->v4l2_buf.index;
> - dev->curr_ctx = ctx->num;
> - s5p_mfc_clean_ctx_int_flags(ctx);
> - if (temp_vb->b->v4l2_planes[0].bytesused == 0) {
> - last_frame = MFC_DEC_LAST_FRAME;
> - mfc_debug(2, "Setting ctx->state to FINISHING\n");
> - ctx->state = MFCINST_FINISHING;
> - }
> - s5p_mfc_decode_one_frame(ctx, last_frame);
> - return 0;
> -}
> -
> -static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
> -{
> - struct s5p_mfc_dev *dev = ctx->dev;
> - unsigned long flags;
> - struct s5p_mfc_buf *dst_mb;
> - struct s5p_mfc_buf *src_mb;
> - unsigned long src_y_addr, src_c_addr, dst_addr;
> - unsigned int dst_size;
> -
> - spin_lock_irqsave(&dev->irqlock, flags);
> - if (list_empty(&ctx->src_queue)) {
> - mfc_debug(2, "no src buffers\n");
> - spin_unlock_irqrestore(&dev->irqlock, flags);
> - return -EAGAIN;
> - }
> - if (list_empty(&ctx->dst_queue)) {
> - mfc_debug(2, "no dst buffers\n");
> - spin_unlock_irqrestore(&dev->irqlock, flags);
> - return -EAGAIN;
> - }
> - src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
> - src_mb->used = 1;
> - src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 0);
> - src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1);
> - s5p_mfc_set_enc_frame_buffer(ctx, src_y_addr, src_c_addr);
> - dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
> - dst_mb->used = 1;
> - dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
> - dst_size = vb2_plane_size(dst_mb->b, 0);
> - s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
> - spin_unlock_irqrestore(&dev->irqlock, flags);
> - dev->curr_ctx = ctx->num;
> - s5p_mfc_clean_ctx_int_flags(ctx);
> - s5p_mfc_encode_one_frame(ctx);
> - return 0;
> -}
> -
> -static void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx)
> -{
> - struct s5p_mfc_dev *dev = ctx->dev;
> - unsigned long flags;
> - struct s5p_mfc_buf *temp_vb;
> -
> - /* Initializing decoding - parsing header */
> - spin_lock_irqsave(&dev->irqlock, flags);
> - mfc_debug(2, "Preparing to init decoding\n");
> - temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
> - s5p_mfc_set_dec_desc_buffer(ctx);
> - mfc_debug(2, "Header size: %d\n",
temp_vb->b->v4l2_planes[0].bytesused);
> - s5p_mfc_set_dec_stream_buffer(ctx,
> - vb2_dma_contig_plane_dma_addr(temp_vb->b, 0),
> - 0, temp_vb->b->v4l2_planes[0].bytesused);
> - spin_unlock_irqrestore(&dev->irqlock, flags);
> - dev->curr_ctx = ctx->num;
> - s5p_mfc_clean_ctx_int_flags(ctx);
> - s5p_mfc_init_decode(ctx);
> -}
> -
> -static void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx)
> -{
> - struct s5p_mfc_dev *dev = ctx->dev;
> - unsigned long flags;
> - struct s5p_mfc_buf *dst_mb;
> - unsigned long dst_addr;
> - unsigned int dst_size;
> -
> - s5p_mfc_set_enc_ref_buffer(ctx);
> - spin_lock_irqsave(&dev->irqlock, flags);
> - dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
> - dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
> - dst_size = vb2_plane_size(dst_mb->b, 0);
> - s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
> - spin_unlock_irqrestore(&dev->irqlock, flags);
> - dev->curr_ctx = ctx->num;
> - s5p_mfc_clean_ctx_int_flags(ctx);
> - s5p_mfc_init_encode(ctx);
> -}
> -
> -static int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx)
> -{
> - struct s5p_mfc_dev *dev = ctx->dev;
> - unsigned long flags;
> - struct s5p_mfc_buf *temp_vb;
> - int ret;
> -
> - /*
> - * Header was parsed now starting processing
> - * First set the output frame buffers
> - */
> - if (ctx->capture_state != QUEUE_BUFS_MMAPED) {
> - mfc_err("It seems that not all destionation buffers were "
> - "mmaped\nMFC requires that all destination are mmaped
"
> - "before starting processing\n");
> - return -EAGAIN;
> - }
> - spin_lock_irqsave(&dev->irqlock, flags);
> - if (list_empty(&ctx->src_queue)) {
> - mfc_err("Header has been deallocated in the middle of"
> - " initialization\n");
> - spin_unlock_irqrestore(&dev->irqlock, flags);
> - return -EIO;
> - }
> - temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
> - mfc_debug(2, "Header size: %d\n",
temp_vb->b->v4l2_planes[0].bytesused);
> - s5p_mfc_set_dec_stream_buffer(ctx,
> - vb2_dma_contig_plane_dma_addr(temp_vb->b, 0),
> - 0, temp_vb->b->v4l2_planes[0].bytesused);
> - spin_unlock_irqrestore(&dev->irqlock, flags);
> - dev->curr_ctx = ctx->num;
> - s5p_mfc_clean_ctx_int_flags(ctx);
> - ret = s5p_mfc_set_dec_frame_buffer(ctx);
> - if (ret) {
> - mfc_err("Failed to alloc frame mem\n");
> - ctx->state = MFCINST_ERROR;
> - }
> - return ret;
> -}
> -
> -/* Try running an operation on hardware */
> -void s5p_mfc_try_run(struct s5p_mfc_dev *dev)
> -{
> - struct s5p_mfc_ctx *ctx;
> - int new_ctx;
> - unsigned int ret = 0;
> -
> - if (test_bit(0, &dev->enter_suspend)) {
> - mfc_debug(1, "Entering suspend so do not schedule any
jobs\n");
> - return;
> - }
> - /* Check whether hardware is not running */
> - if (test_and_set_bit(0, &dev->hw_lock) != 0) {
> - /* This is perfectly ok, the scheduled ctx should wait */
> - mfc_debug(1, "Couldn't lock HW\n");
> - return;
> - }
> - /* Choose the context to run */
> - new_ctx = s5p_mfc_get_new_ctx(dev);
> - if (new_ctx < 0) {
> - /* No contexts to run */
> - if (test_and_clear_bit(0, &dev->hw_lock) == 0) {
> - mfc_err("Failed to unlock hardware\n");
> - return;
> - }
> - mfc_debug(1, "No ctx is scheduled to be run\n");
> - return;
> - }
> - ctx = dev->ctx[new_ctx];
> - /* Got context to run in ctx */
> - /*
> - * Last frame has already been sent to MFC.
> - * Now obtaining frames from MFC buffer
> - */
> - s5p_mfc_clock_on();
> - if (ctx->type == MFCINST_DECODER) {
> - s5p_mfc_set_dec_desc_buffer(ctx);
> - switch (ctx->state) {
> - case MFCINST_FINISHING:
> - s5p_mfc_run_dec_frame(ctx, MFC_DEC_LAST_FRAME);
> - break;
> - case MFCINST_RUNNING:
> - ret = s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME);
> - break;
> - case MFCINST_INIT:
> - s5p_mfc_clean_ctx_int_flags(ctx);
> - ret = s5p_mfc_open_inst_cmd(ctx);
> - break;
> - case MFCINST_RETURN_INST:
> - s5p_mfc_clean_ctx_int_flags(ctx);
> - ret = s5p_mfc_close_inst_cmd(ctx);
> - break;
> - case MFCINST_GOT_INST:
> - s5p_mfc_run_init_dec(ctx);
> - break;
> - case MFCINST_HEAD_PARSED:
> - ret = s5p_mfc_run_init_dec_buffers(ctx);
> - mfc_debug(1, "head parsed\n");
> - break;
> - case MFCINST_RES_CHANGE_INIT:
> - s5p_mfc_run_res_change(ctx);
> - break;
> - case MFCINST_RES_CHANGE_FLUSH:
> - s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME);
> - break;
> - case MFCINST_RES_CHANGE_END:
> - mfc_debug(2, "Finished remaining frames after
resolution
> change\n");
> - ctx->capture_state = QUEUE_FREE;
> - mfc_debug(2, "Will re-init the codec\n");
> - s5p_mfc_run_init_dec(ctx);
> - break;
> - default:
> - ret = -EAGAIN;
> - }
> - } else if (ctx->type == MFCINST_ENCODER) {
> - switch (ctx->state) {
> - case MFCINST_FINISHING:
> - case MFCINST_RUNNING:
> - ret = s5p_mfc_run_enc_frame(ctx);
> - break;
> - case MFCINST_INIT:
> - s5p_mfc_clean_ctx_int_flags(ctx);
> - ret = s5p_mfc_open_inst_cmd(ctx);
> - break;
> - case MFCINST_RETURN_INST:
> - s5p_mfc_clean_ctx_int_flags(ctx);
> - ret = s5p_mfc_close_inst_cmd(ctx);
> - break;
> - case MFCINST_GOT_INST:
> - s5p_mfc_run_init_enc(ctx);
> - break;
> - default:
> - ret = -EAGAIN;
> - }
> - } else {
> - mfc_err("Invalid context type: %d\n", ctx->type);
> - ret = -EAGAIN;
> - }
> -
> - if (ret) {
> - /* Free hardware lock */
> - if (test_and_clear_bit(0, &dev->hw_lock) == 0)
> - mfc_err("Failed to unlock hardware\n");
> -
> - /* This is in deed imporant, as no operation has been
> - * scheduled, reduce the clock count as no one will
> - * ever do this, because no interrupt related to this try_run
> - * will ever come from hardware. */
> - s5p_mfc_clock_off();
> - }
> -}
> -
> -
> -void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq)
> -{
> - struct s5p_mfc_buf *b;
> - int i;
> -
> - while (!list_empty(lh)) {
> - b = list_entry(lh->next, struct s5p_mfc_buf, list);
> - for (i = 0; i < b->b->num_planes; i++)
> - vb2_set_plane_payload(b->b, i, 0);
> - vb2_buffer_done(b->b, VB2_BUF_STATE_ERROR);
> - list_del(&b->list);
> - }
> -}
> -
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
> b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
> index 2ad3def..47a91f5 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
> @@ -17,77 +17,68 @@
>
> #include "s5p_mfc_common.h"
>
> -int s5p_mfc_init_decode(struct s5p_mfc_ctx *ctx);
> -int s5p_mfc_init_encode(struct s5p_mfc_ctx *mfc_ctx);
> +struct s5p_mfc_hw_ops {
> + int (*alloc_dec_temp_buffers)(struct s5p_mfc_ctx *ctx);
> + void (*release_dec_desc_buffer)(struct s5p_mfc_ctx *ctx);
> + int (*alloc_codec_buffers)(struct s5p_mfc_ctx *ctx);
> + void (*release_codec_buffers)(struct s5p_mfc_ctx *ctx);
> + int (*alloc_instance_buffer)(struct s5p_mfc_ctx *ctx);
> + void (*release_instance_buffer)(struct s5p_mfc_ctx *ctx);
> + int (*alloc_dev_context_buffer)(struct s5p_mfc_dev *dev);
> + void (*release_dev_context_buffer)(struct s5p_mfc_dev *dev);
> + void (*dec_calc_dpb_size)(struct s5p_mfc_ctx *ctx);
> + void (*enc_calc_src_size)(struct s5p_mfc_ctx *ctx);
> + int (*set_dec_stream_buffer)(struct s5p_mfc_ctx *ctx,
> + int buf_addr, unsigned int start_num_byte,
> + unsigned int buf_size);
> + int (*set_dec_frame_buffer)(struct s5p_mfc_ctx *ctx);
> + int (*set_enc_stream_buffer)(struct s5p_mfc_ctx *ctx,
> + unsigned long addr, unsigned int size);
> + void (*set_enc_frame_buffer)(struct s5p_mfc_ctx *ctx,
> + unsigned long y_addr, unsigned long c_addr);
> + void (*get_enc_frame_buffer)(struct s5p_mfc_ctx *ctx,
> + unsigned long *y_addr, unsigned long *c_addr);
> + int (*set_enc_ref_buffer)(struct s5p_mfc_ctx *ctx);
> + int (*init_decode)(struct s5p_mfc_ctx *ctx);
> + int (*init_encode)(struct s5p_mfc_ctx *ctx);
> + int (*encode_one_frame)(struct s5p_mfc_ctx *ctx);
> + void (*try_run)(struct s5p_mfc_dev *dev);
> + void (*cleanup_queue)(struct list_head *lh,
> + struct vb2_queue *vq);
> + void (*clear_int_flags)(struct s5p_mfc_dev *dev);
> + void (*write_info)(struct s5p_mfc_ctx *ctx, unsigned int data,
> + unsigned int ofs);
> + unsigned int (*read_info)(struct s5p_mfc_ctx *ctx,
> + unsigned int ofs);
> + int (*get_dspl_y_adr)(struct s5p_mfc_dev *dev);
> + int (*get_dec_y_adr)(struct s5p_mfc_dev *dev);
> + int (*get_dspl_status)(struct s5p_mfc_dev *dev);
> + int (*get_dec_status)(struct s5p_mfc_dev *dev);
> + int (*get_dec_frame_type)(struct s5p_mfc_dev *dev);
> + int (*get_disp_frame_type)(struct s5p_mfc_ctx *ctx);
> + int (*get_consumed_stream)(struct s5p_mfc_dev *dev);
> + int (*get_int_reason)(struct s5p_mfc_dev *dev);
> + int (*get_int_err)(struct s5p_mfc_dev *dev);
> + int (*err_dec)(unsigned int err);
> + int (*err_dspl)(unsigned int err);
> + int (*get_img_width)(struct s5p_mfc_dev *dev);
> + int (*get_img_height)(struct s5p_mfc_dev *dev);
> + int (*get_dpb_count)(struct s5p_mfc_dev *dev);
> + int (*get_mv_count)(struct s5p_mfc_dev *dev);
> + int (*get_inst_no)(struct s5p_mfc_dev *dev);
> + int (*get_enc_strm_size)(struct s5p_mfc_dev *dev);
> + int (*get_enc_slice_type)(struct s5p_mfc_dev *dev);
> + int (*get_enc_dpb_count)(struct s5p_mfc_dev *dev);
> + int (*get_enc_pic_count)(struct s5p_mfc_dev *dev);
> + int (*get_sei_avail_status)(struct s5p_mfc_ctx *ctx);
> + int (*get_mvc_num_views)(struct s5p_mfc_dev *dev);
> + int (*get_mvc_view_id)(struct s5p_mfc_dev *dev);
> + unsigned int (*get_pic_type_top)(struct s5p_mfc_ctx *ctx);
> + unsigned int (*get_pic_type_bot)(struct s5p_mfc_ctx *ctx);
> + unsigned int (*get_crop_info_h)(struct s5p_mfc_ctx *ctx);
> + unsigned int (*get_crop_info_v)(struct s5p_mfc_ctx *ctx);
> +};
>
> -/* Decoding functions */
> -int s5p_mfc_set_dec_frame_buffer(struct s5p_mfc_ctx *ctx);
> -int s5p_mfc_set_dec_stream_buffer(struct s5p_mfc_ctx *ctx, int buf_addr,
> - unsigned int start_num_byte,
> - unsigned int buf_size);
> -
> -/* Encoding functions */
> -void s5p_mfc_set_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
> - unsigned long y_addr, unsigned long c_addr);
> -int s5p_mfc_set_enc_stream_buffer(struct s5p_mfc_ctx *ctx,
> - unsigned long addr, unsigned int size);
> -void s5p_mfc_get_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
> - unsigned long *y_addr, unsigned long *c_addr);
> -int s5p_mfc_set_enc_ref_buffer(struct s5p_mfc_ctx *mfc_ctx);
> -
> -int s5p_mfc_decode_one_frame(struct s5p_mfc_ctx *ctx,
> - enum s5p_mfc_decode_arg last_frame);
> -int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *mfc_ctx);
> -
> -/* Memory allocation */
> -int s5p_mfc_alloc_dec_temp_buffers(struct s5p_mfc_ctx *ctx);
> -void s5p_mfc_set_dec_desc_buffer(struct s5p_mfc_ctx *ctx);
> -void s5p_mfc_release_dec_desc_buffer(struct s5p_mfc_ctx *ctx);
> -
> -int s5p_mfc_alloc_codec_buffers(struct s5p_mfc_ctx *ctx);
> -void s5p_mfc_release_codec_buffers(struct s5p_mfc_ctx *ctx);
> -
> -int s5p_mfc_alloc_instance_buffer(struct s5p_mfc_ctx *ctx);
> -void s5p_mfc_release_instance_buffer(struct s5p_mfc_ctx *ctx);
> -
> -void s5p_mfc_try_run(struct s5p_mfc_dev *dev);
> -void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq);
> -
> -#define s5p_mfc_get_dspl_y_adr() (readl(dev->regs_base + \
> - S5P_FIMV_SI_DISPLAY_Y_ADR) << \
> - MFC_OFFSET_SHIFT)
> -#define s5p_mfc_get_dec_y_adr() (readl(dev->regs_base + \
> - S5P_FIMV_SI_DECODE_Y_ADR) << \
> - MFC_OFFSET_SHIFT)
> -#define s5p_mfc_get_dspl_status() readl(dev->regs_base + \
> - S5P_FIMV_SI_DISPLAY_STATUS)
> -#define s5p_mfc_get_dec_status() readl(dev->regs_base + \
> - S5P_FIMV_SI_DECODE_STATUS)
> -#define s5p_mfc_get_frame_type() (readl(dev->regs_base + \
> - S5P_FIMV_DECODE_FRAME_TYPE) \
> - & S5P_FIMV_DECODE_FRAME_MASK)
> -#define s5p_mfc_get_consumed_stream() readl(dev->regs_base + \
> - S5P_FIMV_SI_CONSUMED_BYTES)
> -#define s5p_mfc_get_int_reason() (readl(dev->regs_base + \
> - S5P_FIMV_RISC2HOST_CMD) & \
> - S5P_FIMV_RISC2HOST_CMD_MASK)
> -#define s5p_mfc_get_int_err() readl(dev->regs_base + \
> - S5P_FIMV_RISC2HOST_ARG2)
> -#define s5p_mfc_err_dec(x) (((x) & S5P_FIMV_ERR_DEC_MASK) >> \
> -
S5P_FIMV_ERR_DEC_SHIFT)
> -#define s5p_mfc_err_dspl(x) (((x) & S5P_FIMV_ERR_DSPL_MASK) >> \
> -
S5P_FIMV_ERR_DSPL_SHIFT)
> -#define s5p_mfc_get_img_width() readl(dev->regs_base + \
> - S5P_FIMV_SI_HRESOL)
> -#define s5p_mfc_get_img_height() readl(dev->regs_base + \
> - S5P_FIMV_SI_VRESOL)
> -#define s5p_mfc_get_dpb_count() readl(dev->regs_base + \
> - S5P_FIMV_SI_BUF_NUMBER)
> -#define s5p_mfc_get_inst_no() readl(dev->regs_base + \
> - S5P_FIMV_RISC2HOST_ARG1)
> -#define s5p_mfc_get_enc_strm_size() readl(dev->regs_base + \
> - S5P_FIMV_ENC_SI_STRM_SIZE)
> -#define s5p_mfc_get_enc_slice_type() readl(dev->regs_base + \
> - S5P_FIMV_ENC_SI_SLICE_TYPE)
> +void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev);
>
> #endif /* S5P_MFC_OPR_H_ */
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
> b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
> new file mode 100644
> index 0000000..fe36c92
> --- /dev/null
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
> @@ -0,0 +1,1698 @@
> +/*
> + * drivers/media/video/samsung/mfc5/s5p_mfc_opr_v5.c
> + *
> + * Samsung MFC (Multi Function Codec - FIMV) driver
> + * This file contains hw related functions.
> + *
> + * Kamil Debski, Copyright (c) 2012 Samsung Electronics Co., Ltd.
> + * http://www.samsung.com/
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include "s5p_mfc_common.h"
> +#include "s5p_mfc_cmd.h"
> +#include "s5p_mfc_ctrl.h"
> +#include "s5p_mfc_debug.h"
> +#include "s5p_mfc_intr.h"
> +#include "s5p_mfc_pm.h"
> +#include "s5p_mfc_opr.h"
> +#include "s5p_mfc_opr_v5.h"
> +#include <asm/cacheflush.h>
> +#include <linux/delay.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/err.h>
> +#include <linux/firmware.h>
> +#include <linux/io.h>
> +#include <linux/jiffies.h>
> +#include <linux/mm.h>
> +#include <linux/sched.h>
> +
> +#define OFFSETA(x) (((x) - dev->bank1) >> MFC_OFFSET_SHIFT)
> +#define OFFSETB(x) (((x) - dev->bank2) >> MFC_OFFSET_SHIFT)
> +
> +/* Allocate temporary buffers for decoding */
> +int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx *ctx)
> +{
> + void *desc_virt;
> + struct s5p_mfc_dev *dev = ctx->dev;
> +
> + ctx->desc_buf = vb2_dma_contig_memops.alloc(
> + dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], DESC_BUF_SIZE);
> + if (IS_ERR_VALUE((int)ctx->desc_buf)) {
> + ctx->desc_buf = NULL;
> + mfc_err("Allocating DESC buffer failed\n");
> + return -ENOMEM;
> + }
> + ctx->desc_phys = s5p_mfc_mem_cookie(
> + dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->desc_buf);
> + BUG_ON(ctx->desc_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
> + desc_virt = vb2_dma_contig_memops.vaddr(ctx->desc_buf);
> + if (desc_virt == NULL) {
> + vb2_dma_contig_memops.put(ctx->desc_buf);
> + ctx->desc_phys = 0;
> + ctx->desc_buf = NULL;
> + mfc_err("Remapping DESC buffer failed\n");
> + return -ENOMEM;
> + }
> + memset(desc_virt, 0, DESC_BUF_SIZE);
> + wmb();
> + return 0;
> +}
> +
> +/* Release temporary buffers for decoding */
> +void s5p_mfc_release_dec_desc_buffer_v5(struct s5p_mfc_ctx *ctx)
> +{
> + if (ctx->desc_phys) {
> + vb2_dma_contig_memops.put(ctx->desc_buf);
> + ctx->desc_phys = 0;
> + ctx->desc_buf = NULL;
> + }
> +}
> +
> +/* Allocate codec buffers */
> +int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + unsigned int enc_ref_y_size = 0;
> + unsigned int enc_ref_c_size = 0;
> + unsigned int guard_width, guard_height;
> +
> + if (ctx->type == MFCINST_DECODER) {
> + mfc_debug(2, "Luma size:%d Chroma size:%d MV size:%d\n",
> + ctx->luma_size, ctx->chroma_size, ctx->mv_size);
> + mfc_debug(2, "Totals bufs: %d\n", ctx->total_dpb_count);
> + } else if (ctx->type == MFCINST_ENCODER) {
> + enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
> + * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
> + enc_ref_y_size = ALIGN(enc_ref_y_size,
S5P_FIMV_NV12MT_SALIGN);
> +
> + if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC) {
> + enc_ref_c_size = ALIGN(ctx->img_width,
> + S5P_FIMV_NV12MT_HALIGN)
> + * ALIGN(ctx->img_height >> 1,
> + S5P_FIMV_NV12MT_VALIGN);
> + enc_ref_c_size = ALIGN(enc_ref_c_size,
> +
S5P_FIMV_NV12MT_SALIGN);
> + } else {
> + guard_width = ALIGN(ctx->img_width + 16,
> +
S5P_FIMV_NV12MT_HALIGN);
> + guard_height = ALIGN((ctx->img_height >> 1) + 4,
> +
S5P_FIMV_NV12MT_VALIGN);
> + enc_ref_c_size = ALIGN(guard_width * guard_height,
> + S5P_FIMV_NV12MT_SALIGN);
> + }
> + mfc_debug(2, "recon luma size: %d chroma size: %d\n",
> + enc_ref_y_size, enc_ref_c_size);
> + } else {
> + return -EINVAL;
> + }
> + /* Codecs have different memory requirements */
> + switch (ctx->codec_mode) {
> + case S5P_MFC_CODEC_H264_DEC:
> + ctx->bank1_size =
> + ALIGN(S5P_FIMV_DEC_NB_IP_SIZE +
> + S5P_FIMV_DEC_VERT_NB_MV_SIZE,
> + S5P_FIMV_DEC_BUF_ALIGN);
> + ctx->bank2_size = ctx->total_dpb_count * ctx->mv_size;
> + break;
> + case S5P_MFC_CODEC_MPEG4_DEC:
> + ctx->bank1_size =
> + ALIGN(S5P_FIMV_DEC_NB_DCAC_SIZE +
> + S5P_FIMV_DEC_UPNB_MV_SIZE +
> + S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
> + S5P_FIMV_DEC_STX_PARSER_SIZE +
> + S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE,
> + S5P_FIMV_DEC_BUF_ALIGN);
> + ctx->bank2_size = 0;
> + break;
> + case S5P_MFC_CODEC_VC1RCV_DEC:
> + case S5P_MFC_CODEC_VC1_DEC:
> + ctx->bank1_size =
> + ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE +
> + S5P_FIMV_DEC_UPNB_MV_SIZE +
> + S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
> + S5P_FIMV_DEC_NB_DCAC_SIZE +
> + 3 * S5P_FIMV_DEC_VC1_BITPLANE_SIZE,
> + S5P_FIMV_DEC_BUF_ALIGN);
> + ctx->bank2_size = 0;
> + break;
> + case S5P_MFC_CODEC_MPEG2_DEC:
> + ctx->bank1_size = 0;
> + ctx->bank2_size = 0;
> + break;
> + case S5P_MFC_CODEC_H263_DEC:
> + ctx->bank1_size =
> + ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE +
> + S5P_FIMV_DEC_UPNB_MV_SIZE +
> + S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
> + S5P_FIMV_DEC_NB_DCAC_SIZE,
> + S5P_FIMV_DEC_BUF_ALIGN);
> + ctx->bank2_size = 0;
> + break;
> + case S5P_MFC_CODEC_H264_ENC:
> + ctx->bank1_size = (enc_ref_y_size * 2) +
> + S5P_FIMV_ENC_UPMV_SIZE +
> + S5P_FIMV_ENC_COLFLG_SIZE +
> + S5P_FIMV_ENC_INTRAMD_SIZE +
> + S5P_FIMV_ENC_NBORINFO_SIZE;
> + ctx->bank2_size = (enc_ref_y_size * 2) +
> + (enc_ref_c_size * 4) +
> + S5P_FIMV_ENC_INTRAPRED_SIZE;
> + break;
> + case S5P_MFC_CODEC_MPEG4_ENC:
> + ctx->bank1_size = (enc_ref_y_size * 2) +
> + S5P_FIMV_ENC_UPMV_SIZE +
> + S5P_FIMV_ENC_COLFLG_SIZE +
> + S5P_FIMV_ENC_ACDCCOEF_SIZE;
> + ctx->bank2_size = (enc_ref_y_size * 2) +
> + (enc_ref_c_size * 4);
> + break;
> + case S5P_MFC_CODEC_H263_ENC:
> + ctx->bank1_size = (enc_ref_y_size * 2) +
> + S5P_FIMV_ENC_UPMV_SIZE +
> + S5P_FIMV_ENC_ACDCCOEF_SIZE;
> + ctx->bank2_size = (enc_ref_y_size * 2) +
> + (enc_ref_c_size * 4);
> + break;
> + default:
> + break;
> + }
> + /* Allocate only if memory from bank 1 is necessary */
> + if (ctx->bank1_size > 0) {
> + ctx->bank1_buf = vb2_dma_contig_memops.alloc(
> + dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_size);
> + if (IS_ERR(ctx->bank1_buf)) {
> + ctx->bank1_buf = NULL;
> + mfc_err("Buf alloc for decoding failed (port A)\n");
> + return -ENOMEM;
> + }
> + ctx->bank1_phys = s5p_mfc_mem_cookie(
> + dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_buf);
> + BUG_ON(ctx->bank1_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
> + }
> + /* Allocate only if memory from bank 2 is necessary */
> + if (ctx->bank2_size > 0) {
> + ctx->bank2_buf = vb2_dma_contig_memops.alloc(
> + dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], ctx->bank2_size);
> + if (IS_ERR(ctx->bank2_buf)) {
> + ctx->bank2_buf = NULL;
> + mfc_err("Buf alloc for decoding failed (port B)\n");
> + return -ENOMEM;
> + }
> + ctx->bank2_phys = s5p_mfc_mem_cookie(
> + dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], ctx->bank2_buf);
> + BUG_ON(ctx->bank2_phys & ((1 << MFC_BANK2_ALIGN_ORDER) - 1));
> + }
> + return 0;
> +}
> +
> +/* Release buffers allocated for codec */
> +void s5p_mfc_release_codec_buffers_v5(struct s5p_mfc_ctx *ctx)
> +{
> + if (ctx->bank1_buf) {
> + vb2_dma_contig_memops.put(ctx->bank1_buf);
> + ctx->bank1_buf = NULL;
> + ctx->bank1_phys = 0;
> + ctx->bank1_size = 0;
> + }
> + if (ctx->bank2_buf) {
> + vb2_dma_contig_memops.put(ctx->bank2_buf);
> + ctx->bank2_buf = NULL;
> + ctx->bank2_phys = 0;
> + ctx->bank2_size = 0;
> + }
> +}
> +
> +/* Allocate memory for instance data buffer */
> +int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx)
> +{
> + void *context_virt;
> + struct s5p_mfc_dev *dev = ctx->dev;
> +
> + if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC ||
> + ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC)
> + ctx->ctx_size = MFC_H264_CTX_BUF_SIZE;
> + else
> + ctx->ctx_size = MFC_CTX_BUF_SIZE;
> + ctx->ctx_buf = vb2_dma_contig_memops.alloc(
> + dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx_size);
> + if (IS_ERR(ctx->ctx_buf)) {
> + mfc_err("Allocating context buffer failed\n");
> + ctx->ctx_phys = 0;
> + ctx->ctx_buf = NULL;
> + return -ENOMEM;
> + }
> + ctx->ctx_phys = s5p_mfc_mem_cookie(
> + dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx_buf);
> + BUG_ON(ctx->ctx_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
> + ctx->ctx_ofs = OFFSETA(ctx->ctx_phys);
> + context_virt = vb2_dma_contig_memops.vaddr(ctx->ctx_buf);
> + if (context_virt == NULL) {
> + mfc_err("Remapping instance buffer failed\n");
> + vb2_dma_contig_memops.put(ctx->ctx_buf);
> + ctx->ctx_phys = 0;
> + ctx->ctx_buf = NULL;
> + return -ENOMEM;
> + }
> + /* Zero content of the allocated memory */
> + memset(context_virt, 0, ctx->ctx_size);
> + wmb();
> +
> + /* Initialize shared memory */
> + ctx->shm_alloc = vb2_dma_contig_memops.alloc(
> + dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], SHARED_BUF_SIZE);
> + if (IS_ERR(ctx->shm_alloc)) {
> + mfc_err("failed to allocate shared memory\n");
> + return PTR_ERR(ctx->shm_alloc);
> + }
> + /* shared memory offset only keeps the offset from base (port a) */
> + ctx->shm_ofs = s5p_mfc_mem_cookie(
> + dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->shm_alloc)
> + - dev->bank1;
> + BUG_ON(ctx->shm_ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
> +
> + ctx->shm = vb2_dma_contig_memops.vaddr(ctx->shm_alloc);
> + if (!ctx->shm) {
> + vb2_dma_contig_memops.put(ctx->shm_alloc);
> + ctx->shm_ofs = 0;
> + ctx->shm_alloc = NULL;
> + mfc_err("failed to virt addr of shared memory\n");
> + return -ENOMEM;
> + }
> + memset((void *)ctx->shm, 0, SHARED_BUF_SIZE);
> + wmb();
> + return 0;
> +}
> +
> +/* Release instance buffer */
> +void s5p_mfc_release_instance_buffer_v5(struct s5p_mfc_ctx *ctx)
> +{
> + if (ctx->ctx_buf) {
> + vb2_dma_contig_memops.put(ctx->ctx_buf);
> + ctx->ctx_phys = 0;
> + ctx->ctx_buf = NULL;
> + }
> + if (ctx->shm_alloc) {
> + vb2_dma_contig_memops.put(ctx->shm_alloc);
> + ctx->shm_alloc = NULL;
> + ctx->shm = NULL;
> + }
> +}
> +
> +int s5p_mfc_alloc_dev_context_buffer_v5(struct s5p_mfc_dev *dev)
> +{
> + /* NOP */
> +
> + return 0;
> +}
> +
> +void s5p_mfc_release_dev_context_buffer_v5(struct s5p_mfc_dev *dev)
> +{
> + /* NOP */
> +}
> +
> +static void s5p_mfc_write_info_v5(struct s5p_mfc_ctx *ctx, unsigned int
data,
> + unsigned int ofs)
> +{
> + writel(data, (ctx->shm + ofs));
> + wmb();
> +}
> +
> +static unsigned int s5p_mfc_read_info_v5(struct s5p_mfc_ctx *ctx,
> + unsigned int ofs)
> +{
> + rmb();
> + return readl(ctx->shm + ofs);
> +}
> +
> +void s5p_mfc_dec_calc_dpb_size_v5(struct s5p_mfc_ctx *ctx)
> +{
> + /* NOP */
> +}
> +
> +void s5p_mfc_enc_calc_src_size_v5(struct s5p_mfc_ctx *ctx)
> +{
> + /* NOP */
> +}
> +
> +/* Set registers for decoding temporary buffers */
> +static void s5p_mfc_set_dec_desc_buffer(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> +
> + mfc_write(dev, OFFSETA(ctx->desc_phys), S5P_FIMV_SI_CH0_DESC_ADR);
> + mfc_write(dev, DESC_BUF_SIZE, S5P_FIMV_SI_CH0_DESC_SIZE);
> +}
> +
> +/* Set registers for shared buffer */
> +static void s5p_mfc_set_shared_buffer(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + mfc_write(dev, ctx->shm_ofs, S5P_FIMV_SI_CH0_HOST_WR_ADR);
> +}
> +
> +/* Set registers for decoding stream buffer */
> +int s5p_mfc_set_dec_stream_buffer_v5(struct s5p_mfc_ctx *ctx, int buf_addr,
> + unsigned int start_num_byte, unsigned int buf_size)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> +
> + mfc_write(dev, OFFSETA(buf_addr), S5P_FIMV_SI_CH0_SB_ST_ADR);
> + mfc_write(dev, ctx->dec_src_buf_size, S5P_FIMV_SI_CH0_CPB_SIZE);
> + mfc_write(dev, buf_size, S5P_FIMV_SI_CH0_SB_FRM_SIZE);
> + s5p_mfc_write_info_v5(ctx, start_num_byte, START_BYTE_NUM);
> + return 0;
> +}
> +
> +/* Set decoding frame buffer */
> +int s5p_mfc_set_dec_frame_buffer_v5(struct s5p_mfc_ctx *ctx)
> +{
> + unsigned int frame_size, i;
> + unsigned int frame_size_ch, frame_size_mv;
> + struct s5p_mfc_dev *dev = ctx->dev;
> + unsigned int dpb;
> + size_t buf_addr1, buf_addr2;
> + int buf_size1, buf_size2;
> +
> + buf_addr1 = ctx->bank1_phys;
> + buf_size1 = ctx->bank1_size;
> + buf_addr2 = ctx->bank2_phys;
> + buf_size2 = ctx->bank2_size;
> + dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) &
> + ~S5P_FIMV_DPB_COUNT_MASK;
> + mfc_write(dev, ctx->total_dpb_count | dpb,
> +
S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
> + s5p_mfc_set_shared_buffer(ctx);
> + switch (ctx->codec_mode) {
> + case S5P_MFC_CODEC_H264_DEC:
> + mfc_write(dev, OFFSETA(buf_addr1),
> + S5P_FIMV_H264_VERT_NB_MV_ADR);
> + buf_addr1 += S5P_FIMV_DEC_VERT_NB_MV_SIZE;
> + buf_size1 -= S5P_FIMV_DEC_VERT_NB_MV_SIZE;
> + mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H264_NB_IP_ADR);
> + buf_addr1 += S5P_FIMV_DEC_NB_IP_SIZE;
> + buf_size1 -= S5P_FIMV_DEC_NB_IP_SIZE;
> + break;
> + case S5P_MFC_CODEC_MPEG4_DEC:
> + mfc_write(dev, OFFSETA(buf_addr1),
S5P_FIMV_MPEG4_NB_DCAC_ADR);
> + buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
> + buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
> + mfc_write(dev, OFFSETA(buf_addr1),
S5P_FIMV_MPEG4_UP_NB_MV_ADR);
> + buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
> + buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
> + mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_SA_MV_ADR);
> + buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
> + buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
> + mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_SP_ADR);
> + buf_addr1 += S5P_FIMV_DEC_STX_PARSER_SIZE;
> + buf_size1 -= S5P_FIMV_DEC_STX_PARSER_SIZE;
> + mfc_write(dev, OFFSETA(buf_addr1),
S5P_FIMV_MPEG4_OT_LINE_ADR);
> + buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
> + buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
> + break;
> + case S5P_MFC_CODEC_H263_DEC:
> + mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_OT_LINE_ADR);
> + buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
> + buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
> + mfc_write(dev, OFFSETA(buf_addr1),
S5P_FIMV_H263_UP_NB_MV_ADR);
> + buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
> + buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
> + mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_SA_MV_ADR);
> + buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
> + buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
> + mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_NB_DCAC_ADR);
> + buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
> + buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
> + break;
> + case S5P_MFC_CODEC_VC1_DEC:
> + case S5P_MFC_CODEC_VC1RCV_DEC:
> + mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_NB_DCAC_ADR);
> + buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
> + buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
> + mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_OT_LINE_ADR);
> + buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
> + buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
> + mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_UP_NB_MV_ADR);
> + buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
> + buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
> + mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_SA_MV_ADR);
> + buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
> + buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
> + mfc_write(dev, OFFSETA(buf_addr1),
S5P_FIMV_VC1_BITPLANE3_ADR);
> + buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
> + buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
> + mfc_write(dev, OFFSETA(buf_addr1),
S5P_FIMV_VC1_BITPLANE2_ADR);
> + buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
> + buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
> + mfc_write(dev, OFFSETA(buf_addr1),
S5P_FIMV_VC1_BITPLANE1_ADR);
> + buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
> + buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
> + break;
> + case S5P_MFC_CODEC_MPEG2_DEC:
> + break;
> + default:
> + mfc_err("Unknown codec for decoding (%x)\n",
> + ctx->codec_mode);
> + return -EINVAL;
> + break;
> + }
> + frame_size = ctx->luma_size;
> + frame_size_ch = ctx->chroma_size;
> + frame_size_mv = ctx->mv_size;
> + mfc_debug(2, "Frm size: %d ch: %d mv: %d\n", frame_size,
frame_size_ch,
> +
frame_size_mv);
> + for (i = 0; i < ctx->total_dpb_count; i++) {
> + /* Bank2 */
> + mfc_debug(2, "Luma %d: %x\n", i,
> + ctx->dst_bufs[i].cookie.raw.luma);
> + mfc_write(dev, OFFSETB(ctx->dst_bufs[i].cookie.raw.luma),
> + S5P_FIMV_DEC_LUMA_ADR + i *
4);
> + mfc_debug(2, "\tChroma %d: %x\n", i,
> + ctx->dst_bufs[i].cookie.raw.chroma);
> + mfc_write(dev, OFFSETA(ctx->dst_bufs[i].cookie.raw.chroma),
> + S5P_FIMV_DEC_CHROMA_ADR + i *
4);
> + if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC) {
> + mfc_debug(2, "\tBuf2: %x, size: %d\n",
> + buf_addr2, buf_size2);
> + mfc_write(dev, OFFSETB(buf_addr2),
> + S5P_FIMV_H264_MV_ADR + i * 4);
> + buf_addr2 += frame_size_mv;
> + buf_size2 -= frame_size_mv;
> + }
> + }
> + mfc_debug(2, "Buf1: %u, buf_size1: %d\n", buf_addr1, buf_size1);
> + mfc_debug(2, "Buf 1/2 size after: %d/%d (frames %d)\n",
> + buf_size1, buf_size2, ctx->total_dpb_count);
> + if (buf_size1 < 0 || buf_size2 < 0) {
> + mfc_debug(2, "Not enough memory has been allocated\n");
> + return -ENOMEM;
> + }
> + s5p_mfc_write_info_v5(ctx, frame_size, ALLOC_LUMA_DPB_SIZE);
> + s5p_mfc_write_info_v5(ctx, frame_size_ch, ALLOC_CHROMA_DPB_SIZE);
> + if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC)
> + s5p_mfc_write_info_v5(ctx, frame_size_mv, ALLOC_MV_SIZE);
> + mfc_write(dev, ((S5P_FIMV_CH_INIT_BUFS & S5P_FIMV_CH_MASK)
> + << S5P_FIMV_CH_SHIFT) |
(ctx->inst_no),
> + S5P_FIMV_SI_CH0_INST_ID);
> + return 0;
> +}
> +
> +/* Set registers for encoding stream buffer */
> +int s5p_mfc_set_enc_stream_buffer_v5(struct s5p_mfc_ctx *ctx,
> + unsigned long addr, unsigned int size)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> +
> + mfc_write(dev, OFFSETA(addr), S5P_FIMV_ENC_SI_CH0_SB_ADR);
> + mfc_write(dev, size, S5P_FIMV_ENC_SI_CH0_SB_SIZE);
> + return 0;
> +}
> +
> +void s5p_mfc_set_enc_frame_buffer_v5(struct s5p_mfc_ctx *ctx,
> + unsigned long y_addr, unsigned long c_addr)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> +
> + mfc_write(dev, OFFSETB(y_addr), S5P_FIMV_ENC_SI_CH0_CUR_Y_ADR);
> + mfc_write(dev, OFFSETB(c_addr), S5P_FIMV_ENC_SI_CH0_CUR_C_ADR);
> +}
> +
> +void s5p_mfc_get_enc_frame_buffer_v5(struct s5p_mfc_ctx *ctx,
> + unsigned long *y_addr, unsigned long *c_addr)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> +
> + *y_addr = dev->bank2 + (mfc_read(dev, S5P_FIMV_ENCODED_Y_ADDR)
> + << MFC_OFFSET_SHIFT);
> + *c_addr = dev->bank2 + (mfc_read(dev, S5P_FIMV_ENCODED_C_ADDR)
> + << MFC_OFFSET_SHIFT);
> +}
> +
> +/* Set encoding ref & codec buffer */
> +int s5p_mfc_set_enc_ref_buffer_v5(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + size_t buf_addr1, buf_addr2;
> + size_t buf_size1, buf_size2;
> + unsigned int enc_ref_y_size, enc_ref_c_size;
> + unsigned int guard_width, guard_height;
> + int i;
> +
> + buf_addr1 = ctx->bank1_phys;
> + buf_size1 = ctx->bank1_size;
> + buf_addr2 = ctx->bank2_phys;
> + buf_size2 = ctx->bank2_size;
> + enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
> + * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
> + enc_ref_y_size = ALIGN(enc_ref_y_size, S5P_FIMV_NV12MT_SALIGN);
> + if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC) {
> + enc_ref_c_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
> + * ALIGN((ctx->img_height >> 1),
S5P_FIMV_NV12MT_VALIGN);
> + enc_ref_c_size = ALIGN(enc_ref_c_size,
S5P_FIMV_NV12MT_SALIGN);
> + } else {
> + guard_width = ALIGN(ctx->img_width + 16,
> + S5P_FIMV_NV12MT_HALIGN);
> + guard_height = ALIGN((ctx->img_height >> 1) + 4,
> + S5P_FIMV_NV12MT_VALIGN);
> + enc_ref_c_size = ALIGN(guard_width * guard_height,
> + S5P_FIMV_NV12MT_SALIGN);
> + }
> + mfc_debug(2, "buf_size1: %d, buf_size2: %d\n", buf_size1, buf_size2);
> + switch (ctx->codec_mode) {
> + case S5P_MFC_CODEC_H264_ENC:
> + for (i = 0; i < 2; i++) {
> + mfc_write(dev, OFFSETA(buf_addr1),
> + S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
> + buf_addr1 += enc_ref_y_size;
> + buf_size1 -= enc_ref_y_size;
> +
> + mfc_write(dev, OFFSETB(buf_addr2),
> + S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
> + buf_addr2 += enc_ref_y_size;
> + buf_size2 -= enc_ref_y_size;
> + }
> + for (i = 0; i < 4; i++) {
> + mfc_write(dev, OFFSETB(buf_addr2),
> + S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
> + buf_addr2 += enc_ref_c_size;
> + buf_size2 -= enc_ref_c_size;
> + }
> + mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H264_UP_MV_ADR);
> + buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
> + buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
> + mfc_write(dev, OFFSETA(buf_addr1),
> + S5P_FIMV_H264_COZERO_FLAG_ADR);
> + buf_addr1 += S5P_FIMV_ENC_COLFLG_SIZE;
> + buf_size1 -= S5P_FIMV_ENC_COLFLG_SIZE;
> + mfc_write(dev, OFFSETA(buf_addr1),
> + S5P_FIMV_H264_UP_INTRA_MD_ADR);
> + buf_addr1 += S5P_FIMV_ENC_INTRAMD_SIZE;
> + buf_size1 -= S5P_FIMV_ENC_INTRAMD_SIZE;
> + mfc_write(dev, OFFSETB(buf_addr2),
> + S5P_FIMV_H264_UP_INTRA_PRED_ADR);
> + buf_addr2 += S5P_FIMV_ENC_INTRAPRED_SIZE;
> + buf_size2 -= S5P_FIMV_ENC_INTRAPRED_SIZE;
> + mfc_write(dev, OFFSETA(buf_addr1),
> + S5P_FIMV_H264_NBOR_INFO_ADR);
> + buf_addr1 += S5P_FIMV_ENC_NBORINFO_SIZE;
> + buf_size1 -= S5P_FIMV_ENC_NBORINFO_SIZE;
> + mfc_debug(2, "buf_size1: %d, buf_size2: %d\n",
> + buf_size1, buf_size2);
> + break;
> + case S5P_MFC_CODEC_MPEG4_ENC:
> + for (i = 0; i < 2; i++) {
> + mfc_write(dev, OFFSETA(buf_addr1),
> + S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
> + buf_addr1 += enc_ref_y_size;
> + buf_size1 -= enc_ref_y_size;
> + mfc_write(dev, OFFSETB(buf_addr2),
> + S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
> + buf_addr2 += enc_ref_y_size;
> + buf_size2 -= enc_ref_y_size;
> + }
> + for (i = 0; i < 4; i++) {
> + mfc_write(dev, OFFSETB(buf_addr2),
> + S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
> + buf_addr2 += enc_ref_c_size;
> + buf_size2 -= enc_ref_c_size;
> + }
> + mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_UP_MV_ADR);
> + buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
> + buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
> + mfc_write(dev, OFFSETA(buf_addr1),
> +
S5P_FIMV_MPEG4_COZERO_FLAG_ADR);
> + buf_addr1 += S5P_FIMV_ENC_COLFLG_SIZE;
> + buf_size1 -= S5P_FIMV_ENC_COLFLG_SIZE;
> + mfc_write(dev, OFFSETA(buf_addr1),
> + S5P_FIMV_MPEG4_ACDC_COEF_ADR);
> + buf_addr1 += S5P_FIMV_ENC_ACDCCOEF_SIZE;
> + buf_size1 -= S5P_FIMV_ENC_ACDCCOEF_SIZE;
> + mfc_debug(2, "buf_size1: %d, buf_size2: %d\n",
> + buf_size1, buf_size2);
> + break;
> + case S5P_MFC_CODEC_H263_ENC:
> + for (i = 0; i < 2; i++) {
> + mfc_write(dev, OFFSETA(buf_addr1),
> + S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
> + buf_addr1 += enc_ref_y_size;
> + buf_size1 -= enc_ref_y_size;
> + mfc_write(dev, OFFSETB(buf_addr2),
> + S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
> + buf_addr2 += enc_ref_y_size;
> + buf_size2 -= enc_ref_y_size;
> + }
> + for (i = 0; i < 4; i++) {
> + mfc_write(dev, OFFSETB(buf_addr2),
> + S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
> + buf_addr2 += enc_ref_c_size;
> + buf_size2 -= enc_ref_c_size;
> + }
> + mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_UP_MV_ADR);
> + buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
> + buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
> + mfc_write(dev, OFFSETA(buf_addr1),
S5P_FIMV_H263_ACDC_COEF_ADR);
> + buf_addr1 += S5P_FIMV_ENC_ACDCCOEF_SIZE;
> + buf_size1 -= S5P_FIMV_ENC_ACDCCOEF_SIZE;
> + mfc_debug(2, "buf_size1: %d, buf_size2: %d\n",
> + buf_size1, buf_size2);
> + break;
> + default:
> + mfc_err("Unknown codec set for encoding: %d\n",
> + ctx->codec_mode);
> + return -EINVAL;
> + }
> + return 0;
> +}
> +
> +static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_enc_params *p = &ctx->enc_params;
> + unsigned int reg;
> + unsigned int shm;
> +
> + /* width */
> + mfc_write(dev, ctx->img_width, S5P_FIMV_ENC_HSIZE_PX);
> + /* height */
> + mfc_write(dev, ctx->img_height, S5P_FIMV_ENC_VSIZE_PX);
> + /* pictype : enable, IDR period */
> + reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
> + reg |= (1 << 18);
> + reg &= ~(0xFFFF);
> + reg |= p->gop_size;
> + mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
> + mfc_write(dev, 0, S5P_FIMV_ENC_B_RECON_WRITE_ON);
> + /* multi-slice control */
> + /* multi-slice MB number or bit size */
> + mfc_write(dev, p->slice_mode, S5P_FIMV_ENC_MSLICE_CTRL);
> + if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) {
> + mfc_write(dev, p->slice_mb, S5P_FIMV_ENC_MSLICE_MB);
> + } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES)
{
> + mfc_write(dev, p->slice_bit, S5P_FIMV_ENC_MSLICE_BIT);
> + } else {
> + mfc_write(dev, 0, S5P_FIMV_ENC_MSLICE_MB);
> + mfc_write(dev, 0, S5P_FIMV_ENC_MSLICE_BIT);
> + }
> + /* cyclic intra refresh */
> + mfc_write(dev, p->intra_refresh_mb, S5P_FIMV_ENC_CIR_CTRL);
> + /* memory structure cur. frame */
> + if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M)
> + mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR);
> + else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT)
> + mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR);
> + /* padding control & value */
> + reg = mfc_read(dev, S5P_FIMV_ENC_PADDING_CTRL);
> + if (p->pad) {
> + /** enable */
> + reg |= (1 << 31);
> + /** cr value */
> + reg &= ~(0xFF << 16);
> + reg |= (p->pad_cr << 16);
> + /** cb value */
> + reg &= ~(0xFF << 8);
> + reg |= (p->pad_cb << 8);
> + /** y value */
> + reg &= ~(0xFF);
> + reg |= (p->pad_luma);
> + } else {
> + /** disable & all value clear */
> + reg = 0;
> + }
> + mfc_write(dev, reg, S5P_FIMV_ENC_PADDING_CTRL);
> + /* rate control config. */
> + reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
> + /** frame-level rate control */
> + reg &= ~(0x1 << 9);
> + reg |= (p->rc_frame << 9);
> + mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
> + /* bit rate */
> + if (p->rc_frame)
> + mfc_write(dev, p->rc_bitrate,
> + S5P_FIMV_ENC_RC_BIT_RATE);
> + else
> + mfc_write(dev, 0, S5P_FIMV_ENC_RC_BIT_RATE);
> + /* reaction coefficient */
> + if (p->rc_frame)
> + mfc_write(dev, p->rc_reaction_coeff, S5P_FIMV_ENC_RC_RPARA);
> + shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
> + /* seq header ctrl */
> + shm &= ~(0x1 << 3);
> + shm |= (p->seq_hdr_mode << 3);
> + /* frame skip mode */
> + shm &= ~(0x3 << 1);
> + shm |= (p->frame_skip_mode << 1);
> + s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
> + /* fixed target bit */
> + s5p_mfc_write_info_v5(ctx, p->fixed_target_bit, RC_CONTROL_CONFIG);
> + return 0;
> +}
> +
> +static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_enc_params *p = &ctx->enc_params;
> + struct s5p_mfc_h264_enc_params *p_264 = &p->codec.h264;
> + unsigned int reg;
> + unsigned int shm;
> +
> + s5p_mfc_set_enc_params(ctx);
> + /* pictype : number of B */
> + reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
> + /* num_b_frame - 0 ~ 2 */
> + reg &= ~(0x3 << 16);
> + reg |= (p->num_b_frame << 16);
> + mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
> + /* profile & level */
> + reg = mfc_read(dev, S5P_FIMV_ENC_PROFILE);
> + /* level */
> + reg &= ~(0xFF << 8);
> + reg |= (p_264->level << 8);
> + /* profile - 0 ~ 2 */
> + reg &= ~(0x3F);
> + reg |= p_264->profile;
> + mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE);
> + /* interlace */
> + mfc_write(dev, p->interlace, S5P_FIMV_ENC_PIC_STRUCT);
> + /* height */
> + if (p->interlace)
> + mfc_write(dev, ctx->img_height >> 1, S5P_FIMV_ENC_VSIZE_PX);
> + /* loopfilter ctrl */
> + mfc_write(dev, p_264->loop_filter_mode, S5P_FIMV_ENC_LF_CTRL);
> + /* loopfilter alpha offset */
> + if (p_264->loop_filter_alpha < 0) {
> + reg = 0x10;
> + reg |= (0xFF - p_264->loop_filter_alpha) + 1;
> + } else {
> + reg = 0x00;
> + reg |= (p_264->loop_filter_alpha & 0xF);
> + }
> + mfc_write(dev, reg, S5P_FIMV_ENC_ALPHA_OFF);
> + /* loopfilter beta offset */
> + if (p_264->loop_filter_beta < 0) {
> + reg = 0x10;
> + reg |= (0xFF - p_264->loop_filter_beta) + 1;
> + } else {
> + reg = 0x00;
> + reg |= (p_264->loop_filter_beta & 0xF);
> + }
> + mfc_write(dev, reg, S5P_FIMV_ENC_BETA_OFF);
> + /* entropy coding mode */
> + if (p_264->entropy_mode == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC)
> + mfc_write(dev, 1, S5P_FIMV_ENC_H264_ENTROPY_MODE);
> + else
> + mfc_write(dev, 0, S5P_FIMV_ENC_H264_ENTROPY_MODE);
> + /* number of ref. picture */
> + reg = mfc_read(dev, S5P_FIMV_ENC_H264_NUM_OF_REF);
> + /* num of ref. pictures of P */
> + reg &= ~(0x3 << 5);
> + reg |= (p_264->num_ref_pic_4p << 5);
> + /* max number of ref. pictures */
> + reg &= ~(0x1F);
> + reg |= p_264->max_ref_pic;
> + mfc_write(dev, reg, S5P_FIMV_ENC_H264_NUM_OF_REF);
> + /* 8x8 transform enable */
> + mfc_write(dev, p_264->_8x8_transform, S5P_FIMV_ENC_H264_TRANS_FLAG);
> + /* rate control config. */
> + reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
> + /* macroblock level rate control */
> + reg &= ~(0x1 << 8);
> + reg |= (p_264->rc_mb << 8);
> + /* frame QP */
> + reg &= ~(0x3F);
> + reg |= p_264->rc_frame_qp;
> + mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
> + /* frame rate */
> + if (p->rc_frame && p->rc_framerate_denom)
> + mfc_write(dev, p->rc_framerate_num * 1000
> + / p->rc_framerate_denom, S5P_FIMV_ENC_RC_FRAME_RATE);
> + else
> + mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
> + /* max & min value of QP */
> + reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
> + /* max QP */
> + reg &= ~(0x3F << 8);
> + reg |= (p_264->rc_max_qp << 8);
> + /* min QP */
> + reg &= ~(0x3F);
> + reg |= p_264->rc_min_qp;
> + mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
> + /* macroblock adaptive scaling features */
> + if (p_264->rc_mb) {
> + reg = mfc_read(dev, S5P_FIMV_ENC_RC_MB_CTRL);
> + /* dark region */
> + reg &= ~(0x1 << 3);
> + reg |= (p_264->rc_mb_dark << 3);
> + /* smooth region */
> + reg &= ~(0x1 << 2);
> + reg |= (p_264->rc_mb_smooth << 2);
> + /* static region */
> + reg &= ~(0x1 << 1);
> + reg |= (p_264->rc_mb_static << 1);
> + /* high activity region */
> + reg &= ~(0x1);
> + reg |= p_264->rc_mb_activity;
> + mfc_write(dev, reg, S5P_FIMV_ENC_RC_MB_CTRL);
> + }
> + if (!p->rc_frame &&
> + !p_264->rc_mb) {
> + shm = s5p_mfc_read_info_v5(ctx, P_B_FRAME_QP);
> + shm &= ~(0xFFF);
> + shm |= ((p_264->rc_b_frame_qp & 0x3F) << 6);
> + shm |= (p_264->rc_p_frame_qp & 0x3F);
> + s5p_mfc_write_info_v5(ctx, shm, P_B_FRAME_QP);
> + }
> + /* extended encoder ctrl */
> + shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
> + /* AR VUI control */
> + shm &= ~(0x1 << 15);
> + shm |= (p_264->vui_sar << 1);
> + s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
> + if (p_264->vui_sar) {
> + /* aspect ration IDC */
> + shm = s5p_mfc_read_info_v5(ctx, SAMPLE_ASPECT_RATIO_IDC);
> + shm &= ~(0xFF);
> + shm |= p_264->vui_sar_idc;
> + s5p_mfc_write_info_v5(ctx, shm, SAMPLE_ASPECT_RATIO_IDC);
> + if (p_264->vui_sar_idc == 0xFF) {
> + /* sample AR info */
> + shm = s5p_mfc_read_info_v5(ctx, EXTENDED_SAR);
> + shm &= ~(0xFFFFFFFF);
> + shm |= p_264->vui_ext_sar_width << 16;
> + shm |= p_264->vui_ext_sar_height;
> + s5p_mfc_write_info_v5(ctx, shm, EXTENDED_SAR);
> + }
> + }
> + /* intra picture period for H.264 */
> + shm = s5p_mfc_read_info_v5(ctx, H264_I_PERIOD);
> + /* control */
> + shm &= ~(0x1 << 16);
> + shm |= (p_264->open_gop << 16);
> + /* value */
> + if (p_264->open_gop) {
> + shm &= ~(0xFFFF);
> + shm |= p_264->open_gop_size;
> + }
> + s5p_mfc_write_info_v5(ctx, shm, H264_I_PERIOD);
> + /* extended encoder ctrl */
> + shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
> + /* vbv buffer size */
> + if (p->frame_skip_mode ==
> + V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
> + shm &= ~(0xFFFF << 16);
> + shm |= (p_264->cpb_size << 16);
> + }
> + s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
> + return 0;
> +}
> +
> +static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_enc_params *p = &ctx->enc_params;
> + struct s5p_mfc_mpeg4_enc_params *p_mpeg4 = &p->codec.mpeg4;
> + unsigned int reg;
> + unsigned int shm;
> + unsigned int framerate;
> +
> + s5p_mfc_set_enc_params(ctx);
> + /* pictype : number of B */
> + reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
> + /* num_b_frame - 0 ~ 2 */
> + reg &= ~(0x3 << 16);
> + reg |= (p->num_b_frame << 16);
> + mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
> + /* profile & level */
> + reg = mfc_read(dev, S5P_FIMV_ENC_PROFILE);
> + /* level */
> + reg &= ~(0xFF << 8);
> + reg |= (p_mpeg4->level << 8);
> + /* profile - 0 ~ 2 */
> + reg &= ~(0x3F);
> + reg |= p_mpeg4->profile;
> + mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE);
> + /* quarter_pixel */
> + mfc_write(dev, p_mpeg4->quarter_pixel, S5P_FIMV_ENC_MPEG4_QUART_PXL);
> + /* qp */
> + if (!p->rc_frame) {
> + shm = s5p_mfc_read_info_v5(ctx, P_B_FRAME_QP);
> + shm &= ~(0xFFF);
> + shm |= ((p_mpeg4->rc_b_frame_qp & 0x3F) << 6);
> + shm |= (p_mpeg4->rc_p_frame_qp & 0x3F);
> + s5p_mfc_write_info_v5(ctx, shm, P_B_FRAME_QP);
> + }
> + /* frame rate */
> + if (p->rc_frame) {
> + if (p->rc_framerate_denom > 0) {
> + framerate = p->rc_framerate_num * 1000 /
> + p->rc_framerate_denom;
> + mfc_write(dev, framerate,
> + S5P_FIMV_ENC_RC_FRAME_RATE);
> + shm = s5p_mfc_read_info_v5(ctx, RC_VOP_TIMING);
> + shm &= ~(0xFFFFFFFF);
> + shm |= (1 << 31);
> + shm |= ((p->rc_framerate_num & 0x7FFF) << 16);
> + shm |= (p->rc_framerate_denom & 0xFFFF);
> + s5p_mfc_write_info_v5(ctx, shm, RC_VOP_TIMING);
> + }
> + } else {
> + mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
> + }
> + /* rate control config. */
> + reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
> + /* frame QP */
> + reg &= ~(0x3F);
> + reg |= p_mpeg4->rc_frame_qp;
> + mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
> + /* max & min value of QP */
> + reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
> + /* max QP */
> + reg &= ~(0x3F << 8);
> + reg |= (p_mpeg4->rc_max_qp << 8);
> + /* min QP */
> + reg &= ~(0x3F);
> + reg |= p_mpeg4->rc_min_qp;
> + mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
> + /* extended encoder ctrl */
> + shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
> + /* vbv buffer size */
> + if (p->frame_skip_mode ==
> + V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
> + shm &= ~(0xFFFF << 16);
> + shm |= (p->vbv_size << 16);
> + }
> + s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
> + return 0;
> +}
> +
> +static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_enc_params *p = &ctx->enc_params;
> + struct s5p_mfc_mpeg4_enc_params *p_h263 = &p->codec.mpeg4;
> + unsigned int reg;
> + unsigned int shm;
> +
> + s5p_mfc_set_enc_params(ctx);
> + /* qp */
> + if (!p->rc_frame) {
> + shm = s5p_mfc_read_info_v5(ctx, P_B_FRAME_QP);
> + shm &= ~(0xFFF);
> + shm |= (p_h263->rc_p_frame_qp & 0x3F);
> + s5p_mfc_write_info_v5(ctx, shm, P_B_FRAME_QP);
> + }
> + /* frame rate */
> + if (p->rc_frame && p->rc_framerate_denom)
> + mfc_write(dev, p->rc_framerate_num * 1000
> + / p->rc_framerate_denom, S5P_FIMV_ENC_RC_FRAME_RATE);
> + else
> + mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
> + /* rate control config. */
> + reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
> + /* frame QP */
> + reg &= ~(0x3F);
> + reg |= p_h263->rc_frame_qp;
> + mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
> + /* max & min value of QP */
> + reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
> + /* max QP */
> + reg &= ~(0x3F << 8);
> + reg |= (p_h263->rc_max_qp << 8);
> + /* min QP */
> + reg &= ~(0x3F);
> + reg |= p_h263->rc_min_qp;
> + mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
> + /* extended encoder ctrl */
> + shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
> + /* vbv buffer size */
> + if (p->frame_skip_mode ==
> + V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
> + shm &= ~(0xFFFF << 16);
> + shm |= (p->vbv_size << 16);
> + }
> + s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
> + return 0;
> +}
> +
> +/* Initialize decoding */
> +int s5p_mfc_init_decode_v5(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> +
> + s5p_mfc_set_shared_buffer(ctx);
> + /* Setup loop filter, for decoding this is only valid for MPEG4 */
> + if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_DEC)
> + mfc_write(dev, ctx->loop_filter_mpeg4, S5P_FIMV_ENC_LF_CTRL);
> + else
> + mfc_write(dev, 0, S5P_FIMV_ENC_LF_CTRL);
> + mfc_write(dev, ((ctx->slice_interface & S5P_FIMV_SLICE_INT_MASK) <<
> + S5P_FIMV_SLICE_INT_SHIFT) | (ctx->display_delay_enable <<
> + S5P_FIMV_DDELAY_ENA_SHIFT) | ((ctx->display_delay &
> + S5P_FIMV_DDELAY_VAL_MASK) << S5P_FIMV_DDELAY_VAL_SHIFT),
> + S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
> + mfc_write(dev,
> + ((S5P_FIMV_CH_SEQ_HEADER & S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT)
> + | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
> + return 0;
> +}
> +
> +static void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + unsigned int dpb;
> +
> + if (flush)
> + dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) | (
> + S5P_FIMV_DPB_FLUSH_MASK << S5P_FIMV_DPB_FLUSH_SHIFT);
> + else
> + dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) &
> + ~(S5P_FIMV_DPB_FLUSH_MASK <<
S5P_FIMV_DPB_FLUSH_SHIFT);
> + mfc_write(dev, dpb, S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
> +}
> +
> +/* Decode a single frame */
> +int s5p_mfc_decode_one_frame_v5(struct s5p_mfc_ctx *ctx,
> + enum s5p_mfc_decode_arg last_frame)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> +
> + mfc_write(dev, ctx->dec_dst_flag, S5P_FIMV_SI_CH0_RELEASE_BUF);
> + s5p_mfc_set_shared_buffer(ctx);
> + s5p_mfc_set_flush(ctx, ctx->dpb_flush_flag);
> + /* Issue different commands to instance basing on whether it
> + * is the last frame or not. */
> + switch (last_frame) {
> + case MFC_DEC_FRAME:
> + mfc_write(dev, ((S5P_FIMV_CH_FRAME_START & S5P_FIMV_CH_MASK)
<<
> + S5P_FIMV_CH_SHIFT) | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
> + break;
> + case MFC_DEC_LAST_FRAME:
> + mfc_write(dev, ((S5P_FIMV_CH_LAST_FRAME & S5P_FIMV_CH_MASK) <<
> + S5P_FIMV_CH_SHIFT) | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
> + break;
> + case MFC_DEC_RES_CHANGE:
> + mfc_write(dev, ((S5P_FIMV_CH_FRAME_START_REALLOC &
> + S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT) | (ctx->inst_no),
> + S5P_FIMV_SI_CH0_INST_ID);
> + break;
> + }
> + mfc_debug(2, "Decoding a usual frame\n");
> + return 0;
> +}
> +
> +int s5p_mfc_init_encode_v5(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> +
> + if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC)
> + s5p_mfc_set_enc_params_h264(ctx);
> + else if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_ENC)
> + s5p_mfc_set_enc_params_mpeg4(ctx);
> + else if (ctx->codec_mode == S5P_MFC_CODEC_H263_ENC)
> + s5p_mfc_set_enc_params_h263(ctx);
> + else {
> + mfc_err("Unknown codec for encoding (%x)\n",
> + ctx->codec_mode);
> + return -EINVAL;
> + }
> + s5p_mfc_set_shared_buffer(ctx);
> + mfc_write(dev, ((S5P_FIMV_CH_SEQ_HEADER << 16) & 0x70000) |
> + (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
> + return 0;
> +}
> +
> +/* Encode a single frame */
> +int s5p_mfc_encode_one_frame_v5(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + /* memory structure cur. frame */
> + if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M)
> + mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR);
> + else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT)
> + mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR);
> + s5p_mfc_set_shared_buffer(ctx);
> + mfc_write(dev, (S5P_FIMV_CH_FRAME_START << 16 & 0x70000) |
> + (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
> + return 0;
> +}
> +
> +static int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev)
> +{
> + unsigned long flags;
> + int new_ctx;
> + int cnt;
> +
> + spin_lock_irqsave(&dev->condlock, flags);
> + new_ctx = (dev->curr_ctx + 1) % MFC_NUM_CONTEXTS;
> + cnt = 0;
> + while (!test_bit(new_ctx, &dev->ctx_work_bits)) {
> + new_ctx = (new_ctx + 1) % MFC_NUM_CONTEXTS;
> + if (++cnt > MFC_NUM_CONTEXTS) {
> + /* No contexts to run */
> + spin_unlock_irqrestore(&dev->condlock, flags);
> + return -EAGAIN;
> + }
> + }
> + spin_unlock_irqrestore(&dev->condlock, flags);
> + return new_ctx;
> +}
> +
> +static void s5p_mfc_run_res_change(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> +
> + s5p_mfc_set_dec_stream_buffer_v5(ctx, 0, 0, 0);
> + dev->curr_ctx = ctx->num;
> + s5p_mfc_clean_ctx_int_flags(ctx);
> + s5p_mfc_decode_one_frame_v5(ctx, MFC_DEC_RES_CHANGE);
> +}
> +
> +static int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx, int last_frame)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_buf *temp_vb;
> + unsigned long flags;
> + unsigned int index;
> +
> + spin_lock_irqsave(&dev->irqlock, flags);
> + /* Frames are being decoded */
> + if (list_empty(&ctx->src_queue)) {
> + mfc_debug(2, "No src buffers\n");
> + spin_unlock_irqrestore(&dev->irqlock, flags);
> + return -EAGAIN;
> + }
> + /* Get the next source buffer */
> + temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
> + temp_vb->used = 1;
> + s5p_mfc_set_dec_stream_buffer_v5(ctx,
> + vb2_dma_contig_plane_dma_addr(temp_vb->b, 0),
> + ctx->consumed_stream,
> + temp_vb->b->v4l2_planes[0].bytesused);
> + spin_unlock_irqrestore(&dev->irqlock, flags);
> + index = temp_vb->b->v4l2_buf.index;
> + dev->curr_ctx = ctx->num;
> + s5p_mfc_clean_ctx_int_flags(ctx);
> + if (temp_vb->b->v4l2_planes[0].bytesused == 0) {
> + last_frame = MFC_DEC_LAST_FRAME;
> + mfc_debug(2, "Setting ctx->state to FINISHING\n");
> + ctx->state = MFCINST_FINISHING;
> + }
> + s5p_mfc_decode_one_frame_v5(ctx, last_frame);
> + return 0;
> +}
> +
> +static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + unsigned long flags;
> + struct s5p_mfc_buf *dst_mb;
> + struct s5p_mfc_buf *src_mb;
> + unsigned long src_y_addr, src_c_addr, dst_addr;
> + unsigned int dst_size;
> +
> + spin_lock_irqsave(&dev->irqlock, flags);
> + if (list_empty(&ctx->src_queue)) {
> + mfc_debug(2, "no src buffers\n");
> + spin_unlock_irqrestore(&dev->irqlock, flags);
> + return -EAGAIN;
> + }
> + if (list_empty(&ctx->dst_queue)) {
> + mfc_debug(2, "no dst buffers\n");
> + spin_unlock_irqrestore(&dev->irqlock, flags);
> + return -EAGAIN;
> + }
> + src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
> + src_mb->used = 1;
> + src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 0);
> + src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1);
> + s5p_mfc_set_enc_frame_buffer_v5(ctx, src_y_addr, src_c_addr);
> + dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
> + dst_mb->used = 1;
> + dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
> + dst_size = vb2_plane_size(dst_mb->b, 0);
> + s5p_mfc_set_enc_stream_buffer_v5(ctx, dst_addr, dst_size);
> + spin_unlock_irqrestore(&dev->irqlock, flags);
> + dev->curr_ctx = ctx->num;
> + s5p_mfc_clean_ctx_int_flags(ctx);
> + s5p_mfc_encode_one_frame_v5(ctx);
> + return 0;
> +}
> +
> +static void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + unsigned long flags;
> + struct s5p_mfc_buf *temp_vb;
> +
> + /* Initializing decoding - parsing header */
> + spin_lock_irqsave(&dev->irqlock, flags);
> + mfc_debug(2, "Preparing to init decoding\n");
> + temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
> + s5p_mfc_set_dec_desc_buffer(ctx);
> + mfc_debug(2, "Header size: %d\n",
temp_vb->b->v4l2_planes[0].bytesused);
> + s5p_mfc_set_dec_stream_buffer_v5(ctx,
> + vb2_dma_contig_plane_dma_addr(temp_vb->b, 0),
> + 0, temp_vb->b->v4l2_planes[0].bytesused);
> + spin_unlock_irqrestore(&dev->irqlock, flags);
> + dev->curr_ctx = ctx->num;
> + s5p_mfc_clean_ctx_int_flags(ctx);
> + s5p_mfc_init_decode_v5(ctx);
> +}
> +
> +static void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + unsigned long flags;
> + struct s5p_mfc_buf *dst_mb;
> + unsigned long dst_addr;
> + unsigned int dst_size;
> +
> + s5p_mfc_set_enc_ref_buffer_v5(ctx);
> + spin_lock_irqsave(&dev->irqlock, flags);
> + dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
> + dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
> + dst_size = vb2_plane_size(dst_mb->b, 0);
> + s5p_mfc_set_enc_stream_buffer_v5(ctx, dst_addr, dst_size);
> + spin_unlock_irqrestore(&dev->irqlock, flags);
> + dev->curr_ctx = ctx->num;
> + s5p_mfc_clean_ctx_int_flags(ctx);
> + s5p_mfc_init_encode_v5(ctx);
> +}
> +
> +static int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + unsigned long flags;
> + struct s5p_mfc_buf *temp_vb;
> + int ret;
> +
> + /*
> + * Header was parsed now starting processing
> + * First set the output frame buffers
> + */
> + if (ctx->capture_state != QUEUE_BUFS_MMAPED) {
> + mfc_err("It seems that not all destionation buffers were\n"
> + "mmaped\nMFC requires that all destination are\n"
> + "mmaped before starting processing\n");
> + return -EAGAIN;
> + }
> + spin_lock_irqsave(&dev->irqlock, flags);
> + if (list_empty(&ctx->src_queue)) {
> + mfc_err("Header has been deallocated in the middle of\n"
> + " initialization\n");
> + spin_unlock_irqrestore(&dev->irqlock, flags);
> + return -EIO;
> + }
> + temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
> + mfc_debug(2, "Header size: %d\n",
temp_vb->b->v4l2_planes[0].bytesused);
> + s5p_mfc_set_dec_stream_buffer_v5(ctx,
> + vb2_dma_contig_plane_dma_addr(temp_vb->b, 0),
> + 0, temp_vb->b->v4l2_planes[0].bytesused);
> + spin_unlock_irqrestore(&dev->irqlock, flags);
> + dev->curr_ctx = ctx->num;
> + s5p_mfc_clean_ctx_int_flags(ctx);
> + ret = s5p_mfc_set_dec_frame_buffer_v5(ctx);
> + if (ret) {
> + mfc_err("Failed to alloc frame mem\n");
> + ctx->state = MFCINST_ERROR;
> + }
> + return ret;
> +}
> +
> +/* Try running an operation on hardware */
> +void s5p_mfc_try_run_v5(struct s5p_mfc_dev *dev)
> +{
> + struct s5p_mfc_ctx *ctx;
> + int new_ctx;
> + unsigned int ret = 0;
> +
> + if (test_bit(0, &dev->enter_suspend)) {
> + mfc_debug(1, "Entering suspend so do not schedule any
jobs\n");
> + return;
> + }
> + /* Check whether hardware is not running */
> + if (test_and_set_bit(0, &dev->hw_lock) != 0) {
> + /* This is perfectly ok, the scheduled ctx should wait */
> + mfc_debug(1, "Couldn't lock HW\n");
> + return;
> + }
> + /* Choose the context to run */
> + new_ctx = s5p_mfc_get_new_ctx(dev);
> + if (new_ctx < 0) {
> + /* No contexts to run */
> + if (test_and_clear_bit(0, &dev->hw_lock) == 0) {
> + mfc_err("Failed to unlock hardware\n");
> + return;
> + }
> + mfc_debug(1, "No ctx is scheduled to be run\n");
> + return;
> + }
> + ctx = dev->ctx[new_ctx];
> + /* Got context to run in ctx */
> + /*
> + * Last frame has already been sent to MFC.
> + * Now obtaining frames from MFC buffer
> + */
> + s5p_mfc_clock_on();
> + if (ctx->type == MFCINST_DECODER) {
> + s5p_mfc_set_dec_desc_buffer(ctx);
> + switch (ctx->state) {
> + case MFCINST_FINISHING:
> + s5p_mfc_run_dec_frame(ctx, MFC_DEC_LAST_FRAME);
> + break;
> + case MFCINST_RUNNING:
> + ret = s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME);
> + break;
> + case MFCINST_INIT:
> + s5p_mfc_clean_ctx_int_flags(ctx);
> + ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
> + ctx);
> + break;
> + case MFCINST_RETURN_INST:
> + s5p_mfc_clean_ctx_int_flags(ctx);
> + ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
> + ctx);
> + break;
> + case MFCINST_GOT_INST:
> + s5p_mfc_run_init_dec(ctx);
> + break;
> + case MFCINST_HEAD_PARSED:
> + ret = s5p_mfc_run_init_dec_buffers(ctx);
> + mfc_debug(1, "head parsed\n");
> + break;
> + case MFCINST_RES_CHANGE_INIT:
> + s5p_mfc_run_res_change(ctx);
> + break;
> + case MFCINST_RES_CHANGE_FLUSH:
> + s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME);
> + break;
> + case MFCINST_RES_CHANGE_END:
> + mfc_debug(2, "Finished remaining frames after
resolution
> change\n");
> + ctx->capture_state = QUEUE_FREE;
> + mfc_debug(2, "Will re-init the codec\n");
> + s5p_mfc_run_init_dec(ctx);
> + break;
> + default:
> + ret = -EAGAIN;
> + }
> + } else if (ctx->type == MFCINST_ENCODER) {
> + switch (ctx->state) {
> + case MFCINST_FINISHING:
> + case MFCINST_RUNNING:
> + ret = s5p_mfc_run_enc_frame(ctx);
> + break;
> + case MFCINST_INIT:
> + s5p_mfc_clean_ctx_int_flags(ctx);
> + ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
> + ctx);
> + break;
> + case MFCINST_RETURN_INST:
> + s5p_mfc_clean_ctx_int_flags(ctx);
> + ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
> + ctx);
> + break;
> + case MFCINST_GOT_INST:
> + s5p_mfc_run_init_enc(ctx);
> + break;
> + default:
> + ret = -EAGAIN;
> + }
> + } else {
> + mfc_err("Invalid context type: %d\n", ctx->type);
> + ret = -EAGAIN;
> + }
> +
> + if (ret) {
> + /* Free hardware lock */
> + if (test_and_clear_bit(0, &dev->hw_lock) == 0)
> + mfc_err("Failed to unlock hardware\n");
> +
> + /* This is in deed imporant, as no operation has been
> + * scheduled, reduce the clock count as no one will
> + * ever do this, because no interrupt related to this try_run
> + * will ever come from hardware. */
> + s5p_mfc_clock_off();
> + }
> +}
> +
> +
> +void s5p_mfc_cleanup_queue_v5(struct list_head *lh, struct vb2_queue *vq)
> +{
> + struct s5p_mfc_buf *b;
> + int i;
> +
> + while (!list_empty(lh)) {
> + b = list_entry(lh->next, struct s5p_mfc_buf, list);
> + for (i = 0; i < b->b->num_planes; i++)
> + vb2_set_plane_payload(b->b, i, 0);
> + vb2_buffer_done(b->b, VB2_BUF_STATE_ERROR);
> + list_del(&b->list);
> + }
> +}
> +
> +void s5p_mfc_clear_int_flags_v5(struct s5p_mfc_dev *dev)
> +{
> + mfc_write(dev, 0, S5P_FIMV_RISC_HOST_INT);
> + mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
> + mfc_write(dev, 0xffff, S5P_FIMV_SI_RTN_CHID);
> +}
> +
> +int s5p_mfc_get_dspl_y_adr_v5(struct s5p_mfc_dev *dev)
> +{
> + return mfc_read(dev, S5P_FIMV_SI_DISPLAY_Y_ADR) << MFC_OFFSET_SHIFT;
> +}
> +
> +int s5p_mfc_get_dec_y_adr_v5(struct s5p_mfc_dev *dev)
> +{
> + return mfc_read(dev, S5P_FIMV_SI_DECODE_Y_ADR) << MFC_OFFSET_SHIFT;
> +}
> +
> +int s5p_mfc_get_dspl_status_v5(struct s5p_mfc_dev *dev)
> +{
> + return mfc_read(dev, S5P_FIMV_SI_DISPLAY_STATUS);
> +}
> +
> +int s5p_mfc_get_dec_status_v5(struct s5p_mfc_dev *dev)
> +{
> + return mfc_read(dev, S5P_FIMV_SI_DECODE_STATUS);
> +}
> +
> +int s5p_mfc_get_dec_frame_type_v5(struct s5p_mfc_dev *dev)
> +{
> + return mfc_read(dev, S5P_FIMV_DECODE_FRAME_TYPE) &
> + S5P_FIMV_DECODE_FRAME_MASK;
> +}
> +
> +int s5p_mfc_get_disp_frame_type_v5(struct s5p_mfc_ctx *ctx)
> +{
> + /* NOP */
> + return -1;
> +}
> +
> +int s5p_mfc_get_consumed_stream_v5(struct s5p_mfc_dev *dev)
> +{
> + return mfc_read(dev, S5P_FIMV_SI_CONSUMED_BYTES);
> +}
> +
> +int s5p_mfc_get_int_reason_v5(struct s5p_mfc_dev *dev)
> +{
> + int reason;
> + reason = mfc_read(dev, S5P_FIMV_RISC2HOST_CMD) &
> + S5P_FIMV_RISC2HOST_CMD_MASK;
> + switch (reason) {
> + case S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET:
> + reason = S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET;
> + break;
> + case S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET:
> + reason = S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET;
> + break;
> + case S5P_FIMV_R2H_CMD_SEQ_DONE_RET:
> + reason = S5P_MFC_R2H_CMD_SEQ_DONE_RET;
> + break;
> + case S5P_FIMV_R2H_CMD_FRAME_DONE_RET:
> + reason = S5P_MFC_R2H_CMD_FRAME_DONE_RET;
> + break;
> + case S5P_FIMV_R2H_CMD_SLICE_DONE_RET:
> + reason = S5P_MFC_R2H_CMD_SLICE_DONE_RET;
> + break;
> + case S5P_FIMV_R2H_CMD_SYS_INIT_RET:
> + reason = S5P_MFC_R2H_CMD_SYS_INIT_RET;
> + break;
> + case S5P_FIMV_R2H_CMD_FW_STATUS_RET:
> + reason = S5P_MFC_R2H_CMD_FW_STATUS_RET;
> + break;
> + case S5P_FIMV_R2H_CMD_SLEEP_RET:
> + reason = S5P_MFC_R2H_CMD_SLEEP_RET;
> + break;
> + case S5P_FIMV_R2H_CMD_WAKEUP_RET:
> + reason = S5P_MFC_R2H_CMD_WAKEUP_RET;
> + break;
> + case S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET:
> + reason = S5P_MFC_R2H_CMD_INIT_BUFFERS_RET;
> + break;
> + case S5P_FIMV_R2H_CMD_ERR_RET:
> + reason = S5P_MFC_R2H_CMD_ERR_RET;
> + break;
> + default:
> + reason = S5P_MFC_R2H_CMD_EMPTY;
> + };
> + return reason;
> +}
> +
> +int s5p_mfc_get_int_err_v5(struct s5p_mfc_dev *dev)
> +{
> + return mfc_read(dev, S5P_FIMV_RISC2HOST_ARG2);
> +}
> +
> +int s5p_mfc_err_dec_v5(unsigned int err)
> +{
> + return (err & S5P_FIMV_ERR_DEC_MASK) >> S5P_FIMV_ERR_DEC_SHIFT;
> +}
> +
> +int s5p_mfc_err_dspl_v5(unsigned int err)
> +{
> + return (err & S5P_FIMV_ERR_DSPL_MASK) >> S5P_FIMV_ERR_DSPL_SHIFT;
> +}
> +
> +int s5p_mfc_get_img_width_v5(struct s5p_mfc_dev *dev)
> +{
> + return mfc_read(dev, S5P_FIMV_SI_HRESOL);
> +}
> +
> +int s5p_mfc_get_img_height_v5(struct s5p_mfc_dev *dev)
> +{
> + return mfc_read(dev, S5P_FIMV_SI_VRESOL);
> +}
> +
> +int s5p_mfc_get_dpb_count_v5(struct s5p_mfc_dev *dev)
> +{
> + return mfc_read(dev, S5P_FIMV_SI_BUF_NUMBER);
> +}
> +
> +int s5p_mfc_get_mv_count_v5(struct s5p_mfc_dev *dev)
> +{
> + /* NOP */
> + return -1;
> +}
> +
> +int s5p_mfc_get_inst_no_v5(struct s5p_mfc_dev *dev)
> +{
> + return mfc_read(dev, S5P_FIMV_RISC2HOST_ARG1);
> +}
> +
> +int s5p_mfc_get_enc_strm_size_v5(struct s5p_mfc_dev *dev)
> +{
> + return mfc_read(dev, S5P_FIMV_ENC_SI_STRM_SIZE);
> +}
> +
> +int s5p_mfc_get_enc_slice_type_v5(struct s5p_mfc_dev *dev)
> +{
> + return mfc_read(dev, S5P_FIMV_ENC_SI_SLICE_TYPE);
> +}
> +
> +int s5p_mfc_get_enc_dpb_count_v5(struct s5p_mfc_dev *dev)
> +{
> + return -1;
> +}
> +
> +int s5p_mfc_get_enc_pic_count_v5(struct s5p_mfc_dev *dev)
> +{
> + return mfc_read(dev, S5P_FIMV_ENC_SI_PIC_CNT);
> +}
> +
> +int s5p_mfc_get_sei_avail_status_v5(struct s5p_mfc_ctx *ctx)
> +{
> + return s5p_mfc_read_info_v5(ctx, FRAME_PACK_SEI_AVAIL);
> +}
> +
> +int s5p_mfc_get_mvc_num_views_v5(struct s5p_mfc_dev *dev)
> +{
> + return -1;
> +}
> +
> +int s5p_mfc_get_mvc_view_id_v5(struct s5p_mfc_dev *dev)
> +{
> + return -1;
> +}
> +
> +unsigned int s5p_mfc_get_pic_type_top_v5(struct s5p_mfc_ctx *ctx)
> +{
> + return s5p_mfc_read_info_v5(ctx, PIC_TIME_TOP);
> +}
> +
> +unsigned int s5p_mfc_get_pic_type_bot_v5(struct s5p_mfc_ctx *ctx)
> +{
> + return s5p_mfc_read_info_v5(ctx, PIC_TIME_BOT);
> +}
> +
> +unsigned int s5p_mfc_get_crop_info_h_v5(struct s5p_mfc_ctx *ctx)
> +{
> + return s5p_mfc_read_info_v5(ctx, CROP_INFO_H);
> +}
> +
> +unsigned int s5p_mfc_get_crop_info_v_v5(struct s5p_mfc_ctx *ctx)
> +{
> + return s5p_mfc_read_info_v5(ctx, CROP_INFO_V);
> +}
> +
> +/* Initialize opr function pointers for MFC v5 */
> +static struct s5p_mfc_hw_ops s5p_mfc_ops_v5 = {
> + .alloc_dec_temp_buffers = s5p_mfc_alloc_dec_temp_buffers_v5,
> + .release_dec_desc_buffer = s5p_mfc_release_dec_desc_buffer_v5,
> + .alloc_codec_buffers = s5p_mfc_alloc_codec_buffers_v5,
> + .release_codec_buffers = s5p_mfc_release_codec_buffers_v5,
> + .alloc_instance_buffer = s5p_mfc_alloc_instance_buffer_v5,
> + .release_instance_buffer = s5p_mfc_release_instance_buffer_v5,
> + .alloc_dev_context_buffer = s5p_mfc_alloc_dev_context_buffer_v5,
> + .release_dev_context_buffer = s5p_mfc_release_dev_context_buffer_v5,
> + .dec_calc_dpb_size = s5p_mfc_dec_calc_dpb_size_v5,
> + .enc_calc_src_size = s5p_mfc_enc_calc_src_size_v5,
> + .set_dec_stream_buffer = s5p_mfc_set_dec_stream_buffer_v5,
> + .set_dec_frame_buffer = s5p_mfc_set_dec_frame_buffer_v5,
> + .set_enc_stream_buffer = s5p_mfc_set_enc_stream_buffer_v5,
> + .set_enc_frame_buffer = s5p_mfc_set_enc_frame_buffer_v5,
> + .get_enc_frame_buffer = s5p_mfc_get_enc_frame_buffer_v5,
> + .set_enc_ref_buffer = s5p_mfc_set_enc_ref_buffer_v5,
> + .init_decode = s5p_mfc_init_decode_v5,
> + .init_encode = s5p_mfc_init_encode_v5,
> + .encode_one_frame = s5p_mfc_encode_one_frame_v5,
> + .try_run = s5p_mfc_try_run_v5,
> + .cleanup_queue = s5p_mfc_cleanup_queue_v5,
> + .clear_int_flags = s5p_mfc_clear_int_flags_v5,
> + .write_info = s5p_mfc_write_info_v5,
> + .read_info = s5p_mfc_read_info_v5,
> + .get_dspl_y_adr = s5p_mfc_get_dspl_y_adr_v5,
> + .get_dec_y_adr = s5p_mfc_get_dec_y_adr_v5,
> + .get_dspl_status = s5p_mfc_get_dspl_status_v5,
> + .get_dec_status = s5p_mfc_get_dec_status_v5,
> + .get_dec_frame_type = s5p_mfc_get_dec_frame_type_v5,
> + .get_disp_frame_type = s5p_mfc_get_disp_frame_type_v5,
> + .get_consumed_stream = s5p_mfc_get_consumed_stream_v5,
> + .get_int_reason = s5p_mfc_get_int_reason_v5,
> + .get_int_err = s5p_mfc_get_int_err_v5,
> + .err_dec = s5p_mfc_err_dec_v5,
> + .err_dspl = s5p_mfc_err_dspl_v5,
> + .get_img_width = s5p_mfc_get_img_width_v5,
> + .get_img_height = s5p_mfc_get_img_height_v5,
> + .get_dpb_count = s5p_mfc_get_dpb_count_v5,
> + .get_mv_count = s5p_mfc_get_mv_count_v5,
> + .get_inst_no = s5p_mfc_get_inst_no_v5,
> + .get_enc_strm_size = s5p_mfc_get_enc_strm_size_v5,
> + .get_enc_slice_type = s5p_mfc_get_enc_slice_type_v5,
> + .get_enc_dpb_count = s5p_mfc_get_enc_dpb_count_v5,
> + .get_enc_pic_count = s5p_mfc_get_enc_pic_count_v5,
> + .get_sei_avail_status = s5p_mfc_get_sei_avail_status_v5,
> + .get_mvc_num_views = s5p_mfc_get_mvc_num_views_v5,
> + .get_mvc_view_id = s5p_mfc_get_mvc_view_id_v5,
> + .get_pic_type_top = s5p_mfc_get_pic_type_top_v5,
> + .get_pic_type_bot = s5p_mfc_get_pic_type_bot_v5,
> + .get_crop_info_h = s5p_mfc_get_crop_info_h_v5,
> + .get_crop_info_v = s5p_mfc_get_crop_info_v_v5,
> +};
> +
> +struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v5(void)
> +{
> + return &s5p_mfc_ops_v5;
> +}
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.h
> b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.h
> new file mode 100644
> index 0000000..19917de
> --- /dev/null
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.h
> @@ -0,0 +1,85 @@
> +/*
> + * drivers/media/video/samsung/mfc5/s5p_mfc_opr_v5.h
> + *
> + * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
> + * Contains declarations of hw related functions.
> + *
> + * Kamil Debski, Copyright (C) 2012 Samsung Electronics Co., Ltd.
> + * http://www.samsung.com/
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef S5P_MFC_OPR_V5_H_
> +#define S5P_MFC_OPR_V5_H_
> +
> +#include "s5p_mfc_common.h"
> +#include "s5p_mfc_opr.h"
> +
> +enum MFC_SHM_OFS {
> + EXTENEDED_DECODE_STATUS = 0x00, /* D */
> + SET_FRAME_TAG = 0x04, /* D */
> + GET_FRAME_TAG_TOP = 0x08, /* D */
> + GET_FRAME_TAG_BOT = 0x0C, /* D */
> + PIC_TIME_TOP = 0x10, /* D */
> + PIC_TIME_BOT = 0x14, /* D */
> + START_BYTE_NUM = 0x18, /* D */
> +
> + CROP_INFO_H = 0x20, /* D */
> + CROP_INFO_V = 0x24, /* D */
> + EXT_ENC_CONTROL = 0x28, /* E */
> + ENC_PARAM_CHANGE = 0x2C, /* E */
> + RC_VOP_TIMING = 0x30, /* E, MPEG4 */
> + HEC_PERIOD = 0x34, /* E, MPEG4 */
> + METADATA_ENABLE = 0x38, /* C */
> + METADATA_STATUS = 0x3C, /* C */
> + METADATA_DISPLAY_INDEX = 0x40, /* C */
> + EXT_METADATA_START_ADDR = 0x44, /* C */
> + PUT_EXTRADATA = 0x48, /* C */
> + EXTRADATA_ADDR = 0x4C, /* C */
> +
> + ALLOC_LUMA_DPB_SIZE = 0x64, /* D */
> + ALLOC_CHROMA_DPB_SIZE = 0x68, /* D */
> + ALLOC_MV_SIZE = 0x6C, /* D */
> + P_B_FRAME_QP = 0x70, /* E */
> + SAMPLE_ASPECT_RATIO_IDC = 0x74, /* E, H.264, depend on
> + ASPECT_RATIO_VUI_ENABLE in EXT_ENC_CONTROL */
> + EXTENDED_SAR = 0x78, /* E, H.264, depned on
> + ASPECT_RATIO_VUI_ENABLE in EXT_ENC_CONTROL */
> + DISP_PIC_PROFILE = 0x7C, /* D */
> + FLUSH_CMD_TYPE = 0x80, /* C */
> + FLUSH_CMD_INBUF1 = 0x84, /* C */
> + FLUSH_CMD_INBUF2 = 0x88, /* C */
> + FLUSH_CMD_OUTBUF = 0x8C, /* E */
> + NEW_RC_BIT_RATE = 0x90, /* E, format as RC_BIT_RATE(0xC5A8)
> + depend on RC_BIT_RATE_CHANGE in ENC_PARAM_CHANGE */
> + NEW_RC_FRAME_RATE = 0x94, /* E, format as RC_FRAME_RATE(0xD0D0)
> + depend on RC_FRAME_RATE_CHANGE in ENC_PARAM_CHANGE */
> + NEW_I_PERIOD = 0x98, /* E, format as I_FRM_CTRL(0xC504)
> + depend on I_PERIOD_CHANGE in ENC_PARAM_CHANGE */
> + H264_I_PERIOD = 0x9C, /* E, H.264, open GOP */
> + RC_CONTROL_CONFIG = 0xA0, /* E */
> + BATCH_INPUT_ADDR = 0xA4, /* E */
> + BATCH_OUTPUT_ADDR = 0xA8, /* E */
> + BATCH_OUTPUT_SIZE = 0xAC, /* E */
> + MIN_LUMA_DPB_SIZE = 0xB0, /* D */
> + DEVICE_FORMAT_ID = 0xB4, /* C */
> + H264_POC_TYPE = 0xB8, /* D */
> + MIN_CHROMA_DPB_SIZE = 0xBC, /* D */
> + DISP_PIC_FRAME_TYPE = 0xC0, /* D */
> + FREE_LUMA_DPB = 0xC4, /* D, VC1 MPEG4 */
> + ASPECT_RATIO_INFO = 0xC8, /* D, MPEG4 */
> + EXTENDED_PAR = 0xCC, /* D, MPEG4 */
> + DBG_HISTORY_INPUT0 = 0xD0, /* C */
> + DBG_HISTORY_INPUT1 = 0xD4, /* C */
> + DBG_HISTORY_OUTPUT = 0xD8, /* C */
> + HIERARCHICAL_P_QP = 0xE0, /* E, H.264 */
> + FRAME_PACK_SEI_ENABLE = 0x168, /* C */
> + FRAME_PACK_SEI_AVAIL = 0x16c, /* D */
> + FRAME_PACK_SEI_INFO = 0x17c, /* E */
> +};
> +
> +struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v5(void);
> +#endif /* S5P_MFC_OPR_H_ */
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_shm.c
> b/drivers/media/platform/s5p-mfc/s5p_mfc_shm.c
> deleted file mode 100644
> index b5933d2..0000000
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_shm.c
> +++ /dev/null
> @@ -1,47 +0,0 @@
> -/*
> - * linux/drivers/media/platform/s5p-mfc/s5p_mfc_shm.c
> - *
> - * Copyright (c) 2010 Samsung Electronics Co., Ltd.
> - * http://www.samsung.com/
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or
> - * (at your option) any later version.
> - */
> -
> -#ifdef CONFIG_ARCH_EXYNOS4
> -#include <linux/dma-mapping.h>
> -#endif
> -#include <linux/io.h>
> -#include "s5p_mfc_common.h"
> -#include "s5p_mfc_debug.h"
> -
> -int s5p_mfc_init_shm(struct s5p_mfc_ctx *ctx)
> -{
> - struct s5p_mfc_dev *dev = ctx->dev;
> - void *shm_alloc_ctx = dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
> -
> - ctx->shm_alloc = vb2_dma_contig_memops.alloc(shm_alloc_ctx,
> - SHARED_BUF_SIZE);
> - if (IS_ERR(ctx->shm_alloc)) {
> - mfc_err("failed to allocate shared memory\n");
> - return PTR_ERR(ctx->shm_alloc);
> - }
> - /* shm_ofs only keeps the offset from base (port a) */
> - ctx->shm_ofs = s5p_mfc_mem_cookie(shm_alloc_ctx, ctx->shm_alloc)
> - - dev->bank1;
> - BUG_ON(ctx->shm_ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
> - ctx->shm = vb2_dma_contig_memops.vaddr(ctx->shm_alloc);
> - if (!ctx->shm) {
> - vb2_dma_contig_memops.put(ctx->shm_alloc);
> - ctx->shm_ofs = 0;
> - ctx->shm_alloc = NULL;
> - mfc_err("failed to virt addr of shared memory\n");
> - return -ENOMEM;
> - }
> - memset((void *)ctx->shm, 0, SHARED_BUF_SIZE);
> - wmb();
> - return 0;
> -}
> -
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_shm.h
> b/drivers/media/platform/s5p-mfc/s5p_mfc_shm.h
> deleted file mode 100644
> index 416ebd7..0000000
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_shm.h
> +++ /dev/null
> @@ -1,90 +0,0 @@
> -/*
> - * linux/drivers/media/platform/s5p-mfc/s5p_mfc_shm.h
> - *
> - * Copyright (c) 2011 Samsung Electronics Co., Ltd.
> - * http://www.samsung.com/
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or
> - * (at your option) any later version.
> - */
> -
> -#ifndef S5P_MFC_SHM_H_
> -#define S5P_MFC_SHM_H_
> -
> -enum MFC_SHM_OFS {
> - EXTENEDED_DECODE_STATUS = 0x00, /* D */
> - SET_FRAME_TAG = 0x04, /* D */
> - GET_FRAME_TAG_TOP = 0x08, /* D */
> - GET_FRAME_TAG_BOT = 0x0C, /* D */
> - PIC_TIME_TOP = 0x10, /* D */
> - PIC_TIME_BOT = 0x14, /* D */
> - START_BYTE_NUM = 0x18, /* D */
> -
> - CROP_INFO_H = 0x20, /* D */
> - CROP_INFO_V = 0x24, /* D */
> - EXT_ENC_CONTROL = 0x28, /* E */
> - ENC_PARAM_CHANGE = 0x2C, /* E */
> - RC_VOP_TIMING = 0x30, /* E, MPEG4 */
> - HEC_PERIOD = 0x34, /* E, MPEG4 */
> - METADATA_ENABLE = 0x38, /* C */
> - METADATA_STATUS = 0x3C, /* C */
> - METADATA_DISPLAY_INDEX = 0x40, /* C */
> - EXT_METADATA_START_ADDR = 0x44, /* C */
> - PUT_EXTRADATA = 0x48, /* C */
> - EXTRADATA_ADDR = 0x4C, /* C */
> -
> - ALLOC_LUMA_DPB_SIZE = 0x64, /* D */
> - ALLOC_CHROMA_DPB_SIZE = 0x68, /* D */
> - ALLOC_MV_SIZE = 0x6C, /* D */
> - P_B_FRAME_QP = 0x70, /* E */
> - SAMPLE_ASPECT_RATIO_IDC = 0x74, /* E, H.264, depend on
> - ASPECT_RATIO_VUI_ENABLE in EXT_ENC_CONTROL */
> - EXTENDED_SAR = 0x78, /* E, H.264, depned on
> - ASPECT_RATIO_VUI_ENABLE in EXT_ENC_CONTROL */
> - DISP_PIC_PROFILE = 0x7C, /* D */
> - FLUSH_CMD_TYPE = 0x80, /* C */
> - FLUSH_CMD_INBUF1 = 0x84, /* C */
> - FLUSH_CMD_INBUF2 = 0x88, /* C */
> - FLUSH_CMD_OUTBUF = 0x8C, /* E */
> - NEW_RC_BIT_RATE = 0x90, /* E, format as RC_BIT_RATE(0xC5A8)
> - depend on RC_BIT_RATE_CHANGE in ENC_PARAM_CHANGE */
> - NEW_RC_FRAME_RATE = 0x94, /* E, format as RC_FRAME_RATE(0xD0D0)
> - depend on RC_FRAME_RATE_CHANGE in ENC_PARAM_CHANGE */
> - NEW_I_PERIOD = 0x98, /* E, format as I_FRM_CTRL(0xC504)
> - depend on I_PERIOD_CHANGE in ENC_PARAM_CHANGE */
> - H264_I_PERIOD = 0x9C, /* E, H.264, open GOP */
> - RC_CONTROL_CONFIG = 0xA0, /* E */
> - BATCH_INPUT_ADDR = 0xA4, /* E */
> - BATCH_OUTPUT_ADDR = 0xA8, /* E */
> - BATCH_OUTPUT_SIZE = 0xAC, /* E */
> - MIN_LUMA_DPB_SIZE = 0xB0, /* D */
> - DEVICE_FORMAT_ID = 0xB4, /* C */
> - H264_POC_TYPE = 0xB8, /* D */
> - MIN_CHROMA_DPB_SIZE = 0xBC, /* D */
> - DISP_PIC_FRAME_TYPE = 0xC0, /* D */
> - FREE_LUMA_DPB = 0xC4, /* D, VC1 MPEG4 */
> - ASPECT_RATIO_INFO = 0xC8, /* D, MPEG4 */
> - EXTENDED_PAR = 0xCC, /* D, MPEG4 */
> - DBG_HISTORY_INPUT0 = 0xD0, /* C */
> - DBG_HISTORY_INPUT1 = 0xD4, /* C */
> - DBG_HISTORY_OUTPUT = 0xD8, /* C */
> - HIERARCHICAL_P_QP = 0xE0, /* E, H.264 */
> -};
> -
> -int s5p_mfc_init_shm(struct s5p_mfc_ctx *ctx);
> -
> -#define s5p_mfc_write_shm(ctx, x, ofs) \
> - do { \
> - writel(x, (ctx->shm + ofs)); \
> - wmb(); \
> - } while (0)
> -
> -static inline u32 s5p_mfc_read_shm(struct s5p_mfc_ctx *ctx, unsigned int
ofs)
> -{
> - rmb();
> - return readl(ctx->shm + ofs);
> -}
> -
> -#endif /* S5P_MFC_SHM_H_ */
> --
> 1.7.0.4
^ permalink raw reply [flat|nested] 15+ messages in thread
* RE: [PATCH v9 4/6] [media] s5p-mfc: Add MFC variant data to device context
2012-10-02 14:55 ` [PATCH v9 4/6] [media] s5p-mfc: Add MFC variant data to device context Arun Kumar K
@ 2012-10-02 11:16 ` Kamil Debski
0 siblings, 0 replies; 15+ messages in thread
From: Kamil Debski @ 2012-10-02 11:16 UTC (permalink / raw)
To: 'Arun Kumar K', linux-media
Cc: jtp.park, janghyuck.kim, jaeryul.oh, ch.naveen, Marek Szyprowski,
Sylwester Nawrocki, hverkuil, kmpark, joshi
> From: Arun Kumar K [mailto:arun.kk@samsung.com]
> Sent: 02 October 2012 16:56
>
> MFC variant data replaces various macros used in the driver
> which will change in a different version of MFC hardware.
> Also does a cleanup of MFC context structure and common files.
>
> Signed-off-by: Jeongtae Park <jtp.park@samsung.com>
> Signed-off-by: Janghyuck Kim <janghyuck.kim@samsung.com>
> Signed-off-by: Jaeryul Oh <jaeryul.oh@samsung.com>
> Signed-off-by: Naveen Krishna Chatradhi <ch.naveen@samsung.com>
> Signed-off-by: Arun Kumar K <arun.kk@samsung.com>
Acked-by: Kamil Debski <k.debski@samsung.com>
> ---
> drivers/media/platform/s5p-mfc/regs-mfc.h | 20 ++
> drivers/media/platform/s5p-mfc/s5p_mfc.c | 78 +++++----
> drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c | 4 +-
> drivers/media/platform/s5p-mfc/s5p_mfc_common.h | 85 ++++++----
> drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c | 7 +-
> drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | 44 +----
> drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c | 213
+++++++++++++++--------
> 7 files changed, 266 insertions(+), 185 deletions(-)
>
> diff --git a/drivers/media/platform/s5p-mfc/regs-mfc.h
> b/drivers/media/platform/s5p-mfc/regs-mfc.h
> index a19bece..f33c54d 100644
> --- a/drivers/media/platform/s5p-mfc/regs-mfc.h
> +++ b/drivers/media/platform/s5p-mfc/regs-mfc.h
> @@ -12,6 +12,9 @@
> #ifndef _REGS_FIMV_H
> #define _REGS_FIMV_H
>
> +#include <linux/kernel.h>
> +#include <linux/sizes.h>
> +
> #define S5P_FIMV_REG_SIZE (S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR)
> #define S5P_FIMV_REG_COUNT ((S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR) /
4)
>
> @@ -414,5 +417,22 @@
> #define S5P_FIMV_SHARED_EXTENDED_SAR 0x0078
> #define S5P_FIMV_SHARED_H264_I_PERIOD 0x009C
> #define S5P_FIMV_SHARED_RC_CONTROL_CONFIG 0x00A0
> +#define S5P_FIMV_SHARED_DISP_FRAME_TYPE_SHIFT 2
> +
> +/* Offset used by the hardware to store addresses */
> +#define MFC_OFFSET_SHIFT 11
> +
> +#define FIRMWARE_ALIGN (128 * SZ_1K) /* 128KB */
> +#define MFC_H264_CTX_BUF_SIZE (600 * SZ_1K) /* 600KB per H264
instance */
> +#define MFC_CTX_BUF_SIZE (10 * SZ_1K) /* 10KB per instance */
> +#define DESC_BUF_SIZE (128 * SZ_1K) /* 128KB for DESC
buffer */
> +#define SHARED_BUF_SIZE (8 * SZ_1K) /* 8KB for shared
buffer */
> +
> +#define DEF_CPB_SIZE (256 * SZ_1K) /* 256KB */
> +#define MAX_CPB_SIZE (4 * SZ_1M) /* 4MB */
> +#define MAX_FW_SIZE (384 * SZ_1K)
> +
> +#define MFC_VERSION 0x51
> +#define MFC_NUM_PORTS 2
>
> #endif /* _REGS_FIMV_H */
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c
> b/drivers/media/platform/s5p-mfc/s5p_mfc.c
> index 3319410..a8299ce 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
> @@ -436,7 +436,6 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx
*ctx,
> unsigned int reason, unsigned int err)
> {
> struct s5p_mfc_dev *dev;
> - unsigned int guard_width, guard_height;
>
> if (ctx == NULL)
> return;
> @@ -450,40 +449,8 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx
*ctx,
> ctx->img_height = s5p_mfc_hw_call(dev->mfc_ops,
get_img_height,
> dev);
>
> - ctx->buf_width = ALIGN(ctx->img_width,
> - S5P_FIMV_NV12MT_HALIGN);
> - ctx->buf_height = ALIGN(ctx->img_height,
> - S5P_FIMV_NV12MT_VALIGN);
> - mfc_debug(2, "SEQ Done: Movie dimensions %dx%d, "
> - "buffer dimensions: %dx%d\n", ctx->img_width,
> - ctx->img_height, ctx->buf_width,
> - ctx->buf_height);
> - if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC) {
> - ctx->luma_size = ALIGN(ctx->buf_width *
> - ctx->buf_height, S5P_FIMV_DEC_BUF_ALIGN);
> - ctx->chroma_size = ALIGN(ctx->buf_width *
> - ALIGN((ctx->img_height >> 1),
> - S5P_FIMV_NV12MT_VALIGN),
> - S5P_FIMV_DEC_BUF_ALIGN);
> - ctx->mv_size = ALIGN(ctx->buf_width *
> - ALIGN((ctx->buf_height >> 2),
> - S5P_FIMV_NV12MT_VALIGN),
> - S5P_FIMV_DEC_BUF_ALIGN);
> - } else {
> - guard_width = ALIGN(ctx->img_width + 24,
> - S5P_FIMV_NV12MT_HALIGN);
> - guard_height = ALIGN(ctx->img_height + 16,
> - S5P_FIMV_NV12MT_VALIGN);
> - ctx->luma_size = ALIGN(guard_width *
> - guard_height, S5P_FIMV_DEC_BUF_ALIGN);
> - guard_width = ALIGN(ctx->img_width + 16,
> - S5P_FIMV_NV12MT_HALIGN);
> - guard_height = ALIGN((ctx->img_height >> 1) + 4,
> - S5P_FIMV_NV12MT_VALIGN);
> - ctx->chroma_size = ALIGN(guard_width *
> - guard_height, S5P_FIMV_DEC_BUF_ALIGN);
> - ctx->mv_size = 0;
> - }
> + s5p_mfc_hw_call(dev->mfc_ops, dec_calc_dpb_size, ctx);
> +
> ctx->dpb_count = s5p_mfc_hw_call(dev->mfc_ops, get_dpb_count,
> dev);
> if (ctx->img_width == 0 || ctx->img_height == 0)
> @@ -993,6 +960,9 @@ static int s5p_mfc_probe(struct platform_device *pdev)
> return -ENODEV;
> }
>
> + dev->variant = (struct s5p_mfc_variant *)
> + platform_get_device_id(pdev)->driver_data;
> +
> ret = s5p_mfc_init_pm(dev);
> if (ret < 0) {
> dev_err(&pdev->dev, "failed to get mfc clock source\n");
> @@ -1235,9 +1205,43 @@ static const struct dev_pm_ops s5p_mfc_pm_ops = {
> NULL)
> };
>
> +struct s5p_mfc_buf_size_v5 mfc_buf_size_v5 = {
> + .h264_ctx = MFC_H264_CTX_BUF_SIZE,
> + .non_h264_ctx = MFC_CTX_BUF_SIZE,
> + .dsc = DESC_BUF_SIZE,
> + .shm = SHARED_BUF_SIZE,
> +};
> +
> +struct s5p_mfc_buf_size buf_size_v5 = {
> + .fw = MAX_FW_SIZE,
> + .cpb = MAX_CPB_SIZE,
> + .priv = &mfc_buf_size_v5,
> +};
> +
> +struct s5p_mfc_buf_align mfc_buf_align_v5 = {
> + .base = MFC_BASE_ALIGN_ORDER,
> +};
> +
> +static struct s5p_mfc_variant mfc_drvdata_v5 = {
> + .version = MFC_VERSION,
> + .port_num = MFC_NUM_PORTS,
> + .buf_size = &buf_size_v5,
> + .buf_align = &mfc_buf_align_v5,
> +};
> +
> +static struct platform_device_id mfc_driver_ids[] = {
> + {
> + .name = "s5p-mfc",
> + .driver_data = (unsigned long)&mfc_drvdata_v5,
> + },
> + {},
> +};
> +MODULE_DEVICE_TABLE(platform, mfc_driver_ids);
> +
> static struct platform_driver s5p_mfc_driver = {
> - .probe = s5p_mfc_probe,
> - .remove = __devexit_p(s5p_mfc_remove),
> + .probe = s5p_mfc_probe,
> + .remove = __devexit_p(s5p_mfc_remove),
> + .id_table = mfc_driver_ids,
> .driver = {
> .name = S5P_MFC_NAME,
> .owner = THIS_MODULE,
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
> b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
> index f3d7874..344b31e 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
> @@ -113,8 +113,8 @@ int s5p_mfc_open_inst_cmd_v5(struct s5p_mfc_ctx *ctx)
> h2r_args.arg[0] = S5P_FIMV_CODEC_NONE;
> };
> h2r_args.arg[1] = 0; /* no crc & no pixelcache */
> - h2r_args.arg[2] = ctx->ctx_ofs;
> - h2r_args.arg[3] = ctx->ctx_size;
> + h2r_args.arg[2] = ctx->ctx.ofs;
> + h2r_args.arg[3] = ctx->ctx.size;
> ret = s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE,
> &h2r_args);
> if (ret) {
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
> b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
> index ccb59ac..e9e89ac 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
> @@ -30,17 +30,6 @@
> * while mmaping */
> #define DST_QUEUE_OFF_BASE (TASK_SIZE / 2)
>
> -/* Offset used by the hardware to store addresses */
> -#define MFC_OFFSET_SHIFT 11
> -
> -#define FIRMWARE_ALIGN 0x20000 /* 128KB */
> -#define MFC_H264_CTX_BUF_SIZE 0x96000 /* 600KB per H264
instance
> */
> -#define MFC_CTX_BUF_SIZE 0x2800 /* 10KB per instance */
> -#define DESC_BUF_SIZE 0x20000 /* 128KB for DESC
buffer */
> -#define SHARED_BUF_SIZE 0x2000 /* 8KB for shared
buffer */
> -
> -#define DEF_CPB_SIZE 0x40000 /* 512KB */
> -
> #define MFC_BANK1_ALLOC_CTX 0
> #define MFC_BANK2_ALLOC_CTX 1
>
> @@ -207,6 +196,48 @@ struct s5p_mfc_pm {
> struct device *device;
> };
>
> +struct s5p_mfc_buf_size_v5 {
> + unsigned int h264_ctx;
> + unsigned int non_h264_ctx;
> + unsigned int dsc;
> + unsigned int shm;
> +};
> +
> +struct s5p_mfc_buf_size {
> + unsigned int fw;
> + unsigned int cpb;
> + void *priv;
> +};
> +
> +struct s5p_mfc_buf_align {
> + unsigned int base;
> +};
> +
> +struct s5p_mfc_variant {
> + unsigned int version;
> + unsigned int port_num;
> + struct s5p_mfc_buf_size *buf_size;
> + struct s5p_mfc_buf_align *buf_align;
> +};
> +
> +/**
> + * struct s5p_mfc_priv_buf - represents internal used buffer
> + * @alloc: allocation-specific context for each buffer
> + * (videobuf2 allocator)
> + * @ofs: offset of each buffer, will be used for MFC
> + * @virt: kernel virtual address, only valid when the
> + * buffer accessed by driver
> + * @dma: DMA address, only valid when kernel DMA API used
> + * @size: size of the buffer
> + */
> +struct s5p_mfc_priv_buf {
> + void *alloc;
> + unsigned long ofs;
> + void *virt;
> + dma_addr_t dma;
> + size_t size;
> +};
> +
> /**
> * struct s5p_mfc_dev - The struct containing driver internal parameters.
> *
> @@ -221,6 +252,7 @@ struct s5p_mfc_pm {
> * @dec_ctrl_handler: control framework handler for decoding
> * @enc_ctrl_handler: control framework handler for encoding
> * @pm: power management control
> + * @variant: MFC hardware variant information
> * @num_inst: couter of active MFC instances
> * @irqlock: lock for operations on videobuf2 queues
> * @condlock: lock for changing/checking if a context is
ready to be
> @@ -259,6 +291,7 @@ struct s5p_mfc_dev {
> struct v4l2_ctrl_handler dec_ctrl_handler;
> struct v4l2_ctrl_handler enc_ctrl_handler;
> struct s5p_mfc_pm pm;
> + struct s5p_mfc_variant *variant;
> int num_inst;
> spinlock_t irqlock; /* lock when operating on videobuf2 queues */
> spinlock_t condlock; /* lock when changing/checking if a context is
> @@ -299,7 +332,6 @@ struct s5p_mfc_h264_enc_params {
> u8 max_ref_pic;
> u8 num_ref_pic_4p;
> int _8x8_transform;
> - int rc_mb;
> int rc_mb_dark;
> int rc_mb_smooth;
> int rc_mb_static;
> @@ -318,6 +350,7 @@ struct s5p_mfc_h264_enc_params {
> enum v4l2_mpeg_video_h264_level level_v4l2;
> int level;
> u16 cpb_size;
> + int interlace;
> };
>
> /**
> @@ -356,6 +389,7 @@ struct s5p_mfc_enc_params {
> u8 pad_cb;
> u8 pad_cr;
> int rc_frame;
> + int rc_mb;
> u32 rc_bitrate;
> u16 rc_reaction_coeff;
> u16 vbv_size;
> @@ -367,7 +401,6 @@ struct s5p_mfc_enc_params {
> u8 num_b_frame;
> u32 rc_framerate_num;
> u32 rc_framerate_denom;
> - int interlace;
>
> union {
> struct s5p_mfc_h264_enc_params h264;
> @@ -452,14 +485,9 @@ struct s5p_mfc_codec_ops {
> * @dpb_count: count of the DPB buffers required by MFC hw
> * @total_dpb_count: count of DPB buffers with additional buffers
> * requested by the application
> - * @ctx_buf: handle to the memory associated with this context
> - * @ctx_phys: address of the memory associated with this
context
> - * @ctx_size: size of the memory associated with this
context
> - * @desc_buf: description buffer for decoding handle
> - * @desc_phys: description buffer for decoding address
> - * @shm_alloc: handle for the shared memory buffer
> - * @shm: virtual address for the shared memory buffer
> - * @shm_ofs: address offset for shared memory
> + * @ctx: context buffer information
> + * @dsc: descriptor buffer information
> + * @shm: shared memory buffer information
> * @enc_params: encoding parameters for MFC
> * @enc_dst_buf_size: size of the buffers for encoder output
> * @frame_type: used to force the type of the next encoded
frame
> @@ -544,18 +572,9 @@ struct s5p_mfc_ctx {
> int total_dpb_count;
>
> /* Buffers */
> - void *ctx_buf;
> - size_t ctx_phys;
> - size_t ctx_ofs;
> - size_t ctx_size;
> -
> - void *desc_buf;
> - size_t desc_phys;
> -
> -
> - void *shm_alloc;
> - void *shm;
> - size_t shm_ofs;
> + struct s5p_mfc_priv_buf ctx;
> + struct s5p_mfc_priv_buf dsc;
> + struct s5p_mfc_priv_buf shm;
>
> struct s5p_mfc_enc_params enc_params;
>
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
> b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
> index 4a39e5e..524380c 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
> @@ -43,7 +43,12 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev
*dev)
> mfc_err("Firmware is not present in the /lib/firmware
directory nor
> compiled in kernel\n");
> return -EINVAL;
> }
> - dev->fw_size = ALIGN(fw_blob->size, FIRMWARE_ALIGN);
> + dev->fw_size = dev->variant->buf_size->fw;
> + if (fw_blob->size > dev->fw_size) {
> + mfc_err("MFC firmware is too big to be loaded\n");
> + release_firmware(fw_blob);
> + return -ENOMEM;
> + }
> if (s5p_mfc_bitproc_buf) {
> mfc_err("Attempting to allocate firmware when it seems that it
is
> already loaded\n");
> release_firmware(fw_blob);
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
> b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
> index 02e1a94..fe34f17 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
> @@ -985,45 +985,13 @@ static int vidioc_s_fmt(struct file *file, void *priv,
> struct v4l2_format *f)
> mfc_debug(2, "fmt - w: %d, h: %d, ctx - w: %d, h: %d\n",
> pix_fmt_mp->width, pix_fmt_mp->height,
> ctx->img_width, ctx->img_height);
> - if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) {
> - ctx->buf_width = ALIGN(ctx->img_width,
> -
S5P_FIMV_NV12M_HALIGN);
> - ctx->luma_size = ALIGN(ctx->img_width,
> - S5P_FIMV_NV12M_HALIGN) *
ALIGN(ctx->img_height,
> - S5P_FIMV_NV12M_LVALIGN);
> - ctx->chroma_size = ALIGN(ctx->img_width,
> - S5P_FIMV_NV12M_HALIGN) *
ALIGN((ctx->img_height
> - >> 1), S5P_FIMV_NV12M_CVALIGN);
> -
> - ctx->luma_size = ALIGN(ctx->luma_size,
> -
S5P_FIMV_NV12M_SALIGN);
> - ctx->chroma_size = ALIGN(ctx->chroma_size,
> -
S5P_FIMV_NV12M_SALIGN);
> -
> - pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
> - pix_fmt_mp->plane_fmt[0].bytesperline =
ctx->buf_width;
> - pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
> - pix_fmt_mp->plane_fmt[1].bytesperline =
ctx->buf_width;
> -
> - } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT) {
> - ctx->buf_width = ALIGN(ctx->img_width,
> -
S5P_FIMV_NV12MT_HALIGN);
> - ctx->luma_size = ALIGN(ctx->img_width,
> - S5P_FIMV_NV12MT_HALIGN) *
ALIGN(ctx->img_height,
> - S5P_FIMV_NV12MT_VALIGN);
> - ctx->chroma_size = ALIGN(ctx->img_width,
> - S5P_FIMV_NV12MT_HALIGN) *
ALIGN((ctx->img_height
> - >> 1), S5P_FIMV_NV12MT_VALIGN);
> - ctx->luma_size = ALIGN(ctx->luma_size,
> -
S5P_FIMV_NV12MT_SALIGN);
> - ctx->chroma_size = ALIGN(ctx->chroma_size,
> -
S5P_FIMV_NV12MT_SALIGN);
> -
> - pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
> - pix_fmt_mp->plane_fmt[0].bytesperline =
ctx->buf_width;
> - pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
> - pix_fmt_mp->plane_fmt[1].bytesperline =
ctx->buf_width;
> - }
> +
> + s5p_mfc_hw_call(dev->mfc_ops, enc_calc_src_size, ctx);
> + pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
> + pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width;
> + pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
> + pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width;
> +
> ctx->src_bufs_cnt = 0;
> ctx->output_state = QUEUE_FREE;
> } else {
> @@ -1349,7 +1317,7 @@ static int s5p_mfc_enc_s_ctrl(struct v4l2_ctrl *ctrl)
> p->codec.h264._8x8_transform = ctrl->val;
> break;
> case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE:
> - p->codec.h264.rc_mb = ctrl->val;
> + p->rc_mb = ctrl->val;
> break;
> case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
> p->codec.h264.rc_frame_qp = ctrl->val;
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
> b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
> index fe36c92..f1871e7 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
> @@ -36,28 +36,29 @@
> /* Allocate temporary buffers for decoding */
> int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx *ctx)
> {
> - void *desc_virt;
> struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
>
> - ctx->desc_buf = vb2_dma_contig_memops.alloc(
> - dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], DESC_BUF_SIZE);
> - if (IS_ERR_VALUE((int)ctx->desc_buf)) {
> - ctx->desc_buf = NULL;
> + ctx->dsc.alloc = vb2_dma_contig_memops.alloc(
> + dev->alloc_ctx[MFC_BANK1_ALLOC_CTX],
> + buf_size->dsc);
> + if (IS_ERR_VALUE((int)ctx->dsc.alloc)) {
> + ctx->dsc.alloc = NULL;
> mfc_err("Allocating DESC buffer failed\n");
> return -ENOMEM;
> }
> - ctx->desc_phys = s5p_mfc_mem_cookie(
> - dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->desc_buf);
> - BUG_ON(ctx->desc_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
> - desc_virt = vb2_dma_contig_memops.vaddr(ctx->desc_buf);
> - if (desc_virt == NULL) {
> - vb2_dma_contig_memops.put(ctx->desc_buf);
> - ctx->desc_phys = 0;
> - ctx->desc_buf = NULL;
> + ctx->dsc.dma = s5p_mfc_mem_cookie(
> + dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->dsc.alloc);
> + BUG_ON(ctx->dsc.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
> + ctx->dsc.virt = vb2_dma_contig_memops.vaddr(ctx->dsc.alloc);
> + if (ctx->dsc.virt == NULL) {
> + vb2_dma_contig_memops.put(ctx->dsc.alloc);
> + ctx->dsc.dma = 0;
> + ctx->dsc.alloc = NULL;
> mfc_err("Remapping DESC buffer failed\n");
> return -ENOMEM;
> }
> - memset(desc_virt, 0, DESC_BUF_SIZE);
> + memset(ctx->dsc.virt, 0, buf_size->dsc);
> wmb();
> return 0;
> }
> @@ -65,10 +66,10 @@ int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx
> *ctx)
> /* Release temporary buffers for decoding */
> void s5p_mfc_release_dec_desc_buffer_v5(struct s5p_mfc_ctx *ctx)
> {
> - if (ctx->desc_phys) {
> - vb2_dma_contig_memops.put(ctx->desc_buf);
> - ctx->desc_phys = 0;
> - ctx->desc_buf = NULL;
> + if (ctx->dsc.dma) {
> + vb2_dma_contig_memops.put(ctx->dsc.alloc);
> + ctx->dsc.alloc = NULL;
> + ctx->dsc.dma = 0;
> }
> }
>
> @@ -229,60 +230,60 @@ void s5p_mfc_release_codec_buffers_v5(struct
s5p_mfc_ctx
> *ctx)
> /* Allocate memory for instance data buffer */
> int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx)
> {
> - void *context_virt;
> struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
>
> - if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC ||
> - ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC)
> - ctx->ctx_size = MFC_H264_CTX_BUF_SIZE;
> + if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC ||
> + ctx->codec_mode == S5P_MFC_CODEC_H264_ENC)
> + ctx->ctx.size = buf_size->h264_ctx;
> else
> - ctx->ctx_size = MFC_CTX_BUF_SIZE;
> - ctx->ctx_buf = vb2_dma_contig_memops.alloc(
> - dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx_size);
> - if (IS_ERR(ctx->ctx_buf)) {
> + ctx->ctx.size = buf_size->non_h264_ctx;
> + ctx->ctx.alloc = vb2_dma_contig_memops.alloc(
> + dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx.size);
> + if (IS_ERR(ctx->ctx.alloc)) {
> mfc_err("Allocating context buffer failed\n");
> - ctx->ctx_phys = 0;
> - ctx->ctx_buf = NULL;
> + ctx->ctx.alloc = NULL;
> return -ENOMEM;
> }
> - ctx->ctx_phys = s5p_mfc_mem_cookie(
> - dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx_buf);
> - BUG_ON(ctx->ctx_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
> - ctx->ctx_ofs = OFFSETA(ctx->ctx_phys);
> - context_virt = vb2_dma_contig_memops.vaddr(ctx->ctx_buf);
> - if (context_virt == NULL) {
> + ctx->ctx.dma = s5p_mfc_mem_cookie(
> + dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx.alloc);
> + BUG_ON(ctx->ctx.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
> + ctx->ctx.ofs = OFFSETA(ctx->ctx.dma);
> + ctx->ctx.virt = vb2_dma_contig_memops.vaddr(ctx->ctx.alloc);
> + if (!ctx->ctx.virt) {
> mfc_err("Remapping instance buffer failed\n");
> - vb2_dma_contig_memops.put(ctx->ctx_buf);
> - ctx->ctx_phys = 0;
> - ctx->ctx_buf = NULL;
> + vb2_dma_contig_memops.put(ctx->ctx.alloc);
> + ctx->ctx.alloc = NULL;
> + ctx->ctx.ofs = 0;
> + ctx->ctx.dma = 0;
> return -ENOMEM;
> }
> /* Zero content of the allocated memory */
> - memset(context_virt, 0, ctx->ctx_size);
> + memset(ctx->ctx.virt, 0, ctx->ctx.size);
> wmb();
>
> /* Initialize shared memory */
> - ctx->shm_alloc = vb2_dma_contig_memops.alloc(
> - dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], SHARED_BUF_SIZE);
> - if (IS_ERR(ctx->shm_alloc)) {
> + ctx->shm.alloc = vb2_dma_contig_memops.alloc(
> + dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], buf_size->shm);
> + if (IS_ERR(ctx->shm.alloc)) {
> mfc_err("failed to allocate shared memory\n");
> - return PTR_ERR(ctx->shm_alloc);
> + return PTR_ERR(ctx->shm.alloc);
> }
> /* shared memory offset only keeps the offset from base (port a) */
> - ctx->shm_ofs = s5p_mfc_mem_cookie(
> - dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->shm_alloc)
> + ctx->shm.ofs = s5p_mfc_mem_cookie(
> + dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->shm.alloc)
> - dev->bank1;
> - BUG_ON(ctx->shm_ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
> + BUG_ON(ctx->shm.ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
>
> - ctx->shm = vb2_dma_contig_memops.vaddr(ctx->shm_alloc);
> - if (!ctx->shm) {
> - vb2_dma_contig_memops.put(ctx->shm_alloc);
> - ctx->shm_ofs = 0;
> - ctx->shm_alloc = NULL;
> + ctx->shm.virt = vb2_dma_contig_memops.vaddr(ctx->shm.alloc);
> + if (!ctx->shm.virt) {
> + vb2_dma_contig_memops.put(ctx->shm.alloc);
> + ctx->shm.alloc = NULL;
> + ctx->shm.ofs = 0;
> mfc_err("failed to virt addr of shared memory\n");
> return -ENOMEM;
> }
> - memset((void *)ctx->shm, 0, SHARED_BUF_SIZE);
> + memset((void *)ctx->shm.virt, 0, buf_size->shm);
> wmb();
> return 0;
> }
> @@ -290,15 +291,18 @@ int s5p_mfc_alloc_instance_buffer_v5(struct
s5p_mfc_ctx
> *ctx)
> /* Release instance buffer */
> void s5p_mfc_release_instance_buffer_v5(struct s5p_mfc_ctx *ctx)
> {
> - if (ctx->ctx_buf) {
> - vb2_dma_contig_memops.put(ctx->ctx_buf);
> - ctx->ctx_phys = 0;
> - ctx->ctx_buf = NULL;
> + if (ctx->ctx.alloc) {
> + vb2_dma_contig_memops.put(ctx->ctx.alloc);
> + ctx->ctx.alloc = NULL;
> + ctx->ctx.ofs = 0;
> + ctx->ctx.virt = NULL;
> + ctx->ctx.dma = 0;
> }
> - if (ctx->shm_alloc) {
> - vb2_dma_contig_memops.put(ctx->shm_alloc);
> - ctx->shm_alloc = NULL;
> - ctx->shm = NULL;
> + if (ctx->shm.alloc) {
> + vb2_dma_contig_memops.put(ctx->shm.alloc);
> + ctx->shm.alloc = NULL;
> + ctx->shm.ofs = 0;
> + ctx->shm.virt = NULL;
> }
> }
>
> @@ -317,7 +321,7 @@ void s5p_mfc_release_dev_context_buffer_v5(struct
> s5p_mfc_dev *dev)
> static void s5p_mfc_write_info_v5(struct s5p_mfc_ctx *ctx, unsigned int
data,
> unsigned int ofs)
> {
> - writel(data, (ctx->shm + ofs));
> + writel(data, (ctx->shm.virt + ofs));
> wmb();
> }
>
> @@ -325,33 +329,94 @@ static unsigned int s5p_mfc_read_info_v5(struct
> s5p_mfc_ctx *ctx,
> unsigned int ofs)
> {
> rmb();
> - return readl(ctx->shm + ofs);
> + return readl(ctx->shm.virt + ofs);
> }
>
> void s5p_mfc_dec_calc_dpb_size_v5(struct s5p_mfc_ctx *ctx)
> {
> - /* NOP */
> + unsigned int guard_width, guard_height;
> +
> + ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN);
> + ctx->buf_height = ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
> + mfc_debug(2,
> + "SEQ Done: Movie dimensions %dx%d, buffer dimensions:
%dx%d\n",
> + ctx->img_width, ctx->img_height, ctx->buf_width,
> + ctx->buf_height);
> +
> + if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC) {
> + ctx->luma_size = ALIGN(ctx->buf_width * ctx->buf_height,
> + S5P_FIMV_DEC_BUF_ALIGN);
> + ctx->chroma_size = ALIGN(ctx->buf_width *
> + ALIGN((ctx->img_height >> 1),
> + S5P_FIMV_NV12MT_VALIGN),
> + S5P_FIMV_DEC_BUF_ALIGN);
> + ctx->mv_size = ALIGN(ctx->buf_width *
> + ALIGN((ctx->buf_height >> 2),
> + S5P_FIMV_NV12MT_VALIGN),
> + S5P_FIMV_DEC_BUF_ALIGN);
> + } else {
> + guard_width =
> + ALIGN(ctx->img_width + 24, S5P_FIMV_NV12MT_HALIGN);
> + guard_height =
> + ALIGN(ctx->img_height + 16, S5P_FIMV_NV12MT_VALIGN);
> + ctx->luma_size = ALIGN(guard_width * guard_height,
> + S5P_FIMV_DEC_BUF_ALIGN);
> +
> + guard_width =
> + ALIGN(ctx->img_width + 16, S5P_FIMV_NV12MT_HALIGN);
> + guard_height =
> + ALIGN((ctx->img_height >> 1) + 4,
> + S5P_FIMV_NV12MT_VALIGN);
> + ctx->chroma_size = ALIGN(guard_width * guard_height,
> + S5P_FIMV_DEC_BUF_ALIGN);
> +
> + ctx->mv_size = 0;
> + }
> }
>
> void s5p_mfc_enc_calc_src_size_v5(struct s5p_mfc_ctx *ctx)
> {
> - /* NOP */
> + if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) {
> + ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN);
> +
> + ctx->luma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN)
> + * ALIGN(ctx->img_height, S5P_FIMV_NV12M_LVALIGN);
> + ctx->chroma_size = ALIGN(ctx->img_width,
S5P_FIMV_NV12M_HALIGN)
> + * ALIGN((ctx->img_height >> 1),
S5P_FIMV_NV12M_CVALIGN);
> +
> + ctx->luma_size = ALIGN(ctx->luma_size, S5P_FIMV_NV12M_SALIGN);
> + ctx->chroma_size =
> + ALIGN(ctx->chroma_size, S5P_FIMV_NV12M_SALIGN);
> + } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT) {
> + ctx->buf_width = ALIGN(ctx->img_width,
S5P_FIMV_NV12MT_HALIGN);
> +
> + ctx->luma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
> + * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
> + ctx->chroma_size =
> + ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
> + * ALIGN((ctx->img_height >> 1),
S5P_FIMV_NV12MT_VALIGN);
> +
> + ctx->luma_size = ALIGN(ctx->luma_size,
S5P_FIMV_NV12MT_SALIGN);
> + ctx->chroma_size =
> + ALIGN(ctx->chroma_size, S5P_FIMV_NV12MT_SALIGN);
> + }
> }
>
> /* Set registers for decoding temporary buffers */
> static void s5p_mfc_set_dec_desc_buffer(struct s5p_mfc_ctx *ctx)
> {
> struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
>
> - mfc_write(dev, OFFSETA(ctx->desc_phys), S5P_FIMV_SI_CH0_DESC_ADR);
> - mfc_write(dev, DESC_BUF_SIZE, S5P_FIMV_SI_CH0_DESC_SIZE);
> + mfc_write(dev, OFFSETA(ctx->dsc.dma), S5P_FIMV_SI_CH0_DESC_ADR);
> + mfc_write(dev, buf_size->dsc, S5P_FIMV_SI_CH0_DESC_SIZE);
> }
>
> /* Set registers for shared buffer */
> static void s5p_mfc_set_shared_buffer(struct s5p_mfc_ctx *ctx)
> {
> struct s5p_mfc_dev *dev = ctx->dev;
> - mfc_write(dev, ctx->shm_ofs, S5P_FIMV_SI_CH0_HOST_WR_ADR);
> + mfc_write(dev, ctx->shm.ofs, S5P_FIMV_SI_CH0_HOST_WR_ADR);
> }
>
> /* Set registers for decoding stream buffer */
> @@ -775,9 +840,9 @@ static int s5p_mfc_set_enc_params_h264(struct
s5p_mfc_ctx
> *ctx)
> reg |= p_264->profile;
> mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE);
> /* interlace */
> - mfc_write(dev, p->interlace, S5P_FIMV_ENC_PIC_STRUCT);
> + mfc_write(dev, p_264->interlace, S5P_FIMV_ENC_PIC_STRUCT);
> /* height */
> - if (p->interlace)
> + if (p_264->interlace)
> mfc_write(dev, ctx->img_height >> 1, S5P_FIMV_ENC_VSIZE_PX);
> /* loopfilter ctrl */
> mfc_write(dev, p_264->loop_filter_mode, S5P_FIMV_ENC_LF_CTRL);
> @@ -819,7 +884,7 @@ static int s5p_mfc_set_enc_params_h264(struct
s5p_mfc_ctx
> *ctx)
> reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
> /* macroblock level rate control */
> reg &= ~(0x1 << 8);
> - reg |= (p_264->rc_mb << 8);
> + reg |= (p->rc_mb << 8);
> /* frame QP */
> reg &= ~(0x3F);
> reg |= p_264->rc_frame_qp;
> @@ -840,7 +905,7 @@ static int s5p_mfc_set_enc_params_h264(struct
s5p_mfc_ctx
> *ctx)
> reg |= p_264->rc_min_qp;
> mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
> /* macroblock adaptive scaling features */
> - if (p_264->rc_mb) {
> + if (p->rc_mb) {
> reg = mfc_read(dev, S5P_FIMV_ENC_RC_MB_CTRL);
> /* dark region */
> reg &= ~(0x1 << 3);
> @@ -856,8 +921,7 @@ static int s5p_mfc_set_enc_params_h264(struct
s5p_mfc_ctx
> *ctx)
> reg |= p_264->rc_mb_activity;
> mfc_write(dev, reg, S5P_FIMV_ENC_RC_MB_CTRL);
> }
> - if (!p->rc_frame &&
> - !p_264->rc_mb) {
> + if (!p->rc_frame && !p->rc_mb) {
> shm = s5p_mfc_read_info_v5(ctx, P_B_FRAME_QP);
> shm &= ~(0xFFF);
> shm |= ((p_264->rc_b_frame_qp & 0x3F) << 6);
> @@ -1487,8 +1551,9 @@ int s5p_mfc_get_dec_frame_type_v5(struct s5p_mfc_dev
*dev)
>
> int s5p_mfc_get_disp_frame_type_v5(struct s5p_mfc_ctx *ctx)
> {
> - /* NOP */
> - return -1;
> + return (s5p_mfc_read_info_v5(ctx, DISP_PIC_FRAME_TYPE) >>
> + S5P_FIMV_SHARED_DISP_FRAME_TYPE_SHIFT) &
> + S5P_FIMV_DECODE_FRAME_MASK;
> }
>
> int s5p_mfc_get_consumed_stream_v5(struct s5p_mfc_dev *dev)
> --
> 1.7.0.4
^ permalink raw reply [flat|nested] 15+ messages in thread
* RE: [PATCH v9 5/6] [media] s5p-mfc: MFCv6 register definitions
2012-10-02 14:55 ` [PATCH v9 5/6] [media] s5p-mfc: MFCv6 register definitions Arun Kumar K
@ 2012-10-02 11:16 ` Kamil Debski
0 siblings, 0 replies; 15+ messages in thread
From: Kamil Debski @ 2012-10-02 11:16 UTC (permalink / raw)
To: 'Arun Kumar K', linux-media
Cc: jtp.park, janghyuck.kim, jaeryul.oh, ch.naveen, Marek Szyprowski,
Sylwester Nawrocki, hverkuil, kmpark, joshi
> From: Arun Kumar K [mailto:arun.kk@samsung.com]
> Sent: 02 October 2012 16:56
>
> From: Jeongtae Park <jtp.park@samsung.com>
>
> Adds register definitions for MFC v6.x firmware
>
> Signed-off-by: Jeongtae Park <jtp.park@samsung.com>
> Signed-off-by: Janghyuck Kim <janghyuck.kim@samsung.com>
> Signed-off-by: Jaeryul Oh <jaeryul.oh@samsung.com>
> Signed-off-by: Naveen Krishna Chatradhi <ch.naveen@samsung.com>
> Signed-off-by: Arun Kumar K <arun.kk@samsung.com>
Acked-by: Kamil Debski <k.debski@samsung.com>
> ---
> drivers/media/platform/s5p-mfc/regs-mfc-v6.h | 408
++++++++++++++++++++++++++
> 1 files changed, 408 insertions(+), 0 deletions(-)
> create mode 100644 drivers/media/platform/s5p-mfc/regs-mfc-v6.h
>
> diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v6.h
> b/drivers/media/platform/s5p-mfc/regs-mfc-v6.h
> new file mode 100644
> index 0000000..363a97c
> --- /dev/null
> +++ b/drivers/media/platform/s5p-mfc/regs-mfc-v6.h
> @@ -0,0 +1,408 @@
> +/*
> + * Register definition file for Samsung MFC V6.x Interface (FIMV) driver
> + *
> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
> + * http://www.samsung.com/
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef _REGS_FIMV_V6_H
> +#define _REGS_FIMV_V6_H
> +
> +#include <linux/kernel.h>
> +#include <linux/sizes.h>
> +
> +#define S5P_FIMV_REG_SIZE_V6 (S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR)
> +#define S5P_FIMV_REG_COUNT_V6 ((S5P_FIMV_END_ADDR -
S5P_FIMV_START_ADDR) / 4)
> +
> +/* Number of bits that the buffer address should be shifted for particular
> + * MFC buffers. */
> +#define S5P_FIMV_MEM_OFFSET_V6 0
> +
> +#define S5P_FIMV_START_ADDR_V6 0x0000
> +#define S5P_FIMV_END_ADDR_V6 0xfd80
> +
> +#define S5P_FIMV_REG_CLEAR_BEGIN_V6 0xf000
> +#define S5P_FIMV_REG_CLEAR_COUNT_V6 1024
> +
> +/* Codec Common Registers */
> +#define S5P_FIMV_RISC_ON_V6 0x0000
> +#define S5P_FIMV_RISC2HOST_INT_V6 0x003C
> +#define S5P_FIMV_HOST2RISC_INT_V6 0x0044
> +#define S5P_FIMV_RISC_BASE_ADDRESS_V6 0x0054
> +
> +#define S5P_FIMV_MFC_RESET_V6 0x1070
> +
> +#define S5P_FIMV_HOST2RISC_CMD_V6 0x1100
> +#define S5P_FIMV_H2R_CMD_EMPTY_V6 0
> +#define S5P_FIMV_H2R_CMD_SYS_INIT_V6 1
> +#define S5P_FIMV_H2R_CMD_OPEN_INSTANCE_V6 2
> +#define S5P_FIMV_CH_SEQ_HEADER_V6 3
> +#define S5P_FIMV_CH_INIT_BUFS_V6 4
> +#define S5P_FIMV_CH_FRAME_START_V6 5
> +#define S5P_FIMV_H2R_CMD_CLOSE_INSTANCE_V6 6
> +#define S5P_FIMV_H2R_CMD_SLEEP_V6 7
> +#define S5P_FIMV_H2R_CMD_WAKEUP_V6 8
> +#define S5P_FIMV_CH_LAST_FRAME_V6 9
> +#define S5P_FIMV_H2R_CMD_FLUSH_V6 10
> +/* RMVME: REALLOC used? */
> +#define S5P_FIMV_CH_FRAME_START_REALLOC_V6 5
> +
> +#define S5P_FIMV_RISC2HOST_CMD_V6 0x1104
> +#define S5P_FIMV_R2H_CMD_EMPTY_V6 0
> +#define S5P_FIMV_R2H_CMD_SYS_INIT_RET_V6 1
> +#define S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET_V6 2
> +#define S5P_FIMV_R2H_CMD_SEQ_DONE_RET_V6 3
> +#define S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET_V6 4
> +
> +#define S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET_V6 6
> +#define S5P_FIMV_R2H_CMD_SLEEP_RET_V6 7
> +#define S5P_FIMV_R2H_CMD_WAKEUP_RET_V6 8
> +#define S5P_FIMV_R2H_CMD_COMPLETE_SEQ_RET_V6 9
> +#define S5P_FIMV_R2H_CMD_DPB_FLUSH_RET_V6 10
> +#define S5P_FIMV_R2H_CMD_NAL_ABORT_RET_V6 11
> +#define S5P_FIMV_R2H_CMD_FW_STATUS_RET_V6 12
> +#define S5P_FIMV_R2H_CMD_FRAME_DONE_RET_V6 13
> +#define S5P_FIMV_R2H_CMD_FIELD_DONE_RET_V6 14
> +#define S5P_FIMV_R2H_CMD_SLICE_DONE_RET_V6 15
> +#define S5P_FIMV_R2H_CMD_ENC_BUFFER_FUL_RET_V6 16
> +#define S5P_FIMV_R2H_CMD_ERR_RET_V6 32
> +
> +#define S5P_FIMV_FW_VERSION_V6 0xf000
> +
> +#define S5P_FIMV_INSTANCE_ID_V6 0xf008
> +#define S5P_FIMV_CODEC_TYPE_V6 0xf00c
> +#define S5P_FIMV_CONTEXT_MEM_ADDR_V6 0xf014
> +#define S5P_FIMV_CONTEXT_MEM_SIZE_V6 0xf018
> +#define S5P_FIMV_PIXEL_FORMAT_V6 0xf020
> +
> +#define S5P_FIMV_METADATA_ENABLE_V6 0xf024
> +#define S5P_FIMV_DBG_BUFFER_ADDR_V6 0xf030
> +#define S5P_FIMV_DBG_BUFFER_SIZE_V6 0xf034
> +#define S5P_FIMV_RET_INSTANCE_ID_V6 0xf070
> +
> +#define S5P_FIMV_ERROR_CODE_V6 0xf074
> +#define S5P_FIMV_ERR_WARNINGS_START_V6 160
> +#define S5P_FIMV_ERR_DEC_MASK_V6 0xffff
> +#define S5P_FIMV_ERR_DEC_SHIFT_V6 0
> +#define S5P_FIMV_ERR_DSPL_MASK_V6 0xffff0000
> +#define S5P_FIMV_ERR_DSPL_SHIFT_V6 16
> +
> +#define S5P_FIMV_DBG_BUFFER_OUTPUT_SIZE_V6 0xf078
> +#define S5P_FIMV_METADATA_STATUS_V6 0xf07C
> +#define S5P_FIMV_METADATA_ADDR_MB_INFO_V6 0xf080
> +#define S5P_FIMV_METADATA_SIZE_MB_INFO_V6 0xf084
> +
> +/* Decoder Registers */
> +#define S5P_FIMV_D_CRC_CTRL_V6 0xf0b0
> +#define S5P_FIMV_D_DEC_OPTIONS_V6 0xf0b4
> +#define S5P_FIMV_D_OPT_FMO_ASO_CTRL_MASK_V6 4
> +#define S5P_FIMV_D_OPT_DDELAY_EN_SHIFT_V6 3
> +#define S5P_FIMV_D_OPT_LF_CTRL_SHIFT_V6 1
> +#define S5P_FIMV_D_OPT_LF_CTRL_MASK_V6 0x3
> +#define S5P_FIMV_D_OPT_TILE_MODE_SHIFT_V6 0
> +
> +#define S5P_FIMV_D_DISPLAY_DELAY_V6 0xf0b8
> +
> +#define S5P_FIMV_D_SET_FRAME_WIDTH_V6 0xf0bc
> +#define S5P_FIMV_D_SET_FRAME_HEIGHT_V6 0xf0c0
> +
> +#define S5P_FIMV_D_SEI_ENABLE_V6 0xf0c4
> +
> +/* Buffer setting registers */
> +#define S5P_FIMV_D_MIN_NUM_DPB_V6 0xf0f0
> +#define S5P_FIMV_D_MIN_LUMA_DPB_SIZE_V6 0xf0f4
> +#define S5P_FIMV_D_MIN_CHROMA_DPB_SIZE_V6 0xf0f8
> +#define S5P_FIMV_D_MVC_NUM_VIEWS_V6 0xf0fc
> +#define S5P_FIMV_D_MIN_NUM_MV_V6 0xf100
> +#define S5P_FIMV_D_NUM_DPB_V6 0xf130
> +#define S5P_FIMV_D_LUMA_DPB_SIZE_V6 0xf134
> +#define S5P_FIMV_D_CHROMA_DPB_SIZE_V6 0xf138
> +#define S5P_FIMV_D_MV_BUFFER_SIZE_V6 0xf13c
> +
> +#define S5P_FIMV_D_LUMA_DPB_V6 0xf140
> +#define S5P_FIMV_D_CHROMA_DPB_V6 0xf240
> +#define S5P_FIMV_D_MV_BUFFER_V6 0xf340
> +
> +#define S5P_FIMV_D_SCRATCH_BUFFER_ADDR_V6 0xf440
> +#define S5P_FIMV_D_SCRATCH_BUFFER_SIZE_V6 0xf444
> +#define S5P_FIMV_D_METADATA_BUFFER_ADDR_V6 0xf448
> +#define S5P_FIMV_D_METADATA_BUFFER_SIZE_V6 0xf44c
> +#define S5P_FIMV_D_NUM_MV_V6 0xf478
> +#define S5P_FIMV_D_CPB_BUFFER_ADDR_V6 0xf4b0
> +#define S5P_FIMV_D_CPB_BUFFER_SIZE_V6 0xf4b4
> +
> +#define S5P_FIMV_D_AVAILABLE_DPB_FLAG_UPPER_V6 0xf4b8
> +#define S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER_V6 0xf4bc
> +#define S5P_FIMV_D_CPB_BUFFER_OFFSET_V6 0xf4c0
> +#define S5P_FIMV_D_SLICE_IF_ENABLE_V6 0xf4c4
> +#define S5P_FIMV_D_PICTURE_TAG_V6 0xf4c8
> +#define S5P_FIMV_D_STREAM_DATA_SIZE_V6 0xf4d0
> +
> +/* Display information register */
> +#define S5P_FIMV_D_DISPLAY_FRAME_WIDTH_V6 0xf500
> +#define S5P_FIMV_D_DISPLAY_FRAME_HEIGHT_V6 0xf504
> +
> +/* Display status */
> +#define S5P_FIMV_D_DISPLAY_STATUS_V6 0xf508
> +
> +#define S5P_FIMV_D_DISPLAY_LUMA_ADDR_V6 0xf50c
> +#define S5P_FIMV_D_DISPLAY_CHROMA_ADDR_V6 0xf510
> +
> +#define S5P_FIMV_D_DISPLAY_FRAME_TYPE_V6 0xf514
> +
> +#define S5P_FIMV_D_DISPLAY_CROP_INFO1_V6 0xf518
> +#define S5P_FIMV_D_DISPLAY_CROP_INFO2_V6 0xf51c
> +#define S5P_FIMV_D_DISPLAY_PICTURE_PROFILE_V6 0xf520
> +#define S5P_FIMV_D_DISPLAY_LUMA_CRC_TOP_V6 0xf524
> +#define S5P_FIMV_D_DISPLAY_CHROMA_CRC_TOP_V6 0xf528
> +#define S5P_FIMV_D_DISPLAY_LUMA_CRC_BOT_V6 0xf52c
> +#define S5P_FIMV_D_DISPLAY_CHROMA_CRC_BOT_V6 0xf530
> +#define S5P_FIMV_D_DISPLAY_ASPECT_RATIO_V6 0xf534
> +#define S5P_FIMV_D_DISPLAY_EXTENDED_AR_V6 0xf538
> +
> +/* Decoded picture information register */
> +#define S5P_FIMV_D_DECODED_FRAME_WIDTH_V6 0xf53c
> +#define S5P_FIMV_D_DECODED_FRAME_HEIGHT_V6 0xf540
> +#define S5P_FIMV_D_DECODED_STATUS_V6 0xf544
> +#define S5P_FIMV_DEC_CRC_GEN_MASK_V6 0x1
> +#define S5P_FIMV_DEC_CRC_GEN_SHIFT_V6 6
> +
> +#define S5P_FIMV_D_DECODED_LUMA_ADDR_V6 0xf548
> +#define S5P_FIMV_D_DECODED_CHROMA_ADDR_V6 0xf54c
> +
> +#define S5P_FIMV_D_DECODED_FRAME_TYPE_V6 0xf550
> +#define S5P_FIMV_DECODE_FRAME_MASK_V6 7
> +
> +#define S5P_FIMV_D_DECODED_CROP_INFO1_V6 0xf554
> +#define S5P_FIMV_D_DECODED_CROP_INFO2_V6 0xf558
> +#define S5P_FIMV_D_DECODED_PICTURE_PROFILE_V6 0xf55c
> +#define S5P_FIMV_D_DECODED_NAL_SIZE_V6 0xf560
> +#define S5P_FIMV_D_DECODED_LUMA_CRC_TOP_V6 0xf564
> +#define S5P_FIMV_D_DECODED_CHROMA_CRC_TOP_V6 0xf568
> +#define S5P_FIMV_D_DECODED_LUMA_CRC_BOT_V6 0xf56c
> +#define S5P_FIMV_D_DECODED_CHROMA_CRC_BOT_V6 0xf570
> +
> +/* Returned value register for specific setting */
> +#define S5P_FIMV_D_RET_PICTURE_TAG_TOP_V6 0xf574
> +#define S5P_FIMV_D_RET_PICTURE_TAG_BOT_V6 0xf578
> +#define S5P_FIMV_D_RET_PICTURE_TIME_TOP_V6 0xf57c
> +#define S5P_FIMV_D_RET_PICTURE_TIME_BOT_V6 0xf580
> +#define S5P_FIMV_D_CHROMA_FORMAT_V6 0xf588
> +#define S5P_FIMV_D_MPEG4_INFO_V6 0xf58c
> +#define S5P_FIMV_D_H264_INFO_V6 0xf590
> +
> +#define S5P_FIMV_D_METADATA_ADDR_CONCEALED_MB_V6 0xf594
> +#define S5P_FIMV_D_METADATA_SIZE_CONCEALED_MB_V6 0xf598
> +#define S5P_FIMV_D_METADATA_ADDR_VC1_PARAM_V6 0xf59c
> +#define S5P_FIMV_D_METADATA_SIZE_VC1_PARAM_V6 0xf5a0
> +#define S5P_FIMV_D_METADATA_ADDR_SEI_NAL_V6 0xf5a4
> +#define S5P_FIMV_D_METADATA_SIZE_SEI_NAL_V6 0xf5a8
> +#define S5P_FIMV_D_METADATA_ADDR_VUI_V6 0xf5ac
> +#define S5P_FIMV_D_METADATA_SIZE_VUI_V6 0xf5b0
> +
> +#define S5P_FIMV_D_MVC_VIEW_ID_V6 0xf5b4
> +
> +/* SEI related information */
> +#define S5P_FIMV_D_FRAME_PACK_SEI_AVAIL_V6 0xf5f0
> +#define S5P_FIMV_D_FRAME_PACK_ARRGMENT_ID_V6 0xf5f4
> +#define S5P_FIMV_D_FRAME_PACK_SEI_INFO_V6 0xf5f8
> +#define S5P_FIMV_D_FRAME_PACK_GRID_POS_V6 0xf5fc
> +
> +/* Encoder Registers */
> +#define S5P_FIMV_E_FRAME_WIDTH_V6 0xf770
> +#define S5P_FIMV_E_FRAME_HEIGHT_V6 0xf774
> +#define S5P_FIMV_E_CROPPED_FRAME_WIDTH_V6 0xf778
> +#define S5P_FIMV_E_CROPPED_FRAME_HEIGHT_V6 0xf77c
> +#define S5P_FIMV_E_FRAME_CROP_OFFSET_V6 0xf780
> +#define S5P_FIMV_E_ENC_OPTIONS_V6 0xf784
> +#define S5P_FIMV_E_PICTURE_PROFILE_V6 0xf788
> +#define S5P_FIMV_E_FIXED_PICTURE_QP_V6 0xf790
> +
> +#define S5P_FIMV_E_RC_CONFIG_V6 0xf794
> +#define S5P_FIMV_E_RC_QP_BOUND_V6 0xf798
> +#define S5P_FIMV_E_RC_RPARAM_V6 0xf79c
> +#define S5P_FIMV_E_MB_RC_CONFIG_V6 0xf7a0
> +#define S5P_FIMV_E_PADDING_CTRL_V6 0xf7a4
> +#define S5P_FIMV_E_MV_HOR_RANGE_V6 0xf7ac
> +#define S5P_FIMV_E_MV_VER_RANGE_V6 0xf7b0
> +
> +#define S5P_FIMV_E_VBV_BUFFER_SIZE_V6 0xf84c
> +#define S5P_FIMV_E_VBV_INIT_DELAY_V6 0xf850
> +#define S5P_FIMV_E_NUM_DPB_V6 0xf890
> +#define S5P_FIMV_E_LUMA_DPB_V6 0xf8c0
> +#define S5P_FIMV_E_CHROMA_DPB_V6 0xf904
> +#define S5P_FIMV_E_ME_BUFFER_V6 0xf948
> +
> +#define S5P_FIMV_E_SCRATCH_BUFFER_ADDR_V6 0xf98c
> +#define S5P_FIMV_E_SCRATCH_BUFFER_SIZE_V6 0xf990
> +#define S5P_FIMV_E_TMV_BUFFER0_V6 0xf994
> +#define S5P_FIMV_E_TMV_BUFFER1_V6 0xf998
> +#define S5P_FIMV_E_SOURCE_LUMA_ADDR_V6 0xf9f0
> +#define S5P_FIMV_E_SOURCE_CHROMA_ADDR_V6 0xf9f4
> +#define S5P_FIMV_E_STREAM_BUFFER_ADDR_V6 0xf9f8
> +#define S5P_FIMV_E_STREAM_BUFFER_SIZE_V6 0xf9fc
> +#define S5P_FIMV_E_ROI_BUFFER_ADDR_V6 0xfA00
> +
> +#define S5P_FIMV_E_PARAM_CHANGE_V6 0xfa04
> +#define S5P_FIMV_E_IR_SIZE_V6 0xfa08
> +#define S5P_FIMV_E_GOP_CONFIG_V6 0xfa0c
> +#define S5P_FIMV_E_MSLICE_MODE_V6 0xfa10
> +#define S5P_FIMV_E_MSLICE_SIZE_MB_V6 0xfa14
> +#define S5P_FIMV_E_MSLICE_SIZE_BITS_V6 0xfa18
> +#define S5P_FIMV_E_FRAME_INSERTION_V6 0xfa1c
> +
> +#define S5P_FIMV_E_RC_FRAME_RATE_V6 0xfa20
> +#define S5P_FIMV_E_RC_BIT_RATE_V6 0xfa24
> +#define S5P_FIMV_E_RC_QP_OFFSET_V6 0xfa28
> +#define S5P_FIMV_E_RC_ROI_CTRL_V6 0xfa2c
> +#define S5P_FIMV_E_PICTURE_TAG_V6 0xfa30
> +#define S5P_FIMV_E_BIT_COUNT_ENABLE_V6 0xfa34
> +#define S5P_FIMV_E_MAX_BIT_COUNT_V6 0xfa38
> +#define S5P_FIMV_E_MIN_BIT_COUNT_V6 0xfa3c
> +
> +#define S5P_FIMV_E_METADATA_BUFFER_ADDR_V6 0xfa40
> +#define S5P_FIMV_E_METADATA_BUFFER_SIZE_V6 0xfa44
> +#define S5P_FIMV_E_STREAM_SIZE_V6 0xfa80
> +#define S5P_FIMV_E_SLICE_TYPE_V6 0xfa84
> +#define S5P_FIMV_E_PICTURE_COUNT_V6 0xfa88
> +#define S5P_FIMV_E_RET_PICTURE_TAG_V6 0xfa8c
> +#define S5P_FIMV_E_STREAM_BUFFER_WRITE_POINTER_V6 0xfa90
> +
> +#define S5P_FIMV_E_ENCODED_SOURCE_LUMA_ADDR_V6 0xfa94
> +#define S5P_FIMV_E_ENCODED_SOURCE_CHROMA_ADDR_V6 0xfa98
> +#define S5P_FIMV_E_RECON_LUMA_DPB_ADDR_V6 0xfa9c
> +#define S5P_FIMV_E_RECON_CHROMA_DPB_ADDR_V6 0xfaa0
> +#define S5P_FIMV_E_METADATA_ADDR_ENC_SLICE_V6 0xfaa4
> +#define S5P_FIMV_E_METADATA_SIZE_ENC_SLICE_V6 0xfaa8
> +
> +#define S5P_FIMV_E_MPEG4_OPTIONS_V6 0xfb10
> +#define S5P_FIMV_E_MPEG4_HEC_PERIOD_V6 0xfb14
> +#define S5P_FIMV_E_ASPECT_RATIO_V6 0xfb50
> +#define S5P_FIMV_E_EXTENDED_SAR_V6 0xfb54
> +
> +#define S5P_FIMV_E_H264_OPTIONS_V6 0xfb58
> +#define S5P_FIMV_E_H264_LF_ALPHA_OFFSET_V6 0xfb5c
> +#define S5P_FIMV_E_H264_LF_BETA_OFFSET_V6 0xfb60
> +#define S5P_FIMV_E_H264_I_PERIOD_V6 0xfb64
> +
> +#define S5P_FIMV_E_H264_FMO_SLICE_GRP_MAP_TYPE_V6 0xfb68
> +#define S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1_V6 0xfb6c
> +#define S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_DIR_V6 0xfb70
> +#define S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_RATE_MINUS1_V6 0xfb74
> +#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_0_V6 0xfb78
> +#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_1_V6 0xfb7c
> +#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_2_V6 0xfb80
> +#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_3_V6 0xfb84
> +
> +#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_0_V6 0xfb88
> +#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_1_V6 0xfb8c
> +#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_2_V6 0xfb90
> +#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_3_V6 0xfb94
> +#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_4_V6 0xfb98
> +#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_5_V6 0xfb9c
> +#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_6_V6 0xfba0
> +#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_7_V6 0xfba4
> +
> +#define S5P_FIMV_E_H264_CHROMA_QP_OFFSET_V6 0xfba8
> +#define S5P_FIMV_E_H264_NUM_T_LAYER_V6 0xfbac
> +
> +#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER0_V6 0xfbb0
> +#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER1_V6 0xfbb4
> +#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER2_V6 0xfbb8
> +#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER3_V6 0xfbbc
> +#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER4_V6 0xfbc0
> +#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER5_V6 0xfbc4
> +#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER6_V6 0xfbc8
> +
> +#define S5P_FIMV_E_H264_FRAME_PACKING_SEI_INFO_V6 0xfc4c
> +#define S5P_FIMV_ENC_FP_ARRANGEMENT_TYPE_SIDE_BY_SIDE_V6 0
> +#define S5P_FIMV_ENC_FP_ARRANGEMENT_TYPE_TOP_BOTTOM_V6 1
> +#define S5P_FIMV_ENC_FP_ARRANGEMENT_TYPE_TEMPORAL_V6 2
> +
> +#define S5P_FIMV_E_MVC_FRAME_QP_VIEW1_V6 0xfd40
> +#define S5P_FIMV_E_MVC_RC_FRAME_RATE_VIEW1_V6 0xfd44
> +#define S5P_FIMV_E_MVC_RC_BIT_RATE_VIEW1_V6 0xfd48
> +#define S5P_FIMV_E_MVC_RC_QBOUND_VIEW1_V6 0xfd4c
> +#define S5P_FIMV_E_MVC_RC_RPARA_VIEW1_V6 0xfd50
> +#define S5P_FIMV_E_MVC_INTER_VIEW_PREDICTION_ON_V6 0xfd80
> +
> +/* Codec numbers */
> +#define S5P_FIMV_CODEC_NONE_V6 -1
> +
> +
> +#define S5P_FIMV_CODEC_H264_DEC_V6 0
> +#define S5P_FIMV_CODEC_H264_MVC_DEC_V6 1
> +
> +#define S5P_FIMV_CODEC_MPEG4_DEC_V6 3
> +#define S5P_FIMV_CODEC_FIMV1_DEC_V6 4
> +#define S5P_FIMV_CODEC_FIMV2_DEC_V6 5
> +#define S5P_FIMV_CODEC_FIMV3_DEC_V6 6
> +#define S5P_FIMV_CODEC_FIMV4_DEC_V6 7
> +#define S5P_FIMV_CODEC_H263_DEC_V6 8
> +#define S5P_FIMV_CODEC_VC1RCV_DEC_V6 9
> +#define S5P_FIMV_CODEC_VC1_DEC_V6 10
> +/* FIXME: Add 11~12 */
> +#define S5P_FIMV_CODEC_MPEG2_DEC_V6 13
> +#define S5P_FIMV_CODEC_VP8_DEC_V6 14
> +/* FIXME: Add 15~16 */
> +#define S5P_FIMV_CODEC_H264_ENC_V6 20
> +#define S5P_FIMV_CODEC_H264_MVC_ENC_V6 21
> +
> +#define S5P_FIMV_CODEC_MPEG4_ENC_V6 23
> +#define S5P_FIMV_CODEC_H263_ENC_V6 24
> +
> +#define S5P_FIMV_NV12M_HALIGN_V6 16
> +#define S5P_FIMV_NV12MT_HALIGN_V6 16
> +#define S5P_FIMV_NV12MT_VALIGN_V6 16
> +
> +#define S5P_FIMV_TMV_BUFFER_ALIGN_V6 16
> +#define S5P_FIMV_LUMA_DPB_BUFFER_ALIGN_V6 256
> +#define S5P_FIMV_CHROMA_DPB_BUFFER_ALIGN_V6 256
> +#define S5P_FIMV_ME_BUFFER_ALIGN_V6 256
> +#define S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6 256
> +
> +#define S5P_FIMV_LUMA_MB_TO_PIXEL_V6 256
> +#define S5P_FIMV_CHROMA_MB_TO_PIXEL_V6 128
> +#define S5P_FIMV_NUM_TMV_BUFFERS_V6 2
> +
> +#define S5P_FIMV_MAX_FRAME_SIZE_V6 (2 * SZ_1M)
> +#define S5P_FIMV_NUM_PIXELS_IN_MB_ROW_V6 16
> +#define S5P_FIMV_NUM_PIXELS_IN_MB_COL_V6 16
> +
> +/* Buffer size requirements defined by hardware */
> +#define S5P_FIMV_TMV_BUFFER_SIZE_V6(w, h) (((w) + 1) * ((h) + 1) * 8)
> +#define S5P_FIMV_ME_BUFFER_SIZE_V6(imw, imh, mbw, mbh) \
> + ((DIV_ROUND_UP(imw, 64) * DIV_ROUND_UP(imh, 64) * 256) + \
> + (DIV_ROUND_UP((mbw) * (mbh), 32) * 16))
> +#define S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V6(w, h) (((w) * 192) + 64)
> +#define S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V6(w, h) \
> + ((w) * ((h) * 64 + 144) + (2048/16 * (h) * 64) + \
> + (2048/16 * 256 + 8320))
> +#define S5P_FIMV_SCRATCH_BUF_SIZE_VC1_DEC_V6(w, h) \
> + (2096 * ((w) + (h) + 1))
> +#define S5P_FIMV_SCRATCH_BUF_SIZE_H263_DEC_V6(w, h) ((w) * 400)
> +#define S5P_FIMV_SCRATCH_BUF_SIZE_VP8_DEC_V6(w, h) \
> + ((w) * 32 + (h) * 128 + (((w) + 1) / 2) * 64 + 2112)
> +#define S5P_FIMV_SCRATCH_BUF_SIZE_H264_ENC_V6(w, h) \
> + (((w) * 64) + (((w) + 1) * 16) + (4096 * 16))
> +#define S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_ENC_V6(w, h) \
> + (((w) * 16) + (((w) + 1) * 16))
> +
> +/* MFC Context buffer sizes */
> +#define MFC_CTX_BUF_SIZE_V6 (28 * SZ_1K) /* 28KB */
> +#define MFC_H264_DEC_CTX_BUF_SIZE_V6 (2 * SZ_1M) /* 2MB */
> +#define MFC_OTHER_DEC_CTX_BUF_SIZE_V6 (20 * SZ_1K) /* 20KB */
> +#define MFC_H264_ENC_CTX_BUF_SIZE_V6 (100 * SZ_1K) /* 100KB */
> +#define MFC_OTHER_ENC_CTX_BUF_SIZE_V6 (12 * SZ_1K) /* 12KB */
> +
> +/* MFCv6 variant defines */
> +#define MAX_FW_SIZE_V6 (SZ_1M) /* 1MB */
> +#define MAX_CPB_SIZE_V6 (3 * SZ_1M) /* 3MB */
> +#define MFC_VERSION_V6 0x61
> +#define MFC_NUM_PORTS_V6 1
> +
> +#endif /* _REGS_FIMV_V6_H */
> --
> 1.7.0.4
^ permalink raw reply [flat|nested] 15+ messages in thread
* RE: [PATCH v9 6/6] [media] s5p-mfc: Update MFC v4l2 driver to support MFC6.x
2012-10-02 14:55 ` [PATCH v9 6/6] [media] s5p-mfc: Update MFC v4l2 driver to support MFC6.x Arun Kumar K
@ 2012-10-02 11:16 ` Kamil Debski
0 siblings, 0 replies; 15+ messages in thread
From: Kamil Debski @ 2012-10-02 11:16 UTC (permalink / raw)
To: 'Arun Kumar K', linux-media
Cc: jtp.park, janghyuck.kim, jaeryul.oh, ch.naveen, Marek Szyprowski,
Sylwester Nawrocki, hverkuil, kmpark, joshi
> From: Arun Kumar K [mailto:arun.kk@samsung.com]
> Sent: 02 October 2012 16:56
>
> From: Jeongtae Park <jtp.park@samsung.com>
>
> Multi Format Codec 6.x is a hardware video coding acceleration
> module present in new Exynos5 SoC series. It is capable of
> handling several new video codecs for decoding and encoding
>
> Signed-off-by: Jeongtae Park <jtp.park@samsung.com>
> Signed-off-by: Janghyuck Kim <janghyuck.kim@samsung.com>
> Signed-off-by: Jaeryul Oh <jaeryul.oh@samsung.com>
> Signed-off-by: Naveen Krishna Chatradhi <ch.naveen@samsung.com>
> Signed-off-by: Arun Kumar K <arun.kk@samsung.com>
Acked-by: Kamil Debski <k.debski@samsung.com>
> ---
> drivers/media/platform/Kconfig | 4 +-
> drivers/media/platform/s5p-mfc/Makefile | 8 +-
> drivers/media/platform/s5p-mfc/regs-mfc.h | 21 +
> drivers/media/platform/s5p-mfc/s5p_mfc.c | 64 +-
> drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c | 7 +-
> drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c | 156 ++
> drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h | 20 +
> drivers/media/platform/s5p-mfc/s5p_mfc_common.h | 61 +-
> drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c | 154 ++-
> drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 193 ++-
> drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | 139 ++-
> drivers/media/platform/s5p-mfc/s5p_mfc_opr.c | 10 +-
> drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c | 1956
+++++++++++++++++++++++
> drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h | 50 +
> drivers/media/platform/s5p-mfc/s5p_mfc_pm.c | 3 +-
> 15 files changed, 2678 insertions(+), 168 deletions(-)
> create mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c
> create mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h
> create mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
> create mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h
>
> diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
> index f588d62..181c768 100644
> --- a/drivers/media/platform/Kconfig
> +++ b/drivers/media/platform/Kconfig
> @@ -165,12 +165,12 @@ config VIDEO_SAMSUNG_S5P_JPEG
> This is a v4l2 driver for Samsung S5P and EXYNOS4 JPEG codec
>
> config VIDEO_SAMSUNG_S5P_MFC
> - tristate "Samsung S5P MFC 5.1 Video Codec"
> + tristate "Samsung S5P MFC Video Codec"
> depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P
> select VIDEOBUF2_DMA_CONTIG
> default n
> help
> - MFC 5.1 driver for V4L2.
> + MFC 5.1 and 6.x driver for V4L2
>
> config VIDEO_MX2_EMMAPRP
> tristate "MX2 eMMa-PrP support"
> diff --git a/drivers/media/platform/s5p-mfc/Makefile
> b/drivers/media/platform/s5p-mfc/Makefile
> index cfb9ee9..379008c 100644
> --- a/drivers/media/platform/s5p-mfc/Makefile
> +++ b/drivers/media/platform/s5p-mfc/Makefile
> @@ -1,6 +1,6 @@
> obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) := s5p-mfc.o
> -s5p-mfc-y += s5p_mfc.o s5p_mfc_intr.o s5p_mfc_opr.o
> +s5p-mfc-y += s5p_mfc.o s5p_mfc_intr.o
> s5p-mfc-y += s5p_mfc_dec.o s5p_mfc_enc.o
> -s5p-mfc-y += s5p_mfc_ctrl.o s5p_mfc_cmd.o
> -s5p-mfc-y += s5p_mfc_pm.o
> -s5p-mfc-y += s5p_mfc_opr_v5.o s5p_mfc_cmd_v5.o
> +s5p-mfc-y += s5p_mfc_ctrl.o s5p_mfc_pm.o
> +s5p-mfc-y += s5p_mfc_opr.o s5p_mfc_opr_v5.o s5p_mfc_opr_v6.o
> +s5p-mfc-y += s5p_mfc_cmd.o s5p_mfc_cmd_v5.o s5p_mfc_cmd_v6.o
> diff --git a/drivers/media/platform/s5p-mfc/regs-mfc.h
> b/drivers/media/platform/s5p-mfc/regs-mfc.h
> index f33c54d..9319e93 100644
> --- a/drivers/media/platform/s5p-mfc/regs-mfc.h
> +++ b/drivers/media/platform/s5p-mfc/regs-mfc.h
> @@ -147,6 +147,7 @@
> #define S5P_FIMV_ENC_PROFILE_H264_MAIN 0
> #define S5P_FIMV_ENC_PROFILE_H264_HIGH 1
> #define S5P_FIMV_ENC_PROFILE_H264_BASELINE 2
> +#define S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_BASELINE 3
> #define S5P_FIMV_ENC_PROFILE_MPEG4_SIMPLE 0
> #define S5P_FIMV_ENC_PROFILE_MPEG4_ADVANCED_SIMPLE 1
> #define S5P_FIMV_ENC_PIC_STRUCT 0x083c /* picture field/frame
flag */
> @@ -216,6 +217,7 @@
> #define S5P_FIMV_DEC_STATUS_RESOLUTION_MASK (3<<4)
> #define S5P_FIMV_DEC_STATUS_RESOLUTION_INC (1<<4)
> #define S5P_FIMV_DEC_STATUS_RESOLUTION_DEC (2<<4)
> +#define S5P_FIMV_DEC_STATUS_RESOLUTION_SHIFT 4
>
> /* Decode frame address */
> #define S5P_FIMV_DECODE_Y_ADR 0x2024
> @@ -380,6 +382,16 @@
> #define S5P_FIMV_R2H_CMD_EDFU_INIT_RET 16
> #define S5P_FIMV_R2H_CMD_ERR_RET 32
>
> +/* Dummy definition for MFCv6 compatibilty */
> +#define S5P_FIMV_CODEC_H264_MVC_DEC -1
> +#define S5P_FIMV_R2H_CMD_FIELD_DONE_RET -1
> +#define S5P_FIMV_MFC_RESET -1
> +#define S5P_FIMV_RISC_ON -1
> +#define S5P_FIMV_RISC_BASE_ADDRESS -1
> +#define S5P_FIMV_CODEC_VP8_DEC -1
> +#define S5P_FIMV_REG_CLEAR_BEGIN 0
> +#define S5P_FIMV_REG_CLEAR_COUNT 0
> +
> /* Error handling defines */
> #define S5P_FIMV_ERR_WARNINGS_START 145
> #define S5P_FIMV_ERR_DEC_MASK 0xFFFF
> @@ -435,4 +447,13 @@
> #define MFC_VERSION 0x51
> #define MFC_NUM_PORTS 2
>
> +#define S5P_FIMV_SHARED_FRAME_PACK_SEI_AVAIL 0x16C
> +#define S5P_FIMV_SHARED_FRAME_PACK_ARRGMENT_ID 0x170
> +#define S5P_FIMV_SHARED_FRAME_PACK_SEI_INFO 0x174
> +#define S5P_FIMV_SHARED_FRAME_PACK_GRID_POS 0x178
> +
> +/* Values for resolution change in display status */
> +#define S5P_FIMV_RES_INCREASE 1
> +#define S5P_FIMV_RES_DECREASE 2
> +
> #endif /* _REGS_FIMV_H */
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c
> b/drivers/media/platform/s5p-mfc/s5p_mfc.c
> index a8299ce..d922e1c 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
> @@ -289,12 +289,14 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx
*ctx,
>
> dst_frame_status = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev)
> & S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK;
> - res_change = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev)
> - & S5P_FIMV_DEC_STATUS_RESOLUTION_MASK;
> + res_change = (s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev)
> + & S5P_FIMV_DEC_STATUS_RESOLUTION_MASK)
> + >> S5P_FIMV_DEC_STATUS_RESOLUTION_SHIFT;
> mfc_debug(2, "Frame Status: %x\n", dst_frame_status);
> if (ctx->state == MFCINST_RES_CHANGE_INIT)
> ctx->state = MFCINST_RES_CHANGE_FLUSH;
> - if (res_change) {
> + if (res_change == S5P_FIMV_RES_INCREASE ||
> + res_change == S5P_FIMV_RES_DECREASE) {
> ctx->state = MFCINST_RES_CHANGE_INIT;
> s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
> wake_up_ctx(ctx, reason, err);
> @@ -453,10 +455,28 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx
> *ctx,
>
> ctx->dpb_count = s5p_mfc_hw_call(dev->mfc_ops, get_dpb_count,
> dev);
> + ctx->mv_count = s5p_mfc_hw_call(dev->mfc_ops, get_mv_count,
> + dev);
> if (ctx->img_width == 0 || ctx->img_height == 0)
> ctx->state = MFCINST_ERROR;
> else
> ctx->state = MFCINST_HEAD_PARSED;
> +
> + if ((ctx->codec_mode == S5P_MFC_CODEC_H264_DEC ||
> + ctx->codec_mode == S5P_MFC_CODEC_H264_MVC_DEC) &&
> + !list_empty(&ctx->src_queue)) {
> + struct s5p_mfc_buf *src_buf;
> + src_buf = list_entry(ctx->src_queue.next,
> + struct s5p_mfc_buf, list);
> + if (s5p_mfc_hw_call(dev->mfc_ops, get_consumed_stream,
> + dev) <
> + src_buf->b->v4l2_planes[0].bytesused)
> + ctx->head_processed = 0;
> + else
> + ctx->head_processed = 1;
> + } else {
> + ctx->head_processed = 1;
> + }
> }
> s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
> clear_work_bit(ctx);
> @@ -487,7 +507,7 @@ static void s5p_mfc_handle_init_buffers(struct
s5p_mfc_ctx
> *ctx,
> spin_unlock(&dev->condlock);
> if (err == 0) {
> ctx->state = MFCINST_RUNNING;
> - if (!ctx->dpb_flush_flag) {
> + if (!ctx->dpb_flush_flag && ctx->head_processed) {
> spin_lock_irqsave(&dev->irqlock, flags);
> if (!list_empty(&ctx->src_queue)) {
> src_buf = list_entry(ctx->src_queue.next,
> @@ -998,6 +1018,7 @@ static int s5p_mfc_probe(struct platform_device *pdev)
> ret = -ENODEV;
> goto err_res;
> }
> +
> dev->mem_dev_r = device_find_child(&dev->plat_dev->dev, "s5p-mfc-r",
> match_child);
> if (!dev->mem_dev_r) {
> @@ -1227,12 +1248,47 @@ static struct s5p_mfc_variant mfc_drvdata_v5 = {
> .port_num = MFC_NUM_PORTS,
> .buf_size = &buf_size_v5,
> .buf_align = &mfc_buf_align_v5,
> + .mclk_name = "sclk_mfc",
> + .fw_name = "s5p-mfc.fw",
> +};
> +
> +struct s5p_mfc_buf_size_v6 mfc_buf_size_v6 = {
> + .dev_ctx = MFC_CTX_BUF_SIZE_V6,
> + .h264_dec_ctx = MFC_H264_DEC_CTX_BUF_SIZE_V6,
> + .other_dec_ctx = MFC_OTHER_DEC_CTX_BUF_SIZE_V6,
> + .h264_enc_ctx = MFC_H264_ENC_CTX_BUF_SIZE_V6,
> + .other_enc_ctx = MFC_OTHER_ENC_CTX_BUF_SIZE_V6,
> +};
> +
> +struct s5p_mfc_buf_size buf_size_v6 = {
> + .fw = MAX_FW_SIZE_V6,
> + .cpb = MAX_CPB_SIZE_V6,
> + .priv = &mfc_buf_size_v6,
> +};
> +
> +struct s5p_mfc_buf_align mfc_buf_align_v6 = {
> + .base = 0,
> +};
> +
> +static struct s5p_mfc_variant mfc_drvdata_v6 = {
> + .version = MFC_VERSION_V6,
> + .port_num = MFC_NUM_PORTS_V6,
> + .buf_size = &buf_size_v6,
> + .buf_align = &mfc_buf_align_v6,
> + .mclk_name = "aclk_333",
> + .fw_name = "s5p-mfc-v6.fw",
> };
>
> static struct platform_device_id mfc_driver_ids[] = {
> {
> .name = "s5p-mfc",
> .driver_data = (unsigned long)&mfc_drvdata_v5,
> + }, {
> + .name = "s5p-mfc-v5",
> + .driver_data = (unsigned long)&mfc_drvdata_v5,
> + }, {
> + .name = "s5p-mfc-v6",
> + .driver_data = (unsigned long)&mfc_drvdata_v6,
> },
> {},
> };
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c
> b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c
> index 47b956d..deed3b7 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c
> @@ -14,11 +14,16 @@
> #include "s5p_mfc_common.h"
> #include "s5p_mfc_debug.h"
> #include "s5p_mfc_cmd_v5.h"
> +#include "s5p_mfc_cmd_v6.h"
>
> static struct s5p_mfc_hw_cmds *s5p_mfc_cmds;
>
> void s5p_mfc_init_hw_cmds(struct s5p_mfc_dev *dev)
> {
> - s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v5();
> + if (IS_MFCV6(dev))
> + s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v6();
> + else
> + s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v5();
> +
> dev->mfc_cmds = s5p_mfc_cmds;
> }
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c
> b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c
> new file mode 100644
> index 0000000..754bfbc
> --- /dev/null
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c
> @@ -0,0 +1,156 @@
> +/*
> + * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c
> + *
> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
> + * http://www.samsung.com/
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include "s5p_mfc_common.h"
> +
> +#include "s5p_mfc_cmd.h"
> +#include "s5p_mfc_debug.h"
> +#include "s5p_mfc_intr.h"
> +#include "s5p_mfc_opr.h"
> +
> +int s5p_mfc_cmd_host2risc_v6(struct s5p_mfc_dev *dev, int cmd,
> + struct s5p_mfc_cmd_args *args)
> +{
> + mfc_debug(2, "Issue the command: %d\n", cmd);
> +
> + /* Reset RISC2HOST command */
> + mfc_write(dev, 0x0, S5P_FIMV_RISC2HOST_CMD_V6);
> +
> + /* Issue the command */
> + mfc_write(dev, cmd, S5P_FIMV_HOST2RISC_CMD_V6);
> + mfc_write(dev, 0x1, S5P_FIMV_HOST2RISC_INT_V6);
> +
> + return 0;
> +}
> +
> +int s5p_mfc_sys_init_cmd_v6(struct s5p_mfc_dev *dev)
> +{
> + struct s5p_mfc_cmd_args h2r_args;
> + struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv;
> +
> + s5p_mfc_hw_call(dev->mfc_ops, alloc_dev_context_buffer, dev);
> + mfc_write(dev, dev->ctx_buf.dma, S5P_FIMV_CONTEXT_MEM_ADDR_V6);
> + mfc_write(dev, buf_size->dev_ctx, S5P_FIMV_CONTEXT_MEM_SIZE_V6);
> + return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_SYS_INIT_V6,
> + &h2r_args);
> +}
> +
> +int s5p_mfc_sleep_cmd_v6(struct s5p_mfc_dev *dev)
> +{
> + struct s5p_mfc_cmd_args h2r_args;
> +
> + memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
> + return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_SLEEP_V6,
> + &h2r_args);
> +}
> +
> +int s5p_mfc_wakeup_cmd_v6(struct s5p_mfc_dev *dev)
> +{
> + struct s5p_mfc_cmd_args h2r_args;
> +
> + memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
> + return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_WAKEUP_V6,
> + &h2r_args);
> +}
> +
> +/* Open a new instance and get its number */
> +int s5p_mfc_open_inst_cmd_v6(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_cmd_args h2r_args;
> + int codec_type;
> +
> + mfc_debug(2, "Requested codec mode: %d\n", ctx->codec_mode);
> + dev->curr_ctx = ctx->num;
> + switch (ctx->codec_mode) {
> + case S5P_MFC_CODEC_H264_DEC:
> + codec_type = S5P_FIMV_CODEC_H264_DEC_V6;
> + break;
> + case S5P_MFC_CODEC_H264_MVC_DEC:
> + codec_type = S5P_FIMV_CODEC_H264_MVC_DEC_V6;
> + break;
> + case S5P_MFC_CODEC_VC1_DEC:
> + codec_type = S5P_FIMV_CODEC_VC1_DEC_V6;
> + break;
> + case S5P_MFC_CODEC_MPEG4_DEC:
> + codec_type = S5P_FIMV_CODEC_MPEG4_DEC_V6;
> + break;
> + case S5P_MFC_CODEC_MPEG2_DEC:
> + codec_type = S5P_FIMV_CODEC_MPEG2_DEC_V6;
> + break;
> + case S5P_MFC_CODEC_H263_DEC:
> + codec_type = S5P_FIMV_CODEC_H263_DEC_V6;
> + break;
> + case S5P_MFC_CODEC_VC1RCV_DEC:
> + codec_type = S5P_FIMV_CODEC_VC1RCV_DEC_V6;
> + break;
> + case S5P_MFC_CODEC_VP8_DEC:
> + codec_type = S5P_FIMV_CODEC_VP8_DEC_V6;
> + break;
> + case S5P_MFC_CODEC_H264_ENC:
> + codec_type = S5P_FIMV_CODEC_H264_ENC_V6;
> + break;
> + case S5P_MFC_CODEC_H264_MVC_ENC:
> + codec_type = S5P_FIMV_CODEC_H264_MVC_ENC_V6;
> + break;
> + case S5P_MFC_CODEC_MPEG4_ENC:
> + codec_type = S5P_FIMV_CODEC_MPEG4_ENC_V6;
> + break;
> + case S5P_MFC_CODEC_H263_ENC:
> + codec_type = S5P_FIMV_CODEC_H263_ENC_V6;
> + break;
> + default:
> + codec_type = S5P_FIMV_CODEC_NONE_V6;
> + };
> + mfc_write(dev, codec_type, S5P_FIMV_CODEC_TYPE_V6);
> + mfc_write(dev, ctx->ctx.dma, S5P_FIMV_CONTEXT_MEM_ADDR_V6);
> + mfc_write(dev, ctx->ctx.size, S5P_FIMV_CONTEXT_MEM_SIZE_V6);
> + mfc_write(dev, 0, S5P_FIMV_D_CRC_CTRL_V6); /* no crc */
> +
> + return s5p_mfc_cmd_host2risc_v6(dev,
S5P_FIMV_H2R_CMD_OPEN_INSTANCE_V6,
> + &h2r_args);
> +}
> +
> +/* Close instance */
> +int s5p_mfc_close_inst_cmd_v6(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_cmd_args h2r_args;
> + int ret = 0;
> +
> + dev->curr_ctx = ctx->num;
> + if (ctx->state != MFCINST_FREE) {
> + mfc_write(dev, ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
> + ret = s5p_mfc_cmd_host2risc_v6(dev,
> + S5P_FIMV_H2R_CMD_CLOSE_INSTANCE_V6,
> + &h2r_args);
> + } else {
> + ret = -EINVAL;
> + }
> +
> + return ret;
> +}
> +
> +/* Initialize cmd function pointers for MFC v6 */
> +static struct s5p_mfc_hw_cmds s5p_mfc_cmds_v6 = {
> + .cmd_host2risc = s5p_mfc_cmd_host2risc_v6,
> + .sys_init_cmd = s5p_mfc_sys_init_cmd_v6,
> + .sleep_cmd = s5p_mfc_sleep_cmd_v6,
> + .wakeup_cmd = s5p_mfc_wakeup_cmd_v6,
> + .open_inst_cmd = s5p_mfc_open_inst_cmd_v6,
> + .close_inst_cmd = s5p_mfc_close_inst_cmd_v6,
> +};
> +
> +struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v6(void)
> +{
> + return &s5p_mfc_cmds_v6;
> +}
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h
> b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h
> new file mode 100644
> index 0000000..b7a8e57
> --- /dev/null
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h
> @@ -0,0 +1,20 @@
> +/*
> + * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h
> + *
> + * Copyright (C) 2011 Samsung Electronics Co., Ltd.
> + * http://www.samsung.com/
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef S5P_MFC_CMD_V6_H_
> +#define S5P_MFC_CMD_V6_H_
> +
> +#include "s5p_mfc_common.h"
> +
> +struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v6(void);
> +
> +#endif /* S5P_MFC_CMD_H_ */
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
> b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
> index e9e89ac..3371f8a 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
> @@ -16,13 +16,14 @@
> #ifndef S5P_MFC_COMMON_H_
> #define S5P_MFC_COMMON_H_
>
> -#include "regs-mfc.h"
> #include <linux/platform_device.h>
> #include <linux/videodev2.h>
> #include <media/v4l2-ctrls.h>
> #include <media/v4l2-device.h>
> #include <media/v4l2-ioctl.h>
> #include <media/videobuf2-core.h>
> +#include "regs-mfc.h"
> +#include "regs-mfc-v6.h"
>
> /* Definitions related to MFC memory */
>
> @@ -203,6 +204,14 @@ struct s5p_mfc_buf_size_v5 {
> unsigned int shm;
> };
>
> +struct s5p_mfc_buf_size_v6 {
> + unsigned int dev_ctx;
> + unsigned int h264_dec_ctx;
> + unsigned int other_dec_ctx;
> + unsigned int h264_enc_ctx;
> + unsigned int other_enc_ctx;
> +};
> +
> struct s5p_mfc_buf_size {
> unsigned int fw;
> unsigned int cpb;
> @@ -218,6 +227,8 @@ struct s5p_mfc_variant {
> unsigned int port_num;
> struct s5p_mfc_buf_size *buf_size;
> struct s5p_mfc_buf_align *buf_align;
> + char *mclk_name;
> + char *fw_name;
> };
>
> /**
> @@ -274,6 +285,7 @@ struct s5p_mfc_priv_buf {
> * @watchdog_work: worker for the watchdog
> * @alloc_ctx: videobuf2 allocator contexts for two memory
banks
> * @enter_suspend: flag set when entering suspend
> + * @ctx_buf: common context memory (MFCv6)
> * @warn_start: hardware error code from which warnings start
> * @mfc_ops: ops structure holding HW operation function pointers
> * @mfc_cmds: cmd structure holding HW commands function
pointers
> @@ -315,6 +327,7 @@ struct s5p_mfc_dev {
> void *alloc_ctx[2];
> unsigned long enter_suspend;
>
> + struct s5p_mfc_priv_buf ctx_buf;
> int warn_start;
> struct s5p_mfc_hw_ops *mfc_ops;
> struct s5p_mfc_hw_cmds *mfc_cmds;
> @@ -351,6 +364,22 @@ struct s5p_mfc_h264_enc_params {
> int level;
> u16 cpb_size;
> int interlace;
> + u8 hier_qp;
> + u8 hier_qp_type;
> + u8 hier_qp_layer;
> + u8 hier_qp_layer_qp[7];
> + u8 sei_frame_packing;
> + u8 sei_fp_curr_frame_0;
> + u8 sei_fp_arrangement_type;
> +
> + u8 fmo;
> + u8 fmo_map_type;
> + u8 fmo_slice_grp;
> + u8 fmo_chg_dir;
> + u32 fmo_chg_rate;
> + u32 fmo_run_len[4];
> + u8 aso;
> + u32 aso_slice_order[8];
> };
>
> /**
> @@ -393,6 +422,7 @@ struct s5p_mfc_enc_params {
> u32 rc_bitrate;
> u16 rc_reaction_coeff;
> u16 vbv_size;
> + u32 vbv_delay;
>
> enum v4l2_mpeg_video_header_mode seq_hdr_mode;
> enum v4l2_mpeg_mfc51_video_frame_skip_mode frame_skip_mode;
> @@ -458,6 +488,8 @@ struct s5p_mfc_codec_ops {
> * decoding buffer
> * @dpb_flush_flag: flag used to indicate that a DPB buffers are being
> * flushed
> + * @head_processed: flag mentioning whether the header data is processed
> + * completely or not
> * @bank1_buf: handle to memory allocated for temporary
buffers from
> * memory bank 1
> * @bank1_phys: address of the temporary buffers from memory
bank 1
> @@ -482,14 +514,20 @@ struct s5p_mfc_codec_ops {
> * @display_delay_enable: display delay for H264 enable flag
> * @after_packed_pb: flag used to track buffer when stream is in
> * Packed PB format
> + * @sei_fp_parse: enable/disable parsing of frame packing SEI
information
> * @dpb_count: count of the DPB buffers required by MFC hw
> * @total_dpb_count: count of DPB buffers with additional buffers
> * requested by the application
> * @ctx: context buffer information
> * @dsc: descriptor buffer information
> * @shm: shared memory buffer information
> + * @mv_count: number of MV buffers allocated for decoding
> * @enc_params: encoding parameters for MFC
> * @enc_dst_buf_size: size of the buffers for encoder output
> + * @luma_dpb_size: dpb buffer size for luma
> + * @chroma_dpb_size: dpb buffer size for chroma
> + * @me_buffer_size: size of the motion estimation buffer
> + * @tmv_buffer_size: size of temporal predictor motion vector buffer
> * @frame_type: used to force the type of the next encoded
frame
> * @ref_queue: list of the reference buffers for encoding
> * @ref_queue_cnt: number of the buffers in the reference list
> @@ -538,6 +576,7 @@ struct s5p_mfc_ctx {
> unsigned long consumed_stream;
>
> unsigned int dpb_flush_flag;
> + unsigned int head_processed;
>
> /* Buffers */
> void *bank1_buf;
> @@ -567,10 +606,11 @@ struct s5p_mfc_ctx {
> int display_delay;
> int display_delay_enable;
> int after_packed_pb;
> + int sei_fp_parse;
>
> int dpb_count;
> int total_dpb_count;
> -
> + int mv_count;
> /* Buffers */
> struct s5p_mfc_priv_buf ctx;
> struct s5p_mfc_priv_buf dsc;
> @@ -579,16 +619,28 @@ struct s5p_mfc_ctx {
> struct s5p_mfc_enc_params enc_params;
>
> size_t enc_dst_buf_size;
> + size_t luma_dpb_size;
> + size_t chroma_dpb_size;
> + size_t me_buffer_size;
> + size_t tmv_buffer_size;
>
> enum v4l2_mpeg_mfc51_video_force_frame_type force_frame_type;
>
> struct list_head ref_queue;
> unsigned int ref_queue_cnt;
>
> + enum v4l2_mpeg_video_multi_slice_mode slice_mode;
> + union {
> + unsigned int mb;
> + unsigned int bits;
> + } slice_size;
> +
> struct s5p_mfc_codec_ops *c_ops;
>
> struct v4l2_ctrl *ctrls[MFC_MAX_CTRLS];
> struct v4l2_ctrl_handler ctrl_handler;
> + unsigned int frame_tag;
> + size_t scratch_buf_size;
> };
>
> /*
> @@ -629,4 +681,9 @@ struct mfc_control {
> #define ctrl_to_ctx(__ctrl) \
> container_of((__ctrl)->handler, struct s5p_mfc_ctx, ctrl_handler)
>
> +#define HAS_PORTNUM(dev) (dev ? (dev->variant ? \
> + (dev->variant->port_num ? 1 : 0) : 0) : 0)
> +#define IS_TWOPORT(dev) (dev->variant->port_num == 2 ? 1 : 0)
> +#define IS_MFCV6(dev) (dev->variant->version >= 0x60 ? 1 :
0)
> +
> #endif /* S5P_MFC_COMMON_H_ */
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
> b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
> index 524380c..9e3f45f 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
> @@ -37,8 +37,9 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev
*dev)
> /* Firmare has to be present as a separate file or compiled
> * into kernel. */
> mfc_debug_enter();
> +
> err = request_firmware((const struct firmware **)&fw_blob,
> - "s5p-mfc.fw", dev->v4l2_dev.dev);
> + dev->variant->fw_name,
dev->v4l2_dev.dev);
> if (err != 0) {
> mfc_err("Firmware is not present in the /lib/firmware
directory nor
> compiled in kernel\n");
> return -EINVAL;
> @@ -82,28 +83,33 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev
*dev)
> return -EIO;
> }
> dev->bank1 = s5p_mfc_bitproc_phys;
> - b_base = vb2_dma_contig_memops.alloc(
> - dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], 1 <<
MFC_BANK2_ALIGN_ORDER);
> - if (IS_ERR(b_base)) {
> - vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
> - s5p_mfc_bitproc_phys = 0;
> - s5p_mfc_bitproc_buf = NULL;
> - mfc_err("Allocating bank2 base failed\n");
> - release_firmware(fw_blob);
> - return -ENOMEM;
> - }
> - bank2_base_phys = s5p_mfc_mem_cookie(
> - dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], b_base);
> - vb2_dma_contig_memops.put(b_base);
> - if (bank2_base_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
> - mfc_err("The base memory for bank 2 is not aligned to
128KB\n");
> - vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
> - s5p_mfc_bitproc_phys = 0;
> - s5p_mfc_bitproc_buf = NULL;
> - release_firmware(fw_blob);
> - return -EIO;
> + if (HAS_PORTNUM(dev) && IS_TWOPORT(dev)) {
> + b_base = vb2_dma_contig_memops.alloc(
> + dev->alloc_ctx[MFC_BANK2_ALLOC_CTX],
> + 1 << MFC_BANK2_ALIGN_ORDER);
> + if (IS_ERR(b_base)) {
> + vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
> + s5p_mfc_bitproc_phys = 0;
> + s5p_mfc_bitproc_buf = 0;
> + mfc_err("Allocating bank2 base failed\n");
> + release_firmware(fw_blob);
> + return -ENOMEM;
> + }
> + bank2_base_phys = s5p_mfc_mem_cookie(
> + dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], b_base);
> + vb2_dma_contig_memops.put(b_base);
> + if (bank2_base_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
> + mfc_err("The base memory for bank 2 is not aligned to
> 128KB\n");
> + vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
> + s5p_mfc_bitproc_phys = 0;
> + s5p_mfc_bitproc_buf = 0;
> + release_firmware(fw_blob);
> + return -EIO;
> + }
> + dev->bank2 = bank2_base_phys;
> + } else {
> + dev->bank2 = dev->bank1;
> }
> - dev->bank2 = bank2_base_phys;
> memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size);
> wmb();
> release_firmware(fw_blob);
> @@ -120,8 +126,9 @@ int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev)
> /* Firmare has to be present as a separate file or compiled
> * into kernel. */
> mfc_debug_enter();
> +
> err = request_firmware((const struct firmware **)&fw_blob,
> - "s5p-mfc.fw", dev->v4l2_dev.dev);
> + dev->variant->fw_name,
dev->v4l2_dev.dev);
> if (err != 0) {
> mfc_err("Firmware is not present in the /lib/firmware
directory nor
> compiled in kernel\n");
> return -EINVAL;
> @@ -162,46 +169,81 @@ int s5p_mfc_reset(struct s5p_mfc_dev *dev)
> {
> unsigned int mc_status;
> unsigned long timeout;
> + int i;
>
> mfc_debug_enter();
> - /* Stop procedure */
> - /* reset RISC */
> - mfc_write(dev, 0x3f6, S5P_FIMV_SW_RESET);
> - /* All reset except for MC */
> - mfc_write(dev, 0x3e2, S5P_FIMV_SW_RESET);
> - mdelay(10);
> -
> - timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
> - /* Check MC status */
> - do {
> - if (time_after(jiffies, timeout)) {
> - mfc_err("Timeout while resetting MFC\n");
> - return -EIO;
> - }
>
> - mc_status = mfc_read(dev, S5P_FIMV_MC_STATUS);
> + if (IS_MFCV6(dev)) {
> + /* Reset IP */
> + /* except RISC, reset */
> + mfc_write(dev, 0xFEE, S5P_FIMV_MFC_RESET_V6);
> + /* reset release */
> + mfc_write(dev, 0x0, S5P_FIMV_MFC_RESET_V6);
> +
> + /* Zero Initialization of MFC registers */
> + mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD_V6);
> + mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD_V6);
> + mfc_write(dev, 0, S5P_FIMV_FW_VERSION_V6);
> +
> + for (i = 0; i < S5P_FIMV_REG_CLEAR_COUNT_V6; i++)
> + mfc_write(dev, 0, S5P_FIMV_REG_CLEAR_BEGIN_V6 +
(i*4));
> +
> + /* Reset */
> + mfc_write(dev, 0, S5P_FIMV_RISC_ON_V6);
> + mfc_write(dev, 0x1FFF, S5P_FIMV_MFC_RESET_V6);
> + mfc_write(dev, 0, S5P_FIMV_MFC_RESET_V6);
> + } else {
> + /* Stop procedure */
> + /* reset RISC */
> + mfc_write(dev, 0x3f6, S5P_FIMV_SW_RESET);
> + /* All reset except for MC */
> + mfc_write(dev, 0x3e2, S5P_FIMV_SW_RESET);
> + mdelay(10);
>
> - } while (mc_status & 0x3);
> + timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
> + /* Check MC status */
> + do {
> + if (time_after(jiffies, timeout)) {
> + mfc_err("Timeout while resetting MFC\n");
> + return -EIO;
> + }
> +
> + mc_status = mfc_read(dev, S5P_FIMV_MC_STATUS);
> +
> + } while (mc_status & 0x3);
> +
> + mfc_write(dev, 0x0, S5P_FIMV_SW_RESET);
> + mfc_write(dev, 0x3fe, S5P_FIMV_SW_RESET);
> + }
>
> - mfc_write(dev, 0x0, S5P_FIMV_SW_RESET);
> - mfc_write(dev, 0x3fe, S5P_FIMV_SW_RESET);
> mfc_debug_leave();
> return 0;
> }
>
> static inline void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev)
> {
> - mfc_write(dev, dev->bank1, S5P_FIMV_MC_DRAMBASE_ADR_A);
> - mfc_write(dev, dev->bank2, S5P_FIMV_MC_DRAMBASE_ADR_B);
> - mfc_debug(2, "Bank1: %08x, Bank2: %08x\n", dev->bank1, dev->bank2);
> + if (IS_MFCV6(dev)) {
> + mfc_write(dev, dev->bank1, S5P_FIMV_RISC_BASE_ADDRESS_V6);
> + mfc_debug(2, "Base Address : %08x\n", dev->bank1);
> + } else {
> + mfc_write(dev, dev->bank1, S5P_FIMV_MC_DRAMBASE_ADR_A);
> + mfc_write(dev, dev->bank2, S5P_FIMV_MC_DRAMBASE_ADR_B);
> + mfc_debug(2, "Bank1: %08x, Bank2: %08x\n",
> + dev->bank1, dev->bank2);
> + }
> }
>
> static inline void s5p_mfc_clear_cmds(struct s5p_mfc_dev *dev)
> {
> - mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH0_INST_ID);
> - mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH1_INST_ID);
> - mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
> - mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD);
> + if (IS_MFCV6(dev)) {
> + /* Zero initialization should be done before RESET.
> + * Nothing to do here. */
> + } else {
> + mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH0_INST_ID);
> + mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH1_INST_ID);
> + mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
> + mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD);
> + }
> }
>
> /* Initialize hardware */
> @@ -229,7 +271,10 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
> s5p_mfc_clear_cmds(dev);
> /* 3. Release reset signal to the RISC */
> s5p_mfc_clean_dev_int_flags(dev);
> - mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
> + if (IS_MFCV6(dev))
> + mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6);
> + else
> + mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
> mfc_debug(2, "Will now wait for completion of firmware transfer\n");
> if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_FW_STATUS_RET)) {
> mfc_err("Failed to load firmware\n");
> @@ -263,7 +308,11 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
> s5p_mfc_clock_off();
> return -EIO;
> }
> - ver = mfc_read(dev, S5P_FIMV_FW_VERSION);
> + if (IS_MFCV6(dev))
> + ver = mfc_read(dev, S5P_FIMV_FW_VERSION_V6);
> + else
> + ver = mfc_read(dev, S5P_FIMV_FW_VERSION);
> +
> mfc_debug(2, "MFC F/W version : %02xyy, %02xmm, %02xdd\n",
> (ver >> 16) & 0xFF, (ver >> 8) & 0xFF, ver & 0xFF);
> s5p_mfc_clock_off();
> @@ -338,7 +387,10 @@ int s5p_mfc_wakeup(struct s5p_mfc_dev *dev)
> return ret;
> }
> /* 4. Release reset signal to the RISC */
> - mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
> + if (IS_MFCV6(dev))
> + mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6);
> + else
> + mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
> mfc_debug(2, "Ok, now will write a command to wakeup the system\n");
> if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_WAKEUP_RET)) {
> mfc_err("Failed to load firmware\n");
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
> b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
> index 8133a4c..e27c994 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
> @@ -31,10 +31,17 @@
> #include "s5p_mfc_pm.h"
>
> #define DEF_SRC_FMT_DEC V4L2_PIX_FMT_H264
> -#define DEF_DST_FMT_DEC V4L2_PIX_FMT_NV12MT
> +#define DEF_DST_FMT_DEC V4L2_PIX_FMT_NV12MT_16X16
>
> static struct s5p_mfc_fmt formats[] = {
> {
> + .name = "4:2:0 2 Planes 16x16 Tiles",
> + .fourcc = V4L2_PIX_FMT_NV12MT_16X16,
> + .codec_mode = S5P_MFC_CODEC_NONE,
> + .type = MFC_FMT_RAW,
> + .num_planes = 2,
> + },
> + {
> .name = "4:2:0 2 Planes 64x32 Tiles",
> .fourcc = V4L2_PIX_FMT_NV12MT,
> .codec_mode = S5P_MFC_CODEC_NONE,
> @@ -42,67 +49,88 @@ static struct s5p_mfc_fmt formats[] = {
> .num_planes = 2,
> },
> {
> - .name = "4:2:0 2 Planes",
> - .fourcc = V4L2_PIX_FMT_NV12M,
> - .codec_mode = S5P_MFC_CODEC_NONE,
> - .type = MFC_FMT_RAW,
> - .num_planes = 2,
> + .name = "4:2:0 2 Planes Y/CbCr",
> + .fourcc = V4L2_PIX_FMT_NV12M,
> + .codec_mode = S5P_MFC_CODEC_NONE,
> + .type = MFC_FMT_RAW,
> + .num_planes = 2,
> + },
> + {
> + .name = "4:2:0 2 Planes Y/CrCb",
> + .fourcc = V4L2_PIX_FMT_NV21M,
> + .codec_mode = S5P_MFC_CODEC_NONE,
> + .type = MFC_FMT_RAW,
> + .num_planes = 2,
> + },
> + {
> + .name = "H264 Encoded Stream",
> + .fourcc = V4L2_PIX_FMT_H264,
> + .codec_mode = S5P_MFC_CODEC_H264_DEC,
> + .type = MFC_FMT_DEC,
> + .num_planes = 1,
> },
> {
> - .name = "H264 Encoded Stream",
> - .fourcc = V4L2_PIX_FMT_H264,
> - .codec_mode = S5P_MFC_CODEC_H264_DEC,
> - .type = MFC_FMT_DEC,
> - .num_planes = 1,
> + .name = "H264/MVC Encoded Stream",
> + .fourcc = V4L2_PIX_FMT_H264_MVC,
> + .codec_mode = S5P_MFC_CODEC_H264_MVC_DEC,
> + .type = MFC_FMT_DEC,
> + .num_planes = 1,
> },
> {
> - .name = "H263 Encoded Stream",
> - .fourcc = V4L2_PIX_FMT_H263,
> - .codec_mode = S5P_MFC_CODEC_H263_DEC,
> - .type = MFC_FMT_DEC,
> - .num_planes = 1,
> + .name = "H263 Encoded Stream",
> + .fourcc = V4L2_PIX_FMT_H263,
> + .codec_mode = S5P_MFC_CODEC_H263_DEC,
> + .type = MFC_FMT_DEC,
> + .num_planes = 1,
> },
> {
> - .name = "MPEG1 Encoded Stream",
> - .fourcc = V4L2_PIX_FMT_MPEG1,
> - .codec_mode = S5P_MFC_CODEC_MPEG2_DEC,
> - .type = MFC_FMT_DEC,
> - .num_planes = 1,
> + .name = "MPEG1 Encoded Stream",
> + .fourcc = V4L2_PIX_FMT_MPEG1,
> + .codec_mode = S5P_MFC_CODEC_MPEG2_DEC,
> + .type = MFC_FMT_DEC,
> + .num_planes = 1,
> },
> {
> - .name = "MPEG2 Encoded Stream",
> - .fourcc = V4L2_PIX_FMT_MPEG2,
> - .codec_mode = S5P_MFC_CODEC_MPEG2_DEC,
> - .type = MFC_FMT_DEC,
> - .num_planes = 1,
> + .name = "MPEG2 Encoded Stream",
> + .fourcc = V4L2_PIX_FMT_MPEG2,
> + .codec_mode = S5P_MFC_CODEC_MPEG2_DEC,
> + .type = MFC_FMT_DEC,
> + .num_planes = 1,
> },
> {
> - .name = "MPEG4 Encoded Stream",
> - .fourcc = V4L2_PIX_FMT_MPEG4,
> - .codec_mode = S5P_MFC_CODEC_MPEG4_DEC,
> - .type = MFC_FMT_DEC,
> - .num_planes = 1,
> + .name = "MPEG4 Encoded Stream",
> + .fourcc = V4L2_PIX_FMT_MPEG4,
> + .codec_mode = S5P_MFC_CODEC_MPEG4_DEC,
> + .type = MFC_FMT_DEC,
> + .num_planes = 1,
> },
> {
> - .name = "XviD Encoded Stream",
> - .fourcc = V4L2_PIX_FMT_XVID,
> - .codec_mode = S5P_MFC_CODEC_MPEG4_DEC,
> - .type = MFC_FMT_DEC,
> - .num_planes = 1,
> + .name = "XviD Encoded Stream",
> + .fourcc = V4L2_PIX_FMT_XVID,
> + .codec_mode = S5P_MFC_CODEC_MPEG4_DEC,
> + .type = MFC_FMT_DEC,
> + .num_planes = 1,
> },
> {
> - .name = "VC1 Encoded Stream",
> - .fourcc = V4L2_PIX_FMT_VC1_ANNEX_G,
> - .codec_mode = S5P_MFC_CODEC_VC1_DEC,
> - .type = MFC_FMT_DEC,
> - .num_planes = 1,
> + .name = "VC1 Encoded Stream",
> + .fourcc = V4L2_PIX_FMT_VC1_ANNEX_G,
> + .codec_mode = S5P_MFC_CODEC_VC1_DEC,
> + .type = MFC_FMT_DEC,
> + .num_planes = 1,
> },
> {
> - .name = "VC1 RCV Encoded Stream",
> - .fourcc = V4L2_PIX_FMT_VC1_ANNEX_L,
> - .codec_mode = S5P_MFC_CODEC_VC1RCV_DEC,
> - .type = MFC_FMT_DEC,
> - .num_planes = 1,
> + .name = "VC1 RCV Encoded Stream",
> + .fourcc = V4L2_PIX_FMT_VC1_ANNEX_L,
> + .codec_mode = S5P_MFC_CODEC_VC1RCV_DEC,
> + .type = MFC_FMT_DEC,
> + .num_planes = 1,
> + },
> + {
> + .name = "VP8 Encoded Stream",
> + .fourcc = V4L2_PIX_FMT_VP8,
> + .codec_mode = S5P_MFC_CODEC_VP8_DEC,
> + .type = MFC_FMT_DEC,
> + .num_planes = 1,
> },
> };
>
> @@ -343,21 +371,36 @@ static int vidioc_g_fmt(struct file *file, void *priv,
> struct v4l2_format *f)
> /* Try format */
> static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format
*f)
> {
> + struct s5p_mfc_dev *dev = video_drvdata(file);
> struct s5p_mfc_fmt *fmt;
>
> - if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
> - mfc_err("This node supports decoding only\n");
> - return -EINVAL;
> - }
> - fmt = find_format(f, MFC_FMT_DEC);
> - if (!fmt) {
> - mfc_err("Unsupported format\n");
> - return -EINVAL;
> - }
> - if (fmt->type != MFC_FMT_DEC) {
> - mfc_err("\n");
> - return -EINVAL;
> + mfc_debug(2, "Type is %d\n", f->type);
> + if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
> + fmt = find_format(f, MFC_FMT_DEC);
> + if (!fmt) {
> + mfc_err("Unsupported format for source.\n");
> + return -EINVAL;
> + }
> + if (!IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_VP8)) {
> + mfc_err("Not supported format.\n");
> + return -EINVAL;
> + }
> + } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
> + fmt = find_format(f, MFC_FMT_RAW);
> + if (!fmt) {
> + mfc_err("Unsupported format for destination.\n");
> + return -EINVAL;
> + }
> + if (IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) {
> + mfc_err("Not supported format.\n");
> + return -EINVAL;
> + } else if (!IS_MFCV6(dev) &&
> + (fmt->fourcc != V4L2_PIX_FMT_NV12MT)) {
> + mfc_err("Not supported format.\n");
> + return -EINVAL;
> + }
> }
> +
> return 0;
> }
>
> @@ -380,6 +423,27 @@ static int vidioc_s_fmt(struct file *file, void *priv,
> struct v4l2_format *f)
> ret = -EBUSY;
> goto out;
> }
> + if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
> + fmt = find_format(f, MFC_FMT_RAW);
> + if (!fmt) {
> + mfc_err("Unsupported format for source.\n");
> + return -EINVAL;
> + }
> + if (!IS_MFCV6(dev) && (fmt->fourcc != V4L2_PIX_FMT_NV12MT)) {
> + mfc_err("Not supported format.\n");
> + return -EINVAL;
> + } else if (IS_MFCV6(dev) &&
> + (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) {
> + mfc_err("Not supported format.\n");
> + return -EINVAL;
> + }
> + ctx->dst_fmt = fmt;
> + mfc_debug_leave();
> + return ret;
> + } else if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
> + mfc_err("Wrong type error for S_FMT : %d", f->type);
> + return -EINVAL;
> + }
> fmt = find_format(f, MFC_FMT_DEC);
> if (!fmt || fmt->codec_mode == S5P_MFC_CODEC_NONE) {
> mfc_err("Unknown codec\n");
> @@ -392,6 +456,10 @@ static int vidioc_s_fmt(struct file *file, void *priv,
> struct v4l2_format *f)
> ret = -EINVAL;
> goto out;
> }
> + if (!IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_VP8)) {
> + mfc_err("Not supported format.\n");
> + return -EINVAL;
> + }
> ctx->src_fmt = fmt;
> ctx->codec_mode = fmt->codec_mode;
> mfc_debug(2, "The codec number is: %d\n", ctx->codec_mode);
> @@ -763,6 +831,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
> void *allocators[])
> {
> struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
> + struct s5p_mfc_dev *dev = ctx->dev;
>
> /* Video output for decoding (source)
> * this can be set after getting an instance */
> @@ -798,7 +867,13 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
> vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
> psize[0] = ctx->luma_size;
> psize[1] = ctx->chroma_size;
> - allocators[0] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
> +
> + if (IS_MFCV6(dev))
> + allocators[0] =
> + ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
> + else
> + allocators[0] =
> + ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
> allocators[1] = ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
> } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
> ctx->state == MFCINST_INIT) {
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
> b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
> index fe34f17..da96017 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
> @@ -35,39 +35,53 @@
>
> static struct s5p_mfc_fmt formats[] = {
> {
> - .name = "4:2:0 2 Planes 64x32 Tiles",
> - .fourcc = V4L2_PIX_FMT_NV12MT,
> - .codec_mode = S5P_MFC_CODEC_NONE,
> - .type = MFC_FMT_RAW,
> - .num_planes = 2,
> + .name = "4:2:0 2 Planes 16x16 Tiles",
> + .fourcc = V4L2_PIX_FMT_NV12MT_16X16,
> + .codec_mode = S5P_MFC_CODEC_NONE,
> + .type = MFC_FMT_RAW,
> + .num_planes = 2,
> },
> {
> - .name = "4:2:0 2 Planes",
> - .fourcc = V4L2_PIX_FMT_NV12M,
> - .codec_mode = S5P_MFC_CODEC_NONE,
> - .type = MFC_FMT_RAW,
> - .num_planes = 2,
> + .name = "4:2:0 2 Planes 64x32 Tiles",
> + .fourcc = V4L2_PIX_FMT_NV12MT,
> + .codec_mode = S5P_MFC_CODEC_NONE,
> + .type = MFC_FMT_RAW,
> + .num_planes = 2,
> },
> {
> - .name = "H264 Encoded Stream",
> - .fourcc = V4L2_PIX_FMT_H264,
> - .codec_mode = S5P_MFC_CODEC_H264_ENC,
> - .type = MFC_FMT_ENC,
> - .num_planes = 1,
> + .name = "4:2:0 2 Planes Y/CbCr",
> + .fourcc = V4L2_PIX_FMT_NV12M,
> + .codec_mode = S5P_MFC_CODEC_NONE,
> + .type = MFC_FMT_RAW,
> + .num_planes = 2,
> },
> {
> - .name = "MPEG4 Encoded Stream",
> - .fourcc = V4L2_PIX_FMT_MPEG4,
> - .codec_mode = S5P_MFC_CODEC_MPEG4_ENC,
> - .type = MFC_FMT_ENC,
> - .num_planes = 1,
> + .name = "4:2:0 2 Planes Y/CrCb",
> + .fourcc = V4L2_PIX_FMT_NV21M,
> + .codec_mode = S5P_MFC_CODEC_NONE,
> + .type = MFC_FMT_RAW,
> + .num_planes = 2,
> },
> {
> - .name = "H263 Encoded Stream",
> - .fourcc = V4L2_PIX_FMT_H263,
> - .codec_mode = S5P_MFC_CODEC_H263_ENC,
> - .type = MFC_FMT_ENC,
> - .num_planes = 1,
> + .name = "H264 Encoded Stream",
> + .fourcc = V4L2_PIX_FMT_H264,
> + .codec_mode = S5P_MFC_CODEC_H264_ENC,
> + .type = MFC_FMT_ENC,
> + .num_planes = 1,
> + },
> + {
> + .name = "MPEG4 Encoded Stream",
> + .fourcc = V4L2_PIX_FMT_MPEG4,
> + .codec_mode = S5P_MFC_CODEC_MPEG4_ENC,
> + .type = MFC_FMT_ENC,
> + .num_planes = 1,
> + },
> + {
> + .name = "H263 Encoded Stream",
> + .fourcc = V4L2_PIX_FMT_H263,
> + .codec_mode = S5P_MFC_CODEC_H263_ENC,
> + .type = MFC_FMT_ENC,
> + .num_planes = 1,
> },
> };
>
> @@ -575,7 +589,8 @@ static int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx)
> if (ctx->state == MFCINST_GOT_INST && ctx->dst_queue_cnt >= 1)
> return 1;
> /* context is ready to encode a frame */
> - if (ctx->state == MFCINST_RUNNING &&
> + if ((ctx->state == MFCINST_RUNNING ||
> + ctx->state == MFCINST_HEAD_PARSED) &&
> ctx->src_queue_cnt >= 1 && ctx->dst_queue_cnt >= 1)
> return 1;
> /* context is ready to encode remain frames */
> @@ -644,13 +659,23 @@ static int enc_post_seq_start(struct s5p_mfc_ctx *ctx)
> vb2_buffer_done(dst_mb->b, VB2_BUF_STATE_DONE);
> spin_unlock_irqrestore(&dev->irqlock, flags);
> }
> - ctx->state = MFCINST_RUNNING;
> - if (s5p_mfc_ctx_ready(ctx)) {
> - spin_lock_irqsave(&dev->condlock, flags);
> - set_bit(ctx->num, &dev->ctx_work_bits);
> - spin_unlock_irqrestore(&dev->condlock, flags);
> +
> + if (IS_MFCV6(dev)) {
> + ctx->state = MFCINST_HEAD_PARSED; /* for INIT_BUFFER cmd */
> + } else {
> + ctx->state = MFCINST_RUNNING;
> + if (s5p_mfc_ctx_ready(ctx)) {
> + spin_lock_irqsave(&dev->condlock, flags);
> + set_bit(ctx->num, &dev->ctx_work_bits);
> + spin_unlock_irqrestore(&dev->condlock, flags);
> + }
> + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
> }
> - s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
> +
> + if (IS_MFCV6(dev))
> + ctx->dpb_count = s5p_mfc_hw_call(dev->mfc_ops,
> + get_enc_dpb_count, dev);
> +
> return 0;
> }
>
> @@ -973,6 +998,17 @@ static int vidioc_s_fmt(struct file *file, void *priv,
> struct v4l2_format *f)
> mfc_err("failed to set output format\n");
> return -EINVAL;
> }
> +
> + if (!IS_MFCV6(dev) &&
> + (fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16)) {
> + mfc_err("Not supported format.\n");
> + return -EINVAL;
> + } else if (IS_MFCV6(dev) &&
> + (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) {
> + mfc_err("Not supported format.\n");
> + return -EINVAL;
> + }
> +
> if (fmt->num_planes != pix_fmt_mp->num_planes) {
> mfc_err("failed to set output format\n");
> ret = -EINVAL;
> @@ -1006,6 +1042,7 @@ out:
> static int vidioc_reqbufs(struct file *file, void *priv,
> struct v4l2_requestbuffers *reqbufs)
> {
> + struct s5p_mfc_dev *dev = video_drvdata(file);
> struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
> int ret = 0;
>
> @@ -1025,13 +1062,16 @@ static int vidioc_reqbufs(struct file *file, void
*priv,
> return ret;
> }
> ctx->capture_state = QUEUE_BUFS_REQUESTED;
> - ret = s5p_mfc_hw_call(ctx->dev->mfc_ops, alloc_codec_buffers,
> - ctx);
> - if (ret) {
> - mfc_err("Failed to allocate encoding buffers\n");
> - reqbufs->count = 0;
> - ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
> - return -ENOMEM;
> +
> + if (!IS_MFCV6(dev)) {
> + ret = s5p_mfc_hw_call(ctx->dev->mfc_ops,
> + alloc_codec_buffers, ctx);
> + if (ret) {
> + mfc_err("Failed to allocate encoding
buffers\n");
> + reqbufs->count = 0;
> + ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
> + return -ENOMEM;
> + }
> }
> } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
> if (ctx->output_state != QUEUE_FREE) {
> @@ -1278,6 +1318,13 @@ static int s5p_mfc_enc_s_ctrl(struct v4l2_ctrl *ctrl)
> p->codec.h264.profile =
> S5P_FIMV_ENC_PROFILE_H264_BASELINE;
> break;
> + case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
> + if (IS_MFCV6(dev))
> + p->codec.h264.profile =
> +
S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_BASELINE;
> + else
> + ret = -EINVAL;
> + break;
> default:
> ret = -EINVAL;
> }
> @@ -1497,6 +1544,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
> unsigned int psize[], void *allocators[])
> {
> struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
> + struct s5p_mfc_dev *dev = ctx->dev;
>
> if (ctx->state != MFCINST_GOT_INST) {
> mfc_err("inavlid state: %d\n", ctx->state);
> @@ -1525,8 +1573,17 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
> *buf_count = MFC_MAX_BUFFERS;
> psize[0] = ctx->luma_size;
> psize[1] = ctx->chroma_size;
> - allocators[0] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
> - allocators[1] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
> + if (IS_MFCV6(dev)) {
> + allocators[0] =
> + ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
> + allocators[1] =
> + ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
> + } else {
> + allocators[0] =
> + ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
> + allocators[1] =
> + ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
> + }
> } else {
> mfc_err("inavlid queue type: %d\n", vq->type);
> return -EINVAL;
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
> b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
> index ef8683e..d69248b 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
> @@ -14,12 +14,18 @@
>
> #include "s5p_mfc_opr.h"
> #include "s5p_mfc_opr_v5.h"
> +#include "s5p_mfc_opr_v6.h"
>
> static struct s5p_mfc_hw_ops *s5p_mfc_ops;
>
> void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev)
> {
> - s5p_mfc_ops = s5p_mfc_init_hw_ops_v5();
> - dev->warn_start = S5P_FIMV_ERR_WARNINGS_START;
> + if (IS_MFCV6(dev)) {
> + s5p_mfc_ops = s5p_mfc_init_hw_ops_v6();
> + dev->warn_start = S5P_FIMV_ERR_WARNINGS_START_V6;
> + } else {
> + s5p_mfc_ops = s5p_mfc_init_hw_ops_v5();
> + dev->warn_start = S5P_FIMV_ERR_WARNINGS_START;
> + }
> dev->mfc_ops = s5p_mfc_ops;
> }
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
> b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
> new file mode 100644
> index 0000000..7fb905b
> --- /dev/null
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
> @@ -0,0 +1,1956 @@
> +/*
> + * drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
> + *
> + * Samsung MFC (Multi Function Codec - FIMV) driver
> + * This file contains hw related functions.
> + *
> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
> + * http://www.samsung.com/
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#undef DEBUG
> +
> +#include <linux/delay.h>
> +#include <linux/mm.h>
> +#include <linux/io.h>
> +#include <linux/jiffies.h>
> +#include <linux/firmware.h>
> +#include <linux/err.h>
> +#include <linux/sched.h>
> +#include <linux/dma-mapping.h>
> +
> +#include <asm/cacheflush.h>
> +
> +#include "s5p_mfc_common.h"
> +#include "s5p_mfc_cmd.h"
> +#include "s5p_mfc_intr.h"
> +#include "s5p_mfc_pm.h"
> +#include "s5p_mfc_debug.h"
> +#include "s5p_mfc_opr.h"
> +#include "s5p_mfc_opr_v6.h"
> +
> +/* #define S5P_MFC_DEBUG_REGWRITE */
> +#ifdef S5P_MFC_DEBUG_REGWRITE
> +#undef writel
> +#define writel(v, r) \
> + do { \
> + pr_err("MFCWRITE(%p): %08x\n", r, (unsigned int)v); \
> + __raw_writel(v, r); \
> + } while (0)
> +#endif /* S5P_MFC_DEBUG_REGWRITE */
> +
> +#define READL(offset) readl(dev->regs_base + (offset))
> +#define WRITEL(data, offset) writel((data), dev->regs_base + (offset))
> +#define OFFSETA(x) (((x) - dev->port_a) >> S5P_FIMV_MEM_OFFSET)
> +#define OFFSETB(x) (((x) - dev->port_b) >> S5P_FIMV_MEM_OFFSET)
> +
> +/* Allocate temporary buffers for decoding */
> +int s5p_mfc_alloc_dec_temp_buffers_v6(struct s5p_mfc_ctx *ctx)
> +{
> + /* NOP */
> +
> + return 0;
> +}
> +
> +/* Release temproary buffers for decoding */
> +void s5p_mfc_release_dec_desc_buffer_v6(struct s5p_mfc_ctx *ctx)
> +{
> + /* NOP */
> +}
> +
> +int s5p_mfc_get_dec_status_v6(struct s5p_mfc_dev *dev)
> +{
> + /* NOP */
> + return -1;
> +}
> +
> +/* Allocate codec buffers */
> +int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + unsigned int mb_width, mb_height;
> +
> + mb_width = MB_WIDTH(ctx->img_width);
> + mb_height = MB_HEIGHT(ctx->img_height);
> +
> + if (ctx->type == MFCINST_DECODER) {
> + mfc_debug(2, "Luma size:%d Chroma size:%d MV size:%d\n",
> + ctx->luma_size, ctx->chroma_size, ctx->mv_size);
> + mfc_debug(2, "Totals bufs: %d\n", ctx->total_dpb_count);
> + } else if (ctx->type == MFCINST_ENCODER) {
> + ctx->tmv_buffer_size = S5P_FIMV_NUM_TMV_BUFFERS_V6 *
> + ALIGN(S5P_FIMV_TMV_BUFFER_SIZE_V6(mb_width,
mb_height),
> + S5P_FIMV_TMV_BUFFER_ALIGN_V6);
> + ctx->luma_dpb_size = ALIGN((mb_width * mb_height) *
> + S5P_FIMV_LUMA_MB_TO_PIXEL_V6,
> + S5P_FIMV_LUMA_DPB_BUFFER_ALIGN_V6);
> + ctx->chroma_dpb_size = ALIGN((mb_width * mb_height) *
> + S5P_FIMV_CHROMA_MB_TO_PIXEL_V6,
> + S5P_FIMV_CHROMA_DPB_BUFFER_ALIGN_V6);
> + ctx->me_buffer_size = ALIGN(S5P_FIMV_ME_BUFFER_SIZE_V6(
> + ctx->img_width, ctx->img_height,
> + mb_width, mb_height),
> + S5P_FIMV_ME_BUFFER_ALIGN_V6);
> +
> + mfc_debug(2, "recon luma size: %d chroma size: %d\n",
> + ctx->luma_dpb_size, ctx->chroma_dpb_size);
> + } else {
> + return -EINVAL;
> + }
> +
> + /* Codecs have different memory requirements */
> + switch (ctx->codec_mode) {
> + case S5P_MFC_CODEC_H264_DEC:
> + case S5P_MFC_CODEC_H264_MVC_DEC:
> + ctx->scratch_buf_size =
> + S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V6(
> + mb_width,
> + mb_height);
> + ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
> + S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
> + ctx->bank1_size =
> + ctx->scratch_buf_size +
> + (ctx->mv_count * ctx->mv_size);
> + break;
> + case S5P_MFC_CODEC_MPEG4_DEC:
> + ctx->scratch_buf_size =
> + S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V6(
> + mb_width,
> + mb_height);
> + ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
> + S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
> + ctx->bank1_size = ctx->scratch_buf_size;
> + break;
> + case S5P_MFC_CODEC_VC1RCV_DEC:
> + case S5P_MFC_CODEC_VC1_DEC:
> + ctx->scratch_buf_size =
> + S5P_FIMV_SCRATCH_BUF_SIZE_VC1_DEC_V6(
> + mb_width,
> + mb_height);
> + ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
> + S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
> + ctx->bank1_size = ctx->scratch_buf_size;
> + break;
> + case S5P_MFC_CODEC_MPEG2_DEC:
> + ctx->bank1_size = 0;
> + ctx->bank2_size = 0;
> + break;
> + case S5P_MFC_CODEC_H263_DEC:
> + ctx->scratch_buf_size =
> + S5P_FIMV_SCRATCH_BUF_SIZE_H263_DEC_V6(
> + mb_width,
> + mb_height);
> + ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
> + S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
> + ctx->bank1_size = ctx->scratch_buf_size;
> + break;
> + case S5P_MFC_CODEC_VP8_DEC:
> + ctx->scratch_buf_size =
> + S5P_FIMV_SCRATCH_BUF_SIZE_VP8_DEC_V6(
> + mb_width,
> + mb_height);
> + ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
> + S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
> + ctx->bank1_size = ctx->scratch_buf_size;
> + break;
> + case S5P_MFC_CODEC_H264_ENC:
> + ctx->scratch_buf_size =
> + S5P_FIMV_SCRATCH_BUF_SIZE_H264_ENC_V6(
> + mb_width,
> + mb_height);
> + ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
> + S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
> + ctx->bank1_size =
> + ctx->scratch_buf_size + ctx->tmv_buffer_size +
> + (ctx->dpb_count * (ctx->luma_dpb_size +
> + ctx->chroma_dpb_size + ctx->me_buffer_size));
> + ctx->bank2_size = 0;
> + break;
> + case S5P_MFC_CODEC_MPEG4_ENC:
> + case S5P_MFC_CODEC_H263_ENC:
> + ctx->scratch_buf_size =
> + S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_ENC_V6(
> + mb_width,
> + mb_height);
> + ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
> + S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
> + ctx->bank1_size =
> + ctx->scratch_buf_size + ctx->tmv_buffer_size +
> + (ctx->dpb_count * (ctx->luma_dpb_size +
> + ctx->chroma_dpb_size + ctx->me_buffer_size));
> + ctx->bank2_size = 0;
> + break;
> + default:
> + break;
> + }
> +
> + /* Allocate only if memory from bank 1 is necessary */
> + if (ctx->bank1_size > 0) {
> + ctx->bank1_buf = vb2_dma_contig_memops.alloc(
> + dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_size);
> + if (IS_ERR(ctx->bank1_buf)) {
> + ctx->bank1_buf = 0;
> + pr_err("Buf alloc for decoding failed (port A)\n");
> + return -ENOMEM;
> + }
> + ctx->bank1_phys = s5p_mfc_mem_cookie(
> + dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_buf);
> + BUG_ON(ctx->bank1_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
> + }
> +
> + return 0;
> +}
> +
> +/* Release buffers allocated for codec */
> +void s5p_mfc_release_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
> +{
> + if (ctx->bank1_buf) {
> + vb2_dma_contig_memops.put(ctx->bank1_buf);
> + ctx->bank1_buf = 0;
> + ctx->bank1_phys = 0;
> + ctx->bank1_size = 0;
> + }
> +}
> +
> +/* Allocate memory for instance data buffer */
> +int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv;
> +
> + mfc_debug_enter();
> +
> + switch (ctx->codec_mode) {
> + case S5P_MFC_CODEC_H264_DEC:
> + case S5P_MFC_CODEC_H264_MVC_DEC:
> + ctx->ctx.size = buf_size->h264_dec_ctx;
> + break;
> + case S5P_MFC_CODEC_MPEG4_DEC:
> + case S5P_MFC_CODEC_H263_DEC:
> + case S5P_MFC_CODEC_VC1RCV_DEC:
> + case S5P_MFC_CODEC_VC1_DEC:
> + case S5P_MFC_CODEC_MPEG2_DEC:
> + case S5P_MFC_CODEC_VP8_DEC:
> + ctx->ctx.size = buf_size->other_dec_ctx;
> + break;
> + case S5P_MFC_CODEC_H264_ENC:
> + ctx->ctx.size = buf_size->h264_enc_ctx;
> + break;
> + case S5P_MFC_CODEC_MPEG4_ENC:
> + case S5P_MFC_CODEC_H263_ENC:
> + ctx->ctx.size = buf_size->other_enc_ctx;
> + break;
> + default:
> + ctx->ctx.size = 0;
> + mfc_err("Codec type(%d) should be checked!\n",
ctx->codec_mode);
> + break;
> + }
> +
> + ctx->ctx.alloc = vb2_dma_contig_memops.alloc(
> + dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx.size);
> + if (IS_ERR(ctx->ctx.alloc)) {
> + mfc_err("Allocating context buffer failed.\n");
> + return PTR_ERR(ctx->ctx.alloc);
> + }
> +
> + ctx->ctx.dma = s5p_mfc_mem_cookie(
> + dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx.alloc);
> +
> + ctx->ctx.virt = vb2_dma_contig_memops.vaddr(ctx->ctx.alloc);
> + if (!ctx->ctx.virt) {
> + vb2_dma_contig_memops.put(ctx->ctx.alloc);
> + ctx->ctx.alloc = NULL;
> + ctx->ctx.dma = 0;
> + ctx->ctx.virt = NULL;
> +
> + mfc_err("Remapping context buffer failed.\n");
> + return -ENOMEM;
> + }
> +
> + memset(ctx->ctx.virt, 0, ctx->ctx.size);
> + wmb();
> +
> + mfc_debug_leave();
> +
> + return 0;
> +}
> +
> +/* Release instance buffer */
> +void s5p_mfc_release_instance_buffer_v6(struct s5p_mfc_ctx *ctx)
> +{
> + mfc_debug_enter();
> +
> + if (ctx->ctx.alloc) {
> + vb2_dma_contig_memops.put(ctx->ctx.alloc);
> + ctx->ctx.alloc = NULL;
> + ctx->ctx.dma = 0;
> + ctx->ctx.virt = NULL;
> + }
> +
> + mfc_debug_leave();
> +}
> +
> +/* Allocate context buffers for SYS_INIT */
> +int s5p_mfc_alloc_dev_context_buffer_v6(struct s5p_mfc_dev *dev)
> +{
> + struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv;
> +
> + mfc_debug_enter();
> +
> + dev->ctx_buf.alloc = vb2_dma_contig_memops.alloc(
> + dev->alloc_ctx[MFC_BANK1_ALLOC_CTX],
buf_size->dev_ctx);
> + if (IS_ERR(dev->ctx_buf.alloc)) {
> + mfc_err("Allocating DESC buffer failed.\n");
> + return PTR_ERR(dev->ctx_buf.alloc);
> + }
> +
> + dev->ctx_buf.dma = s5p_mfc_mem_cookie(
> + dev->alloc_ctx[MFC_BANK1_ALLOC_CTX],
> + dev->ctx_buf.alloc);
> +
> + dev->ctx_buf.virt = vb2_dma_contig_memops.vaddr(dev->ctx_buf.alloc);
> + if (!dev->ctx_buf.virt) {
> + vb2_dma_contig_memops.put(dev->ctx_buf.alloc);
> + dev->ctx_buf.alloc = NULL;
> + dev->ctx_buf.dma = 0;
> +
> + mfc_err("Remapping DESC buffer failed.\n");
> + return -ENOMEM;
> + }
> +
> + memset(dev->ctx_buf.virt, 0, buf_size->dev_ctx);
> + wmb();
> +
> + mfc_debug_leave();
> +
> + return 0;
> +}
> +
> +/* Release context buffers for SYS_INIT */
> +void s5p_mfc_release_dev_context_buffer_v6(struct s5p_mfc_dev *dev)
> +{
> + if (dev->ctx_buf.alloc) {
> + vb2_dma_contig_memops.put(dev->ctx_buf.alloc);
> + dev->ctx_buf.alloc = NULL;
> + dev->ctx_buf.dma = 0;
> + dev->ctx_buf.virt = NULL;
> + }
> +}
> +
> +static int calc_plane(int width, int height)
> +{
> + int mbX, mbY;
> +
> + mbX = DIV_ROUND_UP(width, S5P_FIMV_NUM_PIXELS_IN_MB_ROW_V6);
> + mbY = DIV_ROUND_UP(height, S5P_FIMV_NUM_PIXELS_IN_MB_COL_V6);
> +
> + if (width * height < S5P_FIMV_MAX_FRAME_SIZE_V6)
> + mbY = (mbY + 1) / 2 * 2;
> +
> + return (mbX * S5P_FIMV_NUM_PIXELS_IN_MB_COL_V6) *
> + (mbY * S5P_FIMV_NUM_PIXELS_IN_MB_ROW_V6);
> +}
> +
> +void s5p_mfc_dec_calc_dpb_size_v6(struct s5p_mfc_ctx *ctx)
> +{
> + ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN_V6);
> + ctx->buf_height = ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN_V6);
> + mfc_debug(2, "SEQ Done: Movie dimensions %dx%d,\n"
> + "buffer dimensions: %dx%d\n", ctx->img_width,
> + ctx->img_height, ctx->buf_width, ctx->buf_height);
> +
> + ctx->luma_size = calc_plane(ctx->img_width, ctx->img_height);
> + ctx->chroma_size = calc_plane(ctx->img_width, (ctx->img_height >> 1));
> + if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC ||
> + ctx->codec_mode == S5P_MFC_CODEC_H264_MVC_DEC) {
> + ctx->mv_size = S5P_MFC_DEC_MV_SIZE_V6(ctx->img_width,
> + ctx->img_height);
> + ctx->mv_size = ALIGN(ctx->mv_size, 16);
> + } else {
> + ctx->mv_size = 0;
> + }
> +}
> +
> +void s5p_mfc_enc_calc_src_size_v6(struct s5p_mfc_ctx *ctx)
> +{
> + unsigned int mb_width, mb_height;
> +
> + mb_width = MB_WIDTH(ctx->img_width);
> + mb_height = MB_HEIGHT(ctx->img_height);
> +
> + ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN_V6);
> + ctx->luma_size = ALIGN((mb_width * mb_height) * 256, 256);
> + ctx->chroma_size = ALIGN((mb_width * mb_height) * 128, 256);
> +}
> +
> +/* Set registers for decoding stream buffer */
> +int s5p_mfc_set_dec_stream_buffer_v6(struct s5p_mfc_ctx *ctx, int buf_addr,
> + unsigned int start_num_byte, unsigned int strm_size)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_buf_size *buf_size = dev->variant->buf_size;
> +
> + mfc_debug_enter();
> + mfc_debug(2, "inst_no: %d, buf_addr: 0x%08x,\n"
> + "buf_size: 0x%08x (%d)\n",
> + ctx->inst_no, buf_addr, strm_size, strm_size);
> + WRITEL(strm_size, S5P_FIMV_D_STREAM_DATA_SIZE_V6);
> + WRITEL(buf_addr, S5P_FIMV_D_CPB_BUFFER_ADDR_V6);
> + WRITEL(buf_size->cpb, S5P_FIMV_D_CPB_BUFFER_SIZE_V6);
> + WRITEL(start_num_byte, S5P_FIMV_D_CPB_BUFFER_OFFSET_V6);
> +
> + mfc_debug_leave();
> + return 0;
> +}
> +
> +/* Set decoding frame buffer */
> +int s5p_mfc_set_dec_frame_buffer_v6(struct s5p_mfc_ctx *ctx)
> +{
> + unsigned int frame_size, i;
> + unsigned int frame_size_ch, frame_size_mv;
> + struct s5p_mfc_dev *dev = ctx->dev;
> + size_t buf_addr1;
> + int buf_size1;
> + int align_gap;
> +
> + buf_addr1 = ctx->bank1_phys;
> + buf_size1 = ctx->bank1_size;
> +
> + mfc_debug(2, "Buf1: %p (%d)\n", (void *)buf_addr1, buf_size1);
> + mfc_debug(2, "Total DPB COUNT: %d\n", ctx->total_dpb_count);
> + mfc_debug(2, "Setting display delay to %d\n", ctx->display_delay);
> +
> + WRITEL(ctx->total_dpb_count, S5P_FIMV_D_NUM_DPB_V6);
> + WRITEL(ctx->luma_size, S5P_FIMV_D_LUMA_DPB_SIZE_V6);
> + WRITEL(ctx->chroma_size, S5P_FIMV_D_CHROMA_DPB_SIZE_V6);
> +
> + WRITEL(buf_addr1, S5P_FIMV_D_SCRATCH_BUFFER_ADDR_V6);
> + WRITEL(ctx->scratch_buf_size, S5P_FIMV_D_SCRATCH_BUFFER_SIZE_V6);
> + buf_addr1 += ctx->scratch_buf_size;
> + buf_size1 -= ctx->scratch_buf_size;
> +
> + if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC ||
> + ctx->codec_mode == S5P_FIMV_CODEC_H264_MVC_DEC){
> + WRITEL(ctx->mv_size, S5P_FIMV_D_MV_BUFFER_SIZE_V6);
> + WRITEL(ctx->mv_count, S5P_FIMV_D_NUM_MV_V6);
> + }
> +
> + frame_size = ctx->luma_size;
> + frame_size_ch = ctx->chroma_size;
> + frame_size_mv = ctx->mv_size;
> + mfc_debug(2, "Frame size: %d ch: %d mv: %d\n",
> + frame_size, frame_size_ch, frame_size_mv);
> +
> + for (i = 0; i < ctx->total_dpb_count; i++) {
> + /* Bank2 */
> + mfc_debug(2, "Luma %d: %x\n", i,
> + ctx->dst_bufs[i].cookie.raw.luma);
> + WRITEL(ctx->dst_bufs[i].cookie.raw.luma,
> + S5P_FIMV_D_LUMA_DPB_V6 + i * 4);
> + mfc_debug(2, "\tChroma %d: %x\n", i,
> + ctx->dst_bufs[i].cookie.raw.chroma);
> + WRITEL(ctx->dst_bufs[i].cookie.raw.chroma,
> + S5P_FIMV_D_CHROMA_DPB_V6 + i * 4);
> + }
> + if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC ||
> + ctx->codec_mode == S5P_MFC_CODEC_H264_MVC_DEC) {
> + for (i = 0; i < ctx->mv_count; i++) {
> + /* To test alignment */
> + align_gap = buf_addr1;
> + buf_addr1 = ALIGN(buf_addr1, 16);
> + align_gap = buf_addr1 - align_gap;
> + buf_size1 -= align_gap;
> +
> + mfc_debug(2, "\tBuf1: %x, size: %d\n",
> + buf_addr1, buf_size1);
> + WRITEL(buf_addr1, S5P_FIMV_D_MV_BUFFER_V6 + i * 4);
> + buf_addr1 += frame_size_mv;
> + buf_size1 -= frame_size_mv;
> + }
> + }
> +
> + mfc_debug(2, "Buf1: %u, buf_size1: %d (frames %d)\n",
> + buf_addr1, buf_size1, ctx->total_dpb_count);
> + if (buf_size1 < 0) {
> + mfc_debug(2, "Not enough memory has been allocated.\n");
> + return -ENOMEM;
> + }
> +
> + WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
> + s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
> + S5P_FIMV_CH_INIT_BUFS_V6, NULL);
> +
> + mfc_debug(2, "After setting buffers.\n");
> + return 0;
> +}
> +
> +/* Set registers for encoding stream buffer */
> +int s5p_mfc_set_enc_stream_buffer_v6(struct s5p_mfc_ctx *ctx,
> + unsigned long addr, unsigned int size)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> +
> + WRITEL(addr, S5P_FIMV_E_STREAM_BUFFER_ADDR_V6); /* 16B align */
> + WRITEL(size, S5P_FIMV_E_STREAM_BUFFER_SIZE_V6);
> +
> + mfc_debug(2, "stream buf addr: 0x%08lx, size: 0x%d",
> + addr, size);
> +
> + return 0;
> +}
> +
> +void s5p_mfc_set_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx,
> + unsigned long y_addr, unsigned long c_addr)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> +
> + WRITEL(y_addr, S5P_FIMV_E_SOURCE_LUMA_ADDR_V6); /* 256B align */
> + WRITEL(c_addr, S5P_FIMV_E_SOURCE_CHROMA_ADDR_V6);
> +
> + mfc_debug(2, "enc src y buf addr: 0x%08lx", y_addr);
> + mfc_debug(2, "enc src c buf addr: 0x%08lx", c_addr);
> +}
> +
> +void s5p_mfc_get_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx,
> + unsigned long *y_addr, unsigned long *c_addr)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + unsigned long enc_recon_y_addr, enc_recon_c_addr;
> +
> + *y_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_LUMA_ADDR_V6);
> + *c_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_CHROMA_ADDR_V6);
> +
> + enc_recon_y_addr = READL(S5P_FIMV_E_RECON_LUMA_DPB_ADDR_V6);
> + enc_recon_c_addr = READL(S5P_FIMV_E_RECON_CHROMA_DPB_ADDR_V6);
> +
> + mfc_debug(2, "recon y addr: 0x%08lx", enc_recon_y_addr);
> + mfc_debug(2, "recon c addr: 0x%08lx", enc_recon_c_addr);
> +}
> +
> +/* Set encoding ref & codec buffer */
> +int s5p_mfc_set_enc_ref_buffer_v6(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + size_t buf_addr1, buf_size1;
> + int i;
> +
> + mfc_debug_enter();
> +
> + buf_addr1 = ctx->bank1_phys;
> + buf_size1 = ctx->bank1_size;
> +
> + mfc_debug(2, "Buf1: %p (%d)\n", (void *)buf_addr1, buf_size1);
> +
> + for (i = 0; i < ctx->dpb_count; i++) {
> + WRITEL(buf_addr1, S5P_FIMV_E_LUMA_DPB_V6 + (4 * i));
> + buf_addr1 += ctx->luma_dpb_size;
> + WRITEL(buf_addr1, S5P_FIMV_E_CHROMA_DPB_V6 + (4 * i));
> + buf_addr1 += ctx->chroma_dpb_size;
> + WRITEL(buf_addr1, S5P_FIMV_E_ME_BUFFER_V6 + (4 * i));
> + buf_addr1 += ctx->me_buffer_size;
> + buf_size1 -= (ctx->luma_dpb_size + ctx->chroma_dpb_size +
> + ctx->me_buffer_size);
> + }
> +
> + WRITEL(buf_addr1, S5P_FIMV_E_SCRATCH_BUFFER_ADDR_V6);
> + WRITEL(ctx->scratch_buf_size, S5P_FIMV_E_SCRATCH_BUFFER_SIZE_V6);
> + buf_addr1 += ctx->scratch_buf_size;
> + buf_size1 -= ctx->scratch_buf_size;
> +
> + WRITEL(buf_addr1, S5P_FIMV_E_TMV_BUFFER0_V6);
> + buf_addr1 += ctx->tmv_buffer_size >> 1;
> + WRITEL(buf_addr1, S5P_FIMV_E_TMV_BUFFER1_V6);
> + buf_addr1 += ctx->tmv_buffer_size >> 1;
> + buf_size1 -= ctx->tmv_buffer_size;
> +
> + mfc_debug(2, "Buf1: %u, buf_size1: %d (ref frames %d)\n",
> + buf_addr1, buf_size1, ctx->dpb_count);
> + if (buf_size1 < 0) {
> + mfc_debug(2, "Not enough memory has been allocated.\n");
> + return -ENOMEM;
> + }
> +
> + WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
> + s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
> + S5P_FIMV_CH_INIT_BUFS_V6, NULL);
> +
> + mfc_debug_leave();
> +
> + return 0;
> +}
> +
> +static int s5p_mfc_set_slice_mode(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> +
> + /* multi-slice control */
> + /* multi-slice MB number or bit size */
> + WRITEL(ctx->slice_mode, S5P_FIMV_E_MSLICE_MODE_V6);
> + if (ctx->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) {
> + WRITEL(ctx->slice_size.mb, S5P_FIMV_E_MSLICE_SIZE_MB_V6);
> + } else if (ctx->slice_mode ==
> + V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) {
> + WRITEL(ctx->slice_size.bits, S5P_FIMV_E_MSLICE_SIZE_BITS_V6);
> + } else {
> + WRITEL(0x0, S5P_FIMV_E_MSLICE_SIZE_MB_V6);
> + WRITEL(0x0, S5P_FIMV_E_MSLICE_SIZE_BITS_V6);
> + }
> +
> + return 0;
> +}
> +
> +static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_enc_params *p = &ctx->enc_params;
> + unsigned int reg = 0;
> +
> + mfc_debug_enter();
> +
> + /* width */
> + WRITEL(ctx->img_width, S5P_FIMV_E_FRAME_WIDTH_V6); /* 16 align */
> + /* height */
> + WRITEL(ctx->img_height, S5P_FIMV_E_FRAME_HEIGHT_V6); /* 16 align */
> +
> + /* cropped width */
> + WRITEL(ctx->img_width, S5P_FIMV_E_CROPPED_FRAME_WIDTH_V6);
> + /* cropped height */
> + WRITEL(ctx->img_height, S5P_FIMV_E_CROPPED_FRAME_HEIGHT_V6);
> + /* cropped offset */
> + WRITEL(0x0, S5P_FIMV_E_FRAME_CROP_OFFSET_V6);
> +
> + /* pictype : IDR period */
> + reg = 0;
> + reg |= p->gop_size & 0xFFFF;
> + WRITEL(reg, S5P_FIMV_E_GOP_CONFIG_V6);
> +
> + /* multi-slice control */
> + /* multi-slice MB number or bit size */
> + ctx->slice_mode = p->slice_mode;
> + reg = 0;
> + if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) {
> + reg |= (0x1 << 3);
> + WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
> + ctx->slice_size.mb = p->slice_mb;
> + } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES)
{
> + reg |= (0x1 << 3);
> + WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
> + ctx->slice_size.bits = p->slice_bit;
> + } else {
> + reg &= ~(0x1 << 3);
> + WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
> + }
> +
> + s5p_mfc_set_slice_mode(ctx);
> +
> + /* cyclic intra refresh */
> + WRITEL(p->intra_refresh_mb, S5P_FIMV_E_IR_SIZE_V6);
> + reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6);
> + if (p->intra_refresh_mb == 0)
> + reg &= ~(0x1 << 4);
> + else
> + reg |= (0x1 << 4);
> + WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
> +
> + /* 'NON_REFERENCE_STORE_ENABLE' for debugging */
> + reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6);
> + reg &= ~(0x1 << 9);
> + WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
> +
> + /* memory structure cur. frame */
> + if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) {
> + /* 0: Linear, 1: 2D tiled*/
> + reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6);
> + reg &= ~(0x1 << 7);
> + WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
> + /* 0: NV12(CbCr), 1: NV21(CrCb) */
> + WRITEL(0x0, S5P_FIMV_PIXEL_FORMAT_V6);
> + } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV21M) {
> + /* 0: Linear, 1: 2D tiled*/
> + reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6);
> + reg &= ~(0x1 << 7);
> + WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
> + /* 0: NV12(CbCr), 1: NV21(CrCb) */
> + WRITEL(0x1, S5P_FIMV_PIXEL_FORMAT_V6);
> + } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16) {
> + /* 0: Linear, 1: 2D tiled*/
> + reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6);
> + reg |= (0x1 << 7);
> + WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
> + /* 0: NV12(CbCr), 1: NV21(CrCb) */
> + WRITEL(0x0, S5P_FIMV_PIXEL_FORMAT_V6);
> + }
> +
> + /* memory structure recon. frame */
> + /* 0: Linear, 1: 2D tiled */
> + reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6);
> + reg |= (0x1 << 8);
> + WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
> +
> + /* padding control & value */
> + WRITEL(0x0, S5P_FIMV_E_PADDING_CTRL_V6);
> + if (p->pad) {
> + reg = 0;
> + /** enable */
> + reg |= (1 << 31);
> + /** cr value */
> + reg |= ((p->pad_cr & 0xFF) << 16);
> + /** cb value */
> + reg |= ((p->pad_cb & 0xFF) << 8);
> + /** y value */
> + reg |= p->pad_luma & 0xFF;
> + WRITEL(reg, S5P_FIMV_E_PADDING_CTRL_V6);
> + }
> +
> + /* rate control config. */
> + reg = 0;
> + /* frame-level rate control */
> + reg |= ((p->rc_frame & 0x1) << 9);
> + WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6);
> +
> + /* bit rate */
> + if (p->rc_frame)
> + WRITEL(p->rc_bitrate,
> + S5P_FIMV_E_RC_BIT_RATE_V6);
> + else
> + WRITEL(1, S5P_FIMV_E_RC_BIT_RATE_V6);
> +
> + /* reaction coefficient */
> + if (p->rc_frame) {
> + if (p->rc_reaction_coeff < TIGHT_CBR_MAX) /* tight CBR */
> + WRITEL(1, S5P_FIMV_E_RC_RPARAM_V6);
> + else /* loose CBR */
> + WRITEL(2, S5P_FIMV_E_RC_RPARAM_V6);
> + }
> +
> + /* seq header ctrl */
> + reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6);
> + reg &= ~(0x1 << 2);
> + reg |= ((p->seq_hdr_mode & 0x1) << 2);
> +
> + /* frame skip mode */
> + reg &= ~(0x3);
> + reg |= (p->frame_skip_mode & 0x3);
> + WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
> +
> + /* 'DROP_CONTROL_ENABLE', disable */
> + reg = READL(S5P_FIMV_E_RC_CONFIG_V6);
> + reg &= ~(0x1 << 10);
> + WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6);
> +
> + /* setting for MV range [16, 256] */
> + reg = 0;
> + reg &= ~(0x3FFF);
> + reg = 256;
> + WRITEL(reg, S5P_FIMV_E_MV_HOR_RANGE_V6);
> +
> + reg = 0;
> + reg &= ~(0x3FFF);
> + reg = 256;
> + WRITEL(reg, S5P_FIMV_E_MV_VER_RANGE_V6);
> +
> + WRITEL(0x0, S5P_FIMV_E_FRAME_INSERTION_V6);
> + WRITEL(0x0, S5P_FIMV_E_ROI_BUFFER_ADDR_V6);
> + WRITEL(0x0, S5P_FIMV_E_PARAM_CHANGE_V6);
> + WRITEL(0x0, S5P_FIMV_E_RC_ROI_CTRL_V6);
> + WRITEL(0x0, S5P_FIMV_E_PICTURE_TAG_V6);
> +
> + WRITEL(0x0, S5P_FIMV_E_BIT_COUNT_ENABLE_V6);
> + WRITEL(0x0, S5P_FIMV_E_MAX_BIT_COUNT_V6);
> + WRITEL(0x0, S5P_FIMV_E_MIN_BIT_COUNT_V6);
> +
> + WRITEL(0x0, S5P_FIMV_E_METADATA_BUFFER_ADDR_V6);
> + WRITEL(0x0, S5P_FIMV_E_METADATA_BUFFER_SIZE_V6);
> +
> + mfc_debug_leave();
> +
> + return 0;
> +}
> +
> +static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_enc_params *p = &ctx->enc_params;
> + struct s5p_mfc_h264_enc_params *p_h264 = &p->codec.h264;
> + unsigned int reg = 0;
> + int i;
> +
> + mfc_debug_enter();
> +
> + s5p_mfc_set_enc_params(ctx);
> +
> + /* pictype : number of B */
> + reg = READL(S5P_FIMV_E_GOP_CONFIG_V6);
> + reg &= ~(0x3 << 16);
> + reg |= ((p->num_b_frame & 0x3) << 16);
> + WRITEL(reg, S5P_FIMV_E_GOP_CONFIG_V6);
> +
> + /* profile & level */
> + reg = 0;
> + /** level */
> + reg |= ((p_h264->level & 0xFF) << 8);
> + /** profile - 0 ~ 3 */
> + reg |= p_h264->profile & 0x3F;
> + WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE_V6);
> +
> + /* rate control config. */
> + reg = READL(S5P_FIMV_E_RC_CONFIG_V6);
> + /** macroblock level rate control */
> + reg &= ~(0x1 << 8);
> + reg |= ((p->rc_mb & 0x1) << 8);
> + WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6);
> + /** frame QP */
> + reg &= ~(0x3F);
> + reg |= p_h264->rc_frame_qp & 0x3F;
> + WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6);
> +
> + /* max & min value of QP */
> + reg = 0;
> + /** max QP */
> + reg |= ((p_h264->rc_max_qp & 0x3F) << 8);
> + /** min QP */
> + reg |= p_h264->rc_min_qp & 0x3F;
> + WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_V6);
> +
> + /* other QPs */
> + WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP_V6);
> + if (!p->rc_frame && !p->rc_mb) {
> + reg = 0;
> + reg |= ((p_h264->rc_b_frame_qp & 0x3F) << 16);
> + reg |= ((p_h264->rc_p_frame_qp & 0x3F) << 8);
> + reg |= p_h264->rc_frame_qp & 0x3F;
> + WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP_V6);
> + }
> +
> + /* frame rate */
> + if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) {
> + reg = 0;
> + reg |= ((p->rc_framerate_num & 0xFFFF) << 16);
> + reg |= p->rc_framerate_denom & 0xFFFF;
> + WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE_V6);
> + }
> +
> + /* vbv buffer size */
> + if (p->frame_skip_mode ==
> + V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
> + WRITEL(p_h264->cpb_size & 0xFFFF,
> + S5P_FIMV_E_VBV_BUFFER_SIZE_V6);
> +
> + if (p->rc_frame)
> + WRITEL(p->vbv_delay, S5P_FIMV_E_VBV_INIT_DELAY_V6);
> + }
> +
> + /* interlace */
> + reg = 0;
> + reg |= ((p_h264->interlace & 0x1) << 3);
> + WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
> +
> + /* height */
> + if (p_h264->interlace) {
> + WRITEL(ctx->img_height >> 1,
> + S5P_FIMV_E_FRAME_HEIGHT_V6); /* 32 align */
> + /* cropped height */
> + WRITEL(ctx->img_height >> 1,
> + S5P_FIMV_E_CROPPED_FRAME_HEIGHT_V6);
> + }
> +
> + /* loop filter ctrl */
> + reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
> + reg &= ~(0x3 << 1);
> + reg |= ((p_h264->loop_filter_mode & 0x3) << 1);
> + WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
> +
> + /* loopfilter alpha offset */
> + if (p_h264->loop_filter_alpha < 0) {
> + reg = 0x10;
> + reg |= (0xFF - p_h264->loop_filter_alpha) + 1;
> + } else {
> + reg = 0x00;
> + reg |= (p_h264->loop_filter_alpha & 0xF);
> + }
> + WRITEL(reg, S5P_FIMV_E_H264_LF_ALPHA_OFFSET_V6);
> +
> + /* loopfilter beta offset */
> + if (p_h264->loop_filter_beta < 0) {
> + reg = 0x10;
> + reg |= (0xFF - p_h264->loop_filter_beta) + 1;
> + } else {
> + reg = 0x00;
> + reg |= (p_h264->loop_filter_beta & 0xF);
> + }
> + WRITEL(reg, S5P_FIMV_E_H264_LF_BETA_OFFSET_V6);
> +
> + /* entropy coding mode */
> + reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
> + reg &= ~(0x1);
> + reg |= p_h264->entropy_mode & 0x1;
> + WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
> +
> + /* number of ref. picture */
> + reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
> + reg &= ~(0x1 << 7);
> + reg |= (((p_h264->num_ref_pic_4p - 1) & 0x1) << 7);
> + WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
> +
> + /* 8x8 transform enable */
> + reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
> + reg &= ~(0x3 << 12);
> + reg |= ((p_h264->_8x8_transform & 0x3) << 12);
> + WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
> +
> + /* macroblock adaptive scaling features */
> + WRITEL(0x0, S5P_FIMV_E_MB_RC_CONFIG_V6);
> + if (p->rc_mb) {
> + reg = 0;
> + /** dark region */
> + reg |= ((p_h264->rc_mb_dark & 0x1) << 3);
> + /** smooth region */
> + reg |= ((p_h264->rc_mb_smooth & 0x1) << 2);
> + /** static region */
> + reg |= ((p_h264->rc_mb_static & 0x1) << 1);
> + /** high activity region */
> + reg |= p_h264->rc_mb_activity & 0x1;
> + WRITEL(reg, S5P_FIMV_E_MB_RC_CONFIG_V6);
> + }
> +
> + /* aspect ratio VUI */
> + reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
> + reg &= ~(0x1 << 5);
> + reg |= ((p_h264->vui_sar & 0x1) << 5);
> + WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
> +
> + WRITEL(0x0, S5P_FIMV_E_ASPECT_RATIO_V6);
> + WRITEL(0x0, S5P_FIMV_E_EXTENDED_SAR_V6);
> + if (p_h264->vui_sar) {
> + /* aspect ration IDC */
> + reg = 0;
> + reg |= p_h264->vui_sar_idc & 0xFF;
> + WRITEL(reg, S5P_FIMV_E_ASPECT_RATIO_V6);
> + if (p_h264->vui_sar_idc == 0xFF) {
> + /* extended SAR */
> + reg = 0;
> + reg |= (p_h264->vui_ext_sar_width & 0xFFFF) << 16;
> + reg |= p_h264->vui_ext_sar_height & 0xFFFF;
> + WRITEL(reg, S5P_FIMV_E_EXTENDED_SAR_V6);
> + }
> + }
> +
> + /* intra picture period for H.264 open GOP */
> + /* control */
> + reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
> + reg &= ~(0x1 << 4);
> + reg |= ((p_h264->open_gop & 0x1) << 4);
> + WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
> + /* value */
> + WRITEL(0x0, S5P_FIMV_E_H264_I_PERIOD_V6);
> + if (p_h264->open_gop) {
> + reg = 0;
> + reg |= p_h264->open_gop_size & 0xFFFF;
> + WRITEL(reg, S5P_FIMV_E_H264_I_PERIOD_V6);
> + }
> +
> + /* 'WEIGHTED_BI_PREDICTION' for B is disable */
> + reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
> + reg &= ~(0x3 << 9);
> + WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
> +
> + /* 'CONSTRAINED_INTRA_PRED_ENABLE' is disable */
> + reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
> + reg &= ~(0x1 << 14);
> + WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
> +
> + /* ASO */
> + reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
> + reg &= ~(0x1 << 6);
> + reg |= ((p_h264->aso & 0x1) << 6);
> + WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
> +
> + /* hier qp enable */
> + reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
> + reg &= ~(0x1 << 8);
> + reg |= ((p_h264->open_gop & 0x1) << 8);
> + WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
> + reg = 0;
> + if (p_h264->hier_qp && p_h264->hier_qp_layer) {
> + reg |= (p_h264->hier_qp_type & 0x1) << 0x3;
> + reg |= p_h264->hier_qp_layer & 0x7;
> + WRITEL(reg, S5P_FIMV_E_H264_NUM_T_LAYER_V6);
> + /* QP value for each layer */
> + for (i = 0; i < (p_h264->hier_qp_layer & 0x7); i++)
> + WRITEL(p_h264->hier_qp_layer_qp[i],
> + S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER0_V6 +
> + i * 4);
> + }
> + /* number of coding layer should be zero when hierarchical is disable
*/
> + WRITEL(reg, S5P_FIMV_E_H264_NUM_T_LAYER_V6);
> +
> + /* frame packing SEI generation */
> + reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
> + reg &= ~(0x1 << 25);
> + reg |= ((p_h264->sei_frame_packing & 0x1) << 25);
> + WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
> + if (p_h264->sei_frame_packing) {
> + reg = 0;
> + /** current frame0 flag */
> + reg |= ((p_h264->sei_fp_curr_frame_0 & 0x1) << 2);
> + /** arrangement type */
> + reg |= p_h264->sei_fp_arrangement_type & 0x3;
> + WRITEL(reg, S5P_FIMV_E_H264_FRAME_PACKING_SEI_INFO_V6);
> + }
> +
> + if (p_h264->fmo) {
> + switch (p_h264->fmo_map_type) {
> + case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES:
> + if (p_h264->fmo_slice_grp > 4)
> + p_h264->fmo_slice_grp = 4;
> + for (i = 0; i < (p_h264->fmo_slice_grp & 0xF); i++)
> + WRITEL(p_h264->fmo_run_len[i] - 1,
> + S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_0_V6 +
> + i * 4);
> + break;
> + case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_SCATTERED_SLICES:
> + if (p_h264->fmo_slice_grp > 4)
> + p_h264->fmo_slice_grp = 4;
> + break;
> + case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_RASTER_SCAN:
> + case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_WIPE_SCAN:
> + if (p_h264->fmo_slice_grp > 2)
> + p_h264->fmo_slice_grp = 2;
> + WRITEL(p_h264->fmo_chg_dir & 0x1,
> + S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_DIR_V6);
> + /* the valid range is 0 ~ number of macroblocks -1 */
> + WRITEL(p_h264->fmo_chg_rate,
> +
S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_RATE_MINUS1_V6);
> + break;
> + default:
> + mfc_err("Unsupported map type for FMO: %d\n",
> + p_h264->fmo_map_type);
> + p_h264->fmo_map_type = 0;
> + p_h264->fmo_slice_grp = 1;
> + break;
> + }
> +
> + WRITEL(p_h264->fmo_map_type,
> + S5P_FIMV_E_H264_FMO_SLICE_GRP_MAP_TYPE_V6);
> + WRITEL(p_h264->fmo_slice_grp - 1,
> + S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1_V6);
> + } else {
> + WRITEL(0, S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1_V6);
> + }
> +
> + mfc_debug_leave();
> +
> + return 0;
> +}
> +
> +static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_enc_params *p = &ctx->enc_params;
> + struct s5p_mfc_mpeg4_enc_params *p_mpeg4 = &p->codec.mpeg4;
> + unsigned int reg = 0;
> +
> + mfc_debug_enter();
> +
> + s5p_mfc_set_enc_params(ctx);
> +
> + /* pictype : number of B */
> + reg = READL(S5P_FIMV_E_GOP_CONFIG_V6);
> + reg &= ~(0x3 << 16);
> + reg |= ((p->num_b_frame & 0x3) << 16);
> + WRITEL(reg, S5P_FIMV_E_GOP_CONFIG_V6);
> +
> + /* profile & level */
> + reg = 0;
> + /** level */
> + reg |= ((p_mpeg4->level & 0xFF) << 8);
> + /** profile - 0 ~ 1 */
> + reg |= p_mpeg4->profile & 0x3F;
> + WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE_V6);
> +
> + /* rate control config. */
> + reg = READL(S5P_FIMV_E_RC_CONFIG_V6);
> + /** macroblock level rate control */
> + reg &= ~(0x1 << 8);
> + reg |= ((p->rc_mb & 0x1) << 8);
> + WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6);
> + /** frame QP */
> + reg &= ~(0x3F);
> + reg |= p_mpeg4->rc_frame_qp & 0x3F;
> + WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6);
> +
> + /* max & min value of QP */
> + reg = 0;
> + /** max QP */
> + reg |= ((p_mpeg4->rc_max_qp & 0x3F) << 8);
> + /** min QP */
> + reg |= p_mpeg4->rc_min_qp & 0x3F;
> + WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_V6);
> +
> + /* other QPs */
> + WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP_V6);
> + if (!p->rc_frame && !p->rc_mb) {
> + reg = 0;
> + reg |= ((p_mpeg4->rc_b_frame_qp & 0x3F) << 16);
> + reg |= ((p_mpeg4->rc_p_frame_qp & 0x3F) << 8);
> + reg |= p_mpeg4->rc_frame_qp & 0x3F;
> + WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP_V6);
> + }
> +
> + /* frame rate */
> + if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) {
> + reg = 0;
> + reg |= ((p->rc_framerate_num & 0xFFFF) << 16);
> + reg |= p->rc_framerate_denom & 0xFFFF;
> + WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE_V6);
> + }
> +
> + /* vbv buffer size */
> + if (p->frame_skip_mode ==
> + V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
> + WRITEL(p->vbv_size & 0xFFFF, S5P_FIMV_E_VBV_BUFFER_SIZE_V6);
> +
> + if (p->rc_frame)
> + WRITEL(p->vbv_delay, S5P_FIMV_E_VBV_INIT_DELAY_V6);
> + }
> +
> + /* Disable HEC */
> + WRITEL(0x0, S5P_FIMV_E_MPEG4_OPTIONS_V6);
> + WRITEL(0x0, S5P_FIMV_E_MPEG4_HEC_PERIOD_V6);
> +
> + mfc_debug_leave();
> +
> + return 0;
> +}
> +
> +static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_enc_params *p = &ctx->enc_params;
> + struct s5p_mfc_mpeg4_enc_params *p_h263 = &p->codec.mpeg4;
> + unsigned int reg = 0;
> +
> + mfc_debug_enter();
> +
> + s5p_mfc_set_enc_params(ctx);
> +
> + /* profile & level */
> + reg = 0;
> + /** profile */
> + reg |= (0x1 << 4);
> + WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE_V6);
> +
> + /* rate control config. */
> + reg = READL(S5P_FIMV_E_RC_CONFIG_V6);
> + /** macroblock level rate control */
> + reg &= ~(0x1 << 8);
> + reg |= ((p->rc_mb & 0x1) << 8);
> + WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6);
> + /** frame QP */
> + reg &= ~(0x3F);
> + reg |= p_h263->rc_frame_qp & 0x3F;
> + WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6);
> +
> + /* max & min value of QP */
> + reg = 0;
> + /** max QP */
> + reg |= ((p_h263->rc_max_qp & 0x3F) << 8);
> + /** min QP */
> + reg |= p_h263->rc_min_qp & 0x3F;
> + WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_V6);
> +
> + /* other QPs */
> + WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP_V6);
> + if (!p->rc_frame && !p->rc_mb) {
> + reg = 0;
> + reg |= ((p_h263->rc_b_frame_qp & 0x3F) << 16);
> + reg |= ((p_h263->rc_p_frame_qp & 0x3F) << 8);
> + reg |= p_h263->rc_frame_qp & 0x3F;
> + WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP_V6);
> + }
> +
> + /* frame rate */
> + if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) {
> + reg = 0;
> + reg |= ((p->rc_framerate_num & 0xFFFF) << 16);
> + reg |= p->rc_framerate_denom & 0xFFFF;
> + WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE_V6);
> + }
> +
> + /* vbv buffer size */
> + if (p->frame_skip_mode ==
> + V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
> + WRITEL(p->vbv_size & 0xFFFF, S5P_FIMV_E_VBV_BUFFER_SIZE_V6);
> +
> + if (p->rc_frame)
> + WRITEL(p->vbv_delay, S5P_FIMV_E_VBV_INIT_DELAY_V6);
> + }
> +
> + mfc_debug_leave();
> +
> + return 0;
> +}
> +
> +/* Initialize decoding */
> +int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + unsigned int reg = 0;
> + int fmo_aso_ctrl = 0;
> +
> + mfc_debug_enter();
> + mfc_debug(2, "InstNo: %d/%d\n", ctx->inst_no,
> + S5P_FIMV_CH_SEQ_HEADER_V6);
> + mfc_debug(2, "BUFs: %08x %08x %08x\n",
> + READL(S5P_FIMV_D_CPB_BUFFER_ADDR_V6),
> + READL(S5P_FIMV_D_CPB_BUFFER_ADDR_V6),
> + READL(S5P_FIMV_D_CPB_BUFFER_ADDR_V6));
> +
> + /* FMO_ASO_CTRL - 0: Enable, 1: Disable */
> + reg |= (fmo_aso_ctrl << S5P_FIMV_D_OPT_FMO_ASO_CTRL_MASK_V6);
> +
> + /* When user sets desplay_delay to 0,
> + * It works as "display_delay enable" and delay set to 0.
> + * If user wants display_delay disable, It should be
> + * set to negative value. */
> + if (ctx->display_delay >= 0) {
> + reg |= (0x1 << S5P_FIMV_D_OPT_DDELAY_EN_SHIFT_V6);
> + WRITEL(ctx->display_delay, S5P_FIMV_D_DISPLAY_DELAY_V6);
> + }
> + /* Setup loop filter, for decoding this is only valid for MPEG4 */
> + if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_DEC) {
> + mfc_debug(2, "Set loop filter to: %d\n",
> + ctx->loop_filter_mpeg4);
> + reg |= (ctx->loop_filter_mpeg4 <<
> + S5P_FIMV_D_OPT_LF_CTRL_SHIFT_V6);
> + }
> + if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16)
> + reg |= (0x1 << S5P_FIMV_D_OPT_TILE_MODE_SHIFT_V6);
> +
> + WRITEL(reg, S5P_FIMV_D_DEC_OPTIONS_V6);
> +
> + /* 0: NV12(CbCr), 1: NV21(CrCb) */
> + if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV21M)
> + WRITEL(0x1, S5P_FIMV_PIXEL_FORMAT_V6);
> + else
> + WRITEL(0x0, S5P_FIMV_PIXEL_FORMAT_V6);
> +
> + /* sei parse */
> + WRITEL(ctx->sei_fp_parse & 0x1, S5P_FIMV_D_SEI_ENABLE_V6);
> +
> + WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
> + s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
> + S5P_FIMV_CH_SEQ_HEADER_V6, NULL);
> +
> + mfc_debug_leave();
> + return 0;
> +}
> +
> +static inline void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + unsigned int dpb;
> + if (flush)
> + dpb = READL(S5P_FIMV_SI_CH0_DPB_CONF_CTRL) | (1 << 14);
> + else
> + dpb = READL(S5P_FIMV_SI_CH0_DPB_CONF_CTRL) & ~(1 << 14);
> + WRITEL(dpb, S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
> +}
> +
> +/* Decode a single frame */
> +int s5p_mfc_decode_one_frame_v6(struct s5p_mfc_ctx *ctx,
> + enum s5p_mfc_decode_arg last_frame)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> +
> + WRITEL(ctx->dec_dst_flag, S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER_V6);
> + WRITEL(ctx->slice_interface & 0x1, S5P_FIMV_D_SLICE_IF_ENABLE_V6);
> +
> + WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
> + /* Issue different commands to instance basing on whether it
> + * is the last frame or not. */
> + switch (last_frame) {
> + case 0:
> + s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
> + S5P_FIMV_CH_FRAME_START_V6, NULL);
> + break;
> + case 1:
> + s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
> + S5P_FIMV_CH_LAST_FRAME_V6, NULL);
> + break;
> + default:
> + mfc_err("Unsupported last frame arg.\n");
> + return -EINVAL;
> + }
> +
> + mfc_debug(2, "Decoding a usual frame.\n");
> + return 0;
> +}
> +
> +int s5p_mfc_init_encode_v6(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> +
> + if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC)
> + s5p_mfc_set_enc_params_h264(ctx);
> + else if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_ENC)
> + s5p_mfc_set_enc_params_mpeg4(ctx);
> + else if (ctx->codec_mode == S5P_MFC_CODEC_H263_ENC)
> + s5p_mfc_set_enc_params_h263(ctx);
> + else {
> + mfc_err("Unknown codec for encoding (%x).\n",
> + ctx->codec_mode);
> + return -EINVAL;
> + }
> +
> + WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
> + s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
> + S5P_FIMV_CH_SEQ_HEADER_V6, NULL);
> +
> + return 0;
> +}
> +
> +int s5p_mfc_h264_set_aso_slice_order_v6(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_enc_params *p = &ctx->enc_params;
> + struct s5p_mfc_h264_enc_params *p_h264 = &p->codec.h264;
> + int i;
> +
> + if (p_h264->aso) {
> + for (i = 0; i < 8; i++)
> + WRITEL(p_h264->aso_slice_order[i],
> + S5P_FIMV_E_H264_ASO_SLICE_ORDER_0_V6 + i * 4);
> + }
> + return 0;
> +}
> +
> +/* Encode a single frame */
> +int s5p_mfc_encode_one_frame_v6(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> +
> + mfc_debug(2, "++\n");
> +
> + /* memory structure cur. frame */
> +
> + if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC)
> + s5p_mfc_h264_set_aso_slice_order_v6(ctx);
> +
> + s5p_mfc_set_slice_mode(ctx);
> +
> + WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
> + s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
> + S5P_FIMV_CH_FRAME_START_V6, NULL);
> +
> + mfc_debug(2, "--\n");
> +
> + return 0;
> +}
> +
> +static inline int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev)
> +{
> + unsigned long flags;
> + int new_ctx;
> + int cnt;
> +
> + spin_lock_irqsave(&dev->condlock, flags);
> + mfc_debug(2, "Previos context: %d (bits %08lx)\n", dev->curr_ctx,
> + dev->ctx_work_bits);
> + new_ctx = (dev->curr_ctx + 1) % MFC_NUM_CONTEXTS;
> + cnt = 0;
> + while (!test_bit(new_ctx, &dev->ctx_work_bits)) {
> + new_ctx = (new_ctx + 1) % MFC_NUM_CONTEXTS;
> + cnt++;
> + if (cnt > MFC_NUM_CONTEXTS) {
> + /* No contexts to run */
> + spin_unlock_irqrestore(&dev->condlock, flags);
> + return -EAGAIN;
> + }
> + }
> + spin_unlock_irqrestore(&dev->condlock, flags);
> + return new_ctx;
> +}
> +
> +static inline void s5p_mfc_run_dec_last_frames(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_buf *temp_vb;
> + unsigned long flags;
> +
> + spin_lock_irqsave(&dev->irqlock, flags);
> +
> + /* Frames are being decoded */
> + if (list_empty(&ctx->src_queue)) {
> + mfc_debug(2, "No src buffers.\n");
> + spin_unlock_irqrestore(&dev->irqlock, flags);
> + return;
> + }
> + /* Get the next source buffer */
> + temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
> + temp_vb->used = 1;
> + s5p_mfc_set_dec_stream_buffer_v6(ctx,
> + vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), 0, 0);
> + spin_unlock_irqrestore(&dev->irqlock, flags);
> +
> + dev->curr_ctx = ctx->num;
> + s5p_mfc_clean_ctx_int_flags(ctx);
> + s5p_mfc_decode_one_frame_v6(ctx, 1);
> +}
> +
> +static inline int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + struct s5p_mfc_buf *temp_vb;
> + unsigned long flags;
> + int last_frame = 0;
> + unsigned int index;
> +
> + spin_lock_irqsave(&dev->irqlock, flags);
> +
> + /* Frames are being decoded */
> + if (list_empty(&ctx->src_queue)) {
> + mfc_debug(2, "No src buffers.\n");
> + spin_unlock_irqrestore(&dev->irqlock, flags);
> + return -EAGAIN;
> + }
> + /* Get the next source buffer */
> + temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
> + temp_vb->used = 1;
> + s5p_mfc_set_dec_stream_buffer_v6(ctx,
> + vb2_dma_contig_plane_dma_addr(temp_vb->b, 0),
> + ctx->consumed_stream,
> + temp_vb->b->v4l2_planes[0].bytesused);
> + spin_unlock_irqrestore(&dev->irqlock, flags);
> +
> + index = temp_vb->b->v4l2_buf.index;
> +
> + dev->curr_ctx = ctx->num;
> + s5p_mfc_clean_ctx_int_flags(ctx);
> + if (temp_vb->b->v4l2_planes[0].bytesused == 0) {
> + last_frame = 1;
> + mfc_debug(2, "Setting ctx->state to FINISHING\n");
> + ctx->state = MFCINST_FINISHING;
> + }
> + s5p_mfc_decode_one_frame_v6(ctx, last_frame);
> +
> + return 0;
> +}
> +
> +static inline int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + unsigned long flags;
> + struct s5p_mfc_buf *dst_mb;
> + struct s5p_mfc_buf *src_mb;
> + unsigned long src_y_addr, src_c_addr, dst_addr;
> + /*
> + unsigned int src_y_size, src_c_size;
> + */
> + unsigned int dst_size;
> + unsigned int index;
> +
> + spin_lock_irqsave(&dev->irqlock, flags);
> +
> + if (list_empty(&ctx->src_queue)) {
> + mfc_debug(2, "no src buffers.\n");
> + spin_unlock_irqrestore(&dev->irqlock, flags);
> + return -EAGAIN;
> + }
> +
> + if (list_empty(&ctx->dst_queue)) {
> + mfc_debug(2, "no dst buffers.\n");
> + spin_unlock_irqrestore(&dev->irqlock, flags);
> + return -EAGAIN;
> + }
> +
> + src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
> + src_mb->used = 1;
> + src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 0);
> + src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1);
> +
> + mfc_debug(2, "enc src y addr: 0x%08lx", src_y_addr);
> + mfc_debug(2, "enc src c addr: 0x%08lx", src_c_addr);
> +
> + s5p_mfc_set_enc_frame_buffer_v6(ctx, src_y_addr, src_c_addr);
> +
> + dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
> + dst_mb->used = 1;
> + dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
> + dst_size = vb2_plane_size(dst_mb->b, 0);
> +
> + s5p_mfc_set_enc_stream_buffer_v6(ctx, dst_addr, dst_size);
> +
> + spin_unlock_irqrestore(&dev->irqlock, flags);
> +
> + index = src_mb->b->v4l2_buf.index;
> +
> + dev->curr_ctx = ctx->num;
> + s5p_mfc_clean_ctx_int_flags(ctx);
> + s5p_mfc_encode_one_frame_v6(ctx);
> +
> + return 0;
> +}
> +
> +static inline void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + unsigned long flags;
> + struct s5p_mfc_buf *temp_vb;
> +
> + /* Initializing decoding - parsing header */
> + spin_lock_irqsave(&dev->irqlock, flags);
> + mfc_debug(2, "Preparing to init decoding.\n");
> + temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
> + mfc_debug(2, "Header size: %d\n",
temp_vb->b->v4l2_planes[0].bytesused);
> + s5p_mfc_set_dec_stream_buffer_v6(ctx,
> + vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), 0,
> + temp_vb->b->v4l2_planes[0].bytesused);
> + spin_unlock_irqrestore(&dev->irqlock, flags);
> + dev->curr_ctx = ctx->num;
> + s5p_mfc_clean_ctx_int_flags(ctx);
> + s5p_mfc_init_decode_v6(ctx);
> +}
> +
> +static inline void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + unsigned long flags;
> + struct s5p_mfc_buf *dst_mb;
> + unsigned long dst_addr;
> + unsigned int dst_size;
> +
> + spin_lock_irqsave(&dev->irqlock, flags);
> +
> + dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
> + dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
> + dst_size = vb2_plane_size(dst_mb->b, 0);
> + s5p_mfc_set_enc_stream_buffer_v6(ctx, dst_addr, dst_size);
> + spin_unlock_irqrestore(&dev->irqlock, flags);
> + dev->curr_ctx = ctx->num;
> + s5p_mfc_clean_ctx_int_flags(ctx);
> + s5p_mfc_init_encode_v6(ctx);
> +}
> +
> +static inline int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + int ret;
> + /* Header was parsed now start processing
> + * First set the output frame buffers
> + * s5p_mfc_alloc_dec_buffers(ctx); */
> +
> + if (ctx->capture_state != QUEUE_BUFS_MMAPED) {
> + mfc_err("It seems that not all destionation buffers were\n"
> + "mmaped.MFC requires that all destination are
mmaped\n"
> + "before starting processing.\n");
> + return -EAGAIN;
> + }
> +
> + dev->curr_ctx = ctx->num;
> + s5p_mfc_clean_ctx_int_flags(ctx);
> + ret = s5p_mfc_set_dec_frame_buffer_v6(ctx);
> + if (ret) {
> + mfc_err("Failed to alloc frame mem.\n");
> + ctx->state = MFCINST_ERROR;
> + }
> + return ret;
> +}
> +
> +static inline int s5p_mfc_run_init_enc_buffers(struct s5p_mfc_ctx *ctx)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + int ret;
> +
> + ret = s5p_mfc_alloc_codec_buffers_v6(ctx);
> + if (ret) {
> + mfc_err("Failed to allocate encoding buffers.\n");
> + return -ENOMEM;
> + }
> +
> + /* Header was generated now starting processing
> + * First set the reference frame buffers
> + */
> + if (ctx->capture_state != QUEUE_BUFS_REQUESTED) {
> + mfc_err("It seems that destionation buffers were not\n"
> + "requested.MFC requires that header should be
generated\n"
> + "before allocating codec buffer.\n");
> + return -EAGAIN;
> + }
> +
> + dev->curr_ctx = ctx->num;
> + s5p_mfc_clean_ctx_int_flags(ctx);
> + ret = s5p_mfc_set_enc_ref_buffer_v6(ctx);
> + if (ret) {
> + mfc_err("Failed to alloc frame mem.\n");
> + ctx->state = MFCINST_ERROR;
> + }
> + return ret;
> +}
> +
> +/* Try running an operation on hardware */
> +void s5p_mfc_try_run_v6(struct s5p_mfc_dev *dev)
> +{
> + struct s5p_mfc_ctx *ctx;
> + int new_ctx;
> + unsigned int ret = 0;
> +
> + mfc_debug(1, "Try run dev: %p\n", dev);
> +
> + /* Check whether hardware is not running */
> + if (test_and_set_bit(0, &dev->hw_lock) != 0) {
> + /* This is perfectly ok, the scheduled ctx should wait */
> + mfc_debug(1, "Couldn't lock HW.\n");
> + return;
> + }
> +
> + /* Choose the context to run */
> + new_ctx = s5p_mfc_get_new_ctx(dev);
> + if (new_ctx < 0) {
> + /* No contexts to run */
> + if (test_and_clear_bit(0, &dev->hw_lock) == 0) {
> + mfc_err("Failed to unlock hardware.\n");
> + return;
> + }
> +
> + mfc_debug(1, "No ctx is scheduled to be run.\n");
> + return;
> + }
> +
> + mfc_debug(1, "New context: %d\n", new_ctx);
> + ctx = dev->ctx[new_ctx];
> + mfc_debug(1, "Seting new context to %p\n", ctx);
> + /* Got context to run in ctx */
> + mfc_debug(1, "ctx->dst_queue_cnt=%d ctx->dpb_count=%d ctx-
> >src_queue_cnt=%d\n",
> + ctx->dst_queue_cnt, ctx->dpb_count, ctx->src_queue_cnt);
> + mfc_debug(1, "ctx->state=%d\n", ctx->state);
> + /* Last frame has already been sent to MFC
> + * Now obtaining frames from MFC buffer */
> +
> + s5p_mfc_clock_on();
> + if (ctx->type == MFCINST_DECODER) {
> + switch (ctx->state) {
> + case MFCINST_FINISHING:
> + s5p_mfc_run_dec_last_frames(ctx);
> + break;
> + case MFCINST_RUNNING:
> + ret = s5p_mfc_run_dec_frame(ctx);
> + break;
> + case MFCINST_INIT:
> + s5p_mfc_clean_ctx_int_flags(ctx);
> + ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
> + ctx);
> + break;
> + case MFCINST_RETURN_INST:
> + s5p_mfc_clean_ctx_int_flags(ctx);
> + ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
> + ctx);
> + break;
> + case MFCINST_GOT_INST:
> + s5p_mfc_run_init_dec(ctx);
> + break;
> + case MFCINST_HEAD_PARSED:
> + ret = s5p_mfc_run_init_dec_buffers(ctx);
> + break;
> + case MFCINST_RES_CHANGE_INIT:
> + s5p_mfc_run_dec_last_frames(ctx);
> + break;
> + case MFCINST_RES_CHANGE_FLUSH:
> + s5p_mfc_run_dec_last_frames(ctx);
> + break;
> + case MFCINST_RES_CHANGE_END:
> + mfc_debug(2, "Finished remaining frames after
resolution
> change.\n");
> + ctx->capture_state = QUEUE_FREE;
> + mfc_debug(2, "Will re-init the codec`.\n");
> + s5p_mfc_run_init_dec(ctx);
> + break;
> + default:
> + ret = -EAGAIN;
> + }
> + } else if (ctx->type == MFCINST_ENCODER) {
> + switch (ctx->state) {
> + case MFCINST_FINISHING:
> + case MFCINST_RUNNING:
> + ret = s5p_mfc_run_enc_frame(ctx);
> + break;
> + case MFCINST_INIT:
> + ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
> + ctx);
> + break;
> + case MFCINST_RETURN_INST:
> + ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
> + ctx);
> + break;
> + case MFCINST_GOT_INST:
> + s5p_mfc_run_init_enc(ctx);
> + break;
> + case MFCINST_HEAD_PARSED: /* Only for MFC6.x */
> + ret = s5p_mfc_run_init_enc_buffers(ctx);
> + break;
> + default:
> + ret = -EAGAIN;
> + }
> + } else {
> + mfc_err("invalid context type: %d\n", ctx->type);
> + ret = -EAGAIN;
> + }
> +
> + if (ret) {
> + /* Free hardware lock */
> + if (test_and_clear_bit(0, &dev->hw_lock) == 0)
> + mfc_err("Failed to unlock hardware.\n");
> +
> + /* This is in deed imporant, as no operation has been
> + * scheduled, reduce the clock count as no one will
> + * ever do this, because no interrupt related to this try_run
> + * will ever come from hardware. */
> + s5p_mfc_clock_off();
> + }
> +}
> +
> +
> +void s5p_mfc_cleanup_queue_v6(struct list_head *lh, struct vb2_queue *vq)
> +{
> + struct s5p_mfc_buf *b;
> + int i;
> +
> + while (!list_empty(lh)) {
> + b = list_entry(lh->next, struct s5p_mfc_buf, list);
> + for (i = 0; i < b->b->num_planes; i++)
> + vb2_set_plane_payload(b->b, i, 0);
> + vb2_buffer_done(b->b, VB2_BUF_STATE_ERROR);
> + list_del(&b->list);
> + }
> +}
> +
> +void s5p_mfc_clear_int_flags_v6(struct s5p_mfc_dev *dev)
> +{
> + mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD_V6);
> + mfc_write(dev, 0, S5P_FIMV_RISC2HOST_INT_V6);
> +}
> +
> +void s5p_mfc_write_info_v6(struct s5p_mfc_ctx *ctx, unsigned int data,
> + unsigned int ofs)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> +
> + s5p_mfc_clock_on();
> + WRITEL(data, ofs);
> + s5p_mfc_clock_off();
> +}
> +
> +unsigned int s5p_mfc_read_info_v6(struct s5p_mfc_ctx *ctx, unsigned int
ofs)
> +{
> + struct s5p_mfc_dev *dev = ctx->dev;
> + int ret;
> +
> + s5p_mfc_clock_on();
> + ret = READL(ofs);
> + s5p_mfc_clock_off();
> +
> + return ret;
> +}
> +
> +int s5p_mfc_get_dspl_y_adr_v6(struct s5p_mfc_dev *dev)
> +{
> + return mfc_read(dev, S5P_FIMV_D_DISPLAY_LUMA_ADDR_V6);
> +}
> +
> +int s5p_mfc_get_dec_y_adr_v6(struct s5p_mfc_dev *dev)
> +{
> + return mfc_read(dev, S5P_FIMV_D_DISPLAY_LUMA_ADDR_V6);
> +}
> +
> +int s5p_mfc_get_dspl_status_v6(struct s5p_mfc_dev *dev)
> +{
> + return mfc_read(dev, S5P_FIMV_D_DISPLAY_STATUS_V6);
> +}
> +
> +int s5p_mfc_get_decoded_status_v6(struct s5p_mfc_dev *dev)
> +{
> + return mfc_read(dev, S5P_FIMV_D_DECODED_STATUS_V6);
> +}
> +
> +int s5p_mfc_get_dec_frame_type_v6(struct s5p_mfc_dev *dev)
> +{
> + return mfc_read(dev, S5P_FIMV_D_DECODED_FRAME_TYPE_V6) &
> + S5P_FIMV_DECODE_FRAME_MASK_V6;
> +}
> +
> +int s5p_mfc_get_disp_frame_type_v6(struct s5p_mfc_ctx *ctx)
> +{
> + return mfc_read(ctx->dev, S5P_FIMV_D_DISPLAY_FRAME_TYPE_V6) &
> + S5P_FIMV_DECODE_FRAME_MASK_V6;
> +}
> +
> +int s5p_mfc_get_consumed_stream_v6(struct s5p_mfc_dev *dev)
> +{
> + return mfc_read(dev, S5P_FIMV_D_DECODED_NAL_SIZE_V6);
> +}
> +
> +int s5p_mfc_get_int_reason_v6(struct s5p_mfc_dev *dev)
> +{
> + return mfc_read(dev, S5P_FIMV_RISC2HOST_CMD_V6) &
> + S5P_FIMV_RISC2HOST_CMD_MASK;
> +}
> +
> +int s5p_mfc_get_int_err_v6(struct s5p_mfc_dev *dev)
> +{
> + return mfc_read(dev, S5P_FIMV_ERROR_CODE_V6);
> +}
> +
> +int s5p_mfc_err_dec_v6(unsigned int err)
> +{
> + return (err & S5P_FIMV_ERR_DEC_MASK_V6) >> S5P_FIMV_ERR_DEC_SHIFT_V6;
> +}
> +
> +int s5p_mfc_err_dspl_v6(unsigned int err)
> +{
> + return (err & S5P_FIMV_ERR_DSPL_MASK_V6) >>
S5P_FIMV_ERR_DSPL_SHIFT_V6;
> +}
> +
> +int s5p_mfc_get_img_width_v6(struct s5p_mfc_dev *dev)
> +{
> + return mfc_read(dev, S5P_FIMV_D_DISPLAY_FRAME_WIDTH_V6);
> +}
> +
> +int s5p_mfc_get_img_height_v6(struct s5p_mfc_dev *dev)
> +{
> + return mfc_read(dev, S5P_FIMV_D_DISPLAY_FRAME_HEIGHT_V6);
> +}
> +
> +int s5p_mfc_get_dpb_count_v6(struct s5p_mfc_dev *dev)
> +{
> + return mfc_read(dev, S5P_FIMV_D_MIN_NUM_DPB_V6);
> +}
> +
> +int s5p_mfc_get_mv_count_v6(struct s5p_mfc_dev *dev)
> +{
> + return mfc_read(dev, S5P_FIMV_D_MIN_NUM_MV_V6);
> +}
> +
> +int s5p_mfc_get_inst_no_v6(struct s5p_mfc_dev *dev)
> +{
> + return mfc_read(dev, S5P_FIMV_RET_INSTANCE_ID_V6);
> +}
> +
> +int s5p_mfc_get_enc_dpb_count_v6(struct s5p_mfc_dev *dev)
> +{
> + return mfc_read(dev, S5P_FIMV_E_NUM_DPB_V6);
> +}
> +
> +int s5p_mfc_get_enc_strm_size_v6(struct s5p_mfc_dev *dev)
> +{
> + return mfc_read(dev, S5P_FIMV_E_STREAM_SIZE_V6);
> +}
> +
> +int s5p_mfc_get_enc_slice_type_v6(struct s5p_mfc_dev *dev)
> +{
> + return mfc_read(dev, S5P_FIMV_E_SLICE_TYPE_V6);
> +}
> +
> +int s5p_mfc_get_enc_pic_count_v6(struct s5p_mfc_dev *dev)
> +{
> + return mfc_read(dev, S5P_FIMV_E_PICTURE_COUNT_V6);
> +}
> +
> +int s5p_mfc_get_sei_avail_status_v6(struct s5p_mfc_ctx *ctx)
> +{
> + return mfc_read(ctx->dev, S5P_FIMV_D_FRAME_PACK_SEI_AVAIL_V6);
> +}
> +
> +int s5p_mfc_get_mvc_num_views_v6(struct s5p_mfc_dev *dev)
> +{
> + return mfc_read(dev, S5P_FIMV_D_MVC_NUM_VIEWS_V6);
> +}
> +
> +int s5p_mfc_get_mvc_view_id_v6(struct s5p_mfc_dev *dev)
> +{
> + return mfc_read(dev, S5P_FIMV_D_MVC_VIEW_ID_V6);
> +}
> +
> +unsigned int s5p_mfc_get_pic_type_top_v6(struct s5p_mfc_ctx *ctx)
> +{
> + return s5p_mfc_read_info_v6(ctx, PIC_TIME_TOP_V6);
> +}
> +
> +unsigned int s5p_mfc_get_pic_type_bot_v6(struct s5p_mfc_ctx *ctx)
> +{
> + return s5p_mfc_read_info_v6(ctx, PIC_TIME_BOT_V6);
> +}
> +
> +unsigned int s5p_mfc_get_crop_info_h_v6(struct s5p_mfc_ctx *ctx)
> +{
> + return s5p_mfc_read_info_v6(ctx, CROP_INFO_H_V6);
> +}
> +
> +unsigned int s5p_mfc_get_crop_info_v_v6(struct s5p_mfc_ctx *ctx)
> +{
> + return s5p_mfc_read_info_v6(ctx, CROP_INFO_V_V6);
> +}
> +
> +/* Initialize opr function pointers for MFC v6 */
> +static struct s5p_mfc_hw_ops s5p_mfc_ops_v6 = {
> + .alloc_dec_temp_buffers = s5p_mfc_alloc_dec_temp_buffers_v6,
> + .release_dec_desc_buffer = s5p_mfc_release_dec_desc_buffer_v6,
> + .alloc_codec_buffers = s5p_mfc_alloc_codec_buffers_v6,
> + .release_codec_buffers = s5p_mfc_release_codec_buffers_v6,
> + .alloc_instance_buffer = s5p_mfc_alloc_instance_buffer_v6,
> + .release_instance_buffer = s5p_mfc_release_instance_buffer_v6,
> + .alloc_dev_context_buffer =
> + s5p_mfc_alloc_dev_context_buffer_v6,
> + .release_dev_context_buffer =
> + s5p_mfc_release_dev_context_buffer_v6,
> + .dec_calc_dpb_size = s5p_mfc_dec_calc_dpb_size_v6,
> + .enc_calc_src_size = s5p_mfc_enc_calc_src_size_v6,
> + .set_dec_stream_buffer = s5p_mfc_set_dec_stream_buffer_v6,
> + .set_dec_frame_buffer = s5p_mfc_set_dec_frame_buffer_v6,
> + .set_enc_stream_buffer = s5p_mfc_set_enc_stream_buffer_v6,
> + .set_enc_frame_buffer = s5p_mfc_set_enc_frame_buffer_v6,
> + .get_enc_frame_buffer = s5p_mfc_get_enc_frame_buffer_v6,
> + .set_enc_ref_buffer = s5p_mfc_set_enc_ref_buffer_v6,
> + .init_decode = s5p_mfc_init_decode_v6,
> + .init_encode = s5p_mfc_init_encode_v6,
> + .encode_one_frame = s5p_mfc_encode_one_frame_v6,
> + .try_run = s5p_mfc_try_run_v6,
> + .cleanup_queue = s5p_mfc_cleanup_queue_v6,
> + .clear_int_flags = s5p_mfc_clear_int_flags_v6,
> + .write_info = s5p_mfc_write_info_v6,
> + .read_info = s5p_mfc_read_info_v6,
> + .get_dspl_y_adr = s5p_mfc_get_dspl_y_adr_v6,
> + .get_dec_y_adr = s5p_mfc_get_dec_y_adr_v6,
> + .get_dspl_status = s5p_mfc_get_dspl_status_v6,
> + .get_dec_status = s5p_mfc_get_dec_status_v6,
> + .get_dec_frame_type = s5p_mfc_get_dec_frame_type_v6,
> + .get_disp_frame_type = s5p_mfc_get_disp_frame_type_v6,
> + .get_consumed_stream = s5p_mfc_get_consumed_stream_v6,
> + .get_int_reason = s5p_mfc_get_int_reason_v6,
> + .get_int_err = s5p_mfc_get_int_err_v6,
> + .err_dec = s5p_mfc_err_dec_v6,
> + .err_dspl = s5p_mfc_err_dspl_v6,
> + .get_img_width = s5p_mfc_get_img_width_v6,
> + .get_img_height = s5p_mfc_get_img_height_v6,
> + .get_dpb_count = s5p_mfc_get_dpb_count_v6,
> + .get_mv_count = s5p_mfc_get_mv_count_v6,
> + .get_inst_no = s5p_mfc_get_inst_no_v6,
> + .get_enc_strm_size = s5p_mfc_get_enc_strm_size_v6,
> + .get_enc_slice_type = s5p_mfc_get_enc_slice_type_v6,
> + .get_enc_dpb_count = s5p_mfc_get_enc_dpb_count_v6,
> + .get_enc_pic_count = s5p_mfc_get_enc_pic_count_v6,
> + .get_sei_avail_status = s5p_mfc_get_sei_avail_status_v6,
> + .get_mvc_num_views = s5p_mfc_get_mvc_num_views_v6,
> + .get_mvc_view_id = s5p_mfc_get_mvc_view_id_v6,
> + .get_pic_type_top = s5p_mfc_get_pic_type_top_v6,
> + .get_pic_type_bot = s5p_mfc_get_pic_type_bot_v6,
> + .get_crop_info_h = s5p_mfc_get_crop_info_h_v6,
> + .get_crop_info_v = s5p_mfc_get_crop_info_v_v6,
> +};
> +
> +struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v6(void)
> +{
> + return &s5p_mfc_ops_v6;
> +}
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h
> b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h
> new file mode 100644
> index 0000000..ab164ef
> --- /dev/null
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h
> @@ -0,0 +1,50 @@
> +/*
> + * drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h
> + *
> + * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
> + * Contains declarations of hw related functions.
> + *
> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
> + * http://www.samsung.com/
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef S5P_MFC_OPR_V6_H_
> +#define S5P_MFC_OPR_V6_H_
> +
> +#include "s5p_mfc_common.h"
> +#include "s5p_mfc_opr.h"
> +
> +#define MFC_CTRL_MODE_CUSTOM MFC_CTRL_MODE_SFR
> +
> +#define MB_WIDTH(x_size) DIV_ROUND_UP(x_size, 16)
> +#define MB_HEIGHT(y_size) DIV_ROUND_UP(y_size, 16)
> +#define S5P_MFC_DEC_MV_SIZE_V6(x, y) (MB_WIDTH(x) * \
> + (((MB_HEIGHT(y)+1)/2)*2) * 64 + 128)
> +
> +/* Definition */
> +#define ENC_MULTI_SLICE_MB_MAX ((1 << 30) - 1)
> +#define ENC_MULTI_SLICE_BIT_MIN 2800
> +#define ENC_INTRA_REFRESH_MB_MAX ((1 << 18) - 1)
> +#define ENC_VBV_BUF_SIZE_MAX ((1 << 30) - 1)
> +#define ENC_H264_LOOP_FILTER_AB_MIN -12
> +#define ENC_H264_LOOP_FILTER_AB_MAX 12
> +#define ENC_H264_RC_FRAME_RATE_MAX ((1 << 16) - 1)
> +#define ENC_H263_RC_FRAME_RATE_MAX ((1 << 16) - 1)
> +#define ENC_H264_PROFILE_MAX 3
> +#define ENC_H264_LEVEL_MAX 42
> +#define ENC_MPEG4_VOP_TIME_RES_MAX ((1 << 16) - 1)
> +#define FRAME_DELTA_H264_H263 1
> +#define TIGHT_CBR_MAX 10
> +
> +/* Definitions for shared memory compatibility */
> +#define PIC_TIME_TOP_V6 S5P_FIMV_D_RET_PICTURE_TAG_TOP_V6
> +#define PIC_TIME_BOT_V6 S5P_FIMV_D_RET_PICTURE_TAG_BOT_V6
> +#define CROP_INFO_H_V6 S5P_FIMV_D_DISPLAY_CROP_INFO1_V6
> +#define CROP_INFO_V_V6 S5P_FIMV_D_DISPLAY_CROP_INFO2_V6
> +
> +struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v6(void);
> +#endif /* S5P_MFC_OPR_V6_H_ */
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
> b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
> index 0503d14..367db75 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
> @@ -20,7 +20,6 @@
> #include "s5p_mfc_debug.h"
> #include "s5p_mfc_pm.h"
>
> -#define MFC_CLKNAME "sclk_mfc"
> #define MFC_GATE_CLK_NAME "mfc"
>
> #define CLK_DEBUG
> @@ -51,7 +50,7 @@ int s5p_mfc_init_pm(struct s5p_mfc_dev *dev)
> goto err_p_ip_clk;
> }
>
> - pm->clock = clk_get(&dev->plat_dev->dev, MFC_CLKNAME);
> + pm->clock = clk_get(&dev->plat_dev->dev, dev->variant->mclk_name);
> if (IS_ERR(pm->clock)) {
> mfc_err("Failed to get MFC clock\n");
> ret = PTR_ERR(pm->clock);
> --
> 1.7.0.4
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v9 0/6] Update MFC v4l2 driver to support MFC6.x
@ 2012-10-02 14:55 Arun Kumar K
2012-10-02 11:16 ` Kamil Debski
` (6 more replies)
0 siblings, 7 replies; 15+ messages in thread
From: Arun Kumar K @ 2012-10-02 14:55 UTC (permalink / raw)
To: linux-media
Cc: k.debski, jtp.park, janghyuck.kim, jaeryul.oh, ch.naveen, arun.kk,
m.szyprowski, s.nawrocki, hverkuil, kmpark, joshi
The patchset adds support for MFCv6 firmware in s5p-mfc driver.
The patches are rebased to the latest media-tree.
Changelog v9
- Addressed review comments by Hans Verkuil
http://www.mail-archive.com/linux-media@vger.kernel.org/msg53016.html
Changelog v8
- Addressed review comments by Sylwester Nawrocki
http://www.mail-archive.com/linux-media@vger.kernel.org/msg52942.html
Changelog v7
- Removed unused macros from register files
Changelog v6
- Use s5p_mfc_hw_call macro to call all HW related ops and cmds
- Rebased onto latest media-tree
- Resending patches adding required v4l controls
- Addressed review comments of Patch v5
Changelog v5
- Modified ops mechanism for macro based function call
- Addressed all other review comments on Patch v4
Changelog v4
- Separate patch for callback based architecture.
- Patches divided to enable incremental compilation.
- Working MFCv6 encoder and decoder.
- Addressed review comments given for v3 patchset.
Changelog v3
- Supports MFCv5 and v6 co-existence.
- Tested for encoding & decoding in MFCv5.
- Supports only decoding in MFCv6 now.
- Can be compiled with kernel image and as module.
- Config macros for MFC version selection removed.
- All previous review comments addressed.
Changelog v2
- Addressed review comments received
http://comments.gmane.org/gmane.linux.drivers.video-input-infrastructure/45189
Changelog v1
- Fixed crash issue in Exynos4 SoCs running MFC 5.1
- Encoder not tested
Arun Kumar K (4):
[media] v4l: Add fourcc definitions for new formats
[media] v4l: Add control definitions for new H264 encoder features
[media] s5p-mfc: Update MFCv5 driver for callback based architecture
[media] s5p-mfc: Add MFC variant data to device context
Jeongtae Park (2):
[media] s5p-mfc: MFCv6 register definitions
[media] s5p-mfc: Update MFC v4l2 driver to support MFC6.x
Documentation/DocBook/media/v4l/controls.xml | 268 +++-
Documentation/DocBook/media/v4l/pixfmt-nv12m.xml | 17 +-
Documentation/DocBook/media/v4l/pixfmt.xml | 10 +
drivers/media/platform/Kconfig | 4 +-
drivers/media/platform/s5p-mfc/Makefile | 7 +-
drivers/media/platform/s5p-mfc/regs-mfc-v6.h | 408 +++++
drivers/media/platform/s5p-mfc/regs-mfc.h | 41 +
drivers/media/platform/s5p-mfc/s5p_mfc.c | 296 +++--
drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c | 109 +--
drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h | 15 +-
drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c | 166 ++
drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h | 20 +
drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c | 156 ++
drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h | 20 +
drivers/media/platform/s5p-mfc/s5p_mfc_common.h | 191 ++-
drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c | 194 ++-
drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h | 1 +
drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 258 ++-
drivers/media/platform/s5p-mfc/s5p_mfc_dec.h | 1 +
drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | 239 ++--
drivers/media/platform/s5p-mfc/s5p_mfc_enc.h | 1 +
drivers/media/platform/s5p-mfc/s5p_mfc_intr.c | 11 +-
drivers/media/platform/s5p-mfc/s5p_mfc_opr.c | 1386 +---------------
drivers/media/platform/s5p-mfc/s5p_mfc_opr.h | 133 +-
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c | 1763 +++++++++++++++++++
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.h | 85 +
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c | 1956 ++++++++++++++++++++++
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h | 50 +
drivers/media/platform/s5p-mfc/s5p_mfc_pm.c | 3 +-
drivers/media/platform/s5p-mfc/s5p_mfc_shm.c | 47 -
drivers/media/platform/s5p-mfc/s5p_mfc_shm.h | 90 -
drivers/media/v4l2-core/v4l2-ctrls.c | 42 +
include/linux/v4l2-controls.h | 41 +
include/linux/videodev2.h | 4 +
34 files changed, 5940 insertions(+), 2093 deletions(-)
create mode 100644 drivers/media/platform/s5p-mfc/regs-mfc-v6.h
create mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
create mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h
create mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c
create mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h
create mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
create mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.h
create mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
create mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h
delete mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_shm.c
delete mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_shm.h
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v9 1/6] [media] v4l: Add fourcc definitions for new formats
2012-10-02 14:55 [PATCH v9 0/6] Update MFC v4l2 driver to support MFC6.x Arun Kumar K
2012-10-02 11:16 ` Kamil Debski
@ 2012-10-02 14:55 ` Arun Kumar K
2012-10-02 11:16 ` Kamil Debski
2012-10-02 14:55 ` [PATCH v9 2/6] [media] v4l: Add control definitions for new H264 encoder features Arun Kumar K
` (4 subsequent siblings)
6 siblings, 1 reply; 15+ messages in thread
From: Arun Kumar K @ 2012-10-02 14:55 UTC (permalink / raw)
To: linux-media
Cc: k.debski, jtp.park, janghyuck.kim, jaeryul.oh, ch.naveen, arun.kk,
m.szyprowski, s.nawrocki, hverkuil, kmpark, joshi
Adds the following new fourcc definitions.
For multiplanar YCbCr
- V4L2_PIX_FMT_NV21M
- V4L2_PIX_FMT_NV12MT_16X16
and compressed formats
- V4L2_PIX_FMT_H264_MVC
- V4L2_PIX_FMT_VP8
Signed-off-by: Jeongtae Park <jtp.park@samsung.com>
Signed-off-by: Naveen Krishna Chatradhi <ch.naveen@samsung.com>
Signed-off-by: Arun Kumar K <arun.kk@samsung.com>
---
Documentation/DocBook/media/v4l/pixfmt-nv12m.xml | 17 ++++++++++++-----
Documentation/DocBook/media/v4l/pixfmt.xml | 10 ++++++++++
include/linux/videodev2.h | 4 ++++
3 files changed, 26 insertions(+), 5 deletions(-)
diff --git a/Documentation/DocBook/media/v4l/pixfmt-nv12m.xml b/Documentation/DocBook/media/v4l/pixfmt-nv12m.xml
index 5274c24..a990b34 100644
--- a/Documentation/DocBook/media/v4l/pixfmt-nv12m.xml
+++ b/Documentation/DocBook/media/v4l/pixfmt-nv12m.xml
@@ -1,11 +1,13 @@
- <refentry id="V4L2-PIX-FMT-NV12M">
+ <refentry>
<refmeta>
- <refentrytitle>V4L2_PIX_FMT_NV12M ('NM12')</refentrytitle>
+ <refentrytitle>V4L2_PIX_FMT_NV12M ('NM12'), V4L2_PIX_FMT_NV21M ('NM21'), V4L2_PIX_FMT_NV12MT_16X16</refentrytitle>
&manvol;
</refmeta>
<refnamediv>
- <refname> <constant>V4L2_PIX_FMT_NV12M</constant></refname>
- <refpurpose>Variation of <constant>V4L2_PIX_FMT_NV12</constant> with planes
+ <refname id="V4L2-PIX-FMT-NV12M"><constant>V4L2_PIX_FMT_NV12M</constant></refname>
+ <refname id="V4L2-PIX-FMT-NV21M"><constant>V4L2_PIX_FMT_NV21M</constant></refname>
+ <refname id="V4L2-PIX-FMT-NV12MT_16X16"><constant>V4L2_PIX_FMT_NV12MT_16X16</constant></refname>
+ <refpurpose>Variation of <constant>V4L2_PIX_FMT_NV12</constant> and <constant>V4L2_PIX_FMT_NV21</constant> with planes
non contiguous in memory. </refpurpose>
</refnamediv>
<refsect1>
@@ -22,7 +24,12 @@ The CbCr plane is the same width, in bytes, as the Y plane (and of the image),
but is half as tall in pixels. Each CbCr pair belongs to four pixels. For example,
Cb<subscript>0</subscript>/Cr<subscript>0</subscript> belongs to
Y'<subscript>00</subscript>, Y'<subscript>01</subscript>,
-Y'<subscript>10</subscript>, Y'<subscript>11</subscript>. </para>
+Y'<subscript>10</subscript>, Y'<subscript>11</subscript>.
+<constant>V4L2_PIX_FMT_NV12MT_16X16</constant> is the tiled version of
+<constant>V4L2_PIX_FMT_NV12M</constant> with 16x16 macroblock tiles. Here pixels
+are arranged in 16x16 2D tiles and tiles are arranged in linear order in memory.
+<constant>V4L2_PIX_FMT_NV21M</constant> is the same as <constant>V4L2_PIX_FMT_NV12M</constant>
+except the Cb and Cr bytes are swapped, the CrCb plane starts with a Cr byte.</para>
<para><constant>V4L2_PIX_FMT_NV12M</constant> is intended to be
used only in drivers and applications that support the multi-planar API,
diff --git a/Documentation/DocBook/media/v4l/pixfmt.xml b/Documentation/DocBook/media/v4l/pixfmt.xml
index 1ddbfab..6ca0be4 100644
--- a/Documentation/DocBook/media/v4l/pixfmt.xml
+++ b/Documentation/DocBook/media/v4l/pixfmt.xml
@@ -758,6 +758,11 @@ extended control <constant>V4L2_CID_MPEG_STREAM_TYPE</constant>, see
<entry>'AVC1'</entry>
<entry>H264 video elementary stream without start codes.</entry>
</row>
+ <row id="V4L2-PIX-FMT-H264-MVC">
+ <entry><constant>V4L2_PIX_FMT_H264_MVC</constant></entry>
+ <entry>'MVC'</entry>
+ <entry>H264 MVC video elementary stream.</entry>
+ </row>
<row id="V4L2-PIX-FMT-H263">
<entry><constant>V4L2_PIX_FMT_H263</constant></entry>
<entry>'H263'</entry>
@@ -793,6 +798,11 @@ extended control <constant>V4L2_CID_MPEG_STREAM_TYPE</constant>, see
<entry>'VC1L'</entry>
<entry>VC1, SMPTE 421M Annex L compliant stream.</entry>
</row>
+ <row id="V4L2-PIX-FMT-VP8">
+ <entry><constant>V4L2_PIX_FMT_VP8</constant></entry>
+ <entry>'VP8'</entry>
+ <entry>VP8 video elementary stream.</entry>
+ </row>
</tbody>
</tgroup>
</table>
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 61395ef..16e6ab0 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -366,7 +366,9 @@ struct v4l2_pix_format {
/* two non contiguous planes - one Y, one Cr + Cb interleaved */
#define V4L2_PIX_FMT_NV12M v4l2_fourcc('N', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 */
+#define V4L2_PIX_FMT_NV21M v4l2_fourcc('N', 'M', '2', '1') /* 21 Y/CrCb 4:2:0 */
#define V4L2_PIX_FMT_NV12MT v4l2_fourcc('T', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 64x32 macroblocks */
+#define V4L2_PIX_FMT_NV12MT_16X16 v4l2_fourcc('V', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 16x16 macroblocks */
/* three non contiguous planes - Y, Cb, Cr */
#define V4L2_PIX_FMT_YUV420M v4l2_fourcc('Y', 'M', '1', '2') /* 12 YUV420 planar */
@@ -403,6 +405,7 @@ struct v4l2_pix_format {
#define V4L2_PIX_FMT_MPEG v4l2_fourcc('M', 'P', 'E', 'G') /* MPEG-1/2/4 Multiplexed */
#define V4L2_PIX_FMT_H264 v4l2_fourcc('H', '2', '6', '4') /* H264 with start codes */
#define V4L2_PIX_FMT_H264_NO_SC v4l2_fourcc('A', 'V', 'C', '1') /* H264 without start codes */
+#define V4L2_PIX_FMT_H264_MVC v4l2_fourcc('M', '2', '6', '4') /* H264 MVC */
#define V4L2_PIX_FMT_H263 v4l2_fourcc('H', '2', '6', '3') /* H263 */
#define V4L2_PIX_FMT_MPEG1 v4l2_fourcc('M', 'P', 'G', '1') /* MPEG-1 ES */
#define V4L2_PIX_FMT_MPEG2 v4l2_fourcc('M', 'P', 'G', '2') /* MPEG-2 ES */
@@ -410,6 +413,7 @@ struct v4l2_pix_format {
#define V4L2_PIX_FMT_XVID v4l2_fourcc('X', 'V', 'I', 'D') /* Xvid */
#define V4L2_PIX_FMT_VC1_ANNEX_G v4l2_fourcc('V', 'C', '1', 'G') /* SMPTE 421M Annex G compliant stream */
#define V4L2_PIX_FMT_VC1_ANNEX_L v4l2_fourcc('V', 'C', '1', 'L') /* SMPTE 421M Annex L compliant stream */
+#define V4L2_PIX_FMT_VP8 v4l2_fourcc('V', 'P', '8', '0') /* VP8 */
/* Vendor-specific formats */
#define V4L2_PIX_FMT_CPIA1 v4l2_fourcc('C', 'P', 'I', 'A') /* cpia1 YUV */
--
1.7.0.4
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v9 2/6] [media] v4l: Add control definitions for new H264 encoder features
2012-10-02 14:55 [PATCH v9 0/6] Update MFC v4l2 driver to support MFC6.x Arun Kumar K
2012-10-02 11:16 ` Kamil Debski
2012-10-02 14:55 ` [PATCH v9 1/6] [media] v4l: Add fourcc definitions for new formats Arun Kumar K
@ 2012-10-02 14:55 ` Arun Kumar K
2012-10-02 11:16 ` Kamil Debski
2012-10-02 14:55 ` [PATCH v9 3/6] [media] s5p-mfc: Update MFCv5 driver for callback based architecture Arun Kumar K
` (3 subsequent siblings)
6 siblings, 1 reply; 15+ messages in thread
From: Arun Kumar K @ 2012-10-02 14:55 UTC (permalink / raw)
To: linux-media
Cc: k.debski, jtp.park, janghyuck.kim, jaeryul.oh, ch.naveen, arun.kk,
m.szyprowski, s.nawrocki, hverkuil, kmpark, joshi
New controls are added for supporting H264 encoding features like
- MVC frame packing
- Flexible macroblock ordering
- Arbitrary slice ordering
- Hierarchical coding
Signed-off-by: Jeongtae Park <jtp.park@samsung.com>
Signed-off-by: Naveen Krishna Chatradhi <ch.naveen@samsung.com>
Signed-off-by: Arun Kumar K <arun.kk@samsung.com>
---
Documentation/DocBook/media/v4l/controls.xml | 268 +++++++++++++++++++++++++-
drivers/media/v4l2-core/v4l2-ctrls.c | 42 ++++
include/linux/v4l2-controls.h | 41 ++++
3 files changed, 350 insertions(+), 1 deletions(-)
diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml
index 272a5f7..09e09bd 100644
--- a/Documentation/DocBook/media/v4l/controls.xml
+++ b/Documentation/DocBook/media/v4l/controls.xml
@@ -1586,7 +1586,6 @@ frame counter of the frame that is currently displayed (decoded). This value is
the decoder is started.</entry>
</row>
-
<row><entry></entry></row>
<row>
<entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE</constant> </entry>
@@ -2270,6 +2269,14 @@ Applicable to the MPEG1, MPEG2, MPEG4 encoders.</entry>
</row>
<row><entry></entry></row>
+ <row id="v4l2-mpeg-video-vbv-delay">
+ <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_VBV_DELAY</constant> </entry>
+ <entry>integer</entry>
+ </row><row><entry spanname="descr">Sets the initial delay in milliseconds for
+VBV buffer control.</entry>
+ </row>
+
+ <row><entry></entry></row>
<row>
<entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE</constant> </entry>
<entry>integer</entry>
@@ -2334,6 +2341,265 @@ Applicable to the MPEG4 decoder.</entry>
</row><row><entry spanname="descr">vop_time_increment value for MPEG4. Applicable to the MPEG4 encoder.</entry>
</row>
+ <row><entry></entry></row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING</constant> </entry>
+ <entry>boolean</entry>
+ </row>
+ <row><entry spanname="descr">Enable generation of frame packing supplemental enhancement information in the encoded bitstream.
+The frame packing SEI message contains the arrangement of L and R planes for 3D viewing. Applicable to the H264 encoder.</entry>
+ </row>
+
+ <row><entry></entry></row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_SEI_FP_CURRENT_FRAME_0</constant> </entry>
+ <entry>boolean</entry>
+ </row>
+ <row><entry spanname="descr">Sets current frame as frame0 in frame packing SEI.
+Applicable to the H264 encoder.</entry>
+ </row>
+
+ <row><entry></entry></row>
+ <row id="v4l2-mpeg-video-h264-sei-fp-arrangement-type">
+ <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE</constant> </entry>
+ <entry>enum v4l2_mpeg_video_h264_sei_fp_arrangement_type</entry>
+ </row>
+ <row><entry spanname="descr">Frame packing arrangement type for H264 SEI.
+Applicable to the H264 encoder.
+Possible values are:</entry>
+ </row>
+ <row>
+ <entrytbl spanname="descr" cols="2">
+ <tbody valign="top">
+ <row>
+ <entry><constant>V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_CHEKERBOARD</constant> </entry>
+ <entry>Pixels are alternatively from L and R.</entry>
+ </row>
+ <row>
+ <entry><constant>V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_COLUMN</constant> </entry>
+ <entry>L and R are interlaced by column.</entry>
+ </row>
+ <row>
+ <entry><constant>V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_ROW</constant> </entry>
+ <entry>L and R are interlaced by row.</entry>
+ </row>
+ <row>
+ <entry><constant>V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_SIDE_BY_SIDE</constant> </entry>
+ <entry>L is on the left, R on the right.</entry>
+ </row>
+ <row>
+ <entry><constant>V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_TOP_BOTTOM</constant> </entry>
+ <entry>L is on top, R on bottom.</entry>
+ </row>
+ <row>
+ <entry><constant>V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_TEMPORAL</constant> </entry>
+ <entry>One view per frame.</entry>
+ </row>
+ </tbody>
+ </entrytbl>
+ </row>
+
+ <row><entry></entry></row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_FMO</constant> </entry>
+ <entry>boolean</entry>
+ </row>
+ <row><entry spanname="descr">Enables flexible macroblock ordering in the encoded bitstream. It is a technique
+used for restructuring the ordering of macroblocks in pictures. Applicable to the H264 encoder.</entry>
+ </row>
+
+ <row><entry></entry></row>
+ <row id="v4l2-mpeg-video-h264-fmo-map-type">
+ <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE</constant> </entry>
+ <entry>enum v4l2_mpeg_video_h264_fmo_map_type</entry>
+ </row>
+ <row><entry spanname="descr">When using FMO, the map type divides the image in different scan patterns of macroblocks.
+Applicable to the H264 encoder.
+Possible values are:</entry>
+ </row>
+ <row>
+ <entrytbl spanname="descr" cols="2">
+ <tbody valign="top">
+ <row>
+ <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES</constant> </entry>
+ <entry>Slices are interleaved one after other with macroblocks in run length order.</entry>
+ </row>
+ <row>
+ <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_SCATTERED_SLICES</constant> </entry>
+ <entry>Scatters the macroblocks based on a mathematical function known to both encoder and decoder.</entry>
+ </row>
+ <row>
+ <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_FOREGROUND_WITH_LEFT_OVER</constant> </entry>
+ <entry>Macroblocks arranged in rectangular areas or regions of interest.</entry>
+ </row>
+ <row>
+ <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_BOX_OUT</constant> </entry>
+ <entry>Slice groups grow in a cyclic way from centre to outwards.</entry>
+ </row>
+ <row>
+ <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_RASTER_SCAN</constant> </entry>
+ <entry>Slice groups grow in raster scan pattern from left to right.</entry>
+ </row>
+ <row>
+ <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_WIPE_SCAN</constant> </entry>
+ <entry>Slice groups grow in wipe scan pattern from top to bottom.</entry>
+ </row>
+ <row>
+ <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_EXPLICIT</constant> </entry>
+ <entry>User defined map type.</entry>
+ </row>
+ </tbody>
+ </entrytbl>
+ </row>
+
+ <row><entry></entry></row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_FMO_SLICE_GROUP</constant> </entry>
+ <entry>integer</entry>
+ </row>
+ <row><entry spanname="descr">Number of slice groups in FMO.
+Applicable to the H264 encoder.</entry>
+ </row>
+
+ <row><entry></entry></row>
+ <row id="v4l2-mpeg-video-h264-fmo-change-direction">
+ <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_DIRECTION</constant> </entry>
+ <entry>enum v4l2_mpeg_video_h264_fmo_change_dir</entry>
+ </row>
+ <row><entry spanname="descr">Specifies a direction of the slice group change for raster and wipe maps.
+Applicable to the H264 encoder.
+Possible values are:</entry>
+ </row>
+ <row>
+ <entrytbl spanname="descr" cols="2">
+ <tbody valign="top">
+ <row>
+ <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_CHANGE_DIR_RIGHT</constant> </entry>
+ <entry>Raster scan or wipe right.</entry>
+ </row>
+ <row>
+ <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_CHANGE_DIR_LEFT</constant> </entry>
+ <entry>Reverse raster scan or wipe left.</entry>
+ </row>
+ </tbody>
+ </entrytbl>
+ </row>
+
+ <row><entry></entry></row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_RATE</constant> </entry>
+ <entry>integer</entry>
+ </row>
+ <row><entry spanname="descr">Specifies the size of the first slice group for raster and wipe map.
+Applicable to the H264 encoder.</entry>
+ </row>
+
+ <row><entry></entry></row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH</constant> </entry>
+ <entry>integer</entry>
+ </row>
+ <row><entry spanname="descr">Specifies the number of consecutive macroblocks for the interleaved map.
+Applicable to the H264 encoder.</entry>
+ </row>
+
+ <row><entry></entry></row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_ASO</constant> </entry>
+ <entry>boolean</entry>
+ </row>
+ <row><entry spanname="descr">Enables arbitrary slice ordering in encoded bitstream.
+Applicable to the H264 encoder.</entry>
+ </row>
+
+ <row><entry></entry></row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_ASO_SLICE_ORDER</constant> </entry>
+ <entry>integer</entry>
+ </row><row><entry spanname="descr">Specifies the slice order in ASO. Applicable to the H264 encoder.
+The supplied 32-bit integer is interpreted as follows (bit
+0 = least significant bit):</entry>
+ </row>
+ <row>
+ <entrytbl spanname="descr" cols="2">
+ <tbody valign="top">
+ <row>
+ <entry>Bit 0:15</entry>
+ <entry>Slice ID</entry>
+ </row>
+ <row>
+ <entry>Bit 16:32</entry>
+ <entry>Slice position or order</entry>
+ </row>
+ </tbody>
+ </entrytbl>
+ </row>
+
+ <row><entry></entry></row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING</constant> </entry>
+ <entry>boolean</entry>
+ </row>
+ <row><entry spanname="descr">Enables H264 hierarchical coding.
+Applicable to the H264 encoder.</entry>
+ </row>
+
+ <row><entry></entry></row>
+ <row id="v4l2-mpeg-video-h264-hierarchical-coding-type">
+ <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE</constant> </entry>
+ <entry>enum v4l2_mpeg_video_h264_hierarchical_coding_type</entry>
+ </row>
+ <row><entry spanname="descr">Specifies the hierarchical coding type.
+Applicable to the H264 encoder.
+Possible values are:</entry>
+ </row>
+ <row>
+ <entrytbl spanname="descr" cols="2">
+ <tbody valign="top">
+ <row>
+ <entry><constant>V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B</constant> </entry>
+ <entry>Hierarchical B coding.</entry>
+ </row>
+ <row>
+ <entry><constant>V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P</constant> </entry>
+ <entry>Hierarchical P coding.</entry>
+ </row>
+ </tbody>
+ </entrytbl>
+ </row>
+
+ <row><entry></entry></row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER</constant> </entry>
+ <entry>integer</entry>
+ </row>
+ <row><entry spanname="descr">Specifies the number of hierarchical coding layers.
+Applicable to the H264 encoder.</entry>
+ </row>
+
+ <row><entry></entry></row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP</constant> </entry>
+ <entry>integer</entry>
+ </row><row><entry spanname="descr">Specifies a user defined QP for each layer. Applicable to the H264 encoder.
+The supplied 32-bit integer is interpreted as follows (bit
+0 = least significant bit):</entry>
+ </row>
+ <row>
+ <entrytbl spanname="descr" cols="2">
+ <tbody valign="top">
+ <row>
+ <entry>Bit 0:15</entry>
+ <entry>QP value</entry>
+ </row>
+ <row>
+ <entry>Bit 16:32</entry>
+ <entry>Layer number</entry>
+ </row>
+ </tbody>
+ </entrytbl>
+ </row>
+
</tbody>
</tgroup>
</table>
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index f400035..fb986ec 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -384,6 +384,25 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
"Extended SAR",
NULL,
};
+ static const char * const h264_fp_arrangement_type[] = {
+ "Checkerboard",
+ "Column",
+ "Row",
+ "Side by Side",
+ "Top Bottom",
+ "Temporal",
+ NULL,
+ };
+ static const char * const h264_fmo_map_type[] = {
+ "Interleaved Slices",
+ "Scattered Slices",
+ "Foreground with Leftover",
+ "Box Out",
+ "Raster Scan",
+ "Wipe Scan",
+ "Explicit",
+ NULL,
+ };
static const char * const mpeg_mpeg4_level[] = {
"0",
"0b",
@@ -508,6 +527,10 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
return h264_profile;
case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC:
return vui_sar_idc;
+ case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE:
+ return h264_fp_arrangement_type;
+ case V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE:
+ return h264_fmo_map_type;
case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
return mpeg_mpeg4_level;
case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
@@ -643,6 +666,22 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH: return "Horizontal Size of SAR";
case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE: return "Aspect Ratio VUI Enable";
case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC: return "VUI Aspect Ratio IDC";
+ case V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING: return "H264 Enable Frame Packing SEI";
+ case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_CURRENT_FRAME_0: return "H264 Set Curr. Frame as Frame0";
+ case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE: return "H264 FP Arrangement Type";
+ case V4L2_CID_MPEG_VIDEO_H264_FMO: return "H264 Flexible MB Ordering";
+ case V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE: return "H264 Map Type for FMO";
+ case V4L2_CID_MPEG_VIDEO_H264_FMO_SLICE_GROUP: return "H264 FMO Number of Slice Groups";
+ case V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_DIRECTION: return "H264 FMO Direction of Change";
+ case V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_RATE: return "H264 FMO Size of 1st Slice Grp";
+ case V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH: return "H264 FMO No. of Consecutive MBs";
+ case V4L2_CID_MPEG_VIDEO_H264_ASO: return "H264 Arbitrary Slice Ordering";
+ case V4L2_CID_MPEG_VIDEO_H264_ASO_SLICE_ORDER: return "H264 ASO Slice Order";
+ case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING: return "Enable H264 Hierarchical Coding";
+ case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE: return "H264 Hierarchical Coding Type";
+ case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER:return "H264 Number of HC Layers";
+ case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP:
+ return "H264 Set QP Value for HC Layers";
case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP: return "MPEG4 I-Frame QP Value";
case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP: return "MPEG4 P-Frame QP Value";
case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP: return "MPEG4 B-Frame QP Value";
@@ -657,6 +696,7 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_MPEG_VIDEO_VBV_SIZE: return "VBV Buffer Size";
case V4L2_CID_MPEG_VIDEO_DEC_PTS: return "Video Decoder PTS";
case V4L2_CID_MPEG_VIDEO_DEC_FRAME: return "Video Decoder Frame Count";
+ case V4L2_CID_MPEG_VIDEO_VBV_DELAY: return "Initial Delay for VBV Control";
/* CAMERA controls */
/* Keep the order of the 'case's the same as in videodev2.h! */
@@ -853,6 +893,8 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:
case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC:
+ case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE:
+ case V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE:
case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
diff --git a/include/linux/v4l2-controls.h b/include/linux/v4l2-controls.h
index 421d24c..1c4d0c9 100644
--- a/include/linux/v4l2-controls.h
+++ b/include/linux/v4l2-controls.h
@@ -349,6 +349,7 @@ enum v4l2_mpeg_video_multi_slice_mode {
#define V4L2_CID_MPEG_VIDEO_VBV_SIZE (V4L2_CID_MPEG_BASE+222)
#define V4L2_CID_MPEG_VIDEO_DEC_PTS (V4L2_CID_MPEG_BASE+223)
#define V4L2_CID_MPEG_VIDEO_DEC_FRAME (V4L2_CID_MPEG_BASE+224)
+#define V4L2_CID_MPEG_VIDEO_VBV_DELAY (V4L2_CID_MPEG_BASE+225)
#define V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP (V4L2_CID_MPEG_BASE+300)
#define V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP (V4L2_CID_MPEG_BASE+301)
@@ -439,6 +440,46 @@ enum v4l2_mpeg_video_h264_vui_sar_idc {
V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_2x1 = 16,
V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED = 17,
};
+#define V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING (V4L2_CID_MPEG_BASE+368)
+#define V4L2_CID_MPEG_VIDEO_H264_SEI_FP_CURRENT_FRAME_0 (V4L2_CID_MPEG_BASE+369)
+#define V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE (V4L2_CID_MPEG_BASE+370)
+enum v4l2_mpeg_video_h264_sei_fp_arrangement_type {
+ V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_CHECKERBOARD = 0,
+ V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_COLUMN = 1,
+ V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_ROW = 2,
+ V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_SIDE_BY_SIDE = 3,
+ V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_TOP_BOTTOM = 4,
+ V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_TEMPORAL = 5,
+};
+#define V4L2_CID_MPEG_VIDEO_H264_FMO (V4L2_CID_MPEG_BASE+371)
+#define V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE (V4L2_CID_MPEG_BASE+372)
+enum v4l2_mpeg_video_h264_fmo_map_type {
+ V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES = 0,
+ V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_SCATTERED_SLICES = 1,
+ V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_FOREGROUND_WITH_LEFT_OVER = 2,
+ V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_BOX_OUT = 3,
+ V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_RASTER_SCAN = 4,
+ V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_WIPE_SCAN = 5,
+ V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_EXPLICIT = 6,
+};
+#define V4L2_CID_MPEG_VIDEO_H264_FMO_SLICE_GROUP (V4L2_CID_MPEG_BASE+373)
+#define V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_DIRECTION (V4L2_CID_MPEG_BASE+374)
+enum v4l2_mpeg_video_h264_fmo_change_dir {
+ V4L2_MPEG_VIDEO_H264_FMO_CHANGE_DIR_RIGHT = 0,
+ V4L2_MPEG_VIDEO_H264_FMO_CHANGE_DIR_LEFT = 1,
+};
+#define V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_RATE (V4L2_CID_MPEG_BASE+375)
+#define V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH (V4L2_CID_MPEG_BASE+376)
+#define V4L2_CID_MPEG_VIDEO_H264_ASO (V4L2_CID_MPEG_BASE+377)
+#define V4L2_CID_MPEG_VIDEO_H264_ASO_SLICE_ORDER (V4L2_CID_MPEG_BASE+378)
+#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING (V4L2_CID_MPEG_BASE+379)
+#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE (V4L2_CID_MPEG_BASE+380)
+enum v4l2_mpeg_video_h264_hierarchical_coding_type {
+ V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B = 0,
+ V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P = 1,
+};
+#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER (V4L2_CID_MPEG_BASE+381)
+#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP (V4L2_CID_MPEG_BASE+382)
#define V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP (V4L2_CID_MPEG_BASE+400)
#define V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP (V4L2_CID_MPEG_BASE+401)
#define V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP (V4L2_CID_MPEG_BASE+402)
--
1.7.0.4
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v9 3/6] [media] s5p-mfc: Update MFCv5 driver for callback based architecture
2012-10-02 14:55 [PATCH v9 0/6] Update MFC v4l2 driver to support MFC6.x Arun Kumar K
` (2 preceding siblings ...)
2012-10-02 14:55 ` [PATCH v9 2/6] [media] v4l: Add control definitions for new H264 encoder features Arun Kumar K
@ 2012-10-02 14:55 ` Arun Kumar K
2012-10-02 11:16 ` Kamil Debski
2012-10-02 14:55 ` [PATCH v9 4/6] [media] s5p-mfc: Add MFC variant data to device context Arun Kumar K
` (2 subsequent siblings)
6 siblings, 1 reply; 15+ messages in thread
From: Arun Kumar K @ 2012-10-02 14:55 UTC (permalink / raw)
To: linux-media
Cc: k.debski, jtp.park, janghyuck.kim, jaeryul.oh, ch.naveen, arun.kk,
m.szyprowski, s.nawrocki, hverkuil, kmpark, joshi
Modifies the driver to use a callback based architecture
for hardware dependent calls. This architecture is suitable
for supporting co-existence with newer versions of MFC hardware.
Signed-off-by: Arun Kumar K <arun.kk@samsung.com>
Signed-off-by: Naveen Krishna Chatradhi <ch.naveen@samsung.com>
---
drivers/media/platform/s5p-mfc/Makefile | 3 +-
drivers/media/platform/s5p-mfc/s5p_mfc.c | 154 ++-
drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c | 106 +--
drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h | 15 +-
drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c | 166 +++
drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h | 20 +
drivers/media/platform/s5p-mfc/s5p_mfc_common.h | 45 +-
drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c | 33 +-
drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h | 1 +
drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 85 +-
drivers/media/platform/s5p-mfc/s5p_mfc_dec.h | 1 +
drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | 68 +-
drivers/media/platform/s5p-mfc/s5p_mfc_enc.h | 1 +
drivers/media/platform/s5p-mfc/s5p_mfc_intr.c | 11 +-
drivers/media/platform/s5p-mfc/s5p_mfc_opr.c | 1384 +------------------
drivers/media/platform/s5p-mfc/s5p_mfc_opr.h | 133 +-
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c | 1698 +++++++++++++++++++++++
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.h | 85 ++
drivers/media/platform/s5p-mfc/s5p_mfc_shm.c | 47 -
drivers/media/platform/s5p-mfc/s5p_mfc_shm.h | 90 --
20 files changed, 2312 insertions(+), 1834 deletions(-)
create mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
create mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h
create mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
create mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.h
delete mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_shm.c
delete mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_shm.h
diff --git a/drivers/media/platform/s5p-mfc/Makefile b/drivers/media/platform/s5p-mfc/Makefile
index d066340..cfb9ee9 100644
--- a/drivers/media/platform/s5p-mfc/Makefile
+++ b/drivers/media/platform/s5p-mfc/Makefile
@@ -2,4 +2,5 @@ obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) := s5p-mfc.o
s5p-mfc-y += s5p_mfc.o s5p_mfc_intr.o s5p_mfc_opr.o
s5p-mfc-y += s5p_mfc_dec.o s5p_mfc_enc.o
s5p-mfc-y += s5p_mfc_ctrl.o s5p_mfc_cmd.o
-s5p-mfc-y += s5p_mfc_pm.o s5p_mfc_shm.o
+s5p-mfc-y += s5p_mfc_pm.o
+s5p-mfc-y += s5p_mfc_opr_v5.o s5p_mfc_cmd_v5.o
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index 0476be4..3319410 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -21,15 +21,15 @@
#include <linux/videodev2.h>
#include <linux/workqueue.h>
#include <media/videobuf2-core.h>
-#include "regs-mfc.h"
+#include "s5p_mfc_common.h"
#include "s5p_mfc_ctrl.h"
#include "s5p_mfc_debug.h"
#include "s5p_mfc_dec.h"
#include "s5p_mfc_enc.h"
#include "s5p_mfc_intr.h"
#include "s5p_mfc_opr.h"
+#include "s5p_mfc_cmd.h"
#include "s5p_mfc_pm.h"
-#include "s5p_mfc_shm.h"
#define S5P_MFC_NAME "s5p-mfc"
#define S5P_MFC_DEC_NAME "s5p-mfc-dec"
@@ -115,10 +115,12 @@ static void s5p_mfc_watchdog_worker(struct work_struct *work)
if (!ctx)
continue;
ctx->state = MFCINST_ERROR;
- s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
- s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
+ s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue,
+ &ctx->vq_dst);
+ s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue,
+ &ctx->vq_src);
clear_work_bit(ctx);
- wake_up_ctx(ctx, S5P_FIMV_R2H_CMD_ERR_RET, 0);
+ wake_up_ctx(ctx, S5P_MFC_R2H_CMD_ERR_RET, 0);
}
clear_bit(0, &dev->hw_lock);
spin_unlock_irqrestore(&dev->irqlock, flags);
@@ -155,16 +157,10 @@ static enum s5p_mfc_node_type s5p_mfc_get_node_type(struct file *file)
return MFCNODE_INVALID;
}
-static void s5p_mfc_clear_int_flags(struct s5p_mfc_dev *dev)
-{
- mfc_write(dev, 0, S5P_FIMV_RISC_HOST_INT);
- mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
- mfc_write(dev, 0xffff, S5P_FIMV_SI_RTN_CHID);
-}
-
static void s5p_mfc_handle_frame_all_extracted(struct s5p_mfc_ctx *ctx)
{
struct s5p_mfc_buf *dst_buf;
+ struct s5p_mfc_dev *dev = ctx->dev;
ctx->state = MFCINST_FINISHED;
ctx->sequence++;
@@ -179,8 +175,8 @@ static void s5p_mfc_handle_frame_all_extracted(struct s5p_mfc_ctx *ctx)
ctx->dst_queue_cnt--;
dst_buf->b->v4l2_buf.sequence = (ctx->sequence++);
- if (s5p_mfc_read_shm(ctx, PIC_TIME_TOP) ==
- s5p_mfc_read_shm(ctx, PIC_TIME_BOT))
+ if (s5p_mfc_hw_call(dev->mfc_ops, get_pic_type_top, ctx) ==
+ s5p_mfc_hw_call(dev->mfc_ops, get_pic_type_bot, ctx))
dst_buf->b->v4l2_buf.field = V4L2_FIELD_NONE;
else
dst_buf->b->v4l2_buf.field = V4L2_FIELD_INTERLACED;
@@ -194,8 +190,11 @@ static void s5p_mfc_handle_frame_copy_time(struct s5p_mfc_ctx *ctx)
{
struct s5p_mfc_dev *dev = ctx->dev;
struct s5p_mfc_buf *dst_buf, *src_buf;
- size_t dec_y_addr = s5p_mfc_get_dec_y_adr();
- unsigned int frame_type = s5p_mfc_get_frame_type();
+ size_t dec_y_addr;
+ unsigned int frame_type;
+
+ dec_y_addr = s5p_mfc_hw_call(dev->mfc_ops, get_dec_y_adr, dev);
+ frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_dec_frame_type, dev);
/* Copy timestamp / timecode from decoded src to dst and set
appropraite flags */
@@ -231,10 +230,13 @@ static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err)
{
struct s5p_mfc_dev *dev = ctx->dev;
struct s5p_mfc_buf *dst_buf;
- size_t dspl_y_addr = s5p_mfc_get_dspl_y_adr();
- unsigned int frame_type = s5p_mfc_get_frame_type();
+ size_t dspl_y_addr;
+ unsigned int frame_type;
unsigned int index;
+ dspl_y_addr = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_y_adr, dev);
+ frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_dec_frame_type, dev);
+
/* If frame is same as previous then skip and do not dequeue */
if (frame_type == S5P_FIMV_DECODE_FRAME_SKIPPED) {
if (!ctx->after_packed_pb)
@@ -251,8 +253,10 @@ static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err)
list_del(&dst_buf->list);
ctx->dst_queue_cnt--;
dst_buf->b->v4l2_buf.sequence = ctx->sequence;
- if (s5p_mfc_read_shm(ctx, PIC_TIME_TOP) ==
- s5p_mfc_read_shm(ctx, PIC_TIME_BOT))
+ if (s5p_mfc_hw_call(dev->mfc_ops,
+ get_pic_type_top, ctx) ==
+ s5p_mfc_hw_call(dev->mfc_ops,
+ get_pic_type_bot, ctx))
dst_buf->b->v4l2_buf.field = V4L2_FIELD_NONE;
else
dst_buf->b->v4l2_buf.field =
@@ -283,21 +287,21 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
unsigned int index;
- dst_frame_status = s5p_mfc_get_dspl_status()
+ dst_frame_status = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev)
& S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK;
- res_change = s5p_mfc_get_dspl_status()
+ res_change = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev)
& S5P_FIMV_DEC_STATUS_RESOLUTION_MASK;
mfc_debug(2, "Frame Status: %x\n", dst_frame_status);
if (ctx->state == MFCINST_RES_CHANGE_INIT)
ctx->state = MFCINST_RES_CHANGE_FLUSH;
if (res_change) {
ctx->state = MFCINST_RES_CHANGE_INIT;
- s5p_mfc_clear_int_flags(dev);
+ s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
wake_up_ctx(ctx, reason, err);
if (test_and_clear_bit(0, &dev->hw_lock) == 0)
BUG();
s5p_mfc_clock_off();
- s5p_mfc_try_run(dev);
+ s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
return;
}
if (ctx->dpb_flush_flag)
@@ -331,9 +335,12 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
&& !list_empty(&ctx->src_queue)) {
src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf,
list);
- ctx->consumed_stream += s5p_mfc_get_consumed_stream();
- if (ctx->codec_mode != S5P_FIMV_CODEC_H264_DEC &&
- s5p_mfc_get_frame_type() == S5P_FIMV_DECODE_FRAME_P_FRAME
+ ctx->consumed_stream += s5p_mfc_hw_call(dev->mfc_ops,
+ get_consumed_stream, dev);
+ if (ctx->codec_mode != S5P_MFC_CODEC_H264_DEC &&
+ s5p_mfc_hw_call(dev->mfc_ops,
+ get_dec_frame_type, dev) ==
+ S5P_FIMV_DECODE_FRAME_P_FRAME
&& ctx->consumed_stream + STUFF_BYTE <
src_buf->b->v4l2_planes[0].bytesused) {
/* Run MFC again on the same buffer */
@@ -345,7 +352,7 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
ctx->consumed_stream = 0;
list_del(&src_buf->list);
ctx->src_queue_cnt--;
- if (s5p_mfc_err_dec(err) > 0)
+ if (s5p_mfc_hw_call(dev->mfc_ops, err_dec, err) > 0)
vb2_buffer_done(src_buf->b, VB2_BUF_STATE_ERROR);
else
vb2_buffer_done(src_buf->b, VB2_BUF_STATE_DONE);
@@ -356,12 +363,12 @@ leave_handle_frame:
if ((ctx->src_queue_cnt == 0 && ctx->state != MFCINST_FINISHING)
|| ctx->dst_queue_cnt < ctx->dpb_count)
clear_work_bit(ctx);
- s5p_mfc_clear_int_flags(dev);
+ s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
wake_up_ctx(ctx, reason, err);
if (test_and_clear_bit(0, &dev->hw_lock) == 0)
BUG();
s5p_mfc_clock_off();
- s5p_mfc_try_run(dev);
+ s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
}
/* Error handling for interrupt */
@@ -378,7 +385,7 @@ static void s5p_mfc_handle_error(struct s5p_mfc_ctx *ctx,
dev = ctx->dev;
mfc_err("Interrupt Error: %08x\n", err);
- s5p_mfc_clear_int_flags(dev);
+ s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
wake_up_dev(dev, reason, err);
/* Error recovery is dependent on the state of context */
@@ -407,9 +414,11 @@ static void s5p_mfc_handle_error(struct s5p_mfc_ctx *ctx,
ctx->state = MFCINST_ERROR;
/* Mark all dst buffers as having an error */
spin_lock_irqsave(&dev->irqlock, flags);
- s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
+ s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue,
+ &ctx->vq_dst);
/* Mark all src buffers as having an error */
- s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
+ s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue,
+ &ctx->vq_src);
spin_unlock_irqrestore(&dev->irqlock, flags);
if (test_and_clear_bit(0, &dev->hw_lock) == 0)
BUG();
@@ -436,8 +445,10 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx,
if (ctx->c_ops->post_seq_start(ctx))
mfc_err("post_seq_start() failed\n");
} else {
- ctx->img_width = s5p_mfc_get_img_width();
- ctx->img_height = s5p_mfc_get_img_height();
+ ctx->img_width = s5p_mfc_hw_call(dev->mfc_ops, get_img_width,
+ dev);
+ ctx->img_height = s5p_mfc_hw_call(dev->mfc_ops, get_img_height,
+ dev);
ctx->buf_width = ALIGN(ctx->img_width,
S5P_FIMV_NV12MT_HALIGN);
@@ -473,18 +484,19 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx,
guard_height, S5P_FIMV_DEC_BUF_ALIGN);
ctx->mv_size = 0;
}
- ctx->dpb_count = s5p_mfc_get_dpb_count();
+ ctx->dpb_count = s5p_mfc_hw_call(dev->mfc_ops, get_dpb_count,
+ dev);
if (ctx->img_width == 0 || ctx->img_height == 0)
ctx->state = MFCINST_ERROR;
else
ctx->state = MFCINST_HEAD_PARSED;
}
- s5p_mfc_clear_int_flags(dev);
+ s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
clear_work_bit(ctx);
if (test_and_clear_bit(0, &dev->hw_lock) == 0)
BUG();
s5p_mfc_clock_off();
- s5p_mfc_try_run(dev);
+ s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
wake_up_ctx(ctx, reason, err);
}
@@ -499,7 +511,7 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx,
if (ctx == NULL)
return;
dev = ctx->dev;
- s5p_mfc_clear_int_flags(dev);
+ s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
ctx->int_type = reason;
ctx->int_err = err;
ctx->int_cond = 1;
@@ -528,7 +540,7 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx,
s5p_mfc_clock_off();
wake_up(&ctx->queue);
- s5p_mfc_try_run(dev);
+ s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
} else {
if (test_and_clear_bit(0, &dev->hw_lock) == 0)
BUG();
@@ -552,76 +564,78 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
atomic_set(&dev->watchdog_cnt, 0);
ctx = dev->ctx[dev->curr_ctx];
/* Get the reason of interrupt and the error code */
- reason = s5p_mfc_get_int_reason();
- err = s5p_mfc_get_int_err();
+ reason = s5p_mfc_hw_call(dev->mfc_ops, get_int_reason, dev);
+ err = s5p_mfc_hw_call(dev->mfc_ops, get_int_err, dev);
mfc_debug(1, "Int reason: %d (err: %08x)\n", reason, err);
switch (reason) {
- case S5P_FIMV_R2H_CMD_ERR_RET:
+ case S5P_MFC_R2H_CMD_ERR_RET:
/* An error has occured */
if (ctx->state == MFCINST_RUNNING &&
- s5p_mfc_err_dec(err) >= S5P_FIMV_ERR_WARNINGS_START)
+ s5p_mfc_hw_call(dev->mfc_ops, err_dec, err) >=
+ dev->warn_start)
s5p_mfc_handle_frame(ctx, reason, err);
else
s5p_mfc_handle_error(ctx, reason, err);
clear_bit(0, &dev->enter_suspend);
break;
- case S5P_FIMV_R2H_CMD_SLICE_DONE_RET:
- case S5P_FIMV_R2H_CMD_FRAME_DONE_RET:
+ case S5P_MFC_R2H_CMD_SLICE_DONE_RET:
+ case S5P_MFC_R2H_CMD_FIELD_DONE_RET:
+ case S5P_MFC_R2H_CMD_FRAME_DONE_RET:
if (ctx->c_ops->post_frame_start) {
if (ctx->c_ops->post_frame_start(ctx))
mfc_err("post_frame_start() failed\n");
- s5p_mfc_clear_int_flags(dev);
+ s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
wake_up_ctx(ctx, reason, err);
if (test_and_clear_bit(0, &dev->hw_lock) == 0)
BUG();
s5p_mfc_clock_off();
- s5p_mfc_try_run(dev);
+ s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
} else {
s5p_mfc_handle_frame(ctx, reason, err);
}
break;
- case S5P_FIMV_R2H_CMD_SEQ_DONE_RET:
+ case S5P_MFC_R2H_CMD_SEQ_DONE_RET:
s5p_mfc_handle_seq_done(ctx, reason, err);
break;
- case S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET:
- ctx->inst_no = s5p_mfc_get_inst_no();
+ case S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET:
+ ctx->inst_no = s5p_mfc_hw_call(dev->mfc_ops, get_inst_no, dev);
ctx->state = MFCINST_GOT_INST;
clear_work_bit(ctx);
wake_up(&ctx->queue);
goto irq_cleanup_hw;
- case S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET:
+ case S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET:
clear_work_bit(ctx);
ctx->state = MFCINST_FREE;
wake_up(&ctx->queue);
goto irq_cleanup_hw;
- case S5P_FIMV_R2H_CMD_SYS_INIT_RET:
- case S5P_FIMV_R2H_CMD_FW_STATUS_RET:
- case S5P_FIMV_R2H_CMD_SLEEP_RET:
- case S5P_FIMV_R2H_CMD_WAKEUP_RET:
+ case S5P_MFC_R2H_CMD_SYS_INIT_RET:
+ case S5P_MFC_R2H_CMD_FW_STATUS_RET:
+ case S5P_MFC_R2H_CMD_SLEEP_RET:
+ case S5P_MFC_R2H_CMD_WAKEUP_RET:
if (ctx)
clear_work_bit(ctx);
- s5p_mfc_clear_int_flags(dev);
+ s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
wake_up_dev(dev, reason, err);
clear_bit(0, &dev->hw_lock);
clear_bit(0, &dev->enter_suspend);
break;
- case S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET:
+ case S5P_MFC_R2H_CMD_INIT_BUFFERS_RET:
s5p_mfc_handle_init_buffers(ctx, reason, err);
break;
default:
mfc_debug(2, "Unknown int reason\n");
- s5p_mfc_clear_int_flags(dev);
+ s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
}
mfc_debug_leave();
return IRQ_HANDLED;
irq_cleanup_hw:
- s5p_mfc_clear_int_flags(dev);
+ s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
ctx->int_type = reason;
ctx->int_err = err;
ctx->int_cond = 1;
@@ -630,7 +644,7 @@ irq_cleanup_hw:
s5p_mfc_clock_off();
- s5p_mfc_try_run(dev);
+ s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
mfc_debug(2, "Exit via irq_cleanup_hw\n");
return IRQ_HANDLED;
}
@@ -681,6 +695,7 @@ static int s5p_mfc_open(struct file *file)
if (s5p_mfc_get_node_type(file) == MFCNODE_DECODER) {
ctx->type = MFCINST_DECODER;
ctx->c_ops = get_dec_codec_ops();
+ s5p_mfc_dec_init(ctx);
/* Setup ctrl handler */
ret = s5p_mfc_dec_ctrls_setup(ctx);
if (ret) {
@@ -693,6 +708,7 @@ static int s5p_mfc_open(struct file *file)
/* only for encoder */
INIT_LIST_HEAD(&ctx->ref_queue);
ctx->ref_queue_cnt = 0;
+ s5p_mfc_enc_init(ctx);
/* Setup ctrl handler */
ret = s5p_mfc_enc_ctrls_setup(ctx);
if (ret) {
@@ -823,19 +839,20 @@ static int s5p_mfc_release(struct file *file)
set_bit(ctx->num, &dev->ctx_work_bits);
spin_unlock_irqrestore(&dev->condlock, flags);
s5p_mfc_clean_ctx_int_flags(ctx);
- s5p_mfc_try_run(dev);
+ s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
/* Wait until instance is returned or timeout occured */
if (s5p_mfc_wait_for_done_ctx
- (ctx, S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET, 0)) {
+ (ctx, S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET, 0)) {
s5p_mfc_clock_off();
mfc_err("Err returning instance\n");
}
mfc_debug(2, "After free instance\n");
/* Free resources */
- s5p_mfc_release_codec_buffers(ctx);
- s5p_mfc_release_instance_buffer(ctx);
+ s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers, ctx);
+ s5p_mfc_hw_call(dev->mfc_ops, release_instance_buffer, ctx);
if (ctx->type == MFCINST_DECODER)
- s5p_mfc_release_dec_desc_buffer(ctx);
+ s5p_mfc_hw_call(dev->mfc_ops, release_dec_desc_buffer,
+ ctx);
ctx->inst_no = MFC_NO_INSTANCE_SET;
}
@@ -847,6 +864,7 @@ static int s5p_mfc_release(struct file *file)
mfc_debug(2, "Last instance - release firmware\n");
/* reset <-> F/W release */
s5p_mfc_reset(dev);
+ s5p_mfc_deinit_hw(dev);
s5p_mfc_release_firmware(dev);
del_timer_sync(&dev->watchdog_timer);
if (s5p_mfc_power_off() < 0)
@@ -1094,6 +1112,10 @@ static int s5p_mfc_probe(struct platform_device *pdev)
dev->watchdog_timer.data = (unsigned long)dev;
dev->watchdog_timer.function = s5p_mfc_watchdog;
+ /* Initialize HW ops and commands based on MFC version */
+ s5p_mfc_init_hw_ops(dev);
+ s5p_mfc_init_hw_cmds(dev);
+
pr_debug("%s--\n", __func__);
return 0;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c
index 91a4155..47b956d 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c
@@ -10,111 +10,15 @@
* (at your option) any later version.
*/
-#include "regs-mfc.h"
#include "s5p_mfc_cmd.h"
#include "s5p_mfc_common.h"
#include "s5p_mfc_debug.h"
+#include "s5p_mfc_cmd_v5.h"
-/* This function is used to send a command to the MFC */
-static int s5p_mfc_cmd_host2risc(struct s5p_mfc_dev *dev, int cmd,
- struct s5p_mfc_cmd_args *args)
-{
- int cur_cmd;
- unsigned long timeout;
-
- timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
- /* wait until host to risc command register becomes 'H2R_CMD_EMPTY' */
- do {
- if (time_after(jiffies, timeout)) {
- mfc_err("Timeout while waiting for hardware\n");
- return -EIO;
- }
- cur_cmd = mfc_read(dev, S5P_FIMV_HOST2RISC_CMD);
- } while (cur_cmd != S5P_FIMV_H2R_CMD_EMPTY);
- mfc_write(dev, args->arg[0], S5P_FIMV_HOST2RISC_ARG1);
- mfc_write(dev, args->arg[1], S5P_FIMV_HOST2RISC_ARG2);
- mfc_write(dev, args->arg[2], S5P_FIMV_HOST2RISC_ARG3);
- mfc_write(dev, args->arg[3], S5P_FIMV_HOST2RISC_ARG4);
- /* Issue the command */
- mfc_write(dev, cmd, S5P_FIMV_HOST2RISC_CMD);
- return 0;
-}
-
-/* Initialize the MFC */
-int s5p_mfc_sys_init_cmd(struct s5p_mfc_dev *dev)
-{
- struct s5p_mfc_cmd_args h2r_args;
-
- memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
- h2r_args.arg[0] = dev->fw_size;
- return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SYS_INIT, &h2r_args);
-}
-
-/* Suspend the MFC hardware */
-int s5p_mfc_sleep_cmd(struct s5p_mfc_dev *dev)
-{
- struct s5p_mfc_cmd_args h2r_args;
-
- memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
- return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SLEEP, &h2r_args);
-}
+static struct s5p_mfc_hw_cmds *s5p_mfc_cmds;
-/* Wake up the MFC hardware */
-int s5p_mfc_wakeup_cmd(struct s5p_mfc_dev *dev)
+void s5p_mfc_init_hw_cmds(struct s5p_mfc_dev *dev)
{
- struct s5p_mfc_cmd_args h2r_args;
-
- memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
- return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_WAKEUP, &h2r_args);
-}
-
-
-int s5p_mfc_open_inst_cmd(struct s5p_mfc_ctx *ctx)
-{
- struct s5p_mfc_dev *dev = ctx->dev;
- struct s5p_mfc_cmd_args h2r_args;
- int ret;
-
- /* Preparing decoding - getting instance number */
- mfc_debug(2, "Getting instance number (codec: %d)\n", ctx->codec_mode);
- dev->curr_ctx = ctx->num;
- memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
- h2r_args.arg[0] = ctx->codec_mode;
- h2r_args.arg[1] = 0; /* no crc & no pixelcache */
- h2r_args.arg[2] = ctx->ctx_ofs;
- h2r_args.arg[3] = ctx->ctx_size;
- ret = s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE,
- &h2r_args);
- if (ret) {
- mfc_err("Failed to create a new instance\n");
- ctx->state = MFCINST_ERROR;
- }
- return ret;
+ s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v5();
+ dev->mfc_cmds = s5p_mfc_cmds;
}
-
-int s5p_mfc_close_inst_cmd(struct s5p_mfc_ctx *ctx)
-{
- struct s5p_mfc_dev *dev = ctx->dev;
- struct s5p_mfc_cmd_args h2r_args;
- int ret;
-
- if (ctx->state == MFCINST_FREE) {
- mfc_err("Instance already returned\n");
- ctx->state = MFCINST_ERROR;
- return -EINVAL;
- }
- /* Closing decoding instance */
- mfc_debug(2, "Returning instance number %d\n", ctx->inst_no);
- dev->curr_ctx = ctx->num;
- memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
- h2r_args.arg[0] = ctx->inst_no;
- ret = s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_CLOSE_INSTANCE,
- &h2r_args);
- if (ret) {
- mfc_err("Failed to return an instance\n");
- ctx->state = MFCINST_ERROR;
- return -EINVAL;
- }
- return 0;
-}
-
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h
index 8b090d3..42dcd15 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h
@@ -21,10 +21,15 @@ struct s5p_mfc_cmd_args {
unsigned int arg[MAX_H2R_ARG];
};
-int s5p_mfc_sys_init_cmd(struct s5p_mfc_dev *dev);
-int s5p_mfc_sleep_cmd(struct s5p_mfc_dev *dev);
-int s5p_mfc_wakeup_cmd(struct s5p_mfc_dev *dev);
-int s5p_mfc_open_inst_cmd(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_close_inst_cmd(struct s5p_mfc_ctx *ctx);
+struct s5p_mfc_hw_cmds {
+ int (*cmd_host2risc)(struct s5p_mfc_dev *dev, int cmd,
+ struct s5p_mfc_cmd_args *args);
+ int (*sys_init_cmd)(struct s5p_mfc_dev *dev);
+ int (*sleep_cmd)(struct s5p_mfc_dev *dev);
+ int (*wakeup_cmd)(struct s5p_mfc_dev *dev);
+ int (*open_inst_cmd)(struct s5p_mfc_ctx *ctx);
+ int (*close_inst_cmd)(struct s5p_mfc_ctx *ctx);
+};
+void s5p_mfc_init_hw_cmds(struct s5p_mfc_dev *dev);
#endif /* S5P_MFC_CMD_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
new file mode 100644
index 0000000..f3d7874
--- /dev/null
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
@@ -0,0 +1,166 @@
+/*
+ * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
+ *
+ * Copyright (C) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "regs-mfc.h"
+#include "s5p_mfc_cmd.h"
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_debug.h"
+
+/* This function is used to send a command to the MFC */
+int s5p_mfc_cmd_host2risc_v5(struct s5p_mfc_dev *dev, int cmd,
+ struct s5p_mfc_cmd_args *args)
+{
+ int cur_cmd;
+ unsigned long timeout;
+
+ timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
+ /* wait until host to risc command register becomes 'H2R_CMD_EMPTY' */
+ do {
+ if (time_after(jiffies, timeout)) {
+ mfc_err("Timeout while waiting for hardware\n");
+ return -EIO;
+ }
+ cur_cmd = mfc_read(dev, S5P_FIMV_HOST2RISC_CMD);
+ } while (cur_cmd != S5P_FIMV_H2R_CMD_EMPTY);
+ mfc_write(dev, args->arg[0], S5P_FIMV_HOST2RISC_ARG1);
+ mfc_write(dev, args->arg[1], S5P_FIMV_HOST2RISC_ARG2);
+ mfc_write(dev, args->arg[2], S5P_FIMV_HOST2RISC_ARG3);
+ mfc_write(dev, args->arg[3], S5P_FIMV_HOST2RISC_ARG4);
+ /* Issue the command */
+ mfc_write(dev, cmd, S5P_FIMV_HOST2RISC_CMD);
+ return 0;
+}
+
+/* Initialize the MFC */
+int s5p_mfc_sys_init_cmd_v5(struct s5p_mfc_dev *dev)
+{
+ struct s5p_mfc_cmd_args h2r_args;
+
+ memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+ h2r_args.arg[0] = dev->fw_size;
+ return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_SYS_INIT,
+ &h2r_args);
+}
+
+/* Suspend the MFC hardware */
+int s5p_mfc_sleep_cmd_v5(struct s5p_mfc_dev *dev)
+{
+ struct s5p_mfc_cmd_args h2r_args;
+
+ memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+ return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_SLEEP, &h2r_args);
+}
+
+/* Wake up the MFC hardware */
+int s5p_mfc_wakeup_cmd_v5(struct s5p_mfc_dev *dev)
+{
+ struct s5p_mfc_cmd_args h2r_args;
+
+ memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+ return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_WAKEUP,
+ &h2r_args);
+}
+
+
+int s5p_mfc_open_inst_cmd_v5(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ struct s5p_mfc_cmd_args h2r_args;
+ int ret;
+
+ /* Preparing decoding - getting instance number */
+ mfc_debug(2, "Getting instance number (codec: %d)\n", ctx->codec_mode);
+ dev->curr_ctx = ctx->num;
+ memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+ switch (ctx->codec_mode) {
+ case S5P_MFC_CODEC_H264_DEC:
+ h2r_args.arg[0] = S5P_FIMV_CODEC_H264_DEC;
+ break;
+ case S5P_MFC_CODEC_VC1_DEC:
+ h2r_args.arg[0] = S5P_FIMV_CODEC_VC1_DEC;
+ break;
+ case S5P_MFC_CODEC_MPEG4_DEC:
+ h2r_args.arg[0] = S5P_FIMV_CODEC_MPEG4_DEC;
+ break;
+ case S5P_MFC_CODEC_MPEG2_DEC:
+ h2r_args.arg[0] = S5P_FIMV_CODEC_MPEG2_DEC;
+ break;
+ case S5P_MFC_CODEC_H263_DEC:
+ h2r_args.arg[0] = S5P_FIMV_CODEC_H263_DEC;
+ break;
+ case S5P_MFC_CODEC_VC1RCV_DEC:
+ h2r_args.arg[0] = S5P_FIMV_CODEC_VC1RCV_DEC;
+ break;
+ case S5P_MFC_CODEC_H264_ENC:
+ h2r_args.arg[0] = S5P_FIMV_CODEC_H264_ENC;
+ break;
+ case S5P_MFC_CODEC_MPEG4_ENC:
+ h2r_args.arg[0] = S5P_FIMV_CODEC_MPEG4_ENC;
+ break;
+ case S5P_MFC_CODEC_H263_ENC:
+ h2r_args.arg[0] = S5P_FIMV_CODEC_H263_ENC;
+ break;
+ default:
+ h2r_args.arg[0] = S5P_FIMV_CODEC_NONE;
+ };
+ h2r_args.arg[1] = 0; /* no crc & no pixelcache */
+ h2r_args.arg[2] = ctx->ctx_ofs;
+ h2r_args.arg[3] = ctx->ctx_size;
+ ret = s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE,
+ &h2r_args);
+ if (ret) {
+ mfc_err("Failed to create a new instance\n");
+ ctx->state = MFCINST_ERROR;
+ }
+ return ret;
+}
+
+int s5p_mfc_close_inst_cmd_v5(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ struct s5p_mfc_cmd_args h2r_args;
+ int ret;
+
+ if (ctx->state == MFCINST_FREE) {
+ mfc_err("Instance already returned\n");
+ ctx->state = MFCINST_ERROR;
+ return -EINVAL;
+ }
+ /* Closing decoding instance */
+ mfc_debug(2, "Returning instance number %d\n", ctx->inst_no);
+ dev->curr_ctx = ctx->num;
+ memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+ h2r_args.arg[0] = ctx->inst_no;
+ ret = s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_CLOSE_INSTANCE,
+ &h2r_args);
+ if (ret) {
+ mfc_err("Failed to return an instance\n");
+ ctx->state = MFCINST_ERROR;
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/* Initialize cmd function pointers for MFC v5 */
+static struct s5p_mfc_hw_cmds s5p_mfc_cmds_v5 = {
+ .cmd_host2risc = s5p_mfc_cmd_host2risc_v5,
+ .sys_init_cmd = s5p_mfc_sys_init_cmd_v5,
+ .sleep_cmd = s5p_mfc_sleep_cmd_v5,
+ .wakeup_cmd = s5p_mfc_wakeup_cmd_v5,
+ .open_inst_cmd = s5p_mfc_open_inst_cmd_v5,
+ .close_inst_cmd = s5p_mfc_close_inst_cmd_v5,
+};
+
+struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v5(void)
+{
+ return &s5p_mfc_cmds_v5;
+}
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h
new file mode 100644
index 0000000..6928a55
--- /dev/null
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h
@@ -0,0 +1,20 @@
+/*
+ * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h
+ *
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef S5P_MFC_CMD_V5_H_
+#define S5P_MFC_CMD_V5_H_
+
+#include "s5p_mfc_common.h"
+
+struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v5(void);
+
+#endif /* S5P_MFC_CMD_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
index bd5706a..ccb59ac 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
@@ -74,7 +74,40 @@ static inline dma_addr_t s5p_mfc_mem_cookie(void *a, void *b)
#define MFC_ENC_CAP_PLANE_COUNT 1
#define MFC_ENC_OUT_PLANE_COUNT 2
#define STUFF_BYTE 4
-#define MFC_MAX_CTRLS 64
+#define MFC_MAX_CTRLS 70
+
+#define S5P_MFC_CODEC_NONE -1
+#define S5P_MFC_CODEC_H264_DEC 0
+#define S5P_MFC_CODEC_H264_MVC_DEC 1
+#define S5P_MFC_CODEC_VC1_DEC 2
+#define S5P_MFC_CODEC_MPEG4_DEC 3
+#define S5P_MFC_CODEC_MPEG2_DEC 4
+#define S5P_MFC_CODEC_H263_DEC 5
+#define S5P_MFC_CODEC_VC1RCV_DEC 6
+#define S5P_MFC_CODEC_VP8_DEC 7
+
+#define S5P_MFC_CODEC_H264_ENC 20
+#define S5P_MFC_CODEC_H264_MVC_ENC 21
+#define S5P_MFC_CODEC_MPEG4_ENC 22
+#define S5P_MFC_CODEC_H263_ENC 23
+
+#define S5P_MFC_R2H_CMD_EMPTY 0
+#define S5P_MFC_R2H_CMD_SYS_INIT_RET 1
+#define S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET 2
+#define S5P_MFC_R2H_CMD_SEQ_DONE_RET 3
+#define S5P_MFC_R2H_CMD_INIT_BUFFERS_RET 4
+#define S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET 6
+#define S5P_MFC_R2H_CMD_SLEEP_RET 7
+#define S5P_MFC_R2H_CMD_WAKEUP_RET 8
+#define S5P_MFC_R2H_CMD_COMPLETE_SEQ_RET 9
+#define S5P_MFC_R2H_CMD_DPB_FLUSH_RET 10
+#define S5P_MFC_R2H_CMD_NAL_ABORT_RET 11
+#define S5P_MFC_R2H_CMD_FW_STATUS_RET 12
+#define S5P_MFC_R2H_CMD_FRAME_DONE_RET 13
+#define S5P_MFC_R2H_CMD_FIELD_DONE_RET 14
+#define S5P_MFC_R2H_CMD_SLICE_DONE_RET 15
+#define S5P_MFC_R2H_CMD_ENC_BUFFER_FUL_RET 16
+#define S5P_MFC_R2H_CMD_ERR_RET 32
#define mfc_read(dev, offset) readl(dev->regs_base + (offset))
#define mfc_write(dev, data, offset) writel((data), dev->regs_base + \
@@ -209,6 +242,9 @@ struct s5p_mfc_pm {
* @watchdog_work: worker for the watchdog
* @alloc_ctx: videobuf2 allocator contexts for two memory banks
* @enter_suspend: flag set when entering suspend
+ * @warn_start: hardware error code from which warnings start
+ * @mfc_ops: ops structure holding HW operation function pointers
+ * @mfc_cmds: cmd structure holding HW commands function pointers
*
*/
struct s5p_mfc_dev {
@@ -245,6 +281,10 @@ struct s5p_mfc_dev {
struct work_struct watchdog_work;
void *alloc_ctx[2];
unsigned long enter_suspend;
+
+ int warn_start;
+ struct s5p_mfc_hw_ops *mfc_ops;
+ struct s5p_mfc_hw_cmds *mfc_cmds;
};
/**
@@ -562,6 +602,9 @@ struct mfc_control {
__u8 is_volatile;
};
+/* Macro for making hardware specific calls */
+#define s5p_mfc_hw_call(f, op, args...) \
+ ((f && f->op) ? f->op(args) : -ENODEV)
#define fh_to_ctx(__fh) container_of(__fh, struct s5p_mfc_ctx, fh)
#define ctrl_to_ctx(__ctrl) \
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
index 4d662f1..4a39e5e 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
@@ -15,11 +15,11 @@
#include <linux/firmware.h>
#include <linux/jiffies.h>
#include <linux/sched.h>
-#include "regs-mfc.h"
#include "s5p_mfc_cmd.h"
#include "s5p_mfc_common.h"
#include "s5p_mfc_debug.h"
#include "s5p_mfc_intr.h"
+#include "s5p_mfc_opr.h"
#include "s5p_mfc_pm.h"
static void *s5p_mfc_bitproc_buf;
@@ -226,7 +226,7 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
s5p_mfc_clean_dev_int_flags(dev);
mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
mfc_debug(2, "Will now wait for completion of firmware transfer\n");
- if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_FW_STATUS_RET)) {
+ if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_FW_STATUS_RET)) {
mfc_err("Failed to load firmware\n");
s5p_mfc_reset(dev);
s5p_mfc_clock_off();
@@ -234,7 +234,7 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
}
s5p_mfc_clean_dev_int_flags(dev);
/* 4. Initialize firmware */
- ret = s5p_mfc_sys_init_cmd(dev);
+ ret = s5p_mfc_hw_call(dev->mfc_cmds, sys_init_cmd, dev);
if (ret) {
mfc_err("Failed to send command to MFC - timeout\n");
s5p_mfc_reset(dev);
@@ -242,7 +242,7 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
return ret;
}
mfc_debug(2, "Ok, now will write a command to init the system\n");
- if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_SYS_INIT_RET)) {
+ if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_SYS_INIT_RET)) {
mfc_err("Failed to load firmware\n");
s5p_mfc_reset(dev);
s5p_mfc_clock_off();
@@ -250,7 +250,7 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
}
dev->int_cond = 0;
if (dev->int_err != 0 || dev->int_type !=
- S5P_FIMV_R2H_CMD_SYS_INIT_RET) {
+ S5P_MFC_R2H_CMD_SYS_INIT_RET) {
/* Failure. */
mfc_err("Failed to init firmware - error: %d int: %d\n",
dev->int_err, dev->int_type);
@@ -267,6 +267,17 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
}
+/* Deinitialize hardware */
+void s5p_mfc_deinit_hw(struct s5p_mfc_dev *dev)
+{
+ s5p_mfc_clock_on();
+
+ s5p_mfc_reset(dev);
+ s5p_mfc_hw_call(dev->mfc_ops, release_dev_context_buffer, dev);
+
+ s5p_mfc_clock_off();
+}
+
int s5p_mfc_sleep(struct s5p_mfc_dev *dev)
{
int ret;
@@ -274,19 +285,19 @@ int s5p_mfc_sleep(struct s5p_mfc_dev *dev)
mfc_debug_enter();
s5p_mfc_clock_on();
s5p_mfc_clean_dev_int_flags(dev);
- ret = s5p_mfc_sleep_cmd(dev);
+ ret = s5p_mfc_hw_call(dev->mfc_cmds, sleep_cmd, dev);
if (ret) {
mfc_err("Failed to send command to MFC - timeout\n");
return ret;
}
- if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_SLEEP_RET)) {
+ if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_SLEEP_RET)) {
mfc_err("Failed to sleep\n");
return -EIO;
}
s5p_mfc_clock_off();
dev->int_cond = 0;
if (dev->int_err != 0 || dev->int_type !=
- S5P_FIMV_R2H_CMD_SLEEP_RET) {
+ S5P_MFC_R2H_CMD_SLEEP_RET) {
/* Failure. */
mfc_err("Failed to sleep - error: %d int: %d\n", dev->int_err,
dev->int_type);
@@ -316,7 +327,7 @@ int s5p_mfc_wakeup(struct s5p_mfc_dev *dev)
s5p_mfc_clear_cmds(dev);
s5p_mfc_clean_dev_int_flags(dev);
/* 3. Initialize firmware */
- ret = s5p_mfc_wakeup_cmd(dev);
+ ret = s5p_mfc_hw_call(dev->mfc_cmds, wakeup_cmd, dev);
if (ret) {
mfc_err("Failed to send command to MFC - timeout\n");
return ret;
@@ -324,14 +335,14 @@ int s5p_mfc_wakeup(struct s5p_mfc_dev *dev)
/* 4. Release reset signal to the RISC */
mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
mfc_debug(2, "Ok, now will write a command to wakeup the system\n");
- if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_WAKEUP_RET)) {
+ if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_WAKEUP_RET)) {
mfc_err("Failed to load firmware\n");
return -EIO;
}
s5p_mfc_clock_off();
dev->int_cond = 0;
if (dev->int_err != 0 || dev->int_type !=
- S5P_FIMV_R2H_CMD_WAKEUP_RET) {
+ S5P_MFC_R2H_CMD_WAKEUP_RET) {
/* Failure. */
mfc_err("Failed to wakeup - error: %d int: %d\n", dev->int_err,
dev->int_type);
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h
index e1e0c54..90aa9b9 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h
@@ -20,6 +20,7 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev);
int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev);
int s5p_mfc_init_hw(struct s5p_mfc_dev *dev);
+void s5p_mfc_deinit_hw(struct s5p_mfc_dev *dev);
int s5p_mfc_sleep(struct s5p_mfc_dev *dev);
int s5p_mfc_wakeup(struct s5p_mfc_dev *dev);
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
index 456f5df..8133a4c 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
@@ -23,83 +23,84 @@
#include <linux/workqueue.h>
#include <media/v4l2-ctrls.h>
#include <media/videobuf2-core.h>
-#include "regs-mfc.h"
#include "s5p_mfc_common.h"
#include "s5p_mfc_debug.h"
#include "s5p_mfc_dec.h"
#include "s5p_mfc_intr.h"
#include "s5p_mfc_opr.h"
#include "s5p_mfc_pm.h"
-#include "s5p_mfc_shm.h"
+
+#define DEF_SRC_FMT_DEC V4L2_PIX_FMT_H264
+#define DEF_DST_FMT_DEC V4L2_PIX_FMT_NV12MT
static struct s5p_mfc_fmt formats[] = {
{
.name = "4:2:0 2 Planes 64x32 Tiles",
.fourcc = V4L2_PIX_FMT_NV12MT,
- .codec_mode = S5P_FIMV_CODEC_NONE,
+ .codec_mode = S5P_MFC_CODEC_NONE,
.type = MFC_FMT_RAW,
.num_planes = 2,
- },
+ },
{
.name = "4:2:0 2 Planes",
.fourcc = V4L2_PIX_FMT_NV12M,
- .codec_mode = S5P_FIMV_CODEC_NONE,
+ .codec_mode = S5P_MFC_CODEC_NONE,
.type = MFC_FMT_RAW,
.num_planes = 2,
},
{
.name = "H264 Encoded Stream",
.fourcc = V4L2_PIX_FMT_H264,
- .codec_mode = S5P_FIMV_CODEC_H264_DEC,
+ .codec_mode = S5P_MFC_CODEC_H264_DEC,
.type = MFC_FMT_DEC,
.num_planes = 1,
},
{
.name = "H263 Encoded Stream",
.fourcc = V4L2_PIX_FMT_H263,
- .codec_mode = S5P_FIMV_CODEC_H263_DEC,
+ .codec_mode = S5P_MFC_CODEC_H263_DEC,
.type = MFC_FMT_DEC,
.num_planes = 1,
},
{
.name = "MPEG1 Encoded Stream",
.fourcc = V4L2_PIX_FMT_MPEG1,
- .codec_mode = S5P_FIMV_CODEC_MPEG2_DEC,
+ .codec_mode = S5P_MFC_CODEC_MPEG2_DEC,
.type = MFC_FMT_DEC,
.num_planes = 1,
},
{
.name = "MPEG2 Encoded Stream",
.fourcc = V4L2_PIX_FMT_MPEG2,
- .codec_mode = S5P_FIMV_CODEC_MPEG2_DEC,
+ .codec_mode = S5P_MFC_CODEC_MPEG2_DEC,
.type = MFC_FMT_DEC,
.num_planes = 1,
},
{
.name = "MPEG4 Encoded Stream",
.fourcc = V4L2_PIX_FMT_MPEG4,
- .codec_mode = S5P_FIMV_CODEC_MPEG4_DEC,
+ .codec_mode = S5P_MFC_CODEC_MPEG4_DEC,
.type = MFC_FMT_DEC,
.num_planes = 1,
},
{
.name = "XviD Encoded Stream",
.fourcc = V4L2_PIX_FMT_XVID,
- .codec_mode = S5P_FIMV_CODEC_MPEG4_DEC,
+ .codec_mode = S5P_MFC_CODEC_MPEG4_DEC,
.type = MFC_FMT_DEC,
.num_planes = 1,
},
{
.name = "VC1 Encoded Stream",
.fourcc = V4L2_PIX_FMT_VC1_ANNEX_G,
- .codec_mode = S5P_FIMV_CODEC_VC1_DEC,
+ .codec_mode = S5P_MFC_CODEC_VC1_DEC,
.type = MFC_FMT_DEC,
.num_planes = 1,
},
{
.name = "VC1 RCV Encoded Stream",
.fourcc = V4L2_PIX_FMT_VC1_ANNEX_L,
- .codec_mode = S5P_FIMV_CODEC_VC1RCV_DEC,
+ .codec_mode = S5P_MFC_CODEC_VC1RCV_DEC,
.type = MFC_FMT_DEC,
.num_planes = 1,
},
@@ -297,7 +298,7 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
/* If the MFC is parsing the header,
* so wait until it is finished */
s5p_mfc_clean_ctx_int_flags(ctx);
- s5p_mfc_wait_for_done_ctx(ctx, S5P_FIMV_R2H_CMD_SEQ_DONE_RET,
+ s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_SEQ_DONE_RET,
0);
}
if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
@@ -380,7 +381,7 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
goto out;
}
fmt = find_format(f, MFC_FMT_DEC);
- if (!fmt || fmt->codec_mode == S5P_FIMV_CODEC_NONE) {
+ if (!fmt || fmt->codec_mode == S5P_MFC_CODEC_NONE) {
mfc_err("Unknown codec\n");
ret = -EINVAL;
goto out;
@@ -477,7 +478,7 @@ static int vidioc_reqbufs(struct file *file, void *priv,
return -ENOMEM;
}
ctx->total_dpb_count = reqbufs->count;
- ret = s5p_mfc_alloc_codec_buffers(ctx);
+ ret = s5p_mfc_hw_call(dev->mfc_ops, alloc_codec_buffers, ctx);
if (ret) {
mfc_err("Failed to allocate decoding buffers\n");
reqbufs->count = 0;
@@ -493,7 +494,8 @@ static int vidioc_reqbufs(struct file *file, void *priv,
reqbufs->count = 0;
s5p_mfc_clock_on();
ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
- s5p_mfc_release_codec_buffers(ctx);
+ s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers,
+ ctx);
s5p_mfc_clock_off();
return -ENOMEM;
}
@@ -502,9 +504,9 @@ static int vidioc_reqbufs(struct file *file, void *priv,
set_bit(ctx->num, &dev->ctx_work_bits);
spin_unlock_irqrestore(&dev->condlock, flags);
}
- s5p_mfc_try_run(dev);
+ s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
s5p_mfc_wait_for_done_ctx(ctx,
- S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET, 0);
+ S5P_MFC_R2H_CMD_INIT_BUFFERS_RET, 0);
}
return ret;
}
@@ -587,20 +589,24 @@ static int vidioc_streamon(struct file *file, void *priv,
ctx->src_bufs_cnt = 0;
ctx->capture_state = QUEUE_FREE;
ctx->output_state = QUEUE_FREE;
- s5p_mfc_alloc_instance_buffer(ctx);
- s5p_mfc_alloc_dec_temp_buffers(ctx);
+ s5p_mfc_hw_call(dev->mfc_ops, alloc_instance_buffer,
+ ctx);
+ s5p_mfc_hw_call(dev->mfc_ops, alloc_dec_temp_buffers,
+ ctx);
spin_lock_irqsave(&dev->condlock, flags);
set_bit(ctx->num, &dev->ctx_work_bits);
spin_unlock_irqrestore(&dev->condlock, flags);
s5p_mfc_clean_ctx_int_flags(ctx);
- s5p_mfc_try_run(dev);
+ s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
if (s5p_mfc_wait_for_done_ctx(ctx,
- S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET, 0)) {
+ S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET, 0)) {
/* Error or timeout */
mfc_err("Error getting instance from hardware\n");
- s5p_mfc_release_instance_buffer(ctx);
- s5p_mfc_release_dec_desc_buffer(ctx);
+ s5p_mfc_hw_call(dev->mfc_ops,
+ release_instance_buffer, ctx);
+ s5p_mfc_hw_call(dev->mfc_ops,
+ release_dec_desc_buffer, ctx);
return -EIO;
}
mfc_debug(2, "Got instance number: %d\n", ctx->inst_no);
@@ -669,7 +675,7 @@ static int s5p_mfc_dec_g_v_ctrl(struct v4l2_ctrl *ctrl)
/* Should wait for the header to be parsed */
s5p_mfc_clean_ctx_int_flags(ctx);
s5p_mfc_wait_for_done_ctx(ctx,
- S5P_FIMV_R2H_CMD_SEQ_DONE_RET, 0);
+ S5P_MFC_R2H_CMD_SEQ_DONE_RET, 0);
if (ctx->state >= MFCINST_HEAD_PARSED &&
ctx->state < MFCINST_ABORT) {
ctrl->val = ctx->dpb_count;
@@ -693,6 +699,7 @@ static int vidioc_g_crop(struct file *file, void *priv,
struct v4l2_crop *cr)
{
struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+ struct s5p_mfc_dev *dev = ctx->dev;
u32 left, right, top, bottom;
if (ctx->state != MFCINST_HEAD_PARSED &&
@@ -702,10 +709,10 @@ static int vidioc_g_crop(struct file *file, void *priv,
return -EINVAL;
}
if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_H264) {
- left = s5p_mfc_read_shm(ctx, CROP_INFO_H);
+ left = s5p_mfc_hw_call(dev->mfc_ops, get_crop_info_h, ctx);
right = left >> S5P_FIMV_SHARED_CROP_RIGHT_SHIFT;
left = left & S5P_FIMV_SHARED_CROP_LEFT_MASK;
- top = s5p_mfc_read_shm(ctx, CROP_INFO_V);
+ top = s5p_mfc_hw_call(dev->mfc_ops, get_crop_info_v, ctx);
bottom = top >> S5P_FIMV_SHARED_CROP_BOTTOM_SHIFT;
top = top & S5P_FIMV_SHARED_CROP_TOP_MASK;
cr->c.left = left;
@@ -887,7 +894,7 @@ static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count)
set_bit(ctx->num, &dev->ctx_work_bits);
spin_unlock_irqrestore(&dev->condlock, flags);
}
- s5p_mfc_try_run(dev);
+ s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
return 0;
}
@@ -903,19 +910,21 @@ static int s5p_mfc_stop_streaming(struct vb2_queue *q)
dev->curr_ctx == ctx->num && dev->hw_lock) {
ctx->state = MFCINST_ABORT;
s5p_mfc_wait_for_done_ctx(ctx,
- S5P_FIMV_R2H_CMD_FRAME_DONE_RET, 0);
+ S5P_MFC_R2H_CMD_FRAME_DONE_RET, 0);
aborted = 1;
}
spin_lock_irqsave(&dev->irqlock, flags);
if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
- s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
+ s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue,
+ &ctx->vq_dst);
INIT_LIST_HEAD(&ctx->dst_queue);
ctx->dst_queue_cnt = 0;
ctx->dpb_flush_flag = 1;
ctx->dec_dst_flag = 0;
}
if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
+ s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue,
+ &ctx->vq_src);
INIT_LIST_HEAD(&ctx->src_queue);
ctx->src_queue_cnt = 0;
}
@@ -958,7 +967,7 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
set_bit(ctx->num, &dev->ctx_work_bits);
spin_unlock_irqrestore(&dev->condlock, flags);
}
- s5p_mfc_try_run(dev);
+ s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
}
static struct vb2_ops s5p_mfc_dec_qops = {
@@ -1042,3 +1051,13 @@ void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx *ctx)
ctx->ctrls[i] = NULL;
}
+void s5p_mfc_dec_init(struct s5p_mfc_ctx *ctx)
+{
+ struct v4l2_format f;
+ f.fmt.pix_mp.pixelformat = DEF_SRC_FMT_DEC;
+ ctx->src_fmt = find_format(&f, MFC_FMT_DEC);
+ f.fmt.pix_mp.pixelformat = DEF_DST_FMT_DEC;
+ ctx->dst_fmt = find_format(&f, MFC_FMT_RAW);
+ mfc_debug(2, "Default src_fmt is %x, dest_fmt is %x\n",
+ (unsigned int)ctx->src_fmt, (unsigned int)ctx->dst_fmt);
+}
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.h b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.h
index fdf1d99..d06a7ca 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.h
@@ -19,5 +19,6 @@ const struct v4l2_ioctl_ops *get_dec_v4l2_ioctl_ops(void);
struct s5p_mfc_fmt *get_dec_def_fmt(bool src);
int s5p_mfc_dec_ctrls_setup(struct s5p_mfc_ctx *ctx);
void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_dec_init(struct s5p_mfc_ctx *ctx);
#endif /* S5P_MFC_DEC_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
index fdeebb0..02e1a94 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
@@ -24,46 +24,48 @@
#include <linux/workqueue.h>
#include <media/v4l2-ctrls.h>
#include <media/videobuf2-core.h>
-#include "regs-mfc.h"
#include "s5p_mfc_common.h"
#include "s5p_mfc_debug.h"
#include "s5p_mfc_enc.h"
#include "s5p_mfc_intr.h"
#include "s5p_mfc_opr.h"
+#define DEF_SRC_FMT_ENC V4L2_PIX_FMT_NV12MT
+#define DEF_DST_FMT_ENC V4L2_PIX_FMT_H264
+
static struct s5p_mfc_fmt formats[] = {
{
.name = "4:2:0 2 Planes 64x32 Tiles",
.fourcc = V4L2_PIX_FMT_NV12MT,
- .codec_mode = S5P_FIMV_CODEC_NONE,
+ .codec_mode = S5P_MFC_CODEC_NONE,
.type = MFC_FMT_RAW,
.num_planes = 2,
},
{
.name = "4:2:0 2 Planes",
.fourcc = V4L2_PIX_FMT_NV12M,
- .codec_mode = S5P_FIMV_CODEC_NONE,
+ .codec_mode = S5P_MFC_CODEC_NONE,
.type = MFC_FMT_RAW,
.num_planes = 2,
},
{
.name = "H264 Encoded Stream",
.fourcc = V4L2_PIX_FMT_H264,
- .codec_mode = S5P_FIMV_CODEC_H264_ENC,
+ .codec_mode = S5P_MFC_CODEC_H264_ENC,
.type = MFC_FMT_ENC,
.num_planes = 1,
},
{
.name = "MPEG4 Encoded Stream",
.fourcc = V4L2_PIX_FMT_MPEG4,
- .codec_mode = S5P_FIMV_CODEC_MPEG4_ENC,
+ .codec_mode = S5P_MFC_CODEC_MPEG4_ENC,
.type = MFC_FMT_ENC,
.num_planes = 1,
},
{
.name = "H263 Encoded Stream",
.fourcc = V4L2_PIX_FMT_H263,
- .codec_mode = S5P_FIMV_CODEC_H263_ENC,
+ .codec_mode = S5P_MFC_CODEC_H263_ENC,
.type = MFC_FMT_ENC,
.num_planes = 1,
},
@@ -618,7 +620,8 @@ static int enc_pre_seq_start(struct s5p_mfc_ctx *ctx)
dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
dst_size = vb2_plane_size(dst_mb->b, 0);
- s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
+ s5p_mfc_hw_call(dev->mfc_ops, set_enc_stream_buffer, ctx, dst_addr,
+ dst_size);
spin_unlock_irqrestore(&dev->irqlock, flags);
return 0;
}
@@ -637,7 +640,7 @@ static int enc_post_seq_start(struct s5p_mfc_ctx *ctx)
list_del(&dst_mb->list);
ctx->dst_queue_cnt--;
vb2_set_plane_payload(dst_mb->b, 0,
- s5p_mfc_get_enc_strm_size());
+ s5p_mfc_hw_call(dev->mfc_ops, get_enc_strm_size, dev));
vb2_buffer_done(dst_mb->b, VB2_BUF_STATE_DONE);
spin_unlock_irqrestore(&dev->irqlock, flags);
}
@@ -647,7 +650,7 @@ static int enc_post_seq_start(struct s5p_mfc_ctx *ctx)
set_bit(ctx->num, &dev->ctx_work_bits);
spin_unlock_irqrestore(&dev->condlock, flags);
}
- s5p_mfc_try_run(dev);
+ s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
return 0;
}
@@ -664,14 +667,16 @@ static int enc_pre_frame_start(struct s5p_mfc_ctx *ctx)
src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 0);
src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1);
- s5p_mfc_set_enc_frame_buffer(ctx, src_y_addr, src_c_addr);
+ s5p_mfc_hw_call(dev->mfc_ops, set_enc_frame_buffer, ctx, src_y_addr,
+ src_c_addr);
spin_unlock_irqrestore(&dev->irqlock, flags);
spin_lock_irqsave(&dev->irqlock, flags);
dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
dst_size = vb2_plane_size(dst_mb->b, 0);
- s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
+ s5p_mfc_hw_call(dev->mfc_ops, set_enc_stream_buffer, ctx, dst_addr,
+ dst_size);
spin_unlock_irqrestore(&dev->irqlock, flags);
return 0;
@@ -687,15 +692,16 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx)
unsigned int strm_size;
unsigned long flags;
- slice_type = s5p_mfc_get_enc_slice_type();
- strm_size = s5p_mfc_get_enc_strm_size();
+ slice_type = s5p_mfc_hw_call(dev->mfc_ops, get_enc_slice_type, dev);
+ strm_size = s5p_mfc_hw_call(dev->mfc_ops, get_enc_strm_size, dev);
mfc_debug(2, "Encoded slice type: %d", slice_type);
mfc_debug(2, "Encoded stream size: %d", strm_size);
mfc_debug(2, "Display order: %d",
mfc_read(dev, S5P_FIMV_ENC_SI_PIC_CNT));
spin_lock_irqsave(&dev->irqlock, flags);
if (slice_type >= 0) {
- s5p_mfc_get_enc_frame_buffer(ctx, &enc_y_addr, &enc_c_addr);
+ s5p_mfc_hw_call(dev->mfc_ops, get_enc_frame_buffer, ctx,
+ &enc_y_addr, &enc_c_addr);
list_for_each_entry(mb_entry, &ctx->src_queue, list) {
mb_y_addr = vb2_dma_contig_plane_dma_addr(mb_entry->b, 0);
mb_c_addr = vb2_dma_contig_plane_dma_addr(mb_entry->b, 1);
@@ -945,17 +951,18 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
pix_fmt_mp->plane_fmt[0].bytesperline = 0;
ctx->dst_bufs_cnt = 0;
ctx->capture_state = QUEUE_FREE;
- s5p_mfc_alloc_instance_buffer(ctx);
+ s5p_mfc_hw_call(dev->mfc_ops, alloc_instance_buffer, ctx);
spin_lock_irqsave(&dev->condlock, flags);
set_bit(ctx->num, &dev->ctx_work_bits);
spin_unlock_irqrestore(&dev->condlock, flags);
s5p_mfc_clean_ctx_int_flags(ctx);
- s5p_mfc_try_run(dev);
+ s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
if (s5p_mfc_wait_for_done_ctx(ctx, \
- S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET, 1)) {
+ S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET, 1)) {
/* Error or timeout */
mfc_err("Error getting instance from hardware\n");
- s5p_mfc_release_instance_buffer(ctx);
+ s5p_mfc_hw_call(dev->mfc_ops, release_instance_buffer,
+ ctx);
ret = -EIO;
goto out;
}
@@ -1050,7 +1057,8 @@ static int vidioc_reqbufs(struct file *file, void *priv,
return ret;
}
ctx->capture_state = QUEUE_BUFS_REQUESTED;
- ret = s5p_mfc_alloc_codec_buffers(ctx);
+ ret = s5p_mfc_hw_call(ctx->dev->mfc_ops, alloc_codec_buffers,
+ ctx);
if (ret) {
mfc_err("Failed to allocate encoding buffers\n");
reqbufs->count = 0;
@@ -1657,7 +1665,7 @@ static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count)
set_bit(ctx->num, &dev->ctx_work_bits);
spin_unlock_irqrestore(&dev->condlock, flags);
}
- s5p_mfc_try_run(dev);
+ s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
return 0;
}
@@ -1671,19 +1679,21 @@ static int s5p_mfc_stop_streaming(struct vb2_queue *q)
ctx->state == MFCINST_RUNNING) &&
dev->curr_ctx == ctx->num && dev->hw_lock) {
ctx->state = MFCINST_ABORT;
- s5p_mfc_wait_for_done_ctx(ctx, S5P_FIMV_R2H_CMD_FRAME_DONE_RET,
+ s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_FRAME_DONE_RET,
0);
}
ctx->state = MFCINST_FINISHED;
spin_lock_irqsave(&dev->irqlock, flags);
if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
- s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
+ s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue,
+ &ctx->vq_dst);
INIT_LIST_HEAD(&ctx->dst_queue);
ctx->dst_queue_cnt = 0;
}
if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
cleanup_ref_queue(ctx);
- s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
+ s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue,
+ &ctx->vq_src);
INIT_LIST_HEAD(&ctx->src_queue);
ctx->src_queue_cnt = 0;
}
@@ -1734,7 +1744,7 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
set_bit(ctx->num, &dev->ctx_work_bits);
spin_unlock_irqrestore(&dev->condlock, flags);
}
- s5p_mfc_try_run(dev);
+ s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
}
static struct vb2_ops s5p_mfc_enc_qops = {
@@ -1832,3 +1842,13 @@ void s5p_mfc_enc_ctrls_delete(struct s5p_mfc_ctx *ctx)
for (i = 0; i < NUM_CTRLS; i++)
ctx->ctrls[i] = NULL;
}
+
+void s5p_mfc_enc_init(struct s5p_mfc_ctx *ctx)
+{
+ struct v4l2_format f;
+ f.fmt.pix_mp.pixelformat = DEF_SRC_FMT_ENC;
+ ctx->src_fmt = find_format(&f, MFC_FMT_RAW);
+ f.fmt.pix_mp.pixelformat = DEF_DST_FMT_ENC;
+ ctx->dst_fmt = find_format(&f, MFC_FMT_ENC);
+}
+
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.h b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.h
index ca9fd66..5118d46 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.h
@@ -19,5 +19,6 @@ const struct v4l2_ioctl_ops *get_enc_v4l2_ioctl_ops(void);
struct s5p_mfc_fmt *get_enc_def_fmt(bool src);
int s5p_mfc_enc_ctrls_setup(struct s5p_mfc_ctx *ctx);
void s5p_mfc_enc_ctrls_delete(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_enc_init(struct s5p_mfc_ctx *ctx);
#endif /* S5P_MFC_ENC_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_intr.c b/drivers/media/platform/s5p-mfc/s5p_mfc_intr.c
index 37860e2..5b8f0e0 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_intr.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_intr.c
@@ -17,7 +17,6 @@
#include <linux/io.h>
#include <linux/sched.h>
#include <linux/wait.h>
-#include "regs-mfc.h"
#include "s5p_mfc_common.h"
#include "s5p_mfc_debug.h"
#include "s5p_mfc_intr.h"
@@ -28,7 +27,7 @@ int s5p_mfc_wait_for_done_dev(struct s5p_mfc_dev *dev, int command)
ret = wait_event_interruptible_timeout(dev->queue,
(dev->int_cond && (dev->int_type == command
- || dev->int_type == S5P_FIMV_R2H_CMD_ERR_RET)),
+ || dev->int_type == S5P_MFC_R2H_CMD_ERR_RET)),
msecs_to_jiffies(MFC_INT_TIMEOUT));
if (ret == 0) {
mfc_err("Interrupt (dev->int_type:%d, command:%d) timed out\n",
@@ -40,7 +39,7 @@ int s5p_mfc_wait_for_done_dev(struct s5p_mfc_dev *dev, int command)
}
mfc_debug(1, "Finished waiting (dev->int_type:%d, command: %d)\n",
dev->int_type, command);
- if (dev->int_type == S5P_FIMV_R2H_CMD_ERR_RET)
+ if (dev->int_type == S5P_MFC_R2H_CMD_ERR_RET)
return 1;
return 0;
}
@@ -60,12 +59,12 @@ int s5p_mfc_wait_for_done_ctx(struct s5p_mfc_ctx *ctx,
if (interrupt) {
ret = wait_event_interruptible_timeout(ctx->queue,
(ctx->int_cond && (ctx->int_type == command
- || ctx->int_type == S5P_FIMV_R2H_CMD_ERR_RET)),
+ || ctx->int_type == S5P_MFC_R2H_CMD_ERR_RET)),
msecs_to_jiffies(MFC_INT_TIMEOUT));
} else {
ret = wait_event_timeout(ctx->queue,
(ctx->int_cond && (ctx->int_type == command
- || ctx->int_type == S5P_FIMV_R2H_CMD_ERR_RET)),
+ || ctx->int_type == S5P_MFC_R2H_CMD_ERR_RET)),
msecs_to_jiffies(MFC_INT_TIMEOUT));
}
if (ret == 0) {
@@ -78,7 +77,7 @@ int s5p_mfc_wait_for_done_ctx(struct s5p_mfc_ctx *ctx,
}
mfc_debug(1, "Finished waiting (ctx->int_type:%d, command: %d)\n",
ctx->int_type, command);
- if (ctx->int_type == S5P_FIMV_R2H_CMD_ERR_RET)
+ if (ctx->int_type == S5P_MFC_R2H_CMD_ERR_RET)
return 1;
return 0;
}
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
index b5fd3d4..ef8683e 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
@@ -12,1386 +12,14 @@
* published by the Free Software Foundation.
*/
-#include "regs-mfc.h"
-#include "s5p_mfc_cmd.h"
-#include "s5p_mfc_common.h"
-#include "s5p_mfc_ctrl.h"
-#include "s5p_mfc_debug.h"
-#include "s5p_mfc_intr.h"
#include "s5p_mfc_opr.h"
-#include "s5p_mfc_pm.h"
-#include "s5p_mfc_shm.h"
-#include <asm/cacheflush.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/err.h>
-#include <linux/firmware.h>
-#include <linux/io.h>
-#include <linux/jiffies.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
+#include "s5p_mfc_opr_v5.h"
-#define OFFSETA(x) (((x) - dev->bank1) >> MFC_OFFSET_SHIFT)
-#define OFFSETB(x) (((x) - dev->bank2) >> MFC_OFFSET_SHIFT)
+static struct s5p_mfc_hw_ops *s5p_mfc_ops;
-/* Allocate temporary buffers for decoding */
-int s5p_mfc_alloc_dec_temp_buffers(struct s5p_mfc_ctx *ctx)
+void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev)
{
- void *desc_virt;
- struct s5p_mfc_dev *dev = ctx->dev;
-
- ctx->desc_buf = vb2_dma_contig_memops.alloc(
- dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], DESC_BUF_SIZE);
- if (IS_ERR_VALUE((int)ctx->desc_buf)) {
- ctx->desc_buf = NULL;
- mfc_err("Allocating DESC buffer failed\n");
- return -ENOMEM;
- }
- ctx->desc_phys = s5p_mfc_mem_cookie(
- dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->desc_buf);
- BUG_ON(ctx->desc_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
- desc_virt = vb2_dma_contig_memops.vaddr(ctx->desc_buf);
- if (desc_virt == NULL) {
- vb2_dma_contig_memops.put(ctx->desc_buf);
- ctx->desc_phys = 0;
- ctx->desc_buf = NULL;
- mfc_err("Remapping DESC buffer failed\n");
- return -ENOMEM;
- }
- memset(desc_virt, 0, DESC_BUF_SIZE);
- wmb();
- return 0;
-}
-
-/* Release temporary buffers for decoding */
-void s5p_mfc_release_dec_desc_buffer(struct s5p_mfc_ctx *ctx)
-{
- if (ctx->desc_phys) {
- vb2_dma_contig_memops.put(ctx->desc_buf);
- ctx->desc_phys = 0;
- ctx->desc_buf = NULL;
- }
-}
-
-/* Allocate codec buffers */
-int s5p_mfc_alloc_codec_buffers(struct s5p_mfc_ctx *ctx)
-{
- struct s5p_mfc_dev *dev = ctx->dev;
- unsigned int enc_ref_y_size = 0;
- unsigned int enc_ref_c_size = 0;
- unsigned int guard_width, guard_height;
-
- if (ctx->type == MFCINST_DECODER) {
- mfc_debug(2, "Luma size:%d Chroma size:%d MV size:%d\n",
- ctx->luma_size, ctx->chroma_size, ctx->mv_size);
- mfc_debug(2, "Totals bufs: %d\n", ctx->total_dpb_count);
- } else if (ctx->type == MFCINST_ENCODER) {
- enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
- * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
- enc_ref_y_size = ALIGN(enc_ref_y_size, S5P_FIMV_NV12MT_SALIGN);
-
- if (ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC) {
- enc_ref_c_size = ALIGN(ctx->img_width,
- S5P_FIMV_NV12MT_HALIGN)
- * ALIGN(ctx->img_height >> 1,
- S5P_FIMV_NV12MT_VALIGN);
- enc_ref_c_size = ALIGN(enc_ref_c_size,
- S5P_FIMV_NV12MT_SALIGN);
- } else {
- guard_width = ALIGN(ctx->img_width + 16,
- S5P_FIMV_NV12MT_HALIGN);
- guard_height = ALIGN((ctx->img_height >> 1) + 4,
- S5P_FIMV_NV12MT_VALIGN);
- enc_ref_c_size = ALIGN(guard_width * guard_height,
- S5P_FIMV_NV12MT_SALIGN);
- }
- mfc_debug(2, "recon luma size: %d chroma size: %d\n",
- enc_ref_y_size, enc_ref_c_size);
- } else {
- return -EINVAL;
- }
- /* Codecs have different memory requirements */
- switch (ctx->codec_mode) {
- case S5P_FIMV_CODEC_H264_DEC:
- ctx->bank1_size =
- ALIGN(S5P_FIMV_DEC_NB_IP_SIZE +
- S5P_FIMV_DEC_VERT_NB_MV_SIZE,
- S5P_FIMV_DEC_BUF_ALIGN);
- ctx->bank2_size = ctx->total_dpb_count * ctx->mv_size;
- break;
- case S5P_FIMV_CODEC_MPEG4_DEC:
- ctx->bank1_size =
- ALIGN(S5P_FIMV_DEC_NB_DCAC_SIZE +
- S5P_FIMV_DEC_UPNB_MV_SIZE +
- S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
- S5P_FIMV_DEC_STX_PARSER_SIZE +
- S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE,
- S5P_FIMV_DEC_BUF_ALIGN);
- ctx->bank2_size = 0;
- break;
- case S5P_FIMV_CODEC_VC1RCV_DEC:
- case S5P_FIMV_CODEC_VC1_DEC:
- ctx->bank1_size =
- ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE +
- S5P_FIMV_DEC_UPNB_MV_SIZE +
- S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
- S5P_FIMV_DEC_NB_DCAC_SIZE +
- 3 * S5P_FIMV_DEC_VC1_BITPLANE_SIZE,
- S5P_FIMV_DEC_BUF_ALIGN);
- ctx->bank2_size = 0;
- break;
- case S5P_FIMV_CODEC_MPEG2_DEC:
- ctx->bank1_size = 0;
- ctx->bank2_size = 0;
- break;
- case S5P_FIMV_CODEC_H263_DEC:
- ctx->bank1_size =
- ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE +
- S5P_FIMV_DEC_UPNB_MV_SIZE +
- S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
- S5P_FIMV_DEC_NB_DCAC_SIZE,
- S5P_FIMV_DEC_BUF_ALIGN);
- ctx->bank2_size = 0;
- break;
- case S5P_FIMV_CODEC_H264_ENC:
- ctx->bank1_size = (enc_ref_y_size * 2) +
- S5P_FIMV_ENC_UPMV_SIZE +
- S5P_FIMV_ENC_COLFLG_SIZE +
- S5P_FIMV_ENC_INTRAMD_SIZE +
- S5P_FIMV_ENC_NBORINFO_SIZE;
- ctx->bank2_size = (enc_ref_y_size * 2) +
- (enc_ref_c_size * 4) +
- S5P_FIMV_ENC_INTRAPRED_SIZE;
- break;
- case S5P_FIMV_CODEC_MPEG4_ENC:
- ctx->bank1_size = (enc_ref_y_size * 2) +
- S5P_FIMV_ENC_UPMV_SIZE +
- S5P_FIMV_ENC_COLFLG_SIZE +
- S5P_FIMV_ENC_ACDCCOEF_SIZE;
- ctx->bank2_size = (enc_ref_y_size * 2) +
- (enc_ref_c_size * 4);
- break;
- case S5P_FIMV_CODEC_H263_ENC:
- ctx->bank1_size = (enc_ref_y_size * 2) +
- S5P_FIMV_ENC_UPMV_SIZE +
- S5P_FIMV_ENC_ACDCCOEF_SIZE;
- ctx->bank2_size = (enc_ref_y_size * 2) +
- (enc_ref_c_size * 4);
- break;
- default:
- break;
- }
- /* Allocate only if memory from bank 1 is necessary */
- if (ctx->bank1_size > 0) {
- ctx->bank1_buf = vb2_dma_contig_memops.alloc(
- dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_size);
- if (IS_ERR(ctx->bank1_buf)) {
- ctx->bank1_buf = NULL;
- printk(KERN_ERR
- "Buf alloc for decoding failed (port A)\n");
- return -ENOMEM;
- }
- ctx->bank1_phys = s5p_mfc_mem_cookie(
- dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_buf);
- BUG_ON(ctx->bank1_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
- }
- /* Allocate only if memory from bank 2 is necessary */
- if (ctx->bank2_size > 0) {
- ctx->bank2_buf = vb2_dma_contig_memops.alloc(
- dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], ctx->bank2_size);
- if (IS_ERR(ctx->bank2_buf)) {
- ctx->bank2_buf = NULL;
- mfc_err("Buf alloc for decoding failed (port B)\n");
- return -ENOMEM;
- }
- ctx->bank2_phys = s5p_mfc_mem_cookie(
- dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], ctx->bank2_buf);
- BUG_ON(ctx->bank2_phys & ((1 << MFC_BANK2_ALIGN_ORDER) - 1));
- }
- return 0;
-}
-
-/* Release buffers allocated for codec */
-void s5p_mfc_release_codec_buffers(struct s5p_mfc_ctx *ctx)
-{
- if (ctx->bank1_buf) {
- vb2_dma_contig_memops.put(ctx->bank1_buf);
- ctx->bank1_buf = NULL;
- ctx->bank1_phys = 0;
- ctx->bank1_size = 0;
- }
- if (ctx->bank2_buf) {
- vb2_dma_contig_memops.put(ctx->bank2_buf);
- ctx->bank2_buf = NULL;
- ctx->bank2_phys = 0;
- ctx->bank2_size = 0;
- }
-}
-
-/* Allocate memory for instance data buffer */
-int s5p_mfc_alloc_instance_buffer(struct s5p_mfc_ctx *ctx)
-{
- void *context_virt;
- struct s5p_mfc_dev *dev = ctx->dev;
-
- if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC ||
- ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC)
- ctx->ctx_size = MFC_H264_CTX_BUF_SIZE;
- else
- ctx->ctx_size = MFC_CTX_BUF_SIZE;
- ctx->ctx_buf = vb2_dma_contig_memops.alloc(
- dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx_size);
- if (IS_ERR(ctx->ctx_buf)) {
- mfc_err("Allocating context buffer failed\n");
- ctx->ctx_phys = 0;
- ctx->ctx_buf = NULL;
- return -ENOMEM;
- }
- ctx->ctx_phys = s5p_mfc_mem_cookie(
- dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx_buf);
- BUG_ON(ctx->ctx_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
- ctx->ctx_ofs = OFFSETA(ctx->ctx_phys);
- context_virt = vb2_dma_contig_memops.vaddr(ctx->ctx_buf);
- if (context_virt == NULL) {
- mfc_err("Remapping instance buffer failed\n");
- vb2_dma_contig_memops.put(ctx->ctx_buf);
- ctx->ctx_phys = 0;
- ctx->ctx_buf = NULL;
- return -ENOMEM;
- }
- /* Zero content of the allocated memory */
- memset(context_virt, 0, ctx->ctx_size);
- wmb();
- if (s5p_mfc_init_shm(ctx) < 0) {
- vb2_dma_contig_memops.put(ctx->ctx_buf);
- ctx->ctx_phys = 0;
- ctx->ctx_buf = NULL;
- return -ENOMEM;
- }
- return 0;
-}
-
-/* Release instance buffer */
-void s5p_mfc_release_instance_buffer(struct s5p_mfc_ctx *ctx)
-{
- if (ctx->ctx_buf) {
- vb2_dma_contig_memops.put(ctx->ctx_buf);
- ctx->ctx_phys = 0;
- ctx->ctx_buf = NULL;
- }
- if (ctx->shm_alloc) {
- vb2_dma_contig_memops.put(ctx->shm_alloc);
- ctx->shm_alloc = NULL;
- ctx->shm = NULL;
- }
-}
-
-/* Set registers for decoding temporary buffers */
-void s5p_mfc_set_dec_desc_buffer(struct s5p_mfc_ctx *ctx)
-{
- struct s5p_mfc_dev *dev = ctx->dev;
-
- mfc_write(dev, OFFSETA(ctx->desc_phys), S5P_FIMV_SI_CH0_DESC_ADR);
- mfc_write(dev, DESC_BUF_SIZE, S5P_FIMV_SI_CH0_DESC_SIZE);
-}
-
-/* Set registers for shared buffer */
-static void s5p_mfc_set_shared_buffer(struct s5p_mfc_ctx *ctx)
-{
- struct s5p_mfc_dev *dev = ctx->dev;
- mfc_write(dev, ctx->shm_ofs, S5P_FIMV_SI_CH0_HOST_WR_ADR);
-}
-
-/* Set registers for decoding stream buffer */
-int s5p_mfc_set_dec_stream_buffer(struct s5p_mfc_ctx *ctx, int buf_addr,
- unsigned int start_num_byte, unsigned int buf_size)
-{
- struct s5p_mfc_dev *dev = ctx->dev;
-
- mfc_write(dev, OFFSETA(buf_addr), S5P_FIMV_SI_CH0_SB_ST_ADR);
- mfc_write(dev, ctx->dec_src_buf_size, S5P_FIMV_SI_CH0_CPB_SIZE);
- mfc_write(dev, buf_size, S5P_FIMV_SI_CH0_SB_FRM_SIZE);
- s5p_mfc_write_shm(ctx, start_num_byte, START_BYTE_NUM);
- return 0;
-}
-
-/* Set decoding frame buffer */
-int s5p_mfc_set_dec_frame_buffer(struct s5p_mfc_ctx *ctx)
-{
- unsigned int frame_size, i;
- unsigned int frame_size_ch, frame_size_mv;
- struct s5p_mfc_dev *dev = ctx->dev;
- unsigned int dpb;
- size_t buf_addr1, buf_addr2;
- int buf_size1, buf_size2;
-
- buf_addr1 = ctx->bank1_phys;
- buf_size1 = ctx->bank1_size;
- buf_addr2 = ctx->bank2_phys;
- buf_size2 = ctx->bank2_size;
- dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) &
- ~S5P_FIMV_DPB_COUNT_MASK;
- mfc_write(dev, ctx->total_dpb_count | dpb,
- S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
- s5p_mfc_set_shared_buffer(ctx);
- switch (ctx->codec_mode) {
- case S5P_FIMV_CODEC_H264_DEC:
- mfc_write(dev, OFFSETA(buf_addr1),
- S5P_FIMV_H264_VERT_NB_MV_ADR);
- buf_addr1 += S5P_FIMV_DEC_VERT_NB_MV_SIZE;
- buf_size1 -= S5P_FIMV_DEC_VERT_NB_MV_SIZE;
- mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H264_NB_IP_ADR);
- buf_addr1 += S5P_FIMV_DEC_NB_IP_SIZE;
- buf_size1 -= S5P_FIMV_DEC_NB_IP_SIZE;
- break;
- case S5P_FIMV_CODEC_MPEG4_DEC:
- mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_NB_DCAC_ADR);
- buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
- buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
- mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_UP_NB_MV_ADR);
- buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
- buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
- mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_SA_MV_ADR);
- buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
- buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
- mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_SP_ADR);
- buf_addr1 += S5P_FIMV_DEC_STX_PARSER_SIZE;
- buf_size1 -= S5P_FIMV_DEC_STX_PARSER_SIZE;
- mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_OT_LINE_ADR);
- buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
- buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
- break;
- case S5P_FIMV_CODEC_H263_DEC:
- mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_OT_LINE_ADR);
- buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
- buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
- mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_UP_NB_MV_ADR);
- buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
- buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
- mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_SA_MV_ADR);
- buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
- buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
- mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_NB_DCAC_ADR);
- buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
- buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
- break;
- case S5P_FIMV_CODEC_VC1_DEC:
- case S5P_FIMV_CODEC_VC1RCV_DEC:
- mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_NB_DCAC_ADR);
- buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
- buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
- mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_OT_LINE_ADR);
- buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
- buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
- mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_UP_NB_MV_ADR);
- buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
- buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
- mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_SA_MV_ADR);
- buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
- buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
- mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE3_ADR);
- buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
- buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
- mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE2_ADR);
- buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
- buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
- mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE1_ADR);
- buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
- buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
- break;
- case S5P_FIMV_CODEC_MPEG2_DEC:
- break;
- default:
- mfc_err("Unknown codec for decoding (%x)\n",
- ctx->codec_mode);
- return -EINVAL;
- break;
- }
- frame_size = ctx->luma_size;
- frame_size_ch = ctx->chroma_size;
- frame_size_mv = ctx->mv_size;
- mfc_debug(2, "Frm size: %d ch: %d mv: %d\n", frame_size, frame_size_ch,
- frame_size_mv);
- for (i = 0; i < ctx->total_dpb_count; i++) {
- /* Bank2 */
- mfc_debug(2, "Luma %d: %x\n", i,
- ctx->dst_bufs[i].cookie.raw.luma);
- mfc_write(dev, OFFSETB(ctx->dst_bufs[i].cookie.raw.luma),
- S5P_FIMV_DEC_LUMA_ADR + i * 4);
- mfc_debug(2, "\tChroma %d: %x\n", i,
- ctx->dst_bufs[i].cookie.raw.chroma);
- mfc_write(dev, OFFSETA(ctx->dst_bufs[i].cookie.raw.chroma),
- S5P_FIMV_DEC_CHROMA_ADR + i * 4);
- if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC) {
- mfc_debug(2, "\tBuf2: %x, size: %d\n",
- buf_addr2, buf_size2);
- mfc_write(dev, OFFSETB(buf_addr2),
- S5P_FIMV_H264_MV_ADR + i * 4);
- buf_addr2 += frame_size_mv;
- buf_size2 -= frame_size_mv;
- }
- }
- mfc_debug(2, "Buf1: %u, buf_size1: %d\n", buf_addr1, buf_size1);
- mfc_debug(2, "Buf 1/2 size after: %d/%d (frames %d)\n",
- buf_size1, buf_size2, ctx->total_dpb_count);
- if (buf_size1 < 0 || buf_size2 < 0) {
- mfc_debug(2, "Not enough memory has been allocated\n");
- return -ENOMEM;
- }
- s5p_mfc_write_shm(ctx, frame_size, ALLOC_LUMA_DPB_SIZE);
- s5p_mfc_write_shm(ctx, frame_size_ch, ALLOC_CHROMA_DPB_SIZE);
- if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC)
- s5p_mfc_write_shm(ctx, frame_size_mv, ALLOC_MV_SIZE);
- mfc_write(dev, ((S5P_FIMV_CH_INIT_BUFS & S5P_FIMV_CH_MASK)
- << S5P_FIMV_CH_SHIFT) | (ctx->inst_no),
- S5P_FIMV_SI_CH0_INST_ID);
- return 0;
-}
-
-/* Set registers for encoding stream buffer */
-int s5p_mfc_set_enc_stream_buffer(struct s5p_mfc_ctx *ctx,
- unsigned long addr, unsigned int size)
-{
- struct s5p_mfc_dev *dev = ctx->dev;
-
- mfc_write(dev, OFFSETA(addr), S5P_FIMV_ENC_SI_CH0_SB_ADR);
- mfc_write(dev, size, S5P_FIMV_ENC_SI_CH0_SB_SIZE);
- return 0;
-}
-
-void s5p_mfc_set_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
- unsigned long y_addr, unsigned long c_addr)
-{
- struct s5p_mfc_dev *dev = ctx->dev;
-
- mfc_write(dev, OFFSETB(y_addr), S5P_FIMV_ENC_SI_CH0_CUR_Y_ADR);
- mfc_write(dev, OFFSETB(c_addr), S5P_FIMV_ENC_SI_CH0_CUR_C_ADR);
-}
-
-void s5p_mfc_get_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
- unsigned long *y_addr, unsigned long *c_addr)
-{
- struct s5p_mfc_dev *dev = ctx->dev;
-
- *y_addr = dev->bank2 + (mfc_read(dev, S5P_FIMV_ENCODED_Y_ADDR)
- << MFC_OFFSET_SHIFT);
- *c_addr = dev->bank2 + (mfc_read(dev, S5P_FIMV_ENCODED_C_ADDR)
- << MFC_OFFSET_SHIFT);
-}
-
-/* Set encoding ref & codec buffer */
-int s5p_mfc_set_enc_ref_buffer(struct s5p_mfc_ctx *ctx)
-{
- struct s5p_mfc_dev *dev = ctx->dev;
- size_t buf_addr1, buf_addr2;
- size_t buf_size1, buf_size2;
- unsigned int enc_ref_y_size, enc_ref_c_size;
- unsigned int guard_width, guard_height;
- int i;
-
- buf_addr1 = ctx->bank1_phys;
- buf_size1 = ctx->bank1_size;
- buf_addr2 = ctx->bank2_phys;
- buf_size2 = ctx->bank2_size;
- enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
- * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
- enc_ref_y_size = ALIGN(enc_ref_y_size, S5P_FIMV_NV12MT_SALIGN);
- if (ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC) {
- enc_ref_c_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
- * ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12MT_VALIGN);
- enc_ref_c_size = ALIGN(enc_ref_c_size, S5P_FIMV_NV12MT_SALIGN);
- } else {
- guard_width = ALIGN(ctx->img_width + 16,
- S5P_FIMV_NV12MT_HALIGN);
- guard_height = ALIGN((ctx->img_height >> 1) + 4,
- S5P_FIMV_NV12MT_VALIGN);
- enc_ref_c_size = ALIGN(guard_width * guard_height,
- S5P_FIMV_NV12MT_SALIGN);
- }
- mfc_debug(2, "buf_size1: %d, buf_size2: %d\n", buf_size1, buf_size2);
- switch (ctx->codec_mode) {
- case S5P_FIMV_CODEC_H264_ENC:
- for (i = 0; i < 2; i++) {
- mfc_write(dev, OFFSETA(buf_addr1),
- S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
- buf_addr1 += enc_ref_y_size;
- buf_size1 -= enc_ref_y_size;
-
- mfc_write(dev, OFFSETB(buf_addr2),
- S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
- buf_addr2 += enc_ref_y_size;
- buf_size2 -= enc_ref_y_size;
- }
- for (i = 0; i < 4; i++) {
- mfc_write(dev, OFFSETB(buf_addr2),
- S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
- buf_addr2 += enc_ref_c_size;
- buf_size2 -= enc_ref_c_size;
- }
- mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H264_UP_MV_ADR);
- buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
- buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
- mfc_write(dev, OFFSETA(buf_addr1),
- S5P_FIMV_H264_COZERO_FLAG_ADR);
- buf_addr1 += S5P_FIMV_ENC_COLFLG_SIZE;
- buf_size1 -= S5P_FIMV_ENC_COLFLG_SIZE;
- mfc_write(dev, OFFSETA(buf_addr1),
- S5P_FIMV_H264_UP_INTRA_MD_ADR);
- buf_addr1 += S5P_FIMV_ENC_INTRAMD_SIZE;
- buf_size1 -= S5P_FIMV_ENC_INTRAMD_SIZE;
- mfc_write(dev, OFFSETB(buf_addr2),
- S5P_FIMV_H264_UP_INTRA_PRED_ADR);
- buf_addr2 += S5P_FIMV_ENC_INTRAPRED_SIZE;
- buf_size2 -= S5P_FIMV_ENC_INTRAPRED_SIZE;
- mfc_write(dev, OFFSETA(buf_addr1),
- S5P_FIMV_H264_NBOR_INFO_ADR);
- buf_addr1 += S5P_FIMV_ENC_NBORINFO_SIZE;
- buf_size1 -= S5P_FIMV_ENC_NBORINFO_SIZE;
- mfc_debug(2, "buf_size1: %d, buf_size2: %d\n",
- buf_size1, buf_size2);
- break;
- case S5P_FIMV_CODEC_MPEG4_ENC:
- for (i = 0; i < 2; i++) {
- mfc_write(dev, OFFSETA(buf_addr1),
- S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
- buf_addr1 += enc_ref_y_size;
- buf_size1 -= enc_ref_y_size;
- mfc_write(dev, OFFSETB(buf_addr2),
- S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
- buf_addr2 += enc_ref_y_size;
- buf_size2 -= enc_ref_y_size;
- }
- for (i = 0; i < 4; i++) {
- mfc_write(dev, OFFSETB(buf_addr2),
- S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
- buf_addr2 += enc_ref_c_size;
- buf_size2 -= enc_ref_c_size;
- }
- mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_UP_MV_ADR);
- buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
- buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
- mfc_write(dev, OFFSETA(buf_addr1),
- S5P_FIMV_MPEG4_COZERO_FLAG_ADR);
- buf_addr1 += S5P_FIMV_ENC_COLFLG_SIZE;
- buf_size1 -= S5P_FIMV_ENC_COLFLG_SIZE;
- mfc_write(dev, OFFSETA(buf_addr1),
- S5P_FIMV_MPEG4_ACDC_COEF_ADR);
- buf_addr1 += S5P_FIMV_ENC_ACDCCOEF_SIZE;
- buf_size1 -= S5P_FIMV_ENC_ACDCCOEF_SIZE;
- mfc_debug(2, "buf_size1: %d, buf_size2: %d\n",
- buf_size1, buf_size2);
- break;
- case S5P_FIMV_CODEC_H263_ENC:
- for (i = 0; i < 2; i++) {
- mfc_write(dev, OFFSETA(buf_addr1),
- S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
- buf_addr1 += enc_ref_y_size;
- buf_size1 -= enc_ref_y_size;
- mfc_write(dev, OFFSETB(buf_addr2),
- S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
- buf_addr2 += enc_ref_y_size;
- buf_size2 -= enc_ref_y_size;
- }
- for (i = 0; i < 4; i++) {
- mfc_write(dev, OFFSETB(buf_addr2),
- S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
- buf_addr2 += enc_ref_c_size;
- buf_size2 -= enc_ref_c_size;
- }
- mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_UP_MV_ADR);
- buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
- buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
- mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_ACDC_COEF_ADR);
- buf_addr1 += S5P_FIMV_ENC_ACDCCOEF_SIZE;
- buf_size1 -= S5P_FIMV_ENC_ACDCCOEF_SIZE;
- mfc_debug(2, "buf_size1: %d, buf_size2: %d\n",
- buf_size1, buf_size2);
- break;
- default:
- mfc_err("Unknown codec set for encoding: %d\n",
- ctx->codec_mode);
- return -EINVAL;
- }
- return 0;
-}
-
-static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
-{
- struct s5p_mfc_dev *dev = ctx->dev;
- struct s5p_mfc_enc_params *p = &ctx->enc_params;
- unsigned int reg;
- unsigned int shm;
-
- /* width */
- mfc_write(dev, ctx->img_width, S5P_FIMV_ENC_HSIZE_PX);
- /* height */
- mfc_write(dev, ctx->img_height, S5P_FIMV_ENC_VSIZE_PX);
- /* pictype : enable, IDR period */
- reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
- reg |= (1 << 18);
- reg &= ~(0xFFFF);
- reg |= p->gop_size;
- mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
- mfc_write(dev, 0, S5P_FIMV_ENC_B_RECON_WRITE_ON);
- /* multi-slice control */
- /* multi-slice MB number or bit size */
- mfc_write(dev, p->slice_mode, S5P_FIMV_ENC_MSLICE_CTRL);
- if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) {
- mfc_write(dev, p->slice_mb, S5P_FIMV_ENC_MSLICE_MB);
- } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) {
- mfc_write(dev, p->slice_bit, S5P_FIMV_ENC_MSLICE_BIT);
- } else {
- mfc_write(dev, 0, S5P_FIMV_ENC_MSLICE_MB);
- mfc_write(dev, 0, S5P_FIMV_ENC_MSLICE_BIT);
- }
- /* cyclic intra refresh */
- mfc_write(dev, p->intra_refresh_mb, S5P_FIMV_ENC_CIR_CTRL);
- /* memory structure cur. frame */
- if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M)
- mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR);
- else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT)
- mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR);
- /* padding control & value */
- reg = mfc_read(dev, S5P_FIMV_ENC_PADDING_CTRL);
- if (p->pad) {
- /** enable */
- reg |= (1 << 31);
- /** cr value */
- reg &= ~(0xFF << 16);
- reg |= (p->pad_cr << 16);
- /** cb value */
- reg &= ~(0xFF << 8);
- reg |= (p->pad_cb << 8);
- /** y value */
- reg &= ~(0xFF);
- reg |= (p->pad_luma);
- } else {
- /** disable & all value clear */
- reg = 0;
- }
- mfc_write(dev, reg, S5P_FIMV_ENC_PADDING_CTRL);
- /* rate control config. */
- reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
- /** frame-level rate control */
- reg &= ~(0x1 << 9);
- reg |= (p->rc_frame << 9);
- mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
- /* bit rate */
- if (p->rc_frame)
- mfc_write(dev, p->rc_bitrate,
- S5P_FIMV_ENC_RC_BIT_RATE);
- else
- mfc_write(dev, 0, S5P_FIMV_ENC_RC_BIT_RATE);
- /* reaction coefficient */
- if (p->rc_frame)
- mfc_write(dev, p->rc_reaction_coeff, S5P_FIMV_ENC_RC_RPARA);
- shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
- /* seq header ctrl */
- shm &= ~(0x1 << 3);
- shm |= (p->seq_hdr_mode << 3);
- /* frame skip mode */
- shm &= ~(0x3 << 1);
- shm |= (p->frame_skip_mode << 1);
- s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
- /* fixed target bit */
- s5p_mfc_write_shm(ctx, p->fixed_target_bit, RC_CONTROL_CONFIG);
- return 0;
-}
-
-static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
-{
- struct s5p_mfc_dev *dev = ctx->dev;
- struct s5p_mfc_enc_params *p = &ctx->enc_params;
- struct s5p_mfc_h264_enc_params *p_264 = &p->codec.h264;
- unsigned int reg;
- unsigned int shm;
-
- s5p_mfc_set_enc_params(ctx);
- /* pictype : number of B */
- reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
- /* num_b_frame - 0 ~ 2 */
- reg &= ~(0x3 << 16);
- reg |= (p->num_b_frame << 16);
- mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
- /* profile & level */
- reg = mfc_read(dev, S5P_FIMV_ENC_PROFILE);
- /* level */
- reg &= ~(0xFF << 8);
- reg |= (p_264->level << 8);
- /* profile - 0 ~ 2 */
- reg &= ~(0x3F);
- reg |= p_264->profile;
- mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE);
- /* interlace */
- mfc_write(dev, p->interlace, S5P_FIMV_ENC_PIC_STRUCT);
- /* height */
- if (p->interlace)
- mfc_write(dev, ctx->img_height >> 1, S5P_FIMV_ENC_VSIZE_PX);
- /* loopfilter ctrl */
- mfc_write(dev, p_264->loop_filter_mode, S5P_FIMV_ENC_LF_CTRL);
- /* loopfilter alpha offset */
- if (p_264->loop_filter_alpha < 0) {
- reg = 0x10;
- reg |= (0xFF - p_264->loop_filter_alpha) + 1;
- } else {
- reg = 0x00;
- reg |= (p_264->loop_filter_alpha & 0xF);
- }
- mfc_write(dev, reg, S5P_FIMV_ENC_ALPHA_OFF);
- /* loopfilter beta offset */
- if (p_264->loop_filter_beta < 0) {
- reg = 0x10;
- reg |= (0xFF - p_264->loop_filter_beta) + 1;
- } else {
- reg = 0x00;
- reg |= (p_264->loop_filter_beta & 0xF);
- }
- mfc_write(dev, reg, S5P_FIMV_ENC_BETA_OFF);
- /* entropy coding mode */
- if (p_264->entropy_mode == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC)
- mfc_write(dev, 1, S5P_FIMV_ENC_H264_ENTROPY_MODE);
- else
- mfc_write(dev, 0, S5P_FIMV_ENC_H264_ENTROPY_MODE);
- /* number of ref. picture */
- reg = mfc_read(dev, S5P_FIMV_ENC_H264_NUM_OF_REF);
- /* num of ref. pictures of P */
- reg &= ~(0x3 << 5);
- reg |= (p_264->num_ref_pic_4p << 5);
- /* max number of ref. pictures */
- reg &= ~(0x1F);
- reg |= p_264->max_ref_pic;
- mfc_write(dev, reg, S5P_FIMV_ENC_H264_NUM_OF_REF);
- /* 8x8 transform enable */
- mfc_write(dev, p_264->_8x8_transform, S5P_FIMV_ENC_H264_TRANS_FLAG);
- /* rate control config. */
- reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
- /* macroblock level rate control */
- reg &= ~(0x1 << 8);
- reg |= (p_264->rc_mb << 8);
- /* frame QP */
- reg &= ~(0x3F);
- reg |= p_264->rc_frame_qp;
- mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
- /* frame rate */
- if (p->rc_frame && p->rc_framerate_denom)
- mfc_write(dev, p->rc_framerate_num * 1000
- / p->rc_framerate_denom, S5P_FIMV_ENC_RC_FRAME_RATE);
- else
- mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
- /* max & min value of QP */
- reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
- /* max QP */
- reg &= ~(0x3F << 8);
- reg |= (p_264->rc_max_qp << 8);
- /* min QP */
- reg &= ~(0x3F);
- reg |= p_264->rc_min_qp;
- mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
- /* macroblock adaptive scaling features */
- if (p_264->rc_mb) {
- reg = mfc_read(dev, S5P_FIMV_ENC_RC_MB_CTRL);
- /* dark region */
- reg &= ~(0x1 << 3);
- reg |= (p_264->rc_mb_dark << 3);
- /* smooth region */
- reg &= ~(0x1 << 2);
- reg |= (p_264->rc_mb_smooth << 2);
- /* static region */
- reg &= ~(0x1 << 1);
- reg |= (p_264->rc_mb_static << 1);
- /* high activity region */
- reg &= ~(0x1);
- reg |= p_264->rc_mb_activity;
- mfc_write(dev, reg, S5P_FIMV_ENC_RC_MB_CTRL);
- }
- if (!p->rc_frame &&
- !p_264->rc_mb) {
- shm = s5p_mfc_read_shm(ctx, P_B_FRAME_QP);
- shm &= ~(0xFFF);
- shm |= ((p_264->rc_b_frame_qp & 0x3F) << 6);
- shm |= (p_264->rc_p_frame_qp & 0x3F);
- s5p_mfc_write_shm(ctx, shm, P_B_FRAME_QP);
- }
- /* extended encoder ctrl */
- shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
- /* AR VUI control */
- shm &= ~(0x1 << 15);
- shm |= (p_264->vui_sar << 1);
- s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
- if (p_264->vui_sar) {
- /* aspect ration IDC */
- shm = s5p_mfc_read_shm(ctx, SAMPLE_ASPECT_RATIO_IDC);
- shm &= ~(0xFF);
- shm |= p_264->vui_sar_idc;
- s5p_mfc_write_shm(ctx, shm, SAMPLE_ASPECT_RATIO_IDC);
- if (p_264->vui_sar_idc == 0xFF) {
- /* sample AR info */
- shm = s5p_mfc_read_shm(ctx, EXTENDED_SAR);
- shm &= ~(0xFFFFFFFF);
- shm |= p_264->vui_ext_sar_width << 16;
- shm |= p_264->vui_ext_sar_height;
- s5p_mfc_write_shm(ctx, shm, EXTENDED_SAR);
- }
- }
- /* intra picture period for H.264 */
- shm = s5p_mfc_read_shm(ctx, H264_I_PERIOD);
- /* control */
- shm &= ~(0x1 << 16);
- shm |= (p_264->open_gop << 16);
- /* value */
- if (p_264->open_gop) {
- shm &= ~(0xFFFF);
- shm |= p_264->open_gop_size;
- }
- s5p_mfc_write_shm(ctx, shm, H264_I_PERIOD);
- /* extended encoder ctrl */
- shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
- /* vbv buffer size */
- if (p->frame_skip_mode ==
- V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
- shm &= ~(0xFFFF << 16);
- shm |= (p_264->cpb_size << 16);
- }
- s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
- return 0;
-}
-
-static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
-{
- struct s5p_mfc_dev *dev = ctx->dev;
- struct s5p_mfc_enc_params *p = &ctx->enc_params;
- struct s5p_mfc_mpeg4_enc_params *p_mpeg4 = &p->codec.mpeg4;
- unsigned int reg;
- unsigned int shm;
- unsigned int framerate;
-
- s5p_mfc_set_enc_params(ctx);
- /* pictype : number of B */
- reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
- /* num_b_frame - 0 ~ 2 */
- reg &= ~(0x3 << 16);
- reg |= (p->num_b_frame << 16);
- mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
- /* profile & level */
- reg = mfc_read(dev, S5P_FIMV_ENC_PROFILE);
- /* level */
- reg &= ~(0xFF << 8);
- reg |= (p_mpeg4->level << 8);
- /* profile - 0 ~ 2 */
- reg &= ~(0x3F);
- reg |= p_mpeg4->profile;
- mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE);
- /* quarter_pixel */
- mfc_write(dev, p_mpeg4->quarter_pixel, S5P_FIMV_ENC_MPEG4_QUART_PXL);
- /* qp */
- if (!p->rc_frame) {
- shm = s5p_mfc_read_shm(ctx, P_B_FRAME_QP);
- shm &= ~(0xFFF);
- shm |= ((p_mpeg4->rc_b_frame_qp & 0x3F) << 6);
- shm |= (p_mpeg4->rc_p_frame_qp & 0x3F);
- s5p_mfc_write_shm(ctx, shm, P_B_FRAME_QP);
- }
- /* frame rate */
- if (p->rc_frame) {
- if (p->rc_framerate_denom > 0) {
- framerate = p->rc_framerate_num * 1000 /
- p->rc_framerate_denom;
- mfc_write(dev, framerate,
- S5P_FIMV_ENC_RC_FRAME_RATE);
- shm = s5p_mfc_read_shm(ctx, RC_VOP_TIMING);
- shm &= ~(0xFFFFFFFF);
- shm |= (1 << 31);
- shm |= ((p->rc_framerate_num & 0x7FFF) << 16);
- shm |= (p->rc_framerate_denom & 0xFFFF);
- s5p_mfc_write_shm(ctx, shm, RC_VOP_TIMING);
- }
- } else {
- mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
- }
- /* rate control config. */
- reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
- /* frame QP */
- reg &= ~(0x3F);
- reg |= p_mpeg4->rc_frame_qp;
- mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
- /* max & min value of QP */
- reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
- /* max QP */
- reg &= ~(0x3F << 8);
- reg |= (p_mpeg4->rc_max_qp << 8);
- /* min QP */
- reg &= ~(0x3F);
- reg |= p_mpeg4->rc_min_qp;
- mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
- /* extended encoder ctrl */
- shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
- /* vbv buffer size */
- if (p->frame_skip_mode ==
- V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
- shm &= ~(0xFFFF << 16);
- shm |= (p->vbv_size << 16);
- }
- s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
- return 0;
+ s5p_mfc_ops = s5p_mfc_init_hw_ops_v5();
+ dev->warn_start = S5P_FIMV_ERR_WARNINGS_START;
+ dev->mfc_ops = s5p_mfc_ops;
}
-
-static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)
-{
- struct s5p_mfc_dev *dev = ctx->dev;
- struct s5p_mfc_enc_params *p = &ctx->enc_params;
- struct s5p_mfc_mpeg4_enc_params *p_h263 = &p->codec.mpeg4;
- unsigned int reg;
- unsigned int shm;
-
- s5p_mfc_set_enc_params(ctx);
- /* qp */
- if (!p->rc_frame) {
- shm = s5p_mfc_read_shm(ctx, P_B_FRAME_QP);
- shm &= ~(0xFFF);
- shm |= (p_h263->rc_p_frame_qp & 0x3F);
- s5p_mfc_write_shm(ctx, shm, P_B_FRAME_QP);
- }
- /* frame rate */
- if (p->rc_frame && p->rc_framerate_denom)
- mfc_write(dev, p->rc_framerate_num * 1000
- / p->rc_framerate_denom, S5P_FIMV_ENC_RC_FRAME_RATE);
- else
- mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
- /* rate control config. */
- reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
- /* frame QP */
- reg &= ~(0x3F);
- reg |= p_h263->rc_frame_qp;
- mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
- /* max & min value of QP */
- reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
- /* max QP */
- reg &= ~(0x3F << 8);
- reg |= (p_h263->rc_max_qp << 8);
- /* min QP */
- reg &= ~(0x3F);
- reg |= p_h263->rc_min_qp;
- mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
- /* extended encoder ctrl */
- shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
- /* vbv buffer size */
- if (p->frame_skip_mode ==
- V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
- shm &= ~(0xFFFF << 16);
- shm |= (p->vbv_size << 16);
- }
- s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
- return 0;
-}
-
-/* Initialize decoding */
-int s5p_mfc_init_decode(struct s5p_mfc_ctx *ctx)
-{
- struct s5p_mfc_dev *dev = ctx->dev;
-
- s5p_mfc_set_shared_buffer(ctx);
- /* Setup loop filter, for decoding this is only valid for MPEG4 */
- if (ctx->codec_mode == S5P_FIMV_CODEC_MPEG4_DEC)
- mfc_write(dev, ctx->loop_filter_mpeg4, S5P_FIMV_ENC_LF_CTRL);
- else
- mfc_write(dev, 0, S5P_FIMV_ENC_LF_CTRL);
- mfc_write(dev, ((ctx->slice_interface & S5P_FIMV_SLICE_INT_MASK) <<
- S5P_FIMV_SLICE_INT_SHIFT) | (ctx->display_delay_enable <<
- S5P_FIMV_DDELAY_ENA_SHIFT) | ((ctx->display_delay &
- S5P_FIMV_DDELAY_VAL_MASK) << S5P_FIMV_DDELAY_VAL_SHIFT),
- S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
- mfc_write(dev,
- ((S5P_FIMV_CH_SEQ_HEADER & S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT)
- | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
- return 0;
-}
-
-static void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush)
-{
- struct s5p_mfc_dev *dev = ctx->dev;
- unsigned int dpb;
-
- if (flush)
- dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) | (
- S5P_FIMV_DPB_FLUSH_MASK << S5P_FIMV_DPB_FLUSH_SHIFT);
- else
- dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) &
- ~(S5P_FIMV_DPB_FLUSH_MASK << S5P_FIMV_DPB_FLUSH_SHIFT);
- mfc_write(dev, dpb, S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
-}
-
-/* Decode a single frame */
-int s5p_mfc_decode_one_frame(struct s5p_mfc_ctx *ctx,
- enum s5p_mfc_decode_arg last_frame)
-{
- struct s5p_mfc_dev *dev = ctx->dev;
-
- mfc_write(dev, ctx->dec_dst_flag, S5P_FIMV_SI_CH0_RELEASE_BUF);
- s5p_mfc_set_shared_buffer(ctx);
- s5p_mfc_set_flush(ctx, ctx->dpb_flush_flag);
- /* Issue different commands to instance basing on whether it
- * is the last frame or not. */
- switch (last_frame) {
- case MFC_DEC_FRAME:
- mfc_write(dev, ((S5P_FIMV_CH_FRAME_START & S5P_FIMV_CH_MASK) <<
- S5P_FIMV_CH_SHIFT) | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
- break;
- case MFC_DEC_LAST_FRAME:
- mfc_write(dev, ((S5P_FIMV_CH_LAST_FRAME & S5P_FIMV_CH_MASK) <<
- S5P_FIMV_CH_SHIFT) | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
- break;
- case MFC_DEC_RES_CHANGE:
- mfc_write(dev, ((S5P_FIMV_CH_FRAME_START_REALLOC &
- S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT) | (ctx->inst_no),
- S5P_FIMV_SI_CH0_INST_ID);
- break;
- }
- mfc_debug(2, "Decoding a usual frame\n");
- return 0;
-}
-
-int s5p_mfc_init_encode(struct s5p_mfc_ctx *ctx)
-{
- struct s5p_mfc_dev *dev = ctx->dev;
-
- if (ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC)
- s5p_mfc_set_enc_params_h264(ctx);
- else if (ctx->codec_mode == S5P_FIMV_CODEC_MPEG4_ENC)
- s5p_mfc_set_enc_params_mpeg4(ctx);
- else if (ctx->codec_mode == S5P_FIMV_CODEC_H263_ENC)
- s5p_mfc_set_enc_params_h263(ctx);
- else {
- mfc_err("Unknown codec for encoding (%x)\n",
- ctx->codec_mode);
- return -EINVAL;
- }
- s5p_mfc_set_shared_buffer(ctx);
- mfc_write(dev, ((S5P_FIMV_CH_SEQ_HEADER << 16) & 0x70000) |
- (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
- return 0;
-}
-
-/* Encode a single frame */
-int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *ctx)
-{
- struct s5p_mfc_dev *dev = ctx->dev;
- /* memory structure cur. frame */
- if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M)
- mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR);
- else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT)
- mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR);
- s5p_mfc_set_shared_buffer(ctx);
- mfc_write(dev, (S5P_FIMV_CH_FRAME_START << 16 & 0x70000) |
- (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
- return 0;
-}
-
-static int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev)
-{
- unsigned long flags;
- int new_ctx;
- int cnt;
-
- spin_lock_irqsave(&dev->condlock, flags);
- new_ctx = (dev->curr_ctx + 1) % MFC_NUM_CONTEXTS;
- cnt = 0;
- while (!test_bit(new_ctx, &dev->ctx_work_bits)) {
- new_ctx = (new_ctx + 1) % MFC_NUM_CONTEXTS;
- if (++cnt > MFC_NUM_CONTEXTS) {
- /* No contexts to run */
- spin_unlock_irqrestore(&dev->condlock, flags);
- return -EAGAIN;
- }
- }
- spin_unlock_irqrestore(&dev->condlock, flags);
- return new_ctx;
-}
-
-static void s5p_mfc_run_res_change(struct s5p_mfc_ctx *ctx)
-{
- struct s5p_mfc_dev *dev = ctx->dev;
-
- s5p_mfc_set_dec_stream_buffer(ctx, 0, 0, 0);
- dev->curr_ctx = ctx->num;
- s5p_mfc_clean_ctx_int_flags(ctx);
- s5p_mfc_decode_one_frame(ctx, MFC_DEC_RES_CHANGE);
-}
-
-static int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx, int last_frame)
-{
- struct s5p_mfc_dev *dev = ctx->dev;
- struct s5p_mfc_buf *temp_vb;
- unsigned long flags;
- unsigned int index;
-
- spin_lock_irqsave(&dev->irqlock, flags);
- /* Frames are being decoded */
- if (list_empty(&ctx->src_queue)) {
- mfc_debug(2, "No src buffers\n");
- spin_unlock_irqrestore(&dev->irqlock, flags);
- return -EAGAIN;
- }
- /* Get the next source buffer */
- temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
- temp_vb->used = 1;
- s5p_mfc_set_dec_stream_buffer(ctx,
- vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), ctx->consumed_stream,
- temp_vb->b->v4l2_planes[0].bytesused);
- spin_unlock_irqrestore(&dev->irqlock, flags);
- index = temp_vb->b->v4l2_buf.index;
- dev->curr_ctx = ctx->num;
- s5p_mfc_clean_ctx_int_flags(ctx);
- if (temp_vb->b->v4l2_planes[0].bytesused == 0) {
- last_frame = MFC_DEC_LAST_FRAME;
- mfc_debug(2, "Setting ctx->state to FINISHING\n");
- ctx->state = MFCINST_FINISHING;
- }
- s5p_mfc_decode_one_frame(ctx, last_frame);
- return 0;
-}
-
-static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
-{
- struct s5p_mfc_dev *dev = ctx->dev;
- unsigned long flags;
- struct s5p_mfc_buf *dst_mb;
- struct s5p_mfc_buf *src_mb;
- unsigned long src_y_addr, src_c_addr, dst_addr;
- unsigned int dst_size;
-
- spin_lock_irqsave(&dev->irqlock, flags);
- if (list_empty(&ctx->src_queue)) {
- mfc_debug(2, "no src buffers\n");
- spin_unlock_irqrestore(&dev->irqlock, flags);
- return -EAGAIN;
- }
- if (list_empty(&ctx->dst_queue)) {
- mfc_debug(2, "no dst buffers\n");
- spin_unlock_irqrestore(&dev->irqlock, flags);
- return -EAGAIN;
- }
- src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
- src_mb->used = 1;
- src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 0);
- src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1);
- s5p_mfc_set_enc_frame_buffer(ctx, src_y_addr, src_c_addr);
- dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
- dst_mb->used = 1;
- dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
- dst_size = vb2_plane_size(dst_mb->b, 0);
- s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
- spin_unlock_irqrestore(&dev->irqlock, flags);
- dev->curr_ctx = ctx->num;
- s5p_mfc_clean_ctx_int_flags(ctx);
- s5p_mfc_encode_one_frame(ctx);
- return 0;
-}
-
-static void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx)
-{
- struct s5p_mfc_dev *dev = ctx->dev;
- unsigned long flags;
- struct s5p_mfc_buf *temp_vb;
-
- /* Initializing decoding - parsing header */
- spin_lock_irqsave(&dev->irqlock, flags);
- mfc_debug(2, "Preparing to init decoding\n");
- temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
- s5p_mfc_set_dec_desc_buffer(ctx);
- mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused);
- s5p_mfc_set_dec_stream_buffer(ctx,
- vb2_dma_contig_plane_dma_addr(temp_vb->b, 0),
- 0, temp_vb->b->v4l2_planes[0].bytesused);
- spin_unlock_irqrestore(&dev->irqlock, flags);
- dev->curr_ctx = ctx->num;
- s5p_mfc_clean_ctx_int_flags(ctx);
- s5p_mfc_init_decode(ctx);
-}
-
-static void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx)
-{
- struct s5p_mfc_dev *dev = ctx->dev;
- unsigned long flags;
- struct s5p_mfc_buf *dst_mb;
- unsigned long dst_addr;
- unsigned int dst_size;
-
- s5p_mfc_set_enc_ref_buffer(ctx);
- spin_lock_irqsave(&dev->irqlock, flags);
- dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
- dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
- dst_size = vb2_plane_size(dst_mb->b, 0);
- s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
- spin_unlock_irqrestore(&dev->irqlock, flags);
- dev->curr_ctx = ctx->num;
- s5p_mfc_clean_ctx_int_flags(ctx);
- s5p_mfc_init_encode(ctx);
-}
-
-static int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx)
-{
- struct s5p_mfc_dev *dev = ctx->dev;
- unsigned long flags;
- struct s5p_mfc_buf *temp_vb;
- int ret;
-
- /*
- * Header was parsed now starting processing
- * First set the output frame buffers
- */
- if (ctx->capture_state != QUEUE_BUFS_MMAPED) {
- mfc_err("It seems that not all destionation buffers were "
- "mmaped\nMFC requires that all destination are mmaped "
- "before starting processing\n");
- return -EAGAIN;
- }
- spin_lock_irqsave(&dev->irqlock, flags);
- if (list_empty(&ctx->src_queue)) {
- mfc_err("Header has been deallocated in the middle of"
- " initialization\n");
- spin_unlock_irqrestore(&dev->irqlock, flags);
- return -EIO;
- }
- temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
- mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused);
- s5p_mfc_set_dec_stream_buffer(ctx,
- vb2_dma_contig_plane_dma_addr(temp_vb->b, 0),
- 0, temp_vb->b->v4l2_planes[0].bytesused);
- spin_unlock_irqrestore(&dev->irqlock, flags);
- dev->curr_ctx = ctx->num;
- s5p_mfc_clean_ctx_int_flags(ctx);
- ret = s5p_mfc_set_dec_frame_buffer(ctx);
- if (ret) {
- mfc_err("Failed to alloc frame mem\n");
- ctx->state = MFCINST_ERROR;
- }
- return ret;
-}
-
-/* Try running an operation on hardware */
-void s5p_mfc_try_run(struct s5p_mfc_dev *dev)
-{
- struct s5p_mfc_ctx *ctx;
- int new_ctx;
- unsigned int ret = 0;
-
- if (test_bit(0, &dev->enter_suspend)) {
- mfc_debug(1, "Entering suspend so do not schedule any jobs\n");
- return;
- }
- /* Check whether hardware is not running */
- if (test_and_set_bit(0, &dev->hw_lock) != 0) {
- /* This is perfectly ok, the scheduled ctx should wait */
- mfc_debug(1, "Couldn't lock HW\n");
- return;
- }
- /* Choose the context to run */
- new_ctx = s5p_mfc_get_new_ctx(dev);
- if (new_ctx < 0) {
- /* No contexts to run */
- if (test_and_clear_bit(0, &dev->hw_lock) == 0) {
- mfc_err("Failed to unlock hardware\n");
- return;
- }
- mfc_debug(1, "No ctx is scheduled to be run\n");
- return;
- }
- ctx = dev->ctx[new_ctx];
- /* Got context to run in ctx */
- /*
- * Last frame has already been sent to MFC.
- * Now obtaining frames from MFC buffer
- */
- s5p_mfc_clock_on();
- if (ctx->type == MFCINST_DECODER) {
- s5p_mfc_set_dec_desc_buffer(ctx);
- switch (ctx->state) {
- case MFCINST_FINISHING:
- s5p_mfc_run_dec_frame(ctx, MFC_DEC_LAST_FRAME);
- break;
- case MFCINST_RUNNING:
- ret = s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME);
- break;
- case MFCINST_INIT:
- s5p_mfc_clean_ctx_int_flags(ctx);
- ret = s5p_mfc_open_inst_cmd(ctx);
- break;
- case MFCINST_RETURN_INST:
- s5p_mfc_clean_ctx_int_flags(ctx);
- ret = s5p_mfc_close_inst_cmd(ctx);
- break;
- case MFCINST_GOT_INST:
- s5p_mfc_run_init_dec(ctx);
- break;
- case MFCINST_HEAD_PARSED:
- ret = s5p_mfc_run_init_dec_buffers(ctx);
- mfc_debug(1, "head parsed\n");
- break;
- case MFCINST_RES_CHANGE_INIT:
- s5p_mfc_run_res_change(ctx);
- break;
- case MFCINST_RES_CHANGE_FLUSH:
- s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME);
- break;
- case MFCINST_RES_CHANGE_END:
- mfc_debug(2, "Finished remaining frames after resolution change\n");
- ctx->capture_state = QUEUE_FREE;
- mfc_debug(2, "Will re-init the codec\n");
- s5p_mfc_run_init_dec(ctx);
- break;
- default:
- ret = -EAGAIN;
- }
- } else if (ctx->type == MFCINST_ENCODER) {
- switch (ctx->state) {
- case MFCINST_FINISHING:
- case MFCINST_RUNNING:
- ret = s5p_mfc_run_enc_frame(ctx);
- break;
- case MFCINST_INIT:
- s5p_mfc_clean_ctx_int_flags(ctx);
- ret = s5p_mfc_open_inst_cmd(ctx);
- break;
- case MFCINST_RETURN_INST:
- s5p_mfc_clean_ctx_int_flags(ctx);
- ret = s5p_mfc_close_inst_cmd(ctx);
- break;
- case MFCINST_GOT_INST:
- s5p_mfc_run_init_enc(ctx);
- break;
- default:
- ret = -EAGAIN;
- }
- } else {
- mfc_err("Invalid context type: %d\n", ctx->type);
- ret = -EAGAIN;
- }
-
- if (ret) {
- /* Free hardware lock */
- if (test_and_clear_bit(0, &dev->hw_lock) == 0)
- mfc_err("Failed to unlock hardware\n");
-
- /* This is in deed imporant, as no operation has been
- * scheduled, reduce the clock count as no one will
- * ever do this, because no interrupt related to this try_run
- * will ever come from hardware. */
- s5p_mfc_clock_off();
- }
-}
-
-
-void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq)
-{
- struct s5p_mfc_buf *b;
- int i;
-
- while (!list_empty(lh)) {
- b = list_entry(lh->next, struct s5p_mfc_buf, list);
- for (i = 0; i < b->b->num_planes; i++)
- vb2_set_plane_payload(b->b, i, 0);
- vb2_buffer_done(b->b, VB2_BUF_STATE_ERROR);
- list_del(&b->list);
- }
-}
-
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
index 2ad3def..47a91f5 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
@@ -17,77 +17,68 @@
#include "s5p_mfc_common.h"
-int s5p_mfc_init_decode(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_init_encode(struct s5p_mfc_ctx *mfc_ctx);
+struct s5p_mfc_hw_ops {
+ int (*alloc_dec_temp_buffers)(struct s5p_mfc_ctx *ctx);
+ void (*release_dec_desc_buffer)(struct s5p_mfc_ctx *ctx);
+ int (*alloc_codec_buffers)(struct s5p_mfc_ctx *ctx);
+ void (*release_codec_buffers)(struct s5p_mfc_ctx *ctx);
+ int (*alloc_instance_buffer)(struct s5p_mfc_ctx *ctx);
+ void (*release_instance_buffer)(struct s5p_mfc_ctx *ctx);
+ int (*alloc_dev_context_buffer)(struct s5p_mfc_dev *dev);
+ void (*release_dev_context_buffer)(struct s5p_mfc_dev *dev);
+ void (*dec_calc_dpb_size)(struct s5p_mfc_ctx *ctx);
+ void (*enc_calc_src_size)(struct s5p_mfc_ctx *ctx);
+ int (*set_dec_stream_buffer)(struct s5p_mfc_ctx *ctx,
+ int buf_addr, unsigned int start_num_byte,
+ unsigned int buf_size);
+ int (*set_dec_frame_buffer)(struct s5p_mfc_ctx *ctx);
+ int (*set_enc_stream_buffer)(struct s5p_mfc_ctx *ctx,
+ unsigned long addr, unsigned int size);
+ void (*set_enc_frame_buffer)(struct s5p_mfc_ctx *ctx,
+ unsigned long y_addr, unsigned long c_addr);
+ void (*get_enc_frame_buffer)(struct s5p_mfc_ctx *ctx,
+ unsigned long *y_addr, unsigned long *c_addr);
+ int (*set_enc_ref_buffer)(struct s5p_mfc_ctx *ctx);
+ int (*init_decode)(struct s5p_mfc_ctx *ctx);
+ int (*init_encode)(struct s5p_mfc_ctx *ctx);
+ int (*encode_one_frame)(struct s5p_mfc_ctx *ctx);
+ void (*try_run)(struct s5p_mfc_dev *dev);
+ void (*cleanup_queue)(struct list_head *lh,
+ struct vb2_queue *vq);
+ void (*clear_int_flags)(struct s5p_mfc_dev *dev);
+ void (*write_info)(struct s5p_mfc_ctx *ctx, unsigned int data,
+ unsigned int ofs);
+ unsigned int (*read_info)(struct s5p_mfc_ctx *ctx,
+ unsigned int ofs);
+ int (*get_dspl_y_adr)(struct s5p_mfc_dev *dev);
+ int (*get_dec_y_adr)(struct s5p_mfc_dev *dev);
+ int (*get_dspl_status)(struct s5p_mfc_dev *dev);
+ int (*get_dec_status)(struct s5p_mfc_dev *dev);
+ int (*get_dec_frame_type)(struct s5p_mfc_dev *dev);
+ int (*get_disp_frame_type)(struct s5p_mfc_ctx *ctx);
+ int (*get_consumed_stream)(struct s5p_mfc_dev *dev);
+ int (*get_int_reason)(struct s5p_mfc_dev *dev);
+ int (*get_int_err)(struct s5p_mfc_dev *dev);
+ int (*err_dec)(unsigned int err);
+ int (*err_dspl)(unsigned int err);
+ int (*get_img_width)(struct s5p_mfc_dev *dev);
+ int (*get_img_height)(struct s5p_mfc_dev *dev);
+ int (*get_dpb_count)(struct s5p_mfc_dev *dev);
+ int (*get_mv_count)(struct s5p_mfc_dev *dev);
+ int (*get_inst_no)(struct s5p_mfc_dev *dev);
+ int (*get_enc_strm_size)(struct s5p_mfc_dev *dev);
+ int (*get_enc_slice_type)(struct s5p_mfc_dev *dev);
+ int (*get_enc_dpb_count)(struct s5p_mfc_dev *dev);
+ int (*get_enc_pic_count)(struct s5p_mfc_dev *dev);
+ int (*get_sei_avail_status)(struct s5p_mfc_ctx *ctx);
+ int (*get_mvc_num_views)(struct s5p_mfc_dev *dev);
+ int (*get_mvc_view_id)(struct s5p_mfc_dev *dev);
+ unsigned int (*get_pic_type_top)(struct s5p_mfc_ctx *ctx);
+ unsigned int (*get_pic_type_bot)(struct s5p_mfc_ctx *ctx);
+ unsigned int (*get_crop_info_h)(struct s5p_mfc_ctx *ctx);
+ unsigned int (*get_crop_info_v)(struct s5p_mfc_ctx *ctx);
+};
-/* Decoding functions */
-int s5p_mfc_set_dec_frame_buffer(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_set_dec_stream_buffer(struct s5p_mfc_ctx *ctx, int buf_addr,
- unsigned int start_num_byte,
- unsigned int buf_size);
-
-/* Encoding functions */
-void s5p_mfc_set_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
- unsigned long y_addr, unsigned long c_addr);
-int s5p_mfc_set_enc_stream_buffer(struct s5p_mfc_ctx *ctx,
- unsigned long addr, unsigned int size);
-void s5p_mfc_get_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
- unsigned long *y_addr, unsigned long *c_addr);
-int s5p_mfc_set_enc_ref_buffer(struct s5p_mfc_ctx *mfc_ctx);
-
-int s5p_mfc_decode_one_frame(struct s5p_mfc_ctx *ctx,
- enum s5p_mfc_decode_arg last_frame);
-int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *mfc_ctx);
-
-/* Memory allocation */
-int s5p_mfc_alloc_dec_temp_buffers(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_set_dec_desc_buffer(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_release_dec_desc_buffer(struct s5p_mfc_ctx *ctx);
-
-int s5p_mfc_alloc_codec_buffers(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_release_codec_buffers(struct s5p_mfc_ctx *ctx);
-
-int s5p_mfc_alloc_instance_buffer(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_release_instance_buffer(struct s5p_mfc_ctx *ctx);
-
-void s5p_mfc_try_run(struct s5p_mfc_dev *dev);
-void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq);
-
-#define s5p_mfc_get_dspl_y_adr() (readl(dev->regs_base + \
- S5P_FIMV_SI_DISPLAY_Y_ADR) << \
- MFC_OFFSET_SHIFT)
-#define s5p_mfc_get_dec_y_adr() (readl(dev->regs_base + \
- S5P_FIMV_SI_DECODE_Y_ADR) << \
- MFC_OFFSET_SHIFT)
-#define s5p_mfc_get_dspl_status() readl(dev->regs_base + \
- S5P_FIMV_SI_DISPLAY_STATUS)
-#define s5p_mfc_get_dec_status() readl(dev->regs_base + \
- S5P_FIMV_SI_DECODE_STATUS)
-#define s5p_mfc_get_frame_type() (readl(dev->regs_base + \
- S5P_FIMV_DECODE_FRAME_TYPE) \
- & S5P_FIMV_DECODE_FRAME_MASK)
-#define s5p_mfc_get_consumed_stream() readl(dev->regs_base + \
- S5P_FIMV_SI_CONSUMED_BYTES)
-#define s5p_mfc_get_int_reason() (readl(dev->regs_base + \
- S5P_FIMV_RISC2HOST_CMD) & \
- S5P_FIMV_RISC2HOST_CMD_MASK)
-#define s5p_mfc_get_int_err() readl(dev->regs_base + \
- S5P_FIMV_RISC2HOST_ARG2)
-#define s5p_mfc_err_dec(x) (((x) & S5P_FIMV_ERR_DEC_MASK) >> \
- S5P_FIMV_ERR_DEC_SHIFT)
-#define s5p_mfc_err_dspl(x) (((x) & S5P_FIMV_ERR_DSPL_MASK) >> \
- S5P_FIMV_ERR_DSPL_SHIFT)
-#define s5p_mfc_get_img_width() readl(dev->regs_base + \
- S5P_FIMV_SI_HRESOL)
-#define s5p_mfc_get_img_height() readl(dev->regs_base + \
- S5P_FIMV_SI_VRESOL)
-#define s5p_mfc_get_dpb_count() readl(dev->regs_base + \
- S5P_FIMV_SI_BUF_NUMBER)
-#define s5p_mfc_get_inst_no() readl(dev->regs_base + \
- S5P_FIMV_RISC2HOST_ARG1)
-#define s5p_mfc_get_enc_strm_size() readl(dev->regs_base + \
- S5P_FIMV_ENC_SI_STRM_SIZE)
-#define s5p_mfc_get_enc_slice_type() readl(dev->regs_base + \
- S5P_FIMV_ENC_SI_SLICE_TYPE)
+void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev);
#endif /* S5P_MFC_OPR_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
new file mode 100644
index 0000000..fe36c92
--- /dev/null
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
@@ -0,0 +1,1698 @@
+/*
+ * drivers/media/video/samsung/mfc5/s5p_mfc_opr_v5.c
+ *
+ * Samsung MFC (Multi Function Codec - FIMV) driver
+ * This file contains hw related functions.
+ *
+ * Kamil Debski, Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_cmd.h"
+#include "s5p_mfc_ctrl.h"
+#include "s5p_mfc_debug.h"
+#include "s5p_mfc_intr.h"
+#include "s5p_mfc_pm.h"
+#include "s5p_mfc_opr.h"
+#include "s5p_mfc_opr_v5.h"
+#include <asm/cacheflush.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/firmware.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+
+#define OFFSETA(x) (((x) - dev->bank1) >> MFC_OFFSET_SHIFT)
+#define OFFSETB(x) (((x) - dev->bank2) >> MFC_OFFSET_SHIFT)
+
+/* Allocate temporary buffers for decoding */
+int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx *ctx)
+{
+ void *desc_virt;
+ struct s5p_mfc_dev *dev = ctx->dev;
+
+ ctx->desc_buf = vb2_dma_contig_memops.alloc(
+ dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], DESC_BUF_SIZE);
+ if (IS_ERR_VALUE((int)ctx->desc_buf)) {
+ ctx->desc_buf = NULL;
+ mfc_err("Allocating DESC buffer failed\n");
+ return -ENOMEM;
+ }
+ ctx->desc_phys = s5p_mfc_mem_cookie(
+ dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->desc_buf);
+ BUG_ON(ctx->desc_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
+ desc_virt = vb2_dma_contig_memops.vaddr(ctx->desc_buf);
+ if (desc_virt == NULL) {
+ vb2_dma_contig_memops.put(ctx->desc_buf);
+ ctx->desc_phys = 0;
+ ctx->desc_buf = NULL;
+ mfc_err("Remapping DESC buffer failed\n");
+ return -ENOMEM;
+ }
+ memset(desc_virt, 0, DESC_BUF_SIZE);
+ wmb();
+ return 0;
+}
+
+/* Release temporary buffers for decoding */
+void s5p_mfc_release_dec_desc_buffer_v5(struct s5p_mfc_ctx *ctx)
+{
+ if (ctx->desc_phys) {
+ vb2_dma_contig_memops.put(ctx->desc_buf);
+ ctx->desc_phys = 0;
+ ctx->desc_buf = NULL;
+ }
+}
+
+/* Allocate codec buffers */
+int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ unsigned int enc_ref_y_size = 0;
+ unsigned int enc_ref_c_size = 0;
+ unsigned int guard_width, guard_height;
+
+ if (ctx->type == MFCINST_DECODER) {
+ mfc_debug(2, "Luma size:%d Chroma size:%d MV size:%d\n",
+ ctx->luma_size, ctx->chroma_size, ctx->mv_size);
+ mfc_debug(2, "Totals bufs: %d\n", ctx->total_dpb_count);
+ } else if (ctx->type == MFCINST_ENCODER) {
+ enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
+ * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
+ enc_ref_y_size = ALIGN(enc_ref_y_size, S5P_FIMV_NV12MT_SALIGN);
+
+ if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC) {
+ enc_ref_c_size = ALIGN(ctx->img_width,
+ S5P_FIMV_NV12MT_HALIGN)
+ * ALIGN(ctx->img_height >> 1,
+ S5P_FIMV_NV12MT_VALIGN);
+ enc_ref_c_size = ALIGN(enc_ref_c_size,
+ S5P_FIMV_NV12MT_SALIGN);
+ } else {
+ guard_width = ALIGN(ctx->img_width + 16,
+ S5P_FIMV_NV12MT_HALIGN);
+ guard_height = ALIGN((ctx->img_height >> 1) + 4,
+ S5P_FIMV_NV12MT_VALIGN);
+ enc_ref_c_size = ALIGN(guard_width * guard_height,
+ S5P_FIMV_NV12MT_SALIGN);
+ }
+ mfc_debug(2, "recon luma size: %d chroma size: %d\n",
+ enc_ref_y_size, enc_ref_c_size);
+ } else {
+ return -EINVAL;
+ }
+ /* Codecs have different memory requirements */
+ switch (ctx->codec_mode) {
+ case S5P_MFC_CODEC_H264_DEC:
+ ctx->bank1_size =
+ ALIGN(S5P_FIMV_DEC_NB_IP_SIZE +
+ S5P_FIMV_DEC_VERT_NB_MV_SIZE,
+ S5P_FIMV_DEC_BUF_ALIGN);
+ ctx->bank2_size = ctx->total_dpb_count * ctx->mv_size;
+ break;
+ case S5P_MFC_CODEC_MPEG4_DEC:
+ ctx->bank1_size =
+ ALIGN(S5P_FIMV_DEC_NB_DCAC_SIZE +
+ S5P_FIMV_DEC_UPNB_MV_SIZE +
+ S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
+ S5P_FIMV_DEC_STX_PARSER_SIZE +
+ S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE,
+ S5P_FIMV_DEC_BUF_ALIGN);
+ ctx->bank2_size = 0;
+ break;
+ case S5P_MFC_CODEC_VC1RCV_DEC:
+ case S5P_MFC_CODEC_VC1_DEC:
+ ctx->bank1_size =
+ ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE +
+ S5P_FIMV_DEC_UPNB_MV_SIZE +
+ S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
+ S5P_FIMV_DEC_NB_DCAC_SIZE +
+ 3 * S5P_FIMV_DEC_VC1_BITPLANE_SIZE,
+ S5P_FIMV_DEC_BUF_ALIGN);
+ ctx->bank2_size = 0;
+ break;
+ case S5P_MFC_CODEC_MPEG2_DEC:
+ ctx->bank1_size = 0;
+ ctx->bank2_size = 0;
+ break;
+ case S5P_MFC_CODEC_H263_DEC:
+ ctx->bank1_size =
+ ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE +
+ S5P_FIMV_DEC_UPNB_MV_SIZE +
+ S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
+ S5P_FIMV_DEC_NB_DCAC_SIZE,
+ S5P_FIMV_DEC_BUF_ALIGN);
+ ctx->bank2_size = 0;
+ break;
+ case S5P_MFC_CODEC_H264_ENC:
+ ctx->bank1_size = (enc_ref_y_size * 2) +
+ S5P_FIMV_ENC_UPMV_SIZE +
+ S5P_FIMV_ENC_COLFLG_SIZE +
+ S5P_FIMV_ENC_INTRAMD_SIZE +
+ S5P_FIMV_ENC_NBORINFO_SIZE;
+ ctx->bank2_size = (enc_ref_y_size * 2) +
+ (enc_ref_c_size * 4) +
+ S5P_FIMV_ENC_INTRAPRED_SIZE;
+ break;
+ case S5P_MFC_CODEC_MPEG4_ENC:
+ ctx->bank1_size = (enc_ref_y_size * 2) +
+ S5P_FIMV_ENC_UPMV_SIZE +
+ S5P_FIMV_ENC_COLFLG_SIZE +
+ S5P_FIMV_ENC_ACDCCOEF_SIZE;
+ ctx->bank2_size = (enc_ref_y_size * 2) +
+ (enc_ref_c_size * 4);
+ break;
+ case S5P_MFC_CODEC_H263_ENC:
+ ctx->bank1_size = (enc_ref_y_size * 2) +
+ S5P_FIMV_ENC_UPMV_SIZE +
+ S5P_FIMV_ENC_ACDCCOEF_SIZE;
+ ctx->bank2_size = (enc_ref_y_size * 2) +
+ (enc_ref_c_size * 4);
+ break;
+ default:
+ break;
+ }
+ /* Allocate only if memory from bank 1 is necessary */
+ if (ctx->bank1_size > 0) {
+ ctx->bank1_buf = vb2_dma_contig_memops.alloc(
+ dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_size);
+ if (IS_ERR(ctx->bank1_buf)) {
+ ctx->bank1_buf = NULL;
+ mfc_err("Buf alloc for decoding failed (port A)\n");
+ return -ENOMEM;
+ }
+ ctx->bank1_phys = s5p_mfc_mem_cookie(
+ dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_buf);
+ BUG_ON(ctx->bank1_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
+ }
+ /* Allocate only if memory from bank 2 is necessary */
+ if (ctx->bank2_size > 0) {
+ ctx->bank2_buf = vb2_dma_contig_memops.alloc(
+ dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], ctx->bank2_size);
+ if (IS_ERR(ctx->bank2_buf)) {
+ ctx->bank2_buf = NULL;
+ mfc_err("Buf alloc for decoding failed (port B)\n");
+ return -ENOMEM;
+ }
+ ctx->bank2_phys = s5p_mfc_mem_cookie(
+ dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], ctx->bank2_buf);
+ BUG_ON(ctx->bank2_phys & ((1 << MFC_BANK2_ALIGN_ORDER) - 1));
+ }
+ return 0;
+}
+
+/* Release buffers allocated for codec */
+void s5p_mfc_release_codec_buffers_v5(struct s5p_mfc_ctx *ctx)
+{
+ if (ctx->bank1_buf) {
+ vb2_dma_contig_memops.put(ctx->bank1_buf);
+ ctx->bank1_buf = NULL;
+ ctx->bank1_phys = 0;
+ ctx->bank1_size = 0;
+ }
+ if (ctx->bank2_buf) {
+ vb2_dma_contig_memops.put(ctx->bank2_buf);
+ ctx->bank2_buf = NULL;
+ ctx->bank2_phys = 0;
+ ctx->bank2_size = 0;
+ }
+}
+
+/* Allocate memory for instance data buffer */
+int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx)
+{
+ void *context_virt;
+ struct s5p_mfc_dev *dev = ctx->dev;
+
+ if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC ||
+ ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC)
+ ctx->ctx_size = MFC_H264_CTX_BUF_SIZE;
+ else
+ ctx->ctx_size = MFC_CTX_BUF_SIZE;
+ ctx->ctx_buf = vb2_dma_contig_memops.alloc(
+ dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx_size);
+ if (IS_ERR(ctx->ctx_buf)) {
+ mfc_err("Allocating context buffer failed\n");
+ ctx->ctx_phys = 0;
+ ctx->ctx_buf = NULL;
+ return -ENOMEM;
+ }
+ ctx->ctx_phys = s5p_mfc_mem_cookie(
+ dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx_buf);
+ BUG_ON(ctx->ctx_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
+ ctx->ctx_ofs = OFFSETA(ctx->ctx_phys);
+ context_virt = vb2_dma_contig_memops.vaddr(ctx->ctx_buf);
+ if (context_virt == NULL) {
+ mfc_err("Remapping instance buffer failed\n");
+ vb2_dma_contig_memops.put(ctx->ctx_buf);
+ ctx->ctx_phys = 0;
+ ctx->ctx_buf = NULL;
+ return -ENOMEM;
+ }
+ /* Zero content of the allocated memory */
+ memset(context_virt, 0, ctx->ctx_size);
+ wmb();
+
+ /* Initialize shared memory */
+ ctx->shm_alloc = vb2_dma_contig_memops.alloc(
+ dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], SHARED_BUF_SIZE);
+ if (IS_ERR(ctx->shm_alloc)) {
+ mfc_err("failed to allocate shared memory\n");
+ return PTR_ERR(ctx->shm_alloc);
+ }
+ /* shared memory offset only keeps the offset from base (port a) */
+ ctx->shm_ofs = s5p_mfc_mem_cookie(
+ dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->shm_alloc)
+ - dev->bank1;
+ BUG_ON(ctx->shm_ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
+
+ ctx->shm = vb2_dma_contig_memops.vaddr(ctx->shm_alloc);
+ if (!ctx->shm) {
+ vb2_dma_contig_memops.put(ctx->shm_alloc);
+ ctx->shm_ofs = 0;
+ ctx->shm_alloc = NULL;
+ mfc_err("failed to virt addr of shared memory\n");
+ return -ENOMEM;
+ }
+ memset((void *)ctx->shm, 0, SHARED_BUF_SIZE);
+ wmb();
+ return 0;
+}
+
+/* Release instance buffer */
+void s5p_mfc_release_instance_buffer_v5(struct s5p_mfc_ctx *ctx)
+{
+ if (ctx->ctx_buf) {
+ vb2_dma_contig_memops.put(ctx->ctx_buf);
+ ctx->ctx_phys = 0;
+ ctx->ctx_buf = NULL;
+ }
+ if (ctx->shm_alloc) {
+ vb2_dma_contig_memops.put(ctx->shm_alloc);
+ ctx->shm_alloc = NULL;
+ ctx->shm = NULL;
+ }
+}
+
+int s5p_mfc_alloc_dev_context_buffer_v5(struct s5p_mfc_dev *dev)
+{
+ /* NOP */
+
+ return 0;
+}
+
+void s5p_mfc_release_dev_context_buffer_v5(struct s5p_mfc_dev *dev)
+{
+ /* NOP */
+}
+
+static void s5p_mfc_write_info_v5(struct s5p_mfc_ctx *ctx, unsigned int data,
+ unsigned int ofs)
+{
+ writel(data, (ctx->shm + ofs));
+ wmb();
+}
+
+static unsigned int s5p_mfc_read_info_v5(struct s5p_mfc_ctx *ctx,
+ unsigned int ofs)
+{
+ rmb();
+ return readl(ctx->shm + ofs);
+}
+
+void s5p_mfc_dec_calc_dpb_size_v5(struct s5p_mfc_ctx *ctx)
+{
+ /* NOP */
+}
+
+void s5p_mfc_enc_calc_src_size_v5(struct s5p_mfc_ctx *ctx)
+{
+ /* NOP */
+}
+
+/* Set registers for decoding temporary buffers */
+static void s5p_mfc_set_dec_desc_buffer(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+
+ mfc_write(dev, OFFSETA(ctx->desc_phys), S5P_FIMV_SI_CH0_DESC_ADR);
+ mfc_write(dev, DESC_BUF_SIZE, S5P_FIMV_SI_CH0_DESC_SIZE);
+}
+
+/* Set registers for shared buffer */
+static void s5p_mfc_set_shared_buffer(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ mfc_write(dev, ctx->shm_ofs, S5P_FIMV_SI_CH0_HOST_WR_ADR);
+}
+
+/* Set registers for decoding stream buffer */
+int s5p_mfc_set_dec_stream_buffer_v5(struct s5p_mfc_ctx *ctx, int buf_addr,
+ unsigned int start_num_byte, unsigned int buf_size)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+
+ mfc_write(dev, OFFSETA(buf_addr), S5P_FIMV_SI_CH0_SB_ST_ADR);
+ mfc_write(dev, ctx->dec_src_buf_size, S5P_FIMV_SI_CH0_CPB_SIZE);
+ mfc_write(dev, buf_size, S5P_FIMV_SI_CH0_SB_FRM_SIZE);
+ s5p_mfc_write_info_v5(ctx, start_num_byte, START_BYTE_NUM);
+ return 0;
+}
+
+/* Set decoding frame buffer */
+int s5p_mfc_set_dec_frame_buffer_v5(struct s5p_mfc_ctx *ctx)
+{
+ unsigned int frame_size, i;
+ unsigned int frame_size_ch, frame_size_mv;
+ struct s5p_mfc_dev *dev = ctx->dev;
+ unsigned int dpb;
+ size_t buf_addr1, buf_addr2;
+ int buf_size1, buf_size2;
+
+ buf_addr1 = ctx->bank1_phys;
+ buf_size1 = ctx->bank1_size;
+ buf_addr2 = ctx->bank2_phys;
+ buf_size2 = ctx->bank2_size;
+ dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) &
+ ~S5P_FIMV_DPB_COUNT_MASK;
+ mfc_write(dev, ctx->total_dpb_count | dpb,
+ S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
+ s5p_mfc_set_shared_buffer(ctx);
+ switch (ctx->codec_mode) {
+ case S5P_MFC_CODEC_H264_DEC:
+ mfc_write(dev, OFFSETA(buf_addr1),
+ S5P_FIMV_H264_VERT_NB_MV_ADR);
+ buf_addr1 += S5P_FIMV_DEC_VERT_NB_MV_SIZE;
+ buf_size1 -= S5P_FIMV_DEC_VERT_NB_MV_SIZE;
+ mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H264_NB_IP_ADR);
+ buf_addr1 += S5P_FIMV_DEC_NB_IP_SIZE;
+ buf_size1 -= S5P_FIMV_DEC_NB_IP_SIZE;
+ break;
+ case S5P_MFC_CODEC_MPEG4_DEC:
+ mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_NB_DCAC_ADR);
+ buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
+ buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
+ mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_UP_NB_MV_ADR);
+ buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
+ buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
+ mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_SA_MV_ADR);
+ buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
+ buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
+ mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_SP_ADR);
+ buf_addr1 += S5P_FIMV_DEC_STX_PARSER_SIZE;
+ buf_size1 -= S5P_FIMV_DEC_STX_PARSER_SIZE;
+ mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_OT_LINE_ADR);
+ buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
+ buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
+ break;
+ case S5P_MFC_CODEC_H263_DEC:
+ mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_OT_LINE_ADR);
+ buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
+ buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
+ mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_UP_NB_MV_ADR);
+ buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
+ buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
+ mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_SA_MV_ADR);
+ buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
+ buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
+ mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_NB_DCAC_ADR);
+ buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
+ buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
+ break;
+ case S5P_MFC_CODEC_VC1_DEC:
+ case S5P_MFC_CODEC_VC1RCV_DEC:
+ mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_NB_DCAC_ADR);
+ buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
+ buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
+ mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_OT_LINE_ADR);
+ buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
+ buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
+ mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_UP_NB_MV_ADR);
+ buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
+ buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
+ mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_SA_MV_ADR);
+ buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
+ buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
+ mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE3_ADR);
+ buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
+ buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
+ mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE2_ADR);
+ buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
+ buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
+ mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE1_ADR);
+ buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
+ buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
+ break;
+ case S5P_MFC_CODEC_MPEG2_DEC:
+ break;
+ default:
+ mfc_err("Unknown codec for decoding (%x)\n",
+ ctx->codec_mode);
+ return -EINVAL;
+ break;
+ }
+ frame_size = ctx->luma_size;
+ frame_size_ch = ctx->chroma_size;
+ frame_size_mv = ctx->mv_size;
+ mfc_debug(2, "Frm size: %d ch: %d mv: %d\n", frame_size, frame_size_ch,
+ frame_size_mv);
+ for (i = 0; i < ctx->total_dpb_count; i++) {
+ /* Bank2 */
+ mfc_debug(2, "Luma %d: %x\n", i,
+ ctx->dst_bufs[i].cookie.raw.luma);
+ mfc_write(dev, OFFSETB(ctx->dst_bufs[i].cookie.raw.luma),
+ S5P_FIMV_DEC_LUMA_ADR + i * 4);
+ mfc_debug(2, "\tChroma %d: %x\n", i,
+ ctx->dst_bufs[i].cookie.raw.chroma);
+ mfc_write(dev, OFFSETA(ctx->dst_bufs[i].cookie.raw.chroma),
+ S5P_FIMV_DEC_CHROMA_ADR + i * 4);
+ if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC) {
+ mfc_debug(2, "\tBuf2: %x, size: %d\n",
+ buf_addr2, buf_size2);
+ mfc_write(dev, OFFSETB(buf_addr2),
+ S5P_FIMV_H264_MV_ADR + i * 4);
+ buf_addr2 += frame_size_mv;
+ buf_size2 -= frame_size_mv;
+ }
+ }
+ mfc_debug(2, "Buf1: %u, buf_size1: %d\n", buf_addr1, buf_size1);
+ mfc_debug(2, "Buf 1/2 size after: %d/%d (frames %d)\n",
+ buf_size1, buf_size2, ctx->total_dpb_count);
+ if (buf_size1 < 0 || buf_size2 < 0) {
+ mfc_debug(2, "Not enough memory has been allocated\n");
+ return -ENOMEM;
+ }
+ s5p_mfc_write_info_v5(ctx, frame_size, ALLOC_LUMA_DPB_SIZE);
+ s5p_mfc_write_info_v5(ctx, frame_size_ch, ALLOC_CHROMA_DPB_SIZE);
+ if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC)
+ s5p_mfc_write_info_v5(ctx, frame_size_mv, ALLOC_MV_SIZE);
+ mfc_write(dev, ((S5P_FIMV_CH_INIT_BUFS & S5P_FIMV_CH_MASK)
+ << S5P_FIMV_CH_SHIFT) | (ctx->inst_no),
+ S5P_FIMV_SI_CH0_INST_ID);
+ return 0;
+}
+
+/* Set registers for encoding stream buffer */
+int s5p_mfc_set_enc_stream_buffer_v5(struct s5p_mfc_ctx *ctx,
+ unsigned long addr, unsigned int size)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+
+ mfc_write(dev, OFFSETA(addr), S5P_FIMV_ENC_SI_CH0_SB_ADR);
+ mfc_write(dev, size, S5P_FIMV_ENC_SI_CH0_SB_SIZE);
+ return 0;
+}
+
+void s5p_mfc_set_enc_frame_buffer_v5(struct s5p_mfc_ctx *ctx,
+ unsigned long y_addr, unsigned long c_addr)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+
+ mfc_write(dev, OFFSETB(y_addr), S5P_FIMV_ENC_SI_CH0_CUR_Y_ADR);
+ mfc_write(dev, OFFSETB(c_addr), S5P_FIMV_ENC_SI_CH0_CUR_C_ADR);
+}
+
+void s5p_mfc_get_enc_frame_buffer_v5(struct s5p_mfc_ctx *ctx,
+ unsigned long *y_addr, unsigned long *c_addr)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+
+ *y_addr = dev->bank2 + (mfc_read(dev, S5P_FIMV_ENCODED_Y_ADDR)
+ << MFC_OFFSET_SHIFT);
+ *c_addr = dev->bank2 + (mfc_read(dev, S5P_FIMV_ENCODED_C_ADDR)
+ << MFC_OFFSET_SHIFT);
+}
+
+/* Set encoding ref & codec buffer */
+int s5p_mfc_set_enc_ref_buffer_v5(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ size_t buf_addr1, buf_addr2;
+ size_t buf_size1, buf_size2;
+ unsigned int enc_ref_y_size, enc_ref_c_size;
+ unsigned int guard_width, guard_height;
+ int i;
+
+ buf_addr1 = ctx->bank1_phys;
+ buf_size1 = ctx->bank1_size;
+ buf_addr2 = ctx->bank2_phys;
+ buf_size2 = ctx->bank2_size;
+ enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
+ * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
+ enc_ref_y_size = ALIGN(enc_ref_y_size, S5P_FIMV_NV12MT_SALIGN);
+ if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC) {
+ enc_ref_c_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
+ * ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12MT_VALIGN);
+ enc_ref_c_size = ALIGN(enc_ref_c_size, S5P_FIMV_NV12MT_SALIGN);
+ } else {
+ guard_width = ALIGN(ctx->img_width + 16,
+ S5P_FIMV_NV12MT_HALIGN);
+ guard_height = ALIGN((ctx->img_height >> 1) + 4,
+ S5P_FIMV_NV12MT_VALIGN);
+ enc_ref_c_size = ALIGN(guard_width * guard_height,
+ S5P_FIMV_NV12MT_SALIGN);
+ }
+ mfc_debug(2, "buf_size1: %d, buf_size2: %d\n", buf_size1, buf_size2);
+ switch (ctx->codec_mode) {
+ case S5P_MFC_CODEC_H264_ENC:
+ for (i = 0; i < 2; i++) {
+ mfc_write(dev, OFFSETA(buf_addr1),
+ S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
+ buf_addr1 += enc_ref_y_size;
+ buf_size1 -= enc_ref_y_size;
+
+ mfc_write(dev, OFFSETB(buf_addr2),
+ S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
+ buf_addr2 += enc_ref_y_size;
+ buf_size2 -= enc_ref_y_size;
+ }
+ for (i = 0; i < 4; i++) {
+ mfc_write(dev, OFFSETB(buf_addr2),
+ S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
+ buf_addr2 += enc_ref_c_size;
+ buf_size2 -= enc_ref_c_size;
+ }
+ mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H264_UP_MV_ADR);
+ buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
+ buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
+ mfc_write(dev, OFFSETA(buf_addr1),
+ S5P_FIMV_H264_COZERO_FLAG_ADR);
+ buf_addr1 += S5P_FIMV_ENC_COLFLG_SIZE;
+ buf_size1 -= S5P_FIMV_ENC_COLFLG_SIZE;
+ mfc_write(dev, OFFSETA(buf_addr1),
+ S5P_FIMV_H264_UP_INTRA_MD_ADR);
+ buf_addr1 += S5P_FIMV_ENC_INTRAMD_SIZE;
+ buf_size1 -= S5P_FIMV_ENC_INTRAMD_SIZE;
+ mfc_write(dev, OFFSETB(buf_addr2),
+ S5P_FIMV_H264_UP_INTRA_PRED_ADR);
+ buf_addr2 += S5P_FIMV_ENC_INTRAPRED_SIZE;
+ buf_size2 -= S5P_FIMV_ENC_INTRAPRED_SIZE;
+ mfc_write(dev, OFFSETA(buf_addr1),
+ S5P_FIMV_H264_NBOR_INFO_ADR);
+ buf_addr1 += S5P_FIMV_ENC_NBORINFO_SIZE;
+ buf_size1 -= S5P_FIMV_ENC_NBORINFO_SIZE;
+ mfc_debug(2, "buf_size1: %d, buf_size2: %d\n",
+ buf_size1, buf_size2);
+ break;
+ case S5P_MFC_CODEC_MPEG4_ENC:
+ for (i = 0; i < 2; i++) {
+ mfc_write(dev, OFFSETA(buf_addr1),
+ S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
+ buf_addr1 += enc_ref_y_size;
+ buf_size1 -= enc_ref_y_size;
+ mfc_write(dev, OFFSETB(buf_addr2),
+ S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
+ buf_addr2 += enc_ref_y_size;
+ buf_size2 -= enc_ref_y_size;
+ }
+ for (i = 0; i < 4; i++) {
+ mfc_write(dev, OFFSETB(buf_addr2),
+ S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
+ buf_addr2 += enc_ref_c_size;
+ buf_size2 -= enc_ref_c_size;
+ }
+ mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_UP_MV_ADR);
+ buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
+ buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
+ mfc_write(dev, OFFSETA(buf_addr1),
+ S5P_FIMV_MPEG4_COZERO_FLAG_ADR);
+ buf_addr1 += S5P_FIMV_ENC_COLFLG_SIZE;
+ buf_size1 -= S5P_FIMV_ENC_COLFLG_SIZE;
+ mfc_write(dev, OFFSETA(buf_addr1),
+ S5P_FIMV_MPEG4_ACDC_COEF_ADR);
+ buf_addr1 += S5P_FIMV_ENC_ACDCCOEF_SIZE;
+ buf_size1 -= S5P_FIMV_ENC_ACDCCOEF_SIZE;
+ mfc_debug(2, "buf_size1: %d, buf_size2: %d\n",
+ buf_size1, buf_size2);
+ break;
+ case S5P_MFC_CODEC_H263_ENC:
+ for (i = 0; i < 2; i++) {
+ mfc_write(dev, OFFSETA(buf_addr1),
+ S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
+ buf_addr1 += enc_ref_y_size;
+ buf_size1 -= enc_ref_y_size;
+ mfc_write(dev, OFFSETB(buf_addr2),
+ S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
+ buf_addr2 += enc_ref_y_size;
+ buf_size2 -= enc_ref_y_size;
+ }
+ for (i = 0; i < 4; i++) {
+ mfc_write(dev, OFFSETB(buf_addr2),
+ S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
+ buf_addr2 += enc_ref_c_size;
+ buf_size2 -= enc_ref_c_size;
+ }
+ mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_UP_MV_ADR);
+ buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
+ buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
+ mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_ACDC_COEF_ADR);
+ buf_addr1 += S5P_FIMV_ENC_ACDCCOEF_SIZE;
+ buf_size1 -= S5P_FIMV_ENC_ACDCCOEF_SIZE;
+ mfc_debug(2, "buf_size1: %d, buf_size2: %d\n",
+ buf_size1, buf_size2);
+ break;
+ default:
+ mfc_err("Unknown codec set for encoding: %d\n",
+ ctx->codec_mode);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ struct s5p_mfc_enc_params *p = &ctx->enc_params;
+ unsigned int reg;
+ unsigned int shm;
+
+ /* width */
+ mfc_write(dev, ctx->img_width, S5P_FIMV_ENC_HSIZE_PX);
+ /* height */
+ mfc_write(dev, ctx->img_height, S5P_FIMV_ENC_VSIZE_PX);
+ /* pictype : enable, IDR period */
+ reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
+ reg |= (1 << 18);
+ reg &= ~(0xFFFF);
+ reg |= p->gop_size;
+ mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
+ mfc_write(dev, 0, S5P_FIMV_ENC_B_RECON_WRITE_ON);
+ /* multi-slice control */
+ /* multi-slice MB number or bit size */
+ mfc_write(dev, p->slice_mode, S5P_FIMV_ENC_MSLICE_CTRL);
+ if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) {
+ mfc_write(dev, p->slice_mb, S5P_FIMV_ENC_MSLICE_MB);
+ } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) {
+ mfc_write(dev, p->slice_bit, S5P_FIMV_ENC_MSLICE_BIT);
+ } else {
+ mfc_write(dev, 0, S5P_FIMV_ENC_MSLICE_MB);
+ mfc_write(dev, 0, S5P_FIMV_ENC_MSLICE_BIT);
+ }
+ /* cyclic intra refresh */
+ mfc_write(dev, p->intra_refresh_mb, S5P_FIMV_ENC_CIR_CTRL);
+ /* memory structure cur. frame */
+ if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M)
+ mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR);
+ else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT)
+ mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR);
+ /* padding control & value */
+ reg = mfc_read(dev, S5P_FIMV_ENC_PADDING_CTRL);
+ if (p->pad) {
+ /** enable */
+ reg |= (1 << 31);
+ /** cr value */
+ reg &= ~(0xFF << 16);
+ reg |= (p->pad_cr << 16);
+ /** cb value */
+ reg &= ~(0xFF << 8);
+ reg |= (p->pad_cb << 8);
+ /** y value */
+ reg &= ~(0xFF);
+ reg |= (p->pad_luma);
+ } else {
+ /** disable & all value clear */
+ reg = 0;
+ }
+ mfc_write(dev, reg, S5P_FIMV_ENC_PADDING_CTRL);
+ /* rate control config. */
+ reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
+ /** frame-level rate control */
+ reg &= ~(0x1 << 9);
+ reg |= (p->rc_frame << 9);
+ mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
+ /* bit rate */
+ if (p->rc_frame)
+ mfc_write(dev, p->rc_bitrate,
+ S5P_FIMV_ENC_RC_BIT_RATE);
+ else
+ mfc_write(dev, 0, S5P_FIMV_ENC_RC_BIT_RATE);
+ /* reaction coefficient */
+ if (p->rc_frame)
+ mfc_write(dev, p->rc_reaction_coeff, S5P_FIMV_ENC_RC_RPARA);
+ shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
+ /* seq header ctrl */
+ shm &= ~(0x1 << 3);
+ shm |= (p->seq_hdr_mode << 3);
+ /* frame skip mode */
+ shm &= ~(0x3 << 1);
+ shm |= (p->frame_skip_mode << 1);
+ s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
+ /* fixed target bit */
+ s5p_mfc_write_info_v5(ctx, p->fixed_target_bit, RC_CONTROL_CONFIG);
+ return 0;
+}
+
+static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ struct s5p_mfc_enc_params *p = &ctx->enc_params;
+ struct s5p_mfc_h264_enc_params *p_264 = &p->codec.h264;
+ unsigned int reg;
+ unsigned int shm;
+
+ s5p_mfc_set_enc_params(ctx);
+ /* pictype : number of B */
+ reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
+ /* num_b_frame - 0 ~ 2 */
+ reg &= ~(0x3 << 16);
+ reg |= (p->num_b_frame << 16);
+ mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
+ /* profile & level */
+ reg = mfc_read(dev, S5P_FIMV_ENC_PROFILE);
+ /* level */
+ reg &= ~(0xFF << 8);
+ reg |= (p_264->level << 8);
+ /* profile - 0 ~ 2 */
+ reg &= ~(0x3F);
+ reg |= p_264->profile;
+ mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE);
+ /* interlace */
+ mfc_write(dev, p->interlace, S5P_FIMV_ENC_PIC_STRUCT);
+ /* height */
+ if (p->interlace)
+ mfc_write(dev, ctx->img_height >> 1, S5P_FIMV_ENC_VSIZE_PX);
+ /* loopfilter ctrl */
+ mfc_write(dev, p_264->loop_filter_mode, S5P_FIMV_ENC_LF_CTRL);
+ /* loopfilter alpha offset */
+ if (p_264->loop_filter_alpha < 0) {
+ reg = 0x10;
+ reg |= (0xFF - p_264->loop_filter_alpha) + 1;
+ } else {
+ reg = 0x00;
+ reg |= (p_264->loop_filter_alpha & 0xF);
+ }
+ mfc_write(dev, reg, S5P_FIMV_ENC_ALPHA_OFF);
+ /* loopfilter beta offset */
+ if (p_264->loop_filter_beta < 0) {
+ reg = 0x10;
+ reg |= (0xFF - p_264->loop_filter_beta) + 1;
+ } else {
+ reg = 0x00;
+ reg |= (p_264->loop_filter_beta & 0xF);
+ }
+ mfc_write(dev, reg, S5P_FIMV_ENC_BETA_OFF);
+ /* entropy coding mode */
+ if (p_264->entropy_mode == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC)
+ mfc_write(dev, 1, S5P_FIMV_ENC_H264_ENTROPY_MODE);
+ else
+ mfc_write(dev, 0, S5P_FIMV_ENC_H264_ENTROPY_MODE);
+ /* number of ref. picture */
+ reg = mfc_read(dev, S5P_FIMV_ENC_H264_NUM_OF_REF);
+ /* num of ref. pictures of P */
+ reg &= ~(0x3 << 5);
+ reg |= (p_264->num_ref_pic_4p << 5);
+ /* max number of ref. pictures */
+ reg &= ~(0x1F);
+ reg |= p_264->max_ref_pic;
+ mfc_write(dev, reg, S5P_FIMV_ENC_H264_NUM_OF_REF);
+ /* 8x8 transform enable */
+ mfc_write(dev, p_264->_8x8_transform, S5P_FIMV_ENC_H264_TRANS_FLAG);
+ /* rate control config. */
+ reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
+ /* macroblock level rate control */
+ reg &= ~(0x1 << 8);
+ reg |= (p_264->rc_mb << 8);
+ /* frame QP */
+ reg &= ~(0x3F);
+ reg |= p_264->rc_frame_qp;
+ mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
+ /* frame rate */
+ if (p->rc_frame && p->rc_framerate_denom)
+ mfc_write(dev, p->rc_framerate_num * 1000
+ / p->rc_framerate_denom, S5P_FIMV_ENC_RC_FRAME_RATE);
+ else
+ mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
+ /* max & min value of QP */
+ reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
+ /* max QP */
+ reg &= ~(0x3F << 8);
+ reg |= (p_264->rc_max_qp << 8);
+ /* min QP */
+ reg &= ~(0x3F);
+ reg |= p_264->rc_min_qp;
+ mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
+ /* macroblock adaptive scaling features */
+ if (p_264->rc_mb) {
+ reg = mfc_read(dev, S5P_FIMV_ENC_RC_MB_CTRL);
+ /* dark region */
+ reg &= ~(0x1 << 3);
+ reg |= (p_264->rc_mb_dark << 3);
+ /* smooth region */
+ reg &= ~(0x1 << 2);
+ reg |= (p_264->rc_mb_smooth << 2);
+ /* static region */
+ reg &= ~(0x1 << 1);
+ reg |= (p_264->rc_mb_static << 1);
+ /* high activity region */
+ reg &= ~(0x1);
+ reg |= p_264->rc_mb_activity;
+ mfc_write(dev, reg, S5P_FIMV_ENC_RC_MB_CTRL);
+ }
+ if (!p->rc_frame &&
+ !p_264->rc_mb) {
+ shm = s5p_mfc_read_info_v5(ctx, P_B_FRAME_QP);
+ shm &= ~(0xFFF);
+ shm |= ((p_264->rc_b_frame_qp & 0x3F) << 6);
+ shm |= (p_264->rc_p_frame_qp & 0x3F);
+ s5p_mfc_write_info_v5(ctx, shm, P_B_FRAME_QP);
+ }
+ /* extended encoder ctrl */
+ shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
+ /* AR VUI control */
+ shm &= ~(0x1 << 15);
+ shm |= (p_264->vui_sar << 1);
+ s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
+ if (p_264->vui_sar) {
+ /* aspect ration IDC */
+ shm = s5p_mfc_read_info_v5(ctx, SAMPLE_ASPECT_RATIO_IDC);
+ shm &= ~(0xFF);
+ shm |= p_264->vui_sar_idc;
+ s5p_mfc_write_info_v5(ctx, shm, SAMPLE_ASPECT_RATIO_IDC);
+ if (p_264->vui_sar_idc == 0xFF) {
+ /* sample AR info */
+ shm = s5p_mfc_read_info_v5(ctx, EXTENDED_SAR);
+ shm &= ~(0xFFFFFFFF);
+ shm |= p_264->vui_ext_sar_width << 16;
+ shm |= p_264->vui_ext_sar_height;
+ s5p_mfc_write_info_v5(ctx, shm, EXTENDED_SAR);
+ }
+ }
+ /* intra picture period for H.264 */
+ shm = s5p_mfc_read_info_v5(ctx, H264_I_PERIOD);
+ /* control */
+ shm &= ~(0x1 << 16);
+ shm |= (p_264->open_gop << 16);
+ /* value */
+ if (p_264->open_gop) {
+ shm &= ~(0xFFFF);
+ shm |= p_264->open_gop_size;
+ }
+ s5p_mfc_write_info_v5(ctx, shm, H264_I_PERIOD);
+ /* extended encoder ctrl */
+ shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
+ /* vbv buffer size */
+ if (p->frame_skip_mode ==
+ V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
+ shm &= ~(0xFFFF << 16);
+ shm |= (p_264->cpb_size << 16);
+ }
+ s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
+ return 0;
+}
+
+static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ struct s5p_mfc_enc_params *p = &ctx->enc_params;
+ struct s5p_mfc_mpeg4_enc_params *p_mpeg4 = &p->codec.mpeg4;
+ unsigned int reg;
+ unsigned int shm;
+ unsigned int framerate;
+
+ s5p_mfc_set_enc_params(ctx);
+ /* pictype : number of B */
+ reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
+ /* num_b_frame - 0 ~ 2 */
+ reg &= ~(0x3 << 16);
+ reg |= (p->num_b_frame << 16);
+ mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
+ /* profile & level */
+ reg = mfc_read(dev, S5P_FIMV_ENC_PROFILE);
+ /* level */
+ reg &= ~(0xFF << 8);
+ reg |= (p_mpeg4->level << 8);
+ /* profile - 0 ~ 2 */
+ reg &= ~(0x3F);
+ reg |= p_mpeg4->profile;
+ mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE);
+ /* quarter_pixel */
+ mfc_write(dev, p_mpeg4->quarter_pixel, S5P_FIMV_ENC_MPEG4_QUART_PXL);
+ /* qp */
+ if (!p->rc_frame) {
+ shm = s5p_mfc_read_info_v5(ctx, P_B_FRAME_QP);
+ shm &= ~(0xFFF);
+ shm |= ((p_mpeg4->rc_b_frame_qp & 0x3F) << 6);
+ shm |= (p_mpeg4->rc_p_frame_qp & 0x3F);
+ s5p_mfc_write_info_v5(ctx, shm, P_B_FRAME_QP);
+ }
+ /* frame rate */
+ if (p->rc_frame) {
+ if (p->rc_framerate_denom > 0) {
+ framerate = p->rc_framerate_num * 1000 /
+ p->rc_framerate_denom;
+ mfc_write(dev, framerate,
+ S5P_FIMV_ENC_RC_FRAME_RATE);
+ shm = s5p_mfc_read_info_v5(ctx, RC_VOP_TIMING);
+ shm &= ~(0xFFFFFFFF);
+ shm |= (1 << 31);
+ shm |= ((p->rc_framerate_num & 0x7FFF) << 16);
+ shm |= (p->rc_framerate_denom & 0xFFFF);
+ s5p_mfc_write_info_v5(ctx, shm, RC_VOP_TIMING);
+ }
+ } else {
+ mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
+ }
+ /* rate control config. */
+ reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
+ /* frame QP */
+ reg &= ~(0x3F);
+ reg |= p_mpeg4->rc_frame_qp;
+ mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
+ /* max & min value of QP */
+ reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
+ /* max QP */
+ reg &= ~(0x3F << 8);
+ reg |= (p_mpeg4->rc_max_qp << 8);
+ /* min QP */
+ reg &= ~(0x3F);
+ reg |= p_mpeg4->rc_min_qp;
+ mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
+ /* extended encoder ctrl */
+ shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
+ /* vbv buffer size */
+ if (p->frame_skip_mode ==
+ V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
+ shm &= ~(0xFFFF << 16);
+ shm |= (p->vbv_size << 16);
+ }
+ s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
+ return 0;
+}
+
+static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ struct s5p_mfc_enc_params *p = &ctx->enc_params;
+ struct s5p_mfc_mpeg4_enc_params *p_h263 = &p->codec.mpeg4;
+ unsigned int reg;
+ unsigned int shm;
+
+ s5p_mfc_set_enc_params(ctx);
+ /* qp */
+ if (!p->rc_frame) {
+ shm = s5p_mfc_read_info_v5(ctx, P_B_FRAME_QP);
+ shm &= ~(0xFFF);
+ shm |= (p_h263->rc_p_frame_qp & 0x3F);
+ s5p_mfc_write_info_v5(ctx, shm, P_B_FRAME_QP);
+ }
+ /* frame rate */
+ if (p->rc_frame && p->rc_framerate_denom)
+ mfc_write(dev, p->rc_framerate_num * 1000
+ / p->rc_framerate_denom, S5P_FIMV_ENC_RC_FRAME_RATE);
+ else
+ mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
+ /* rate control config. */
+ reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
+ /* frame QP */
+ reg &= ~(0x3F);
+ reg |= p_h263->rc_frame_qp;
+ mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
+ /* max & min value of QP */
+ reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
+ /* max QP */
+ reg &= ~(0x3F << 8);
+ reg |= (p_h263->rc_max_qp << 8);
+ /* min QP */
+ reg &= ~(0x3F);
+ reg |= p_h263->rc_min_qp;
+ mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
+ /* extended encoder ctrl */
+ shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
+ /* vbv buffer size */
+ if (p->frame_skip_mode ==
+ V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
+ shm &= ~(0xFFFF << 16);
+ shm |= (p->vbv_size << 16);
+ }
+ s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
+ return 0;
+}
+
+/* Initialize decoding */
+int s5p_mfc_init_decode_v5(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+
+ s5p_mfc_set_shared_buffer(ctx);
+ /* Setup loop filter, for decoding this is only valid for MPEG4 */
+ if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_DEC)
+ mfc_write(dev, ctx->loop_filter_mpeg4, S5P_FIMV_ENC_LF_CTRL);
+ else
+ mfc_write(dev, 0, S5P_FIMV_ENC_LF_CTRL);
+ mfc_write(dev, ((ctx->slice_interface & S5P_FIMV_SLICE_INT_MASK) <<
+ S5P_FIMV_SLICE_INT_SHIFT) | (ctx->display_delay_enable <<
+ S5P_FIMV_DDELAY_ENA_SHIFT) | ((ctx->display_delay &
+ S5P_FIMV_DDELAY_VAL_MASK) << S5P_FIMV_DDELAY_VAL_SHIFT),
+ S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
+ mfc_write(dev,
+ ((S5P_FIMV_CH_SEQ_HEADER & S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT)
+ | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
+ return 0;
+}
+
+static void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ unsigned int dpb;
+
+ if (flush)
+ dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) | (
+ S5P_FIMV_DPB_FLUSH_MASK << S5P_FIMV_DPB_FLUSH_SHIFT);
+ else
+ dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) &
+ ~(S5P_FIMV_DPB_FLUSH_MASK << S5P_FIMV_DPB_FLUSH_SHIFT);
+ mfc_write(dev, dpb, S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
+}
+
+/* Decode a single frame */
+int s5p_mfc_decode_one_frame_v5(struct s5p_mfc_ctx *ctx,
+ enum s5p_mfc_decode_arg last_frame)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+
+ mfc_write(dev, ctx->dec_dst_flag, S5P_FIMV_SI_CH0_RELEASE_BUF);
+ s5p_mfc_set_shared_buffer(ctx);
+ s5p_mfc_set_flush(ctx, ctx->dpb_flush_flag);
+ /* Issue different commands to instance basing on whether it
+ * is the last frame or not. */
+ switch (last_frame) {
+ case MFC_DEC_FRAME:
+ mfc_write(dev, ((S5P_FIMV_CH_FRAME_START & S5P_FIMV_CH_MASK) <<
+ S5P_FIMV_CH_SHIFT) | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
+ break;
+ case MFC_DEC_LAST_FRAME:
+ mfc_write(dev, ((S5P_FIMV_CH_LAST_FRAME & S5P_FIMV_CH_MASK) <<
+ S5P_FIMV_CH_SHIFT) | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
+ break;
+ case MFC_DEC_RES_CHANGE:
+ mfc_write(dev, ((S5P_FIMV_CH_FRAME_START_REALLOC &
+ S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT) | (ctx->inst_no),
+ S5P_FIMV_SI_CH0_INST_ID);
+ break;
+ }
+ mfc_debug(2, "Decoding a usual frame\n");
+ return 0;
+}
+
+int s5p_mfc_init_encode_v5(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+
+ if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC)
+ s5p_mfc_set_enc_params_h264(ctx);
+ else if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_ENC)
+ s5p_mfc_set_enc_params_mpeg4(ctx);
+ else if (ctx->codec_mode == S5P_MFC_CODEC_H263_ENC)
+ s5p_mfc_set_enc_params_h263(ctx);
+ else {
+ mfc_err("Unknown codec for encoding (%x)\n",
+ ctx->codec_mode);
+ return -EINVAL;
+ }
+ s5p_mfc_set_shared_buffer(ctx);
+ mfc_write(dev, ((S5P_FIMV_CH_SEQ_HEADER << 16) & 0x70000) |
+ (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
+ return 0;
+}
+
+/* Encode a single frame */
+int s5p_mfc_encode_one_frame_v5(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ /* memory structure cur. frame */
+ if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M)
+ mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR);
+ else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT)
+ mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR);
+ s5p_mfc_set_shared_buffer(ctx);
+ mfc_write(dev, (S5P_FIMV_CH_FRAME_START << 16 & 0x70000) |
+ (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
+ return 0;
+}
+
+static int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev)
+{
+ unsigned long flags;
+ int new_ctx;
+ int cnt;
+
+ spin_lock_irqsave(&dev->condlock, flags);
+ new_ctx = (dev->curr_ctx + 1) % MFC_NUM_CONTEXTS;
+ cnt = 0;
+ while (!test_bit(new_ctx, &dev->ctx_work_bits)) {
+ new_ctx = (new_ctx + 1) % MFC_NUM_CONTEXTS;
+ if (++cnt > MFC_NUM_CONTEXTS) {
+ /* No contexts to run */
+ spin_unlock_irqrestore(&dev->condlock, flags);
+ return -EAGAIN;
+ }
+ }
+ spin_unlock_irqrestore(&dev->condlock, flags);
+ return new_ctx;
+}
+
+static void s5p_mfc_run_res_change(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+
+ s5p_mfc_set_dec_stream_buffer_v5(ctx, 0, 0, 0);
+ dev->curr_ctx = ctx->num;
+ s5p_mfc_clean_ctx_int_flags(ctx);
+ s5p_mfc_decode_one_frame_v5(ctx, MFC_DEC_RES_CHANGE);
+}
+
+static int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx, int last_frame)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ struct s5p_mfc_buf *temp_vb;
+ unsigned long flags;
+ unsigned int index;
+
+ spin_lock_irqsave(&dev->irqlock, flags);
+ /* Frames are being decoded */
+ if (list_empty(&ctx->src_queue)) {
+ mfc_debug(2, "No src buffers\n");
+ spin_unlock_irqrestore(&dev->irqlock, flags);
+ return -EAGAIN;
+ }
+ /* Get the next source buffer */
+ temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+ temp_vb->used = 1;
+ s5p_mfc_set_dec_stream_buffer_v5(ctx,
+ vb2_dma_contig_plane_dma_addr(temp_vb->b, 0),
+ ctx->consumed_stream,
+ temp_vb->b->v4l2_planes[0].bytesused);
+ spin_unlock_irqrestore(&dev->irqlock, flags);
+ index = temp_vb->b->v4l2_buf.index;
+ dev->curr_ctx = ctx->num;
+ s5p_mfc_clean_ctx_int_flags(ctx);
+ if (temp_vb->b->v4l2_planes[0].bytesused == 0) {
+ last_frame = MFC_DEC_LAST_FRAME;
+ mfc_debug(2, "Setting ctx->state to FINISHING\n");
+ ctx->state = MFCINST_FINISHING;
+ }
+ s5p_mfc_decode_one_frame_v5(ctx, last_frame);
+ return 0;
+}
+
+static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ unsigned long flags;
+ struct s5p_mfc_buf *dst_mb;
+ struct s5p_mfc_buf *src_mb;
+ unsigned long src_y_addr, src_c_addr, dst_addr;
+ unsigned int dst_size;
+
+ spin_lock_irqsave(&dev->irqlock, flags);
+ if (list_empty(&ctx->src_queue)) {
+ mfc_debug(2, "no src buffers\n");
+ spin_unlock_irqrestore(&dev->irqlock, flags);
+ return -EAGAIN;
+ }
+ if (list_empty(&ctx->dst_queue)) {
+ mfc_debug(2, "no dst buffers\n");
+ spin_unlock_irqrestore(&dev->irqlock, flags);
+ return -EAGAIN;
+ }
+ src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+ src_mb->used = 1;
+ src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 0);
+ src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1);
+ s5p_mfc_set_enc_frame_buffer_v5(ctx, src_y_addr, src_c_addr);
+ dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
+ dst_mb->used = 1;
+ dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
+ dst_size = vb2_plane_size(dst_mb->b, 0);
+ s5p_mfc_set_enc_stream_buffer_v5(ctx, dst_addr, dst_size);
+ spin_unlock_irqrestore(&dev->irqlock, flags);
+ dev->curr_ctx = ctx->num;
+ s5p_mfc_clean_ctx_int_flags(ctx);
+ s5p_mfc_encode_one_frame_v5(ctx);
+ return 0;
+}
+
+static void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ unsigned long flags;
+ struct s5p_mfc_buf *temp_vb;
+
+ /* Initializing decoding - parsing header */
+ spin_lock_irqsave(&dev->irqlock, flags);
+ mfc_debug(2, "Preparing to init decoding\n");
+ temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+ s5p_mfc_set_dec_desc_buffer(ctx);
+ mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused);
+ s5p_mfc_set_dec_stream_buffer_v5(ctx,
+ vb2_dma_contig_plane_dma_addr(temp_vb->b, 0),
+ 0, temp_vb->b->v4l2_planes[0].bytesused);
+ spin_unlock_irqrestore(&dev->irqlock, flags);
+ dev->curr_ctx = ctx->num;
+ s5p_mfc_clean_ctx_int_flags(ctx);
+ s5p_mfc_init_decode_v5(ctx);
+}
+
+static void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ unsigned long flags;
+ struct s5p_mfc_buf *dst_mb;
+ unsigned long dst_addr;
+ unsigned int dst_size;
+
+ s5p_mfc_set_enc_ref_buffer_v5(ctx);
+ spin_lock_irqsave(&dev->irqlock, flags);
+ dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
+ dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
+ dst_size = vb2_plane_size(dst_mb->b, 0);
+ s5p_mfc_set_enc_stream_buffer_v5(ctx, dst_addr, dst_size);
+ spin_unlock_irqrestore(&dev->irqlock, flags);
+ dev->curr_ctx = ctx->num;
+ s5p_mfc_clean_ctx_int_flags(ctx);
+ s5p_mfc_init_encode_v5(ctx);
+}
+
+static int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ unsigned long flags;
+ struct s5p_mfc_buf *temp_vb;
+ int ret;
+
+ /*
+ * Header was parsed now starting processing
+ * First set the output frame buffers
+ */
+ if (ctx->capture_state != QUEUE_BUFS_MMAPED) {
+ mfc_err("It seems that not all destionation buffers were\n"
+ "mmaped\nMFC requires that all destination are\n"
+ "mmaped before starting processing\n");
+ return -EAGAIN;
+ }
+ spin_lock_irqsave(&dev->irqlock, flags);
+ if (list_empty(&ctx->src_queue)) {
+ mfc_err("Header has been deallocated in the middle of\n"
+ " initialization\n");
+ spin_unlock_irqrestore(&dev->irqlock, flags);
+ return -EIO;
+ }
+ temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+ mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused);
+ s5p_mfc_set_dec_stream_buffer_v5(ctx,
+ vb2_dma_contig_plane_dma_addr(temp_vb->b, 0),
+ 0, temp_vb->b->v4l2_planes[0].bytesused);
+ spin_unlock_irqrestore(&dev->irqlock, flags);
+ dev->curr_ctx = ctx->num;
+ s5p_mfc_clean_ctx_int_flags(ctx);
+ ret = s5p_mfc_set_dec_frame_buffer_v5(ctx);
+ if (ret) {
+ mfc_err("Failed to alloc frame mem\n");
+ ctx->state = MFCINST_ERROR;
+ }
+ return ret;
+}
+
+/* Try running an operation on hardware */
+void s5p_mfc_try_run_v5(struct s5p_mfc_dev *dev)
+{
+ struct s5p_mfc_ctx *ctx;
+ int new_ctx;
+ unsigned int ret = 0;
+
+ if (test_bit(0, &dev->enter_suspend)) {
+ mfc_debug(1, "Entering suspend so do not schedule any jobs\n");
+ return;
+ }
+ /* Check whether hardware is not running */
+ if (test_and_set_bit(0, &dev->hw_lock) != 0) {
+ /* This is perfectly ok, the scheduled ctx should wait */
+ mfc_debug(1, "Couldn't lock HW\n");
+ return;
+ }
+ /* Choose the context to run */
+ new_ctx = s5p_mfc_get_new_ctx(dev);
+ if (new_ctx < 0) {
+ /* No contexts to run */
+ if (test_and_clear_bit(0, &dev->hw_lock) == 0) {
+ mfc_err("Failed to unlock hardware\n");
+ return;
+ }
+ mfc_debug(1, "No ctx is scheduled to be run\n");
+ return;
+ }
+ ctx = dev->ctx[new_ctx];
+ /* Got context to run in ctx */
+ /*
+ * Last frame has already been sent to MFC.
+ * Now obtaining frames from MFC buffer
+ */
+ s5p_mfc_clock_on();
+ if (ctx->type == MFCINST_DECODER) {
+ s5p_mfc_set_dec_desc_buffer(ctx);
+ switch (ctx->state) {
+ case MFCINST_FINISHING:
+ s5p_mfc_run_dec_frame(ctx, MFC_DEC_LAST_FRAME);
+ break;
+ case MFCINST_RUNNING:
+ ret = s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME);
+ break;
+ case MFCINST_INIT:
+ s5p_mfc_clean_ctx_int_flags(ctx);
+ ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
+ ctx);
+ break;
+ case MFCINST_RETURN_INST:
+ s5p_mfc_clean_ctx_int_flags(ctx);
+ ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
+ ctx);
+ break;
+ case MFCINST_GOT_INST:
+ s5p_mfc_run_init_dec(ctx);
+ break;
+ case MFCINST_HEAD_PARSED:
+ ret = s5p_mfc_run_init_dec_buffers(ctx);
+ mfc_debug(1, "head parsed\n");
+ break;
+ case MFCINST_RES_CHANGE_INIT:
+ s5p_mfc_run_res_change(ctx);
+ break;
+ case MFCINST_RES_CHANGE_FLUSH:
+ s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME);
+ break;
+ case MFCINST_RES_CHANGE_END:
+ mfc_debug(2, "Finished remaining frames after resolution change\n");
+ ctx->capture_state = QUEUE_FREE;
+ mfc_debug(2, "Will re-init the codec\n");
+ s5p_mfc_run_init_dec(ctx);
+ break;
+ default:
+ ret = -EAGAIN;
+ }
+ } else if (ctx->type == MFCINST_ENCODER) {
+ switch (ctx->state) {
+ case MFCINST_FINISHING:
+ case MFCINST_RUNNING:
+ ret = s5p_mfc_run_enc_frame(ctx);
+ break;
+ case MFCINST_INIT:
+ s5p_mfc_clean_ctx_int_flags(ctx);
+ ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
+ ctx);
+ break;
+ case MFCINST_RETURN_INST:
+ s5p_mfc_clean_ctx_int_flags(ctx);
+ ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
+ ctx);
+ break;
+ case MFCINST_GOT_INST:
+ s5p_mfc_run_init_enc(ctx);
+ break;
+ default:
+ ret = -EAGAIN;
+ }
+ } else {
+ mfc_err("Invalid context type: %d\n", ctx->type);
+ ret = -EAGAIN;
+ }
+
+ if (ret) {
+ /* Free hardware lock */
+ if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+ mfc_err("Failed to unlock hardware\n");
+
+ /* This is in deed imporant, as no operation has been
+ * scheduled, reduce the clock count as no one will
+ * ever do this, because no interrupt related to this try_run
+ * will ever come from hardware. */
+ s5p_mfc_clock_off();
+ }
+}
+
+
+void s5p_mfc_cleanup_queue_v5(struct list_head *lh, struct vb2_queue *vq)
+{
+ struct s5p_mfc_buf *b;
+ int i;
+
+ while (!list_empty(lh)) {
+ b = list_entry(lh->next, struct s5p_mfc_buf, list);
+ for (i = 0; i < b->b->num_planes; i++)
+ vb2_set_plane_payload(b->b, i, 0);
+ vb2_buffer_done(b->b, VB2_BUF_STATE_ERROR);
+ list_del(&b->list);
+ }
+}
+
+void s5p_mfc_clear_int_flags_v5(struct s5p_mfc_dev *dev)
+{
+ mfc_write(dev, 0, S5P_FIMV_RISC_HOST_INT);
+ mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
+ mfc_write(dev, 0xffff, S5P_FIMV_SI_RTN_CHID);
+}
+
+int s5p_mfc_get_dspl_y_adr_v5(struct s5p_mfc_dev *dev)
+{
+ return mfc_read(dev, S5P_FIMV_SI_DISPLAY_Y_ADR) << MFC_OFFSET_SHIFT;
+}
+
+int s5p_mfc_get_dec_y_adr_v5(struct s5p_mfc_dev *dev)
+{
+ return mfc_read(dev, S5P_FIMV_SI_DECODE_Y_ADR) << MFC_OFFSET_SHIFT;
+}
+
+int s5p_mfc_get_dspl_status_v5(struct s5p_mfc_dev *dev)
+{
+ return mfc_read(dev, S5P_FIMV_SI_DISPLAY_STATUS);
+}
+
+int s5p_mfc_get_dec_status_v5(struct s5p_mfc_dev *dev)
+{
+ return mfc_read(dev, S5P_FIMV_SI_DECODE_STATUS);
+}
+
+int s5p_mfc_get_dec_frame_type_v5(struct s5p_mfc_dev *dev)
+{
+ return mfc_read(dev, S5P_FIMV_DECODE_FRAME_TYPE) &
+ S5P_FIMV_DECODE_FRAME_MASK;
+}
+
+int s5p_mfc_get_disp_frame_type_v5(struct s5p_mfc_ctx *ctx)
+{
+ /* NOP */
+ return -1;
+}
+
+int s5p_mfc_get_consumed_stream_v5(struct s5p_mfc_dev *dev)
+{
+ return mfc_read(dev, S5P_FIMV_SI_CONSUMED_BYTES);
+}
+
+int s5p_mfc_get_int_reason_v5(struct s5p_mfc_dev *dev)
+{
+ int reason;
+ reason = mfc_read(dev, S5P_FIMV_RISC2HOST_CMD) &
+ S5P_FIMV_RISC2HOST_CMD_MASK;
+ switch (reason) {
+ case S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET:
+ reason = S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET;
+ break;
+ case S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET:
+ reason = S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET;
+ break;
+ case S5P_FIMV_R2H_CMD_SEQ_DONE_RET:
+ reason = S5P_MFC_R2H_CMD_SEQ_DONE_RET;
+ break;
+ case S5P_FIMV_R2H_CMD_FRAME_DONE_RET:
+ reason = S5P_MFC_R2H_CMD_FRAME_DONE_RET;
+ break;
+ case S5P_FIMV_R2H_CMD_SLICE_DONE_RET:
+ reason = S5P_MFC_R2H_CMD_SLICE_DONE_RET;
+ break;
+ case S5P_FIMV_R2H_CMD_SYS_INIT_RET:
+ reason = S5P_MFC_R2H_CMD_SYS_INIT_RET;
+ break;
+ case S5P_FIMV_R2H_CMD_FW_STATUS_RET:
+ reason = S5P_MFC_R2H_CMD_FW_STATUS_RET;
+ break;
+ case S5P_FIMV_R2H_CMD_SLEEP_RET:
+ reason = S5P_MFC_R2H_CMD_SLEEP_RET;
+ break;
+ case S5P_FIMV_R2H_CMD_WAKEUP_RET:
+ reason = S5P_MFC_R2H_CMD_WAKEUP_RET;
+ break;
+ case S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET:
+ reason = S5P_MFC_R2H_CMD_INIT_BUFFERS_RET;
+ break;
+ case S5P_FIMV_R2H_CMD_ERR_RET:
+ reason = S5P_MFC_R2H_CMD_ERR_RET;
+ break;
+ default:
+ reason = S5P_MFC_R2H_CMD_EMPTY;
+ };
+ return reason;
+}
+
+int s5p_mfc_get_int_err_v5(struct s5p_mfc_dev *dev)
+{
+ return mfc_read(dev, S5P_FIMV_RISC2HOST_ARG2);
+}
+
+int s5p_mfc_err_dec_v5(unsigned int err)
+{
+ return (err & S5P_FIMV_ERR_DEC_MASK) >> S5P_FIMV_ERR_DEC_SHIFT;
+}
+
+int s5p_mfc_err_dspl_v5(unsigned int err)
+{
+ return (err & S5P_FIMV_ERR_DSPL_MASK) >> S5P_FIMV_ERR_DSPL_SHIFT;
+}
+
+int s5p_mfc_get_img_width_v5(struct s5p_mfc_dev *dev)
+{
+ return mfc_read(dev, S5P_FIMV_SI_HRESOL);
+}
+
+int s5p_mfc_get_img_height_v5(struct s5p_mfc_dev *dev)
+{
+ return mfc_read(dev, S5P_FIMV_SI_VRESOL);
+}
+
+int s5p_mfc_get_dpb_count_v5(struct s5p_mfc_dev *dev)
+{
+ return mfc_read(dev, S5P_FIMV_SI_BUF_NUMBER);
+}
+
+int s5p_mfc_get_mv_count_v5(struct s5p_mfc_dev *dev)
+{
+ /* NOP */
+ return -1;
+}
+
+int s5p_mfc_get_inst_no_v5(struct s5p_mfc_dev *dev)
+{
+ return mfc_read(dev, S5P_FIMV_RISC2HOST_ARG1);
+}
+
+int s5p_mfc_get_enc_strm_size_v5(struct s5p_mfc_dev *dev)
+{
+ return mfc_read(dev, S5P_FIMV_ENC_SI_STRM_SIZE);
+}
+
+int s5p_mfc_get_enc_slice_type_v5(struct s5p_mfc_dev *dev)
+{
+ return mfc_read(dev, S5P_FIMV_ENC_SI_SLICE_TYPE);
+}
+
+int s5p_mfc_get_enc_dpb_count_v5(struct s5p_mfc_dev *dev)
+{
+ return -1;
+}
+
+int s5p_mfc_get_enc_pic_count_v5(struct s5p_mfc_dev *dev)
+{
+ return mfc_read(dev, S5P_FIMV_ENC_SI_PIC_CNT);
+}
+
+int s5p_mfc_get_sei_avail_status_v5(struct s5p_mfc_ctx *ctx)
+{
+ return s5p_mfc_read_info_v5(ctx, FRAME_PACK_SEI_AVAIL);
+}
+
+int s5p_mfc_get_mvc_num_views_v5(struct s5p_mfc_dev *dev)
+{
+ return -1;
+}
+
+int s5p_mfc_get_mvc_view_id_v5(struct s5p_mfc_dev *dev)
+{
+ return -1;
+}
+
+unsigned int s5p_mfc_get_pic_type_top_v5(struct s5p_mfc_ctx *ctx)
+{
+ return s5p_mfc_read_info_v5(ctx, PIC_TIME_TOP);
+}
+
+unsigned int s5p_mfc_get_pic_type_bot_v5(struct s5p_mfc_ctx *ctx)
+{
+ return s5p_mfc_read_info_v5(ctx, PIC_TIME_BOT);
+}
+
+unsigned int s5p_mfc_get_crop_info_h_v5(struct s5p_mfc_ctx *ctx)
+{
+ return s5p_mfc_read_info_v5(ctx, CROP_INFO_H);
+}
+
+unsigned int s5p_mfc_get_crop_info_v_v5(struct s5p_mfc_ctx *ctx)
+{
+ return s5p_mfc_read_info_v5(ctx, CROP_INFO_V);
+}
+
+/* Initialize opr function pointers for MFC v5 */
+static struct s5p_mfc_hw_ops s5p_mfc_ops_v5 = {
+ .alloc_dec_temp_buffers = s5p_mfc_alloc_dec_temp_buffers_v5,
+ .release_dec_desc_buffer = s5p_mfc_release_dec_desc_buffer_v5,
+ .alloc_codec_buffers = s5p_mfc_alloc_codec_buffers_v5,
+ .release_codec_buffers = s5p_mfc_release_codec_buffers_v5,
+ .alloc_instance_buffer = s5p_mfc_alloc_instance_buffer_v5,
+ .release_instance_buffer = s5p_mfc_release_instance_buffer_v5,
+ .alloc_dev_context_buffer = s5p_mfc_alloc_dev_context_buffer_v5,
+ .release_dev_context_buffer = s5p_mfc_release_dev_context_buffer_v5,
+ .dec_calc_dpb_size = s5p_mfc_dec_calc_dpb_size_v5,
+ .enc_calc_src_size = s5p_mfc_enc_calc_src_size_v5,
+ .set_dec_stream_buffer = s5p_mfc_set_dec_stream_buffer_v5,
+ .set_dec_frame_buffer = s5p_mfc_set_dec_frame_buffer_v5,
+ .set_enc_stream_buffer = s5p_mfc_set_enc_stream_buffer_v5,
+ .set_enc_frame_buffer = s5p_mfc_set_enc_frame_buffer_v5,
+ .get_enc_frame_buffer = s5p_mfc_get_enc_frame_buffer_v5,
+ .set_enc_ref_buffer = s5p_mfc_set_enc_ref_buffer_v5,
+ .init_decode = s5p_mfc_init_decode_v5,
+ .init_encode = s5p_mfc_init_encode_v5,
+ .encode_one_frame = s5p_mfc_encode_one_frame_v5,
+ .try_run = s5p_mfc_try_run_v5,
+ .cleanup_queue = s5p_mfc_cleanup_queue_v5,
+ .clear_int_flags = s5p_mfc_clear_int_flags_v5,
+ .write_info = s5p_mfc_write_info_v5,
+ .read_info = s5p_mfc_read_info_v5,
+ .get_dspl_y_adr = s5p_mfc_get_dspl_y_adr_v5,
+ .get_dec_y_adr = s5p_mfc_get_dec_y_adr_v5,
+ .get_dspl_status = s5p_mfc_get_dspl_status_v5,
+ .get_dec_status = s5p_mfc_get_dec_status_v5,
+ .get_dec_frame_type = s5p_mfc_get_dec_frame_type_v5,
+ .get_disp_frame_type = s5p_mfc_get_disp_frame_type_v5,
+ .get_consumed_stream = s5p_mfc_get_consumed_stream_v5,
+ .get_int_reason = s5p_mfc_get_int_reason_v5,
+ .get_int_err = s5p_mfc_get_int_err_v5,
+ .err_dec = s5p_mfc_err_dec_v5,
+ .err_dspl = s5p_mfc_err_dspl_v5,
+ .get_img_width = s5p_mfc_get_img_width_v5,
+ .get_img_height = s5p_mfc_get_img_height_v5,
+ .get_dpb_count = s5p_mfc_get_dpb_count_v5,
+ .get_mv_count = s5p_mfc_get_mv_count_v5,
+ .get_inst_no = s5p_mfc_get_inst_no_v5,
+ .get_enc_strm_size = s5p_mfc_get_enc_strm_size_v5,
+ .get_enc_slice_type = s5p_mfc_get_enc_slice_type_v5,
+ .get_enc_dpb_count = s5p_mfc_get_enc_dpb_count_v5,
+ .get_enc_pic_count = s5p_mfc_get_enc_pic_count_v5,
+ .get_sei_avail_status = s5p_mfc_get_sei_avail_status_v5,
+ .get_mvc_num_views = s5p_mfc_get_mvc_num_views_v5,
+ .get_mvc_view_id = s5p_mfc_get_mvc_view_id_v5,
+ .get_pic_type_top = s5p_mfc_get_pic_type_top_v5,
+ .get_pic_type_bot = s5p_mfc_get_pic_type_bot_v5,
+ .get_crop_info_h = s5p_mfc_get_crop_info_h_v5,
+ .get_crop_info_v = s5p_mfc_get_crop_info_v_v5,
+};
+
+struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v5(void)
+{
+ return &s5p_mfc_ops_v5;
+}
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.h b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.h
new file mode 100644
index 0000000..19917de
--- /dev/null
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.h
@@ -0,0 +1,85 @@
+/*
+ * drivers/media/video/samsung/mfc5/s5p_mfc_opr_v5.h
+ *
+ * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
+ * Contains declarations of hw related functions.
+ *
+ * Kamil Debski, Copyright (C) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef S5P_MFC_OPR_V5_H_
+#define S5P_MFC_OPR_V5_H_
+
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_opr.h"
+
+enum MFC_SHM_OFS {
+ EXTENEDED_DECODE_STATUS = 0x00, /* D */
+ SET_FRAME_TAG = 0x04, /* D */
+ GET_FRAME_TAG_TOP = 0x08, /* D */
+ GET_FRAME_TAG_BOT = 0x0C, /* D */
+ PIC_TIME_TOP = 0x10, /* D */
+ PIC_TIME_BOT = 0x14, /* D */
+ START_BYTE_NUM = 0x18, /* D */
+
+ CROP_INFO_H = 0x20, /* D */
+ CROP_INFO_V = 0x24, /* D */
+ EXT_ENC_CONTROL = 0x28, /* E */
+ ENC_PARAM_CHANGE = 0x2C, /* E */
+ RC_VOP_TIMING = 0x30, /* E, MPEG4 */
+ HEC_PERIOD = 0x34, /* E, MPEG4 */
+ METADATA_ENABLE = 0x38, /* C */
+ METADATA_STATUS = 0x3C, /* C */
+ METADATA_DISPLAY_INDEX = 0x40, /* C */
+ EXT_METADATA_START_ADDR = 0x44, /* C */
+ PUT_EXTRADATA = 0x48, /* C */
+ EXTRADATA_ADDR = 0x4C, /* C */
+
+ ALLOC_LUMA_DPB_SIZE = 0x64, /* D */
+ ALLOC_CHROMA_DPB_SIZE = 0x68, /* D */
+ ALLOC_MV_SIZE = 0x6C, /* D */
+ P_B_FRAME_QP = 0x70, /* E */
+ SAMPLE_ASPECT_RATIO_IDC = 0x74, /* E, H.264, depend on
+ ASPECT_RATIO_VUI_ENABLE in EXT_ENC_CONTROL */
+ EXTENDED_SAR = 0x78, /* E, H.264, depned on
+ ASPECT_RATIO_VUI_ENABLE in EXT_ENC_CONTROL */
+ DISP_PIC_PROFILE = 0x7C, /* D */
+ FLUSH_CMD_TYPE = 0x80, /* C */
+ FLUSH_CMD_INBUF1 = 0x84, /* C */
+ FLUSH_CMD_INBUF2 = 0x88, /* C */
+ FLUSH_CMD_OUTBUF = 0x8C, /* E */
+ NEW_RC_BIT_RATE = 0x90, /* E, format as RC_BIT_RATE(0xC5A8)
+ depend on RC_BIT_RATE_CHANGE in ENC_PARAM_CHANGE */
+ NEW_RC_FRAME_RATE = 0x94, /* E, format as RC_FRAME_RATE(0xD0D0)
+ depend on RC_FRAME_RATE_CHANGE in ENC_PARAM_CHANGE */
+ NEW_I_PERIOD = 0x98, /* E, format as I_FRM_CTRL(0xC504)
+ depend on I_PERIOD_CHANGE in ENC_PARAM_CHANGE */
+ H264_I_PERIOD = 0x9C, /* E, H.264, open GOP */
+ RC_CONTROL_CONFIG = 0xA0, /* E */
+ BATCH_INPUT_ADDR = 0xA4, /* E */
+ BATCH_OUTPUT_ADDR = 0xA8, /* E */
+ BATCH_OUTPUT_SIZE = 0xAC, /* E */
+ MIN_LUMA_DPB_SIZE = 0xB0, /* D */
+ DEVICE_FORMAT_ID = 0xB4, /* C */
+ H264_POC_TYPE = 0xB8, /* D */
+ MIN_CHROMA_DPB_SIZE = 0xBC, /* D */
+ DISP_PIC_FRAME_TYPE = 0xC0, /* D */
+ FREE_LUMA_DPB = 0xC4, /* D, VC1 MPEG4 */
+ ASPECT_RATIO_INFO = 0xC8, /* D, MPEG4 */
+ EXTENDED_PAR = 0xCC, /* D, MPEG4 */
+ DBG_HISTORY_INPUT0 = 0xD0, /* C */
+ DBG_HISTORY_INPUT1 = 0xD4, /* C */
+ DBG_HISTORY_OUTPUT = 0xD8, /* C */
+ HIERARCHICAL_P_QP = 0xE0, /* E, H.264 */
+ FRAME_PACK_SEI_ENABLE = 0x168, /* C */
+ FRAME_PACK_SEI_AVAIL = 0x16c, /* D */
+ FRAME_PACK_SEI_INFO = 0x17c, /* E */
+};
+
+struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v5(void);
+#endif /* S5P_MFC_OPR_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_shm.c b/drivers/media/platform/s5p-mfc/s5p_mfc_shm.c
deleted file mode 100644
index b5933d2..0000000
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_shm.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * linux/drivers/media/platform/s5p-mfc/s5p_mfc_shm.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifdef CONFIG_ARCH_EXYNOS4
-#include <linux/dma-mapping.h>
-#endif
-#include <linux/io.h>
-#include "s5p_mfc_common.h"
-#include "s5p_mfc_debug.h"
-
-int s5p_mfc_init_shm(struct s5p_mfc_ctx *ctx)
-{
- struct s5p_mfc_dev *dev = ctx->dev;
- void *shm_alloc_ctx = dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
-
- ctx->shm_alloc = vb2_dma_contig_memops.alloc(shm_alloc_ctx,
- SHARED_BUF_SIZE);
- if (IS_ERR(ctx->shm_alloc)) {
- mfc_err("failed to allocate shared memory\n");
- return PTR_ERR(ctx->shm_alloc);
- }
- /* shm_ofs only keeps the offset from base (port a) */
- ctx->shm_ofs = s5p_mfc_mem_cookie(shm_alloc_ctx, ctx->shm_alloc)
- - dev->bank1;
- BUG_ON(ctx->shm_ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
- ctx->shm = vb2_dma_contig_memops.vaddr(ctx->shm_alloc);
- if (!ctx->shm) {
- vb2_dma_contig_memops.put(ctx->shm_alloc);
- ctx->shm_ofs = 0;
- ctx->shm_alloc = NULL;
- mfc_err("failed to virt addr of shared memory\n");
- return -ENOMEM;
- }
- memset((void *)ctx->shm, 0, SHARED_BUF_SIZE);
- wmb();
- return 0;
-}
-
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_shm.h b/drivers/media/platform/s5p-mfc/s5p_mfc_shm.h
deleted file mode 100644
index 416ebd7..0000000
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_shm.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * linux/drivers/media/platform/s5p-mfc/s5p_mfc_shm.h
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef S5P_MFC_SHM_H_
-#define S5P_MFC_SHM_H_
-
-enum MFC_SHM_OFS {
- EXTENEDED_DECODE_STATUS = 0x00, /* D */
- SET_FRAME_TAG = 0x04, /* D */
- GET_FRAME_TAG_TOP = 0x08, /* D */
- GET_FRAME_TAG_BOT = 0x0C, /* D */
- PIC_TIME_TOP = 0x10, /* D */
- PIC_TIME_BOT = 0x14, /* D */
- START_BYTE_NUM = 0x18, /* D */
-
- CROP_INFO_H = 0x20, /* D */
- CROP_INFO_V = 0x24, /* D */
- EXT_ENC_CONTROL = 0x28, /* E */
- ENC_PARAM_CHANGE = 0x2C, /* E */
- RC_VOP_TIMING = 0x30, /* E, MPEG4 */
- HEC_PERIOD = 0x34, /* E, MPEG4 */
- METADATA_ENABLE = 0x38, /* C */
- METADATA_STATUS = 0x3C, /* C */
- METADATA_DISPLAY_INDEX = 0x40, /* C */
- EXT_METADATA_START_ADDR = 0x44, /* C */
- PUT_EXTRADATA = 0x48, /* C */
- EXTRADATA_ADDR = 0x4C, /* C */
-
- ALLOC_LUMA_DPB_SIZE = 0x64, /* D */
- ALLOC_CHROMA_DPB_SIZE = 0x68, /* D */
- ALLOC_MV_SIZE = 0x6C, /* D */
- P_B_FRAME_QP = 0x70, /* E */
- SAMPLE_ASPECT_RATIO_IDC = 0x74, /* E, H.264, depend on
- ASPECT_RATIO_VUI_ENABLE in EXT_ENC_CONTROL */
- EXTENDED_SAR = 0x78, /* E, H.264, depned on
- ASPECT_RATIO_VUI_ENABLE in EXT_ENC_CONTROL */
- DISP_PIC_PROFILE = 0x7C, /* D */
- FLUSH_CMD_TYPE = 0x80, /* C */
- FLUSH_CMD_INBUF1 = 0x84, /* C */
- FLUSH_CMD_INBUF2 = 0x88, /* C */
- FLUSH_CMD_OUTBUF = 0x8C, /* E */
- NEW_RC_BIT_RATE = 0x90, /* E, format as RC_BIT_RATE(0xC5A8)
- depend on RC_BIT_RATE_CHANGE in ENC_PARAM_CHANGE */
- NEW_RC_FRAME_RATE = 0x94, /* E, format as RC_FRAME_RATE(0xD0D0)
- depend on RC_FRAME_RATE_CHANGE in ENC_PARAM_CHANGE */
- NEW_I_PERIOD = 0x98, /* E, format as I_FRM_CTRL(0xC504)
- depend on I_PERIOD_CHANGE in ENC_PARAM_CHANGE */
- H264_I_PERIOD = 0x9C, /* E, H.264, open GOP */
- RC_CONTROL_CONFIG = 0xA0, /* E */
- BATCH_INPUT_ADDR = 0xA4, /* E */
- BATCH_OUTPUT_ADDR = 0xA8, /* E */
- BATCH_OUTPUT_SIZE = 0xAC, /* E */
- MIN_LUMA_DPB_SIZE = 0xB0, /* D */
- DEVICE_FORMAT_ID = 0xB4, /* C */
- H264_POC_TYPE = 0xB8, /* D */
- MIN_CHROMA_DPB_SIZE = 0xBC, /* D */
- DISP_PIC_FRAME_TYPE = 0xC0, /* D */
- FREE_LUMA_DPB = 0xC4, /* D, VC1 MPEG4 */
- ASPECT_RATIO_INFO = 0xC8, /* D, MPEG4 */
- EXTENDED_PAR = 0xCC, /* D, MPEG4 */
- DBG_HISTORY_INPUT0 = 0xD0, /* C */
- DBG_HISTORY_INPUT1 = 0xD4, /* C */
- DBG_HISTORY_OUTPUT = 0xD8, /* C */
- HIERARCHICAL_P_QP = 0xE0, /* E, H.264 */
-};
-
-int s5p_mfc_init_shm(struct s5p_mfc_ctx *ctx);
-
-#define s5p_mfc_write_shm(ctx, x, ofs) \
- do { \
- writel(x, (ctx->shm + ofs)); \
- wmb(); \
- } while (0)
-
-static inline u32 s5p_mfc_read_shm(struct s5p_mfc_ctx *ctx, unsigned int ofs)
-{
- rmb();
- return readl(ctx->shm + ofs);
-}
-
-#endif /* S5P_MFC_SHM_H_ */
--
1.7.0.4
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v9 4/6] [media] s5p-mfc: Add MFC variant data to device context
2012-10-02 14:55 [PATCH v9 0/6] Update MFC v4l2 driver to support MFC6.x Arun Kumar K
` (3 preceding siblings ...)
2012-10-02 14:55 ` [PATCH v9 3/6] [media] s5p-mfc: Update MFCv5 driver for callback based architecture Arun Kumar K
@ 2012-10-02 14:55 ` Arun Kumar K
2012-10-02 11:16 ` Kamil Debski
2012-10-02 14:55 ` [PATCH v9 5/6] [media] s5p-mfc: MFCv6 register definitions Arun Kumar K
2012-10-02 14:55 ` [PATCH v9 6/6] [media] s5p-mfc: Update MFC v4l2 driver to support MFC6.x Arun Kumar K
6 siblings, 1 reply; 15+ messages in thread
From: Arun Kumar K @ 2012-10-02 14:55 UTC (permalink / raw)
To: linux-media
Cc: k.debski, jtp.park, janghyuck.kim, jaeryul.oh, ch.naveen, arun.kk,
m.szyprowski, s.nawrocki, hverkuil, kmpark, joshi
MFC variant data replaces various macros used in the driver
which will change in a different version of MFC hardware.
Also does a cleanup of MFC context structure and common files.
Signed-off-by: Jeongtae Park <jtp.park@samsung.com>
Signed-off-by: Janghyuck Kim <janghyuck.kim@samsung.com>
Signed-off-by: Jaeryul Oh <jaeryul.oh@samsung.com>
Signed-off-by: Naveen Krishna Chatradhi <ch.naveen@samsung.com>
Signed-off-by: Arun Kumar K <arun.kk@samsung.com>
---
drivers/media/platform/s5p-mfc/regs-mfc.h | 20 ++
drivers/media/platform/s5p-mfc/s5p_mfc.c | 78 +++++----
drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c | 4 +-
drivers/media/platform/s5p-mfc/s5p_mfc_common.h | 85 ++++++----
drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c | 7 +-
drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | 44 +----
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c | 213 +++++++++++++++--------
7 files changed, 266 insertions(+), 185 deletions(-)
diff --git a/drivers/media/platform/s5p-mfc/regs-mfc.h b/drivers/media/platform/s5p-mfc/regs-mfc.h
index a19bece..f33c54d 100644
--- a/drivers/media/platform/s5p-mfc/regs-mfc.h
+++ b/drivers/media/platform/s5p-mfc/regs-mfc.h
@@ -12,6 +12,9 @@
#ifndef _REGS_FIMV_H
#define _REGS_FIMV_H
+#include <linux/kernel.h>
+#include <linux/sizes.h>
+
#define S5P_FIMV_REG_SIZE (S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR)
#define S5P_FIMV_REG_COUNT ((S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR) / 4)
@@ -414,5 +417,22 @@
#define S5P_FIMV_SHARED_EXTENDED_SAR 0x0078
#define S5P_FIMV_SHARED_H264_I_PERIOD 0x009C
#define S5P_FIMV_SHARED_RC_CONTROL_CONFIG 0x00A0
+#define S5P_FIMV_SHARED_DISP_FRAME_TYPE_SHIFT 2
+
+/* Offset used by the hardware to store addresses */
+#define MFC_OFFSET_SHIFT 11
+
+#define FIRMWARE_ALIGN (128 * SZ_1K) /* 128KB */
+#define MFC_H264_CTX_BUF_SIZE (600 * SZ_1K) /* 600KB per H264 instance */
+#define MFC_CTX_BUF_SIZE (10 * SZ_1K) /* 10KB per instance */
+#define DESC_BUF_SIZE (128 * SZ_1K) /* 128KB for DESC buffer */
+#define SHARED_BUF_SIZE (8 * SZ_1K) /* 8KB for shared buffer */
+
+#define DEF_CPB_SIZE (256 * SZ_1K) /* 256KB */
+#define MAX_CPB_SIZE (4 * SZ_1M) /* 4MB */
+#define MAX_FW_SIZE (384 * SZ_1K)
+
+#define MFC_VERSION 0x51
+#define MFC_NUM_PORTS 2
#endif /* _REGS_FIMV_H */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index 3319410..a8299ce 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -436,7 +436,6 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx,
unsigned int reason, unsigned int err)
{
struct s5p_mfc_dev *dev;
- unsigned int guard_width, guard_height;
if (ctx == NULL)
return;
@@ -450,40 +449,8 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx,
ctx->img_height = s5p_mfc_hw_call(dev->mfc_ops, get_img_height,
dev);
- ctx->buf_width = ALIGN(ctx->img_width,
- S5P_FIMV_NV12MT_HALIGN);
- ctx->buf_height = ALIGN(ctx->img_height,
- S5P_FIMV_NV12MT_VALIGN);
- mfc_debug(2, "SEQ Done: Movie dimensions %dx%d, "
- "buffer dimensions: %dx%d\n", ctx->img_width,
- ctx->img_height, ctx->buf_width,
- ctx->buf_height);
- if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC) {
- ctx->luma_size = ALIGN(ctx->buf_width *
- ctx->buf_height, S5P_FIMV_DEC_BUF_ALIGN);
- ctx->chroma_size = ALIGN(ctx->buf_width *
- ALIGN((ctx->img_height >> 1),
- S5P_FIMV_NV12MT_VALIGN),
- S5P_FIMV_DEC_BUF_ALIGN);
- ctx->mv_size = ALIGN(ctx->buf_width *
- ALIGN((ctx->buf_height >> 2),
- S5P_FIMV_NV12MT_VALIGN),
- S5P_FIMV_DEC_BUF_ALIGN);
- } else {
- guard_width = ALIGN(ctx->img_width + 24,
- S5P_FIMV_NV12MT_HALIGN);
- guard_height = ALIGN(ctx->img_height + 16,
- S5P_FIMV_NV12MT_VALIGN);
- ctx->luma_size = ALIGN(guard_width *
- guard_height, S5P_FIMV_DEC_BUF_ALIGN);
- guard_width = ALIGN(ctx->img_width + 16,
- S5P_FIMV_NV12MT_HALIGN);
- guard_height = ALIGN((ctx->img_height >> 1) + 4,
- S5P_FIMV_NV12MT_VALIGN);
- ctx->chroma_size = ALIGN(guard_width *
- guard_height, S5P_FIMV_DEC_BUF_ALIGN);
- ctx->mv_size = 0;
- }
+ s5p_mfc_hw_call(dev->mfc_ops, dec_calc_dpb_size, ctx);
+
ctx->dpb_count = s5p_mfc_hw_call(dev->mfc_ops, get_dpb_count,
dev);
if (ctx->img_width == 0 || ctx->img_height == 0)
@@ -993,6 +960,9 @@ static int s5p_mfc_probe(struct platform_device *pdev)
return -ENODEV;
}
+ dev->variant = (struct s5p_mfc_variant *)
+ platform_get_device_id(pdev)->driver_data;
+
ret = s5p_mfc_init_pm(dev);
if (ret < 0) {
dev_err(&pdev->dev, "failed to get mfc clock source\n");
@@ -1235,9 +1205,43 @@ static const struct dev_pm_ops s5p_mfc_pm_ops = {
NULL)
};
+struct s5p_mfc_buf_size_v5 mfc_buf_size_v5 = {
+ .h264_ctx = MFC_H264_CTX_BUF_SIZE,
+ .non_h264_ctx = MFC_CTX_BUF_SIZE,
+ .dsc = DESC_BUF_SIZE,
+ .shm = SHARED_BUF_SIZE,
+};
+
+struct s5p_mfc_buf_size buf_size_v5 = {
+ .fw = MAX_FW_SIZE,
+ .cpb = MAX_CPB_SIZE,
+ .priv = &mfc_buf_size_v5,
+};
+
+struct s5p_mfc_buf_align mfc_buf_align_v5 = {
+ .base = MFC_BASE_ALIGN_ORDER,
+};
+
+static struct s5p_mfc_variant mfc_drvdata_v5 = {
+ .version = MFC_VERSION,
+ .port_num = MFC_NUM_PORTS,
+ .buf_size = &buf_size_v5,
+ .buf_align = &mfc_buf_align_v5,
+};
+
+static struct platform_device_id mfc_driver_ids[] = {
+ {
+ .name = "s5p-mfc",
+ .driver_data = (unsigned long)&mfc_drvdata_v5,
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(platform, mfc_driver_ids);
+
static struct platform_driver s5p_mfc_driver = {
- .probe = s5p_mfc_probe,
- .remove = __devexit_p(s5p_mfc_remove),
+ .probe = s5p_mfc_probe,
+ .remove = __devexit_p(s5p_mfc_remove),
+ .id_table = mfc_driver_ids,
.driver = {
.name = S5P_MFC_NAME,
.owner = THIS_MODULE,
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
index f3d7874..344b31e 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
@@ -113,8 +113,8 @@ int s5p_mfc_open_inst_cmd_v5(struct s5p_mfc_ctx *ctx)
h2r_args.arg[0] = S5P_FIMV_CODEC_NONE;
};
h2r_args.arg[1] = 0; /* no crc & no pixelcache */
- h2r_args.arg[2] = ctx->ctx_ofs;
- h2r_args.arg[3] = ctx->ctx_size;
+ h2r_args.arg[2] = ctx->ctx.ofs;
+ h2r_args.arg[3] = ctx->ctx.size;
ret = s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE,
&h2r_args);
if (ret) {
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
index ccb59ac..e9e89ac 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
@@ -30,17 +30,6 @@
* while mmaping */
#define DST_QUEUE_OFF_BASE (TASK_SIZE / 2)
-/* Offset used by the hardware to store addresses */
-#define MFC_OFFSET_SHIFT 11
-
-#define FIRMWARE_ALIGN 0x20000 /* 128KB */
-#define MFC_H264_CTX_BUF_SIZE 0x96000 /* 600KB per H264 instance */
-#define MFC_CTX_BUF_SIZE 0x2800 /* 10KB per instance */
-#define DESC_BUF_SIZE 0x20000 /* 128KB for DESC buffer */
-#define SHARED_BUF_SIZE 0x2000 /* 8KB for shared buffer */
-
-#define DEF_CPB_SIZE 0x40000 /* 512KB */
-
#define MFC_BANK1_ALLOC_CTX 0
#define MFC_BANK2_ALLOC_CTX 1
@@ -207,6 +196,48 @@ struct s5p_mfc_pm {
struct device *device;
};
+struct s5p_mfc_buf_size_v5 {
+ unsigned int h264_ctx;
+ unsigned int non_h264_ctx;
+ unsigned int dsc;
+ unsigned int shm;
+};
+
+struct s5p_mfc_buf_size {
+ unsigned int fw;
+ unsigned int cpb;
+ void *priv;
+};
+
+struct s5p_mfc_buf_align {
+ unsigned int base;
+};
+
+struct s5p_mfc_variant {
+ unsigned int version;
+ unsigned int port_num;
+ struct s5p_mfc_buf_size *buf_size;
+ struct s5p_mfc_buf_align *buf_align;
+};
+
+/**
+ * struct s5p_mfc_priv_buf - represents internal used buffer
+ * @alloc: allocation-specific context for each buffer
+ * (videobuf2 allocator)
+ * @ofs: offset of each buffer, will be used for MFC
+ * @virt: kernel virtual address, only valid when the
+ * buffer accessed by driver
+ * @dma: DMA address, only valid when kernel DMA API used
+ * @size: size of the buffer
+ */
+struct s5p_mfc_priv_buf {
+ void *alloc;
+ unsigned long ofs;
+ void *virt;
+ dma_addr_t dma;
+ size_t size;
+};
+
/**
* struct s5p_mfc_dev - The struct containing driver internal parameters.
*
@@ -221,6 +252,7 @@ struct s5p_mfc_pm {
* @dec_ctrl_handler: control framework handler for decoding
* @enc_ctrl_handler: control framework handler for encoding
* @pm: power management control
+ * @variant: MFC hardware variant information
* @num_inst: couter of active MFC instances
* @irqlock: lock for operations on videobuf2 queues
* @condlock: lock for changing/checking if a context is ready to be
@@ -259,6 +291,7 @@ struct s5p_mfc_dev {
struct v4l2_ctrl_handler dec_ctrl_handler;
struct v4l2_ctrl_handler enc_ctrl_handler;
struct s5p_mfc_pm pm;
+ struct s5p_mfc_variant *variant;
int num_inst;
spinlock_t irqlock; /* lock when operating on videobuf2 queues */
spinlock_t condlock; /* lock when changing/checking if a context is
@@ -299,7 +332,6 @@ struct s5p_mfc_h264_enc_params {
u8 max_ref_pic;
u8 num_ref_pic_4p;
int _8x8_transform;
- int rc_mb;
int rc_mb_dark;
int rc_mb_smooth;
int rc_mb_static;
@@ -318,6 +350,7 @@ struct s5p_mfc_h264_enc_params {
enum v4l2_mpeg_video_h264_level level_v4l2;
int level;
u16 cpb_size;
+ int interlace;
};
/**
@@ -356,6 +389,7 @@ struct s5p_mfc_enc_params {
u8 pad_cb;
u8 pad_cr;
int rc_frame;
+ int rc_mb;
u32 rc_bitrate;
u16 rc_reaction_coeff;
u16 vbv_size;
@@ -367,7 +401,6 @@ struct s5p_mfc_enc_params {
u8 num_b_frame;
u32 rc_framerate_num;
u32 rc_framerate_denom;
- int interlace;
union {
struct s5p_mfc_h264_enc_params h264;
@@ -452,14 +485,9 @@ struct s5p_mfc_codec_ops {
* @dpb_count: count of the DPB buffers required by MFC hw
* @total_dpb_count: count of DPB buffers with additional buffers
* requested by the application
- * @ctx_buf: handle to the memory associated with this context
- * @ctx_phys: address of the memory associated with this context
- * @ctx_size: size of the memory associated with this context
- * @desc_buf: description buffer for decoding handle
- * @desc_phys: description buffer for decoding address
- * @shm_alloc: handle for the shared memory buffer
- * @shm: virtual address for the shared memory buffer
- * @shm_ofs: address offset for shared memory
+ * @ctx: context buffer information
+ * @dsc: descriptor buffer information
+ * @shm: shared memory buffer information
* @enc_params: encoding parameters for MFC
* @enc_dst_buf_size: size of the buffers for encoder output
* @frame_type: used to force the type of the next encoded frame
@@ -544,18 +572,9 @@ struct s5p_mfc_ctx {
int total_dpb_count;
/* Buffers */
- void *ctx_buf;
- size_t ctx_phys;
- size_t ctx_ofs;
- size_t ctx_size;
-
- void *desc_buf;
- size_t desc_phys;
-
-
- void *shm_alloc;
- void *shm;
- size_t shm_ofs;
+ struct s5p_mfc_priv_buf ctx;
+ struct s5p_mfc_priv_buf dsc;
+ struct s5p_mfc_priv_buf shm;
struct s5p_mfc_enc_params enc_params;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
index 4a39e5e..524380c 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
@@ -43,7 +43,12 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev)
mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
return -EINVAL;
}
- dev->fw_size = ALIGN(fw_blob->size, FIRMWARE_ALIGN);
+ dev->fw_size = dev->variant->buf_size->fw;
+ if (fw_blob->size > dev->fw_size) {
+ mfc_err("MFC firmware is too big to be loaded\n");
+ release_firmware(fw_blob);
+ return -ENOMEM;
+ }
if (s5p_mfc_bitproc_buf) {
mfc_err("Attempting to allocate firmware when it seems that it is already loaded\n");
release_firmware(fw_blob);
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
index 02e1a94..fe34f17 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
@@ -985,45 +985,13 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
mfc_debug(2, "fmt - w: %d, h: %d, ctx - w: %d, h: %d\n",
pix_fmt_mp->width, pix_fmt_mp->height,
ctx->img_width, ctx->img_height);
- if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) {
- ctx->buf_width = ALIGN(ctx->img_width,
- S5P_FIMV_NV12M_HALIGN);
- ctx->luma_size = ALIGN(ctx->img_width,
- S5P_FIMV_NV12M_HALIGN) * ALIGN(ctx->img_height,
- S5P_FIMV_NV12M_LVALIGN);
- ctx->chroma_size = ALIGN(ctx->img_width,
- S5P_FIMV_NV12M_HALIGN) * ALIGN((ctx->img_height
- >> 1), S5P_FIMV_NV12M_CVALIGN);
-
- ctx->luma_size = ALIGN(ctx->luma_size,
- S5P_FIMV_NV12M_SALIGN);
- ctx->chroma_size = ALIGN(ctx->chroma_size,
- S5P_FIMV_NV12M_SALIGN);
-
- pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
- pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width;
- pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
- pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width;
-
- } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT) {
- ctx->buf_width = ALIGN(ctx->img_width,
- S5P_FIMV_NV12MT_HALIGN);
- ctx->luma_size = ALIGN(ctx->img_width,
- S5P_FIMV_NV12MT_HALIGN) * ALIGN(ctx->img_height,
- S5P_FIMV_NV12MT_VALIGN);
- ctx->chroma_size = ALIGN(ctx->img_width,
- S5P_FIMV_NV12MT_HALIGN) * ALIGN((ctx->img_height
- >> 1), S5P_FIMV_NV12MT_VALIGN);
- ctx->luma_size = ALIGN(ctx->luma_size,
- S5P_FIMV_NV12MT_SALIGN);
- ctx->chroma_size = ALIGN(ctx->chroma_size,
- S5P_FIMV_NV12MT_SALIGN);
-
- pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
- pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width;
- pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
- pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width;
- }
+
+ s5p_mfc_hw_call(dev->mfc_ops, enc_calc_src_size, ctx);
+ pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
+ pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width;
+ pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
+ pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width;
+
ctx->src_bufs_cnt = 0;
ctx->output_state = QUEUE_FREE;
} else {
@@ -1349,7 +1317,7 @@ static int s5p_mfc_enc_s_ctrl(struct v4l2_ctrl *ctrl)
p->codec.h264._8x8_transform = ctrl->val;
break;
case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE:
- p->codec.h264.rc_mb = ctrl->val;
+ p->rc_mb = ctrl->val;
break;
case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
p->codec.h264.rc_frame_qp = ctrl->val;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
index fe36c92..f1871e7 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
@@ -36,28 +36,29 @@
/* Allocate temporary buffers for decoding */
int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx *ctx)
{
- void *desc_virt;
struct s5p_mfc_dev *dev = ctx->dev;
+ struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
- ctx->desc_buf = vb2_dma_contig_memops.alloc(
- dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], DESC_BUF_SIZE);
- if (IS_ERR_VALUE((int)ctx->desc_buf)) {
- ctx->desc_buf = NULL;
+ ctx->dsc.alloc = vb2_dma_contig_memops.alloc(
+ dev->alloc_ctx[MFC_BANK1_ALLOC_CTX],
+ buf_size->dsc);
+ if (IS_ERR_VALUE((int)ctx->dsc.alloc)) {
+ ctx->dsc.alloc = NULL;
mfc_err("Allocating DESC buffer failed\n");
return -ENOMEM;
}
- ctx->desc_phys = s5p_mfc_mem_cookie(
- dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->desc_buf);
- BUG_ON(ctx->desc_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
- desc_virt = vb2_dma_contig_memops.vaddr(ctx->desc_buf);
- if (desc_virt == NULL) {
- vb2_dma_contig_memops.put(ctx->desc_buf);
- ctx->desc_phys = 0;
- ctx->desc_buf = NULL;
+ ctx->dsc.dma = s5p_mfc_mem_cookie(
+ dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->dsc.alloc);
+ BUG_ON(ctx->dsc.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
+ ctx->dsc.virt = vb2_dma_contig_memops.vaddr(ctx->dsc.alloc);
+ if (ctx->dsc.virt == NULL) {
+ vb2_dma_contig_memops.put(ctx->dsc.alloc);
+ ctx->dsc.dma = 0;
+ ctx->dsc.alloc = NULL;
mfc_err("Remapping DESC buffer failed\n");
return -ENOMEM;
}
- memset(desc_virt, 0, DESC_BUF_SIZE);
+ memset(ctx->dsc.virt, 0, buf_size->dsc);
wmb();
return 0;
}
@@ -65,10 +66,10 @@ int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx *ctx)
/* Release temporary buffers for decoding */
void s5p_mfc_release_dec_desc_buffer_v5(struct s5p_mfc_ctx *ctx)
{
- if (ctx->desc_phys) {
- vb2_dma_contig_memops.put(ctx->desc_buf);
- ctx->desc_phys = 0;
- ctx->desc_buf = NULL;
+ if (ctx->dsc.dma) {
+ vb2_dma_contig_memops.put(ctx->dsc.alloc);
+ ctx->dsc.alloc = NULL;
+ ctx->dsc.dma = 0;
}
}
@@ -229,60 +230,60 @@ void s5p_mfc_release_codec_buffers_v5(struct s5p_mfc_ctx *ctx)
/* Allocate memory for instance data buffer */
int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx)
{
- void *context_virt;
struct s5p_mfc_dev *dev = ctx->dev;
+ struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
- if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC ||
- ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC)
- ctx->ctx_size = MFC_H264_CTX_BUF_SIZE;
+ if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC ||
+ ctx->codec_mode == S5P_MFC_CODEC_H264_ENC)
+ ctx->ctx.size = buf_size->h264_ctx;
else
- ctx->ctx_size = MFC_CTX_BUF_SIZE;
- ctx->ctx_buf = vb2_dma_contig_memops.alloc(
- dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx_size);
- if (IS_ERR(ctx->ctx_buf)) {
+ ctx->ctx.size = buf_size->non_h264_ctx;
+ ctx->ctx.alloc = vb2_dma_contig_memops.alloc(
+ dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx.size);
+ if (IS_ERR(ctx->ctx.alloc)) {
mfc_err("Allocating context buffer failed\n");
- ctx->ctx_phys = 0;
- ctx->ctx_buf = NULL;
+ ctx->ctx.alloc = NULL;
return -ENOMEM;
}
- ctx->ctx_phys = s5p_mfc_mem_cookie(
- dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx_buf);
- BUG_ON(ctx->ctx_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
- ctx->ctx_ofs = OFFSETA(ctx->ctx_phys);
- context_virt = vb2_dma_contig_memops.vaddr(ctx->ctx_buf);
- if (context_virt == NULL) {
+ ctx->ctx.dma = s5p_mfc_mem_cookie(
+ dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx.alloc);
+ BUG_ON(ctx->ctx.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
+ ctx->ctx.ofs = OFFSETA(ctx->ctx.dma);
+ ctx->ctx.virt = vb2_dma_contig_memops.vaddr(ctx->ctx.alloc);
+ if (!ctx->ctx.virt) {
mfc_err("Remapping instance buffer failed\n");
- vb2_dma_contig_memops.put(ctx->ctx_buf);
- ctx->ctx_phys = 0;
- ctx->ctx_buf = NULL;
+ vb2_dma_contig_memops.put(ctx->ctx.alloc);
+ ctx->ctx.alloc = NULL;
+ ctx->ctx.ofs = 0;
+ ctx->ctx.dma = 0;
return -ENOMEM;
}
/* Zero content of the allocated memory */
- memset(context_virt, 0, ctx->ctx_size);
+ memset(ctx->ctx.virt, 0, ctx->ctx.size);
wmb();
/* Initialize shared memory */
- ctx->shm_alloc = vb2_dma_contig_memops.alloc(
- dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], SHARED_BUF_SIZE);
- if (IS_ERR(ctx->shm_alloc)) {
+ ctx->shm.alloc = vb2_dma_contig_memops.alloc(
+ dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], buf_size->shm);
+ if (IS_ERR(ctx->shm.alloc)) {
mfc_err("failed to allocate shared memory\n");
- return PTR_ERR(ctx->shm_alloc);
+ return PTR_ERR(ctx->shm.alloc);
}
/* shared memory offset only keeps the offset from base (port a) */
- ctx->shm_ofs = s5p_mfc_mem_cookie(
- dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->shm_alloc)
+ ctx->shm.ofs = s5p_mfc_mem_cookie(
+ dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->shm.alloc)
- dev->bank1;
- BUG_ON(ctx->shm_ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
+ BUG_ON(ctx->shm.ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
- ctx->shm = vb2_dma_contig_memops.vaddr(ctx->shm_alloc);
- if (!ctx->shm) {
- vb2_dma_contig_memops.put(ctx->shm_alloc);
- ctx->shm_ofs = 0;
- ctx->shm_alloc = NULL;
+ ctx->shm.virt = vb2_dma_contig_memops.vaddr(ctx->shm.alloc);
+ if (!ctx->shm.virt) {
+ vb2_dma_contig_memops.put(ctx->shm.alloc);
+ ctx->shm.alloc = NULL;
+ ctx->shm.ofs = 0;
mfc_err("failed to virt addr of shared memory\n");
return -ENOMEM;
}
- memset((void *)ctx->shm, 0, SHARED_BUF_SIZE);
+ memset((void *)ctx->shm.virt, 0, buf_size->shm);
wmb();
return 0;
}
@@ -290,15 +291,18 @@ int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx)
/* Release instance buffer */
void s5p_mfc_release_instance_buffer_v5(struct s5p_mfc_ctx *ctx)
{
- if (ctx->ctx_buf) {
- vb2_dma_contig_memops.put(ctx->ctx_buf);
- ctx->ctx_phys = 0;
- ctx->ctx_buf = NULL;
+ if (ctx->ctx.alloc) {
+ vb2_dma_contig_memops.put(ctx->ctx.alloc);
+ ctx->ctx.alloc = NULL;
+ ctx->ctx.ofs = 0;
+ ctx->ctx.virt = NULL;
+ ctx->ctx.dma = 0;
}
- if (ctx->shm_alloc) {
- vb2_dma_contig_memops.put(ctx->shm_alloc);
- ctx->shm_alloc = NULL;
- ctx->shm = NULL;
+ if (ctx->shm.alloc) {
+ vb2_dma_contig_memops.put(ctx->shm.alloc);
+ ctx->shm.alloc = NULL;
+ ctx->shm.ofs = 0;
+ ctx->shm.virt = NULL;
}
}
@@ -317,7 +321,7 @@ void s5p_mfc_release_dev_context_buffer_v5(struct s5p_mfc_dev *dev)
static void s5p_mfc_write_info_v5(struct s5p_mfc_ctx *ctx, unsigned int data,
unsigned int ofs)
{
- writel(data, (ctx->shm + ofs));
+ writel(data, (ctx->shm.virt + ofs));
wmb();
}
@@ -325,33 +329,94 @@ static unsigned int s5p_mfc_read_info_v5(struct s5p_mfc_ctx *ctx,
unsigned int ofs)
{
rmb();
- return readl(ctx->shm + ofs);
+ return readl(ctx->shm.virt + ofs);
}
void s5p_mfc_dec_calc_dpb_size_v5(struct s5p_mfc_ctx *ctx)
{
- /* NOP */
+ unsigned int guard_width, guard_height;
+
+ ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN);
+ ctx->buf_height = ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
+ mfc_debug(2,
+ "SEQ Done: Movie dimensions %dx%d, buffer dimensions: %dx%d\n",
+ ctx->img_width, ctx->img_height, ctx->buf_width,
+ ctx->buf_height);
+
+ if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC) {
+ ctx->luma_size = ALIGN(ctx->buf_width * ctx->buf_height,
+ S5P_FIMV_DEC_BUF_ALIGN);
+ ctx->chroma_size = ALIGN(ctx->buf_width *
+ ALIGN((ctx->img_height >> 1),
+ S5P_FIMV_NV12MT_VALIGN),
+ S5P_FIMV_DEC_BUF_ALIGN);
+ ctx->mv_size = ALIGN(ctx->buf_width *
+ ALIGN((ctx->buf_height >> 2),
+ S5P_FIMV_NV12MT_VALIGN),
+ S5P_FIMV_DEC_BUF_ALIGN);
+ } else {
+ guard_width =
+ ALIGN(ctx->img_width + 24, S5P_FIMV_NV12MT_HALIGN);
+ guard_height =
+ ALIGN(ctx->img_height + 16, S5P_FIMV_NV12MT_VALIGN);
+ ctx->luma_size = ALIGN(guard_width * guard_height,
+ S5P_FIMV_DEC_BUF_ALIGN);
+
+ guard_width =
+ ALIGN(ctx->img_width + 16, S5P_FIMV_NV12MT_HALIGN);
+ guard_height =
+ ALIGN((ctx->img_height >> 1) + 4,
+ S5P_FIMV_NV12MT_VALIGN);
+ ctx->chroma_size = ALIGN(guard_width * guard_height,
+ S5P_FIMV_DEC_BUF_ALIGN);
+
+ ctx->mv_size = 0;
+ }
}
void s5p_mfc_enc_calc_src_size_v5(struct s5p_mfc_ctx *ctx)
{
- /* NOP */
+ if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) {
+ ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN);
+
+ ctx->luma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN)
+ * ALIGN(ctx->img_height, S5P_FIMV_NV12M_LVALIGN);
+ ctx->chroma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN)
+ * ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12M_CVALIGN);
+
+ ctx->luma_size = ALIGN(ctx->luma_size, S5P_FIMV_NV12M_SALIGN);
+ ctx->chroma_size =
+ ALIGN(ctx->chroma_size, S5P_FIMV_NV12M_SALIGN);
+ } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT) {
+ ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN);
+
+ ctx->luma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
+ * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
+ ctx->chroma_size =
+ ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
+ * ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12MT_VALIGN);
+
+ ctx->luma_size = ALIGN(ctx->luma_size, S5P_FIMV_NV12MT_SALIGN);
+ ctx->chroma_size =
+ ALIGN(ctx->chroma_size, S5P_FIMV_NV12MT_SALIGN);
+ }
}
/* Set registers for decoding temporary buffers */
static void s5p_mfc_set_dec_desc_buffer(struct s5p_mfc_ctx *ctx)
{
struct s5p_mfc_dev *dev = ctx->dev;
+ struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
- mfc_write(dev, OFFSETA(ctx->desc_phys), S5P_FIMV_SI_CH0_DESC_ADR);
- mfc_write(dev, DESC_BUF_SIZE, S5P_FIMV_SI_CH0_DESC_SIZE);
+ mfc_write(dev, OFFSETA(ctx->dsc.dma), S5P_FIMV_SI_CH0_DESC_ADR);
+ mfc_write(dev, buf_size->dsc, S5P_FIMV_SI_CH0_DESC_SIZE);
}
/* Set registers for shared buffer */
static void s5p_mfc_set_shared_buffer(struct s5p_mfc_ctx *ctx)
{
struct s5p_mfc_dev *dev = ctx->dev;
- mfc_write(dev, ctx->shm_ofs, S5P_FIMV_SI_CH0_HOST_WR_ADR);
+ mfc_write(dev, ctx->shm.ofs, S5P_FIMV_SI_CH0_HOST_WR_ADR);
}
/* Set registers for decoding stream buffer */
@@ -775,9 +840,9 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
reg |= p_264->profile;
mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE);
/* interlace */
- mfc_write(dev, p->interlace, S5P_FIMV_ENC_PIC_STRUCT);
+ mfc_write(dev, p_264->interlace, S5P_FIMV_ENC_PIC_STRUCT);
/* height */
- if (p->interlace)
+ if (p_264->interlace)
mfc_write(dev, ctx->img_height >> 1, S5P_FIMV_ENC_VSIZE_PX);
/* loopfilter ctrl */
mfc_write(dev, p_264->loop_filter_mode, S5P_FIMV_ENC_LF_CTRL);
@@ -819,7 +884,7 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
/* macroblock level rate control */
reg &= ~(0x1 << 8);
- reg |= (p_264->rc_mb << 8);
+ reg |= (p->rc_mb << 8);
/* frame QP */
reg &= ~(0x3F);
reg |= p_264->rc_frame_qp;
@@ -840,7 +905,7 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
reg |= p_264->rc_min_qp;
mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
/* macroblock adaptive scaling features */
- if (p_264->rc_mb) {
+ if (p->rc_mb) {
reg = mfc_read(dev, S5P_FIMV_ENC_RC_MB_CTRL);
/* dark region */
reg &= ~(0x1 << 3);
@@ -856,8 +921,7 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
reg |= p_264->rc_mb_activity;
mfc_write(dev, reg, S5P_FIMV_ENC_RC_MB_CTRL);
}
- if (!p->rc_frame &&
- !p_264->rc_mb) {
+ if (!p->rc_frame && !p->rc_mb) {
shm = s5p_mfc_read_info_v5(ctx, P_B_FRAME_QP);
shm &= ~(0xFFF);
shm |= ((p_264->rc_b_frame_qp & 0x3F) << 6);
@@ -1487,8 +1551,9 @@ int s5p_mfc_get_dec_frame_type_v5(struct s5p_mfc_dev *dev)
int s5p_mfc_get_disp_frame_type_v5(struct s5p_mfc_ctx *ctx)
{
- /* NOP */
- return -1;
+ return (s5p_mfc_read_info_v5(ctx, DISP_PIC_FRAME_TYPE) >>
+ S5P_FIMV_SHARED_DISP_FRAME_TYPE_SHIFT) &
+ S5P_FIMV_DECODE_FRAME_MASK;
}
int s5p_mfc_get_consumed_stream_v5(struct s5p_mfc_dev *dev)
--
1.7.0.4
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v9 5/6] [media] s5p-mfc: MFCv6 register definitions
2012-10-02 14:55 [PATCH v9 0/6] Update MFC v4l2 driver to support MFC6.x Arun Kumar K
` (4 preceding siblings ...)
2012-10-02 14:55 ` [PATCH v9 4/6] [media] s5p-mfc: Add MFC variant data to device context Arun Kumar K
@ 2012-10-02 14:55 ` Arun Kumar K
2012-10-02 11:16 ` Kamil Debski
2012-10-02 14:55 ` [PATCH v9 6/6] [media] s5p-mfc: Update MFC v4l2 driver to support MFC6.x Arun Kumar K
6 siblings, 1 reply; 15+ messages in thread
From: Arun Kumar K @ 2012-10-02 14:55 UTC (permalink / raw)
To: linux-media
Cc: k.debski, jtp.park, janghyuck.kim, jaeryul.oh, ch.naveen, arun.kk,
m.szyprowski, s.nawrocki, hverkuil, kmpark, joshi
From: Jeongtae Park <jtp.park@samsung.com>
Adds register definitions for MFC v6.x firmware
Signed-off-by: Jeongtae Park <jtp.park@samsung.com>
Signed-off-by: Janghyuck Kim <janghyuck.kim@samsung.com>
Signed-off-by: Jaeryul Oh <jaeryul.oh@samsung.com>
Signed-off-by: Naveen Krishna Chatradhi <ch.naveen@samsung.com>
Signed-off-by: Arun Kumar K <arun.kk@samsung.com>
---
drivers/media/platform/s5p-mfc/regs-mfc-v6.h | 408 ++++++++++++++++++++++++++
1 files changed, 408 insertions(+), 0 deletions(-)
create mode 100644 drivers/media/platform/s5p-mfc/regs-mfc-v6.h
diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v6.h b/drivers/media/platform/s5p-mfc/regs-mfc-v6.h
new file mode 100644
index 0000000..363a97c
--- /dev/null
+++ b/drivers/media/platform/s5p-mfc/regs-mfc-v6.h
@@ -0,0 +1,408 @@
+/*
+ * Register definition file for Samsung MFC V6.x Interface (FIMV) driver
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _REGS_FIMV_V6_H
+#define _REGS_FIMV_V6_H
+
+#include <linux/kernel.h>
+#include <linux/sizes.h>
+
+#define S5P_FIMV_REG_SIZE_V6 (S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR)
+#define S5P_FIMV_REG_COUNT_V6 ((S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR) / 4)
+
+/* Number of bits that the buffer address should be shifted for particular
+ * MFC buffers. */
+#define S5P_FIMV_MEM_OFFSET_V6 0
+
+#define S5P_FIMV_START_ADDR_V6 0x0000
+#define S5P_FIMV_END_ADDR_V6 0xfd80
+
+#define S5P_FIMV_REG_CLEAR_BEGIN_V6 0xf000
+#define S5P_FIMV_REG_CLEAR_COUNT_V6 1024
+
+/* Codec Common Registers */
+#define S5P_FIMV_RISC_ON_V6 0x0000
+#define S5P_FIMV_RISC2HOST_INT_V6 0x003C
+#define S5P_FIMV_HOST2RISC_INT_V6 0x0044
+#define S5P_FIMV_RISC_BASE_ADDRESS_V6 0x0054
+
+#define S5P_FIMV_MFC_RESET_V6 0x1070
+
+#define S5P_FIMV_HOST2RISC_CMD_V6 0x1100
+#define S5P_FIMV_H2R_CMD_EMPTY_V6 0
+#define S5P_FIMV_H2R_CMD_SYS_INIT_V6 1
+#define S5P_FIMV_H2R_CMD_OPEN_INSTANCE_V6 2
+#define S5P_FIMV_CH_SEQ_HEADER_V6 3
+#define S5P_FIMV_CH_INIT_BUFS_V6 4
+#define S5P_FIMV_CH_FRAME_START_V6 5
+#define S5P_FIMV_H2R_CMD_CLOSE_INSTANCE_V6 6
+#define S5P_FIMV_H2R_CMD_SLEEP_V6 7
+#define S5P_FIMV_H2R_CMD_WAKEUP_V6 8
+#define S5P_FIMV_CH_LAST_FRAME_V6 9
+#define S5P_FIMV_H2R_CMD_FLUSH_V6 10
+/* RMVME: REALLOC used? */
+#define S5P_FIMV_CH_FRAME_START_REALLOC_V6 5
+
+#define S5P_FIMV_RISC2HOST_CMD_V6 0x1104
+#define S5P_FIMV_R2H_CMD_EMPTY_V6 0
+#define S5P_FIMV_R2H_CMD_SYS_INIT_RET_V6 1
+#define S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET_V6 2
+#define S5P_FIMV_R2H_CMD_SEQ_DONE_RET_V6 3
+#define S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET_V6 4
+
+#define S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET_V6 6
+#define S5P_FIMV_R2H_CMD_SLEEP_RET_V6 7
+#define S5P_FIMV_R2H_CMD_WAKEUP_RET_V6 8
+#define S5P_FIMV_R2H_CMD_COMPLETE_SEQ_RET_V6 9
+#define S5P_FIMV_R2H_CMD_DPB_FLUSH_RET_V6 10
+#define S5P_FIMV_R2H_CMD_NAL_ABORT_RET_V6 11
+#define S5P_FIMV_R2H_CMD_FW_STATUS_RET_V6 12
+#define S5P_FIMV_R2H_CMD_FRAME_DONE_RET_V6 13
+#define S5P_FIMV_R2H_CMD_FIELD_DONE_RET_V6 14
+#define S5P_FIMV_R2H_CMD_SLICE_DONE_RET_V6 15
+#define S5P_FIMV_R2H_CMD_ENC_BUFFER_FUL_RET_V6 16
+#define S5P_FIMV_R2H_CMD_ERR_RET_V6 32
+
+#define S5P_FIMV_FW_VERSION_V6 0xf000
+
+#define S5P_FIMV_INSTANCE_ID_V6 0xf008
+#define S5P_FIMV_CODEC_TYPE_V6 0xf00c
+#define S5P_FIMV_CONTEXT_MEM_ADDR_V6 0xf014
+#define S5P_FIMV_CONTEXT_MEM_SIZE_V6 0xf018
+#define S5P_FIMV_PIXEL_FORMAT_V6 0xf020
+
+#define S5P_FIMV_METADATA_ENABLE_V6 0xf024
+#define S5P_FIMV_DBG_BUFFER_ADDR_V6 0xf030
+#define S5P_FIMV_DBG_BUFFER_SIZE_V6 0xf034
+#define S5P_FIMV_RET_INSTANCE_ID_V6 0xf070
+
+#define S5P_FIMV_ERROR_CODE_V6 0xf074
+#define S5P_FIMV_ERR_WARNINGS_START_V6 160
+#define S5P_FIMV_ERR_DEC_MASK_V6 0xffff
+#define S5P_FIMV_ERR_DEC_SHIFT_V6 0
+#define S5P_FIMV_ERR_DSPL_MASK_V6 0xffff0000
+#define S5P_FIMV_ERR_DSPL_SHIFT_V6 16
+
+#define S5P_FIMV_DBG_BUFFER_OUTPUT_SIZE_V6 0xf078
+#define S5P_FIMV_METADATA_STATUS_V6 0xf07C
+#define S5P_FIMV_METADATA_ADDR_MB_INFO_V6 0xf080
+#define S5P_FIMV_METADATA_SIZE_MB_INFO_V6 0xf084
+
+/* Decoder Registers */
+#define S5P_FIMV_D_CRC_CTRL_V6 0xf0b0
+#define S5P_FIMV_D_DEC_OPTIONS_V6 0xf0b4
+#define S5P_FIMV_D_OPT_FMO_ASO_CTRL_MASK_V6 4
+#define S5P_FIMV_D_OPT_DDELAY_EN_SHIFT_V6 3
+#define S5P_FIMV_D_OPT_LF_CTRL_SHIFT_V6 1
+#define S5P_FIMV_D_OPT_LF_CTRL_MASK_V6 0x3
+#define S5P_FIMV_D_OPT_TILE_MODE_SHIFT_V6 0
+
+#define S5P_FIMV_D_DISPLAY_DELAY_V6 0xf0b8
+
+#define S5P_FIMV_D_SET_FRAME_WIDTH_V6 0xf0bc
+#define S5P_FIMV_D_SET_FRAME_HEIGHT_V6 0xf0c0
+
+#define S5P_FIMV_D_SEI_ENABLE_V6 0xf0c4
+
+/* Buffer setting registers */
+#define S5P_FIMV_D_MIN_NUM_DPB_V6 0xf0f0
+#define S5P_FIMV_D_MIN_LUMA_DPB_SIZE_V6 0xf0f4
+#define S5P_FIMV_D_MIN_CHROMA_DPB_SIZE_V6 0xf0f8
+#define S5P_FIMV_D_MVC_NUM_VIEWS_V6 0xf0fc
+#define S5P_FIMV_D_MIN_NUM_MV_V6 0xf100
+#define S5P_FIMV_D_NUM_DPB_V6 0xf130
+#define S5P_FIMV_D_LUMA_DPB_SIZE_V6 0xf134
+#define S5P_FIMV_D_CHROMA_DPB_SIZE_V6 0xf138
+#define S5P_FIMV_D_MV_BUFFER_SIZE_V6 0xf13c
+
+#define S5P_FIMV_D_LUMA_DPB_V6 0xf140
+#define S5P_FIMV_D_CHROMA_DPB_V6 0xf240
+#define S5P_FIMV_D_MV_BUFFER_V6 0xf340
+
+#define S5P_FIMV_D_SCRATCH_BUFFER_ADDR_V6 0xf440
+#define S5P_FIMV_D_SCRATCH_BUFFER_SIZE_V6 0xf444
+#define S5P_FIMV_D_METADATA_BUFFER_ADDR_V6 0xf448
+#define S5P_FIMV_D_METADATA_BUFFER_SIZE_V6 0xf44c
+#define S5P_FIMV_D_NUM_MV_V6 0xf478
+#define S5P_FIMV_D_CPB_BUFFER_ADDR_V6 0xf4b0
+#define S5P_FIMV_D_CPB_BUFFER_SIZE_V6 0xf4b4
+
+#define S5P_FIMV_D_AVAILABLE_DPB_FLAG_UPPER_V6 0xf4b8
+#define S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER_V6 0xf4bc
+#define S5P_FIMV_D_CPB_BUFFER_OFFSET_V6 0xf4c0
+#define S5P_FIMV_D_SLICE_IF_ENABLE_V6 0xf4c4
+#define S5P_FIMV_D_PICTURE_TAG_V6 0xf4c8
+#define S5P_FIMV_D_STREAM_DATA_SIZE_V6 0xf4d0
+
+/* Display information register */
+#define S5P_FIMV_D_DISPLAY_FRAME_WIDTH_V6 0xf500
+#define S5P_FIMV_D_DISPLAY_FRAME_HEIGHT_V6 0xf504
+
+/* Display status */
+#define S5P_FIMV_D_DISPLAY_STATUS_V6 0xf508
+
+#define S5P_FIMV_D_DISPLAY_LUMA_ADDR_V6 0xf50c
+#define S5P_FIMV_D_DISPLAY_CHROMA_ADDR_V6 0xf510
+
+#define S5P_FIMV_D_DISPLAY_FRAME_TYPE_V6 0xf514
+
+#define S5P_FIMV_D_DISPLAY_CROP_INFO1_V6 0xf518
+#define S5P_FIMV_D_DISPLAY_CROP_INFO2_V6 0xf51c
+#define S5P_FIMV_D_DISPLAY_PICTURE_PROFILE_V6 0xf520
+#define S5P_FIMV_D_DISPLAY_LUMA_CRC_TOP_V6 0xf524
+#define S5P_FIMV_D_DISPLAY_CHROMA_CRC_TOP_V6 0xf528
+#define S5P_FIMV_D_DISPLAY_LUMA_CRC_BOT_V6 0xf52c
+#define S5P_FIMV_D_DISPLAY_CHROMA_CRC_BOT_V6 0xf530
+#define S5P_FIMV_D_DISPLAY_ASPECT_RATIO_V6 0xf534
+#define S5P_FIMV_D_DISPLAY_EXTENDED_AR_V6 0xf538
+
+/* Decoded picture information register */
+#define S5P_FIMV_D_DECODED_FRAME_WIDTH_V6 0xf53c
+#define S5P_FIMV_D_DECODED_FRAME_HEIGHT_V6 0xf540
+#define S5P_FIMV_D_DECODED_STATUS_V6 0xf544
+#define S5P_FIMV_DEC_CRC_GEN_MASK_V6 0x1
+#define S5P_FIMV_DEC_CRC_GEN_SHIFT_V6 6
+
+#define S5P_FIMV_D_DECODED_LUMA_ADDR_V6 0xf548
+#define S5P_FIMV_D_DECODED_CHROMA_ADDR_V6 0xf54c
+
+#define S5P_FIMV_D_DECODED_FRAME_TYPE_V6 0xf550
+#define S5P_FIMV_DECODE_FRAME_MASK_V6 7
+
+#define S5P_FIMV_D_DECODED_CROP_INFO1_V6 0xf554
+#define S5P_FIMV_D_DECODED_CROP_INFO2_V6 0xf558
+#define S5P_FIMV_D_DECODED_PICTURE_PROFILE_V6 0xf55c
+#define S5P_FIMV_D_DECODED_NAL_SIZE_V6 0xf560
+#define S5P_FIMV_D_DECODED_LUMA_CRC_TOP_V6 0xf564
+#define S5P_FIMV_D_DECODED_CHROMA_CRC_TOP_V6 0xf568
+#define S5P_FIMV_D_DECODED_LUMA_CRC_BOT_V6 0xf56c
+#define S5P_FIMV_D_DECODED_CHROMA_CRC_BOT_V6 0xf570
+
+/* Returned value register for specific setting */
+#define S5P_FIMV_D_RET_PICTURE_TAG_TOP_V6 0xf574
+#define S5P_FIMV_D_RET_PICTURE_TAG_BOT_V6 0xf578
+#define S5P_FIMV_D_RET_PICTURE_TIME_TOP_V6 0xf57c
+#define S5P_FIMV_D_RET_PICTURE_TIME_BOT_V6 0xf580
+#define S5P_FIMV_D_CHROMA_FORMAT_V6 0xf588
+#define S5P_FIMV_D_MPEG4_INFO_V6 0xf58c
+#define S5P_FIMV_D_H264_INFO_V6 0xf590
+
+#define S5P_FIMV_D_METADATA_ADDR_CONCEALED_MB_V6 0xf594
+#define S5P_FIMV_D_METADATA_SIZE_CONCEALED_MB_V6 0xf598
+#define S5P_FIMV_D_METADATA_ADDR_VC1_PARAM_V6 0xf59c
+#define S5P_FIMV_D_METADATA_SIZE_VC1_PARAM_V6 0xf5a0
+#define S5P_FIMV_D_METADATA_ADDR_SEI_NAL_V6 0xf5a4
+#define S5P_FIMV_D_METADATA_SIZE_SEI_NAL_V6 0xf5a8
+#define S5P_FIMV_D_METADATA_ADDR_VUI_V6 0xf5ac
+#define S5P_FIMV_D_METADATA_SIZE_VUI_V6 0xf5b0
+
+#define S5P_FIMV_D_MVC_VIEW_ID_V6 0xf5b4
+
+/* SEI related information */
+#define S5P_FIMV_D_FRAME_PACK_SEI_AVAIL_V6 0xf5f0
+#define S5P_FIMV_D_FRAME_PACK_ARRGMENT_ID_V6 0xf5f4
+#define S5P_FIMV_D_FRAME_PACK_SEI_INFO_V6 0xf5f8
+#define S5P_FIMV_D_FRAME_PACK_GRID_POS_V6 0xf5fc
+
+/* Encoder Registers */
+#define S5P_FIMV_E_FRAME_WIDTH_V6 0xf770
+#define S5P_FIMV_E_FRAME_HEIGHT_V6 0xf774
+#define S5P_FIMV_E_CROPPED_FRAME_WIDTH_V6 0xf778
+#define S5P_FIMV_E_CROPPED_FRAME_HEIGHT_V6 0xf77c
+#define S5P_FIMV_E_FRAME_CROP_OFFSET_V6 0xf780
+#define S5P_FIMV_E_ENC_OPTIONS_V6 0xf784
+#define S5P_FIMV_E_PICTURE_PROFILE_V6 0xf788
+#define S5P_FIMV_E_FIXED_PICTURE_QP_V6 0xf790
+
+#define S5P_FIMV_E_RC_CONFIG_V6 0xf794
+#define S5P_FIMV_E_RC_QP_BOUND_V6 0xf798
+#define S5P_FIMV_E_RC_RPARAM_V6 0xf79c
+#define S5P_FIMV_E_MB_RC_CONFIG_V6 0xf7a0
+#define S5P_FIMV_E_PADDING_CTRL_V6 0xf7a4
+#define S5P_FIMV_E_MV_HOR_RANGE_V6 0xf7ac
+#define S5P_FIMV_E_MV_VER_RANGE_V6 0xf7b0
+
+#define S5P_FIMV_E_VBV_BUFFER_SIZE_V6 0xf84c
+#define S5P_FIMV_E_VBV_INIT_DELAY_V6 0xf850
+#define S5P_FIMV_E_NUM_DPB_V6 0xf890
+#define S5P_FIMV_E_LUMA_DPB_V6 0xf8c0
+#define S5P_FIMV_E_CHROMA_DPB_V6 0xf904
+#define S5P_FIMV_E_ME_BUFFER_V6 0xf948
+
+#define S5P_FIMV_E_SCRATCH_BUFFER_ADDR_V6 0xf98c
+#define S5P_FIMV_E_SCRATCH_BUFFER_SIZE_V6 0xf990
+#define S5P_FIMV_E_TMV_BUFFER0_V6 0xf994
+#define S5P_FIMV_E_TMV_BUFFER1_V6 0xf998
+#define S5P_FIMV_E_SOURCE_LUMA_ADDR_V6 0xf9f0
+#define S5P_FIMV_E_SOURCE_CHROMA_ADDR_V6 0xf9f4
+#define S5P_FIMV_E_STREAM_BUFFER_ADDR_V6 0xf9f8
+#define S5P_FIMV_E_STREAM_BUFFER_SIZE_V6 0xf9fc
+#define S5P_FIMV_E_ROI_BUFFER_ADDR_V6 0xfA00
+
+#define S5P_FIMV_E_PARAM_CHANGE_V6 0xfa04
+#define S5P_FIMV_E_IR_SIZE_V6 0xfa08
+#define S5P_FIMV_E_GOP_CONFIG_V6 0xfa0c
+#define S5P_FIMV_E_MSLICE_MODE_V6 0xfa10
+#define S5P_FIMV_E_MSLICE_SIZE_MB_V6 0xfa14
+#define S5P_FIMV_E_MSLICE_SIZE_BITS_V6 0xfa18
+#define S5P_FIMV_E_FRAME_INSERTION_V6 0xfa1c
+
+#define S5P_FIMV_E_RC_FRAME_RATE_V6 0xfa20
+#define S5P_FIMV_E_RC_BIT_RATE_V6 0xfa24
+#define S5P_FIMV_E_RC_QP_OFFSET_V6 0xfa28
+#define S5P_FIMV_E_RC_ROI_CTRL_V6 0xfa2c
+#define S5P_FIMV_E_PICTURE_TAG_V6 0xfa30
+#define S5P_FIMV_E_BIT_COUNT_ENABLE_V6 0xfa34
+#define S5P_FIMV_E_MAX_BIT_COUNT_V6 0xfa38
+#define S5P_FIMV_E_MIN_BIT_COUNT_V6 0xfa3c
+
+#define S5P_FIMV_E_METADATA_BUFFER_ADDR_V6 0xfa40
+#define S5P_FIMV_E_METADATA_BUFFER_SIZE_V6 0xfa44
+#define S5P_FIMV_E_STREAM_SIZE_V6 0xfa80
+#define S5P_FIMV_E_SLICE_TYPE_V6 0xfa84
+#define S5P_FIMV_E_PICTURE_COUNT_V6 0xfa88
+#define S5P_FIMV_E_RET_PICTURE_TAG_V6 0xfa8c
+#define S5P_FIMV_E_STREAM_BUFFER_WRITE_POINTER_V6 0xfa90
+
+#define S5P_FIMV_E_ENCODED_SOURCE_LUMA_ADDR_V6 0xfa94
+#define S5P_FIMV_E_ENCODED_SOURCE_CHROMA_ADDR_V6 0xfa98
+#define S5P_FIMV_E_RECON_LUMA_DPB_ADDR_V6 0xfa9c
+#define S5P_FIMV_E_RECON_CHROMA_DPB_ADDR_V6 0xfaa0
+#define S5P_FIMV_E_METADATA_ADDR_ENC_SLICE_V6 0xfaa4
+#define S5P_FIMV_E_METADATA_SIZE_ENC_SLICE_V6 0xfaa8
+
+#define S5P_FIMV_E_MPEG4_OPTIONS_V6 0xfb10
+#define S5P_FIMV_E_MPEG4_HEC_PERIOD_V6 0xfb14
+#define S5P_FIMV_E_ASPECT_RATIO_V6 0xfb50
+#define S5P_FIMV_E_EXTENDED_SAR_V6 0xfb54
+
+#define S5P_FIMV_E_H264_OPTIONS_V6 0xfb58
+#define S5P_FIMV_E_H264_LF_ALPHA_OFFSET_V6 0xfb5c
+#define S5P_FIMV_E_H264_LF_BETA_OFFSET_V6 0xfb60
+#define S5P_FIMV_E_H264_I_PERIOD_V6 0xfb64
+
+#define S5P_FIMV_E_H264_FMO_SLICE_GRP_MAP_TYPE_V6 0xfb68
+#define S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1_V6 0xfb6c
+#define S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_DIR_V6 0xfb70
+#define S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_RATE_MINUS1_V6 0xfb74
+#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_0_V6 0xfb78
+#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_1_V6 0xfb7c
+#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_2_V6 0xfb80
+#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_3_V6 0xfb84
+
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_0_V6 0xfb88
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_1_V6 0xfb8c
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_2_V6 0xfb90
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_3_V6 0xfb94
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_4_V6 0xfb98
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_5_V6 0xfb9c
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_6_V6 0xfba0
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_7_V6 0xfba4
+
+#define S5P_FIMV_E_H264_CHROMA_QP_OFFSET_V6 0xfba8
+#define S5P_FIMV_E_H264_NUM_T_LAYER_V6 0xfbac
+
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER0_V6 0xfbb0
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER1_V6 0xfbb4
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER2_V6 0xfbb8
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER3_V6 0xfbbc
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER4_V6 0xfbc0
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER5_V6 0xfbc4
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER6_V6 0xfbc8
+
+#define S5P_FIMV_E_H264_FRAME_PACKING_SEI_INFO_V6 0xfc4c
+#define S5P_FIMV_ENC_FP_ARRANGEMENT_TYPE_SIDE_BY_SIDE_V6 0
+#define S5P_FIMV_ENC_FP_ARRANGEMENT_TYPE_TOP_BOTTOM_V6 1
+#define S5P_FIMV_ENC_FP_ARRANGEMENT_TYPE_TEMPORAL_V6 2
+
+#define S5P_FIMV_E_MVC_FRAME_QP_VIEW1_V6 0xfd40
+#define S5P_FIMV_E_MVC_RC_FRAME_RATE_VIEW1_V6 0xfd44
+#define S5P_FIMV_E_MVC_RC_BIT_RATE_VIEW1_V6 0xfd48
+#define S5P_FIMV_E_MVC_RC_QBOUND_VIEW1_V6 0xfd4c
+#define S5P_FIMV_E_MVC_RC_RPARA_VIEW1_V6 0xfd50
+#define S5P_FIMV_E_MVC_INTER_VIEW_PREDICTION_ON_V6 0xfd80
+
+/* Codec numbers */
+#define S5P_FIMV_CODEC_NONE_V6 -1
+
+
+#define S5P_FIMV_CODEC_H264_DEC_V6 0
+#define S5P_FIMV_CODEC_H264_MVC_DEC_V6 1
+
+#define S5P_FIMV_CODEC_MPEG4_DEC_V6 3
+#define S5P_FIMV_CODEC_FIMV1_DEC_V6 4
+#define S5P_FIMV_CODEC_FIMV2_DEC_V6 5
+#define S5P_FIMV_CODEC_FIMV3_DEC_V6 6
+#define S5P_FIMV_CODEC_FIMV4_DEC_V6 7
+#define S5P_FIMV_CODEC_H263_DEC_V6 8
+#define S5P_FIMV_CODEC_VC1RCV_DEC_V6 9
+#define S5P_FIMV_CODEC_VC1_DEC_V6 10
+/* FIXME: Add 11~12 */
+#define S5P_FIMV_CODEC_MPEG2_DEC_V6 13
+#define S5P_FIMV_CODEC_VP8_DEC_V6 14
+/* FIXME: Add 15~16 */
+#define S5P_FIMV_CODEC_H264_ENC_V6 20
+#define S5P_FIMV_CODEC_H264_MVC_ENC_V6 21
+
+#define S5P_FIMV_CODEC_MPEG4_ENC_V6 23
+#define S5P_FIMV_CODEC_H263_ENC_V6 24
+
+#define S5P_FIMV_NV12M_HALIGN_V6 16
+#define S5P_FIMV_NV12MT_HALIGN_V6 16
+#define S5P_FIMV_NV12MT_VALIGN_V6 16
+
+#define S5P_FIMV_TMV_BUFFER_ALIGN_V6 16
+#define S5P_FIMV_LUMA_DPB_BUFFER_ALIGN_V6 256
+#define S5P_FIMV_CHROMA_DPB_BUFFER_ALIGN_V6 256
+#define S5P_FIMV_ME_BUFFER_ALIGN_V6 256
+#define S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6 256
+
+#define S5P_FIMV_LUMA_MB_TO_PIXEL_V6 256
+#define S5P_FIMV_CHROMA_MB_TO_PIXEL_V6 128
+#define S5P_FIMV_NUM_TMV_BUFFERS_V6 2
+
+#define S5P_FIMV_MAX_FRAME_SIZE_V6 (2 * SZ_1M)
+#define S5P_FIMV_NUM_PIXELS_IN_MB_ROW_V6 16
+#define S5P_FIMV_NUM_PIXELS_IN_MB_COL_V6 16
+
+/* Buffer size requirements defined by hardware */
+#define S5P_FIMV_TMV_BUFFER_SIZE_V6(w, h) (((w) + 1) * ((h) + 1) * 8)
+#define S5P_FIMV_ME_BUFFER_SIZE_V6(imw, imh, mbw, mbh) \
+ ((DIV_ROUND_UP(imw, 64) * DIV_ROUND_UP(imh, 64) * 256) + \
+ (DIV_ROUND_UP((mbw) * (mbh), 32) * 16))
+#define S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V6(w, h) (((w) * 192) + 64)
+#define S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V6(w, h) \
+ ((w) * ((h) * 64 + 144) + (2048/16 * (h) * 64) + \
+ (2048/16 * 256 + 8320))
+#define S5P_FIMV_SCRATCH_BUF_SIZE_VC1_DEC_V6(w, h) \
+ (2096 * ((w) + (h) + 1))
+#define S5P_FIMV_SCRATCH_BUF_SIZE_H263_DEC_V6(w, h) ((w) * 400)
+#define S5P_FIMV_SCRATCH_BUF_SIZE_VP8_DEC_V6(w, h) \
+ ((w) * 32 + (h) * 128 + (((w) + 1) / 2) * 64 + 2112)
+#define S5P_FIMV_SCRATCH_BUF_SIZE_H264_ENC_V6(w, h) \
+ (((w) * 64) + (((w) + 1) * 16) + (4096 * 16))
+#define S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_ENC_V6(w, h) \
+ (((w) * 16) + (((w) + 1) * 16))
+
+/* MFC Context buffer sizes */
+#define MFC_CTX_BUF_SIZE_V6 (28 * SZ_1K) /* 28KB */
+#define MFC_H264_DEC_CTX_BUF_SIZE_V6 (2 * SZ_1M) /* 2MB */
+#define MFC_OTHER_DEC_CTX_BUF_SIZE_V6 (20 * SZ_1K) /* 20KB */
+#define MFC_H264_ENC_CTX_BUF_SIZE_V6 (100 * SZ_1K) /* 100KB */
+#define MFC_OTHER_ENC_CTX_BUF_SIZE_V6 (12 * SZ_1K) /* 12KB */
+
+/* MFCv6 variant defines */
+#define MAX_FW_SIZE_V6 (SZ_1M) /* 1MB */
+#define MAX_CPB_SIZE_V6 (3 * SZ_1M) /* 3MB */
+#define MFC_VERSION_V6 0x61
+#define MFC_NUM_PORTS_V6 1
+
+#endif /* _REGS_FIMV_V6_H */
--
1.7.0.4
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v9 6/6] [media] s5p-mfc: Update MFC v4l2 driver to support MFC6.x
2012-10-02 14:55 [PATCH v9 0/6] Update MFC v4l2 driver to support MFC6.x Arun Kumar K
` (5 preceding siblings ...)
2012-10-02 14:55 ` [PATCH v9 5/6] [media] s5p-mfc: MFCv6 register definitions Arun Kumar K
@ 2012-10-02 14:55 ` Arun Kumar K
2012-10-02 11:16 ` Kamil Debski
6 siblings, 1 reply; 15+ messages in thread
From: Arun Kumar K @ 2012-10-02 14:55 UTC (permalink / raw)
To: linux-media
Cc: k.debski, jtp.park, janghyuck.kim, jaeryul.oh, ch.naveen, arun.kk,
m.szyprowski, s.nawrocki, hverkuil, kmpark, joshi
From: Jeongtae Park <jtp.park@samsung.com>
Multi Format Codec 6.x is a hardware video coding acceleration
module present in new Exynos5 SoC series. It is capable of
handling several new video codecs for decoding and encoding
Signed-off-by: Jeongtae Park <jtp.park@samsung.com>
Signed-off-by: Janghyuck Kim <janghyuck.kim@samsung.com>
Signed-off-by: Jaeryul Oh <jaeryul.oh@samsung.com>
Signed-off-by: Naveen Krishna Chatradhi <ch.naveen@samsung.com>
Signed-off-by: Arun Kumar K <arun.kk@samsung.com>
---
drivers/media/platform/Kconfig | 4 +-
drivers/media/platform/s5p-mfc/Makefile | 8 +-
drivers/media/platform/s5p-mfc/regs-mfc.h | 21 +
drivers/media/platform/s5p-mfc/s5p_mfc.c | 64 +-
drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c | 7 +-
drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c | 156 ++
drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h | 20 +
drivers/media/platform/s5p-mfc/s5p_mfc_common.h | 61 +-
drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c | 154 ++-
drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 193 ++-
drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | 139 ++-
drivers/media/platform/s5p-mfc/s5p_mfc_opr.c | 10 +-
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c | 1956 +++++++++++++++++++++++
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h | 50 +
drivers/media/platform/s5p-mfc/s5p_mfc_pm.c | 3 +-
15 files changed, 2678 insertions(+), 168 deletions(-)
create mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c
create mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h
create mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
create mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index f588d62..181c768 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -165,12 +165,12 @@ config VIDEO_SAMSUNG_S5P_JPEG
This is a v4l2 driver for Samsung S5P and EXYNOS4 JPEG codec
config VIDEO_SAMSUNG_S5P_MFC
- tristate "Samsung S5P MFC 5.1 Video Codec"
+ tristate "Samsung S5P MFC Video Codec"
depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P
select VIDEOBUF2_DMA_CONTIG
default n
help
- MFC 5.1 driver for V4L2.
+ MFC 5.1 and 6.x driver for V4L2
config VIDEO_MX2_EMMAPRP
tristate "MX2 eMMa-PrP support"
diff --git a/drivers/media/platform/s5p-mfc/Makefile b/drivers/media/platform/s5p-mfc/Makefile
index cfb9ee9..379008c 100644
--- a/drivers/media/platform/s5p-mfc/Makefile
+++ b/drivers/media/platform/s5p-mfc/Makefile
@@ -1,6 +1,6 @@
obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) := s5p-mfc.o
-s5p-mfc-y += s5p_mfc.o s5p_mfc_intr.o s5p_mfc_opr.o
+s5p-mfc-y += s5p_mfc.o s5p_mfc_intr.o
s5p-mfc-y += s5p_mfc_dec.o s5p_mfc_enc.o
-s5p-mfc-y += s5p_mfc_ctrl.o s5p_mfc_cmd.o
-s5p-mfc-y += s5p_mfc_pm.o
-s5p-mfc-y += s5p_mfc_opr_v5.o s5p_mfc_cmd_v5.o
+s5p-mfc-y += s5p_mfc_ctrl.o s5p_mfc_pm.o
+s5p-mfc-y += s5p_mfc_opr.o s5p_mfc_opr_v5.o s5p_mfc_opr_v6.o
+s5p-mfc-y += s5p_mfc_cmd.o s5p_mfc_cmd_v5.o s5p_mfc_cmd_v6.o
diff --git a/drivers/media/platform/s5p-mfc/regs-mfc.h b/drivers/media/platform/s5p-mfc/regs-mfc.h
index f33c54d..9319e93 100644
--- a/drivers/media/platform/s5p-mfc/regs-mfc.h
+++ b/drivers/media/platform/s5p-mfc/regs-mfc.h
@@ -147,6 +147,7 @@
#define S5P_FIMV_ENC_PROFILE_H264_MAIN 0
#define S5P_FIMV_ENC_PROFILE_H264_HIGH 1
#define S5P_FIMV_ENC_PROFILE_H264_BASELINE 2
+#define S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_BASELINE 3
#define S5P_FIMV_ENC_PROFILE_MPEG4_SIMPLE 0
#define S5P_FIMV_ENC_PROFILE_MPEG4_ADVANCED_SIMPLE 1
#define S5P_FIMV_ENC_PIC_STRUCT 0x083c /* picture field/frame flag */
@@ -216,6 +217,7 @@
#define S5P_FIMV_DEC_STATUS_RESOLUTION_MASK (3<<4)
#define S5P_FIMV_DEC_STATUS_RESOLUTION_INC (1<<4)
#define S5P_FIMV_DEC_STATUS_RESOLUTION_DEC (2<<4)
+#define S5P_FIMV_DEC_STATUS_RESOLUTION_SHIFT 4
/* Decode frame address */
#define S5P_FIMV_DECODE_Y_ADR 0x2024
@@ -380,6 +382,16 @@
#define S5P_FIMV_R2H_CMD_EDFU_INIT_RET 16
#define S5P_FIMV_R2H_CMD_ERR_RET 32
+/* Dummy definition for MFCv6 compatibilty */
+#define S5P_FIMV_CODEC_H264_MVC_DEC -1
+#define S5P_FIMV_R2H_CMD_FIELD_DONE_RET -1
+#define S5P_FIMV_MFC_RESET -1
+#define S5P_FIMV_RISC_ON -1
+#define S5P_FIMV_RISC_BASE_ADDRESS -1
+#define S5P_FIMV_CODEC_VP8_DEC -1
+#define S5P_FIMV_REG_CLEAR_BEGIN 0
+#define S5P_FIMV_REG_CLEAR_COUNT 0
+
/* Error handling defines */
#define S5P_FIMV_ERR_WARNINGS_START 145
#define S5P_FIMV_ERR_DEC_MASK 0xFFFF
@@ -435,4 +447,13 @@
#define MFC_VERSION 0x51
#define MFC_NUM_PORTS 2
+#define S5P_FIMV_SHARED_FRAME_PACK_SEI_AVAIL 0x16C
+#define S5P_FIMV_SHARED_FRAME_PACK_ARRGMENT_ID 0x170
+#define S5P_FIMV_SHARED_FRAME_PACK_SEI_INFO 0x174
+#define S5P_FIMV_SHARED_FRAME_PACK_GRID_POS 0x178
+
+/* Values for resolution change in display status */
+#define S5P_FIMV_RES_INCREASE 1
+#define S5P_FIMV_RES_DECREASE 2
+
#endif /* _REGS_FIMV_H */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index a8299ce..d922e1c 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -289,12 +289,14 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
dst_frame_status = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev)
& S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK;
- res_change = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev)
- & S5P_FIMV_DEC_STATUS_RESOLUTION_MASK;
+ res_change = (s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev)
+ & S5P_FIMV_DEC_STATUS_RESOLUTION_MASK)
+ >> S5P_FIMV_DEC_STATUS_RESOLUTION_SHIFT;
mfc_debug(2, "Frame Status: %x\n", dst_frame_status);
if (ctx->state == MFCINST_RES_CHANGE_INIT)
ctx->state = MFCINST_RES_CHANGE_FLUSH;
- if (res_change) {
+ if (res_change == S5P_FIMV_RES_INCREASE ||
+ res_change == S5P_FIMV_RES_DECREASE) {
ctx->state = MFCINST_RES_CHANGE_INIT;
s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
wake_up_ctx(ctx, reason, err);
@@ -453,10 +455,28 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx,
ctx->dpb_count = s5p_mfc_hw_call(dev->mfc_ops, get_dpb_count,
dev);
+ ctx->mv_count = s5p_mfc_hw_call(dev->mfc_ops, get_mv_count,
+ dev);
if (ctx->img_width == 0 || ctx->img_height == 0)
ctx->state = MFCINST_ERROR;
else
ctx->state = MFCINST_HEAD_PARSED;
+
+ if ((ctx->codec_mode == S5P_MFC_CODEC_H264_DEC ||
+ ctx->codec_mode == S5P_MFC_CODEC_H264_MVC_DEC) &&
+ !list_empty(&ctx->src_queue)) {
+ struct s5p_mfc_buf *src_buf;
+ src_buf = list_entry(ctx->src_queue.next,
+ struct s5p_mfc_buf, list);
+ if (s5p_mfc_hw_call(dev->mfc_ops, get_consumed_stream,
+ dev) <
+ src_buf->b->v4l2_planes[0].bytesused)
+ ctx->head_processed = 0;
+ else
+ ctx->head_processed = 1;
+ } else {
+ ctx->head_processed = 1;
+ }
}
s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
clear_work_bit(ctx);
@@ -487,7 +507,7 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx,
spin_unlock(&dev->condlock);
if (err == 0) {
ctx->state = MFCINST_RUNNING;
- if (!ctx->dpb_flush_flag) {
+ if (!ctx->dpb_flush_flag && ctx->head_processed) {
spin_lock_irqsave(&dev->irqlock, flags);
if (!list_empty(&ctx->src_queue)) {
src_buf = list_entry(ctx->src_queue.next,
@@ -998,6 +1018,7 @@ static int s5p_mfc_probe(struct platform_device *pdev)
ret = -ENODEV;
goto err_res;
}
+
dev->mem_dev_r = device_find_child(&dev->plat_dev->dev, "s5p-mfc-r",
match_child);
if (!dev->mem_dev_r) {
@@ -1227,12 +1248,47 @@ static struct s5p_mfc_variant mfc_drvdata_v5 = {
.port_num = MFC_NUM_PORTS,
.buf_size = &buf_size_v5,
.buf_align = &mfc_buf_align_v5,
+ .mclk_name = "sclk_mfc",
+ .fw_name = "s5p-mfc.fw",
+};
+
+struct s5p_mfc_buf_size_v6 mfc_buf_size_v6 = {
+ .dev_ctx = MFC_CTX_BUF_SIZE_V6,
+ .h264_dec_ctx = MFC_H264_DEC_CTX_BUF_SIZE_V6,
+ .other_dec_ctx = MFC_OTHER_DEC_CTX_BUF_SIZE_V6,
+ .h264_enc_ctx = MFC_H264_ENC_CTX_BUF_SIZE_V6,
+ .other_enc_ctx = MFC_OTHER_ENC_CTX_BUF_SIZE_V6,
+};
+
+struct s5p_mfc_buf_size buf_size_v6 = {
+ .fw = MAX_FW_SIZE_V6,
+ .cpb = MAX_CPB_SIZE_V6,
+ .priv = &mfc_buf_size_v6,
+};
+
+struct s5p_mfc_buf_align mfc_buf_align_v6 = {
+ .base = 0,
+};
+
+static struct s5p_mfc_variant mfc_drvdata_v6 = {
+ .version = MFC_VERSION_V6,
+ .port_num = MFC_NUM_PORTS_V6,
+ .buf_size = &buf_size_v6,
+ .buf_align = &mfc_buf_align_v6,
+ .mclk_name = "aclk_333",
+ .fw_name = "s5p-mfc-v6.fw",
};
static struct platform_device_id mfc_driver_ids[] = {
{
.name = "s5p-mfc",
.driver_data = (unsigned long)&mfc_drvdata_v5,
+ }, {
+ .name = "s5p-mfc-v5",
+ .driver_data = (unsigned long)&mfc_drvdata_v5,
+ }, {
+ .name = "s5p-mfc-v6",
+ .driver_data = (unsigned long)&mfc_drvdata_v6,
},
{},
};
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c
index 47b956d..deed3b7 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c
@@ -14,11 +14,16 @@
#include "s5p_mfc_common.h"
#include "s5p_mfc_debug.h"
#include "s5p_mfc_cmd_v5.h"
+#include "s5p_mfc_cmd_v6.h"
static struct s5p_mfc_hw_cmds *s5p_mfc_cmds;
void s5p_mfc_init_hw_cmds(struct s5p_mfc_dev *dev)
{
- s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v5();
+ if (IS_MFCV6(dev))
+ s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v6();
+ else
+ s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v5();
+
dev->mfc_cmds = s5p_mfc_cmds;
}
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c
new file mode 100644
index 0000000..754bfbc
--- /dev/null
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c
@@ -0,0 +1,156 @@
+/*
+ * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "s5p_mfc_common.h"
+
+#include "s5p_mfc_cmd.h"
+#include "s5p_mfc_debug.h"
+#include "s5p_mfc_intr.h"
+#include "s5p_mfc_opr.h"
+
+int s5p_mfc_cmd_host2risc_v6(struct s5p_mfc_dev *dev, int cmd,
+ struct s5p_mfc_cmd_args *args)
+{
+ mfc_debug(2, "Issue the command: %d\n", cmd);
+
+ /* Reset RISC2HOST command */
+ mfc_write(dev, 0x0, S5P_FIMV_RISC2HOST_CMD_V6);
+
+ /* Issue the command */
+ mfc_write(dev, cmd, S5P_FIMV_HOST2RISC_CMD_V6);
+ mfc_write(dev, 0x1, S5P_FIMV_HOST2RISC_INT_V6);
+
+ return 0;
+}
+
+int s5p_mfc_sys_init_cmd_v6(struct s5p_mfc_dev *dev)
+{
+ struct s5p_mfc_cmd_args h2r_args;
+ struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv;
+
+ s5p_mfc_hw_call(dev->mfc_ops, alloc_dev_context_buffer, dev);
+ mfc_write(dev, dev->ctx_buf.dma, S5P_FIMV_CONTEXT_MEM_ADDR_V6);
+ mfc_write(dev, buf_size->dev_ctx, S5P_FIMV_CONTEXT_MEM_SIZE_V6);
+ return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_SYS_INIT_V6,
+ &h2r_args);
+}
+
+int s5p_mfc_sleep_cmd_v6(struct s5p_mfc_dev *dev)
+{
+ struct s5p_mfc_cmd_args h2r_args;
+
+ memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+ return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_SLEEP_V6,
+ &h2r_args);
+}
+
+int s5p_mfc_wakeup_cmd_v6(struct s5p_mfc_dev *dev)
+{
+ struct s5p_mfc_cmd_args h2r_args;
+
+ memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+ return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_WAKEUP_V6,
+ &h2r_args);
+}
+
+/* Open a new instance and get its number */
+int s5p_mfc_open_inst_cmd_v6(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ struct s5p_mfc_cmd_args h2r_args;
+ int codec_type;
+
+ mfc_debug(2, "Requested codec mode: %d\n", ctx->codec_mode);
+ dev->curr_ctx = ctx->num;
+ switch (ctx->codec_mode) {
+ case S5P_MFC_CODEC_H264_DEC:
+ codec_type = S5P_FIMV_CODEC_H264_DEC_V6;
+ break;
+ case S5P_MFC_CODEC_H264_MVC_DEC:
+ codec_type = S5P_FIMV_CODEC_H264_MVC_DEC_V6;
+ break;
+ case S5P_MFC_CODEC_VC1_DEC:
+ codec_type = S5P_FIMV_CODEC_VC1_DEC_V6;
+ break;
+ case S5P_MFC_CODEC_MPEG4_DEC:
+ codec_type = S5P_FIMV_CODEC_MPEG4_DEC_V6;
+ break;
+ case S5P_MFC_CODEC_MPEG2_DEC:
+ codec_type = S5P_FIMV_CODEC_MPEG2_DEC_V6;
+ break;
+ case S5P_MFC_CODEC_H263_DEC:
+ codec_type = S5P_FIMV_CODEC_H263_DEC_V6;
+ break;
+ case S5P_MFC_CODEC_VC1RCV_DEC:
+ codec_type = S5P_FIMV_CODEC_VC1RCV_DEC_V6;
+ break;
+ case S5P_MFC_CODEC_VP8_DEC:
+ codec_type = S5P_FIMV_CODEC_VP8_DEC_V6;
+ break;
+ case S5P_MFC_CODEC_H264_ENC:
+ codec_type = S5P_FIMV_CODEC_H264_ENC_V6;
+ break;
+ case S5P_MFC_CODEC_H264_MVC_ENC:
+ codec_type = S5P_FIMV_CODEC_H264_MVC_ENC_V6;
+ break;
+ case S5P_MFC_CODEC_MPEG4_ENC:
+ codec_type = S5P_FIMV_CODEC_MPEG4_ENC_V6;
+ break;
+ case S5P_MFC_CODEC_H263_ENC:
+ codec_type = S5P_FIMV_CODEC_H263_ENC_V6;
+ break;
+ default:
+ codec_type = S5P_FIMV_CODEC_NONE_V6;
+ };
+ mfc_write(dev, codec_type, S5P_FIMV_CODEC_TYPE_V6);
+ mfc_write(dev, ctx->ctx.dma, S5P_FIMV_CONTEXT_MEM_ADDR_V6);
+ mfc_write(dev, ctx->ctx.size, S5P_FIMV_CONTEXT_MEM_SIZE_V6);
+ mfc_write(dev, 0, S5P_FIMV_D_CRC_CTRL_V6); /* no crc */
+
+ return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE_V6,
+ &h2r_args);
+}
+
+/* Close instance */
+int s5p_mfc_close_inst_cmd_v6(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ struct s5p_mfc_cmd_args h2r_args;
+ int ret = 0;
+
+ dev->curr_ctx = ctx->num;
+ if (ctx->state != MFCINST_FREE) {
+ mfc_write(dev, ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
+ ret = s5p_mfc_cmd_host2risc_v6(dev,
+ S5P_FIMV_H2R_CMD_CLOSE_INSTANCE_V6,
+ &h2r_args);
+ } else {
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+/* Initialize cmd function pointers for MFC v6 */
+static struct s5p_mfc_hw_cmds s5p_mfc_cmds_v6 = {
+ .cmd_host2risc = s5p_mfc_cmd_host2risc_v6,
+ .sys_init_cmd = s5p_mfc_sys_init_cmd_v6,
+ .sleep_cmd = s5p_mfc_sleep_cmd_v6,
+ .wakeup_cmd = s5p_mfc_wakeup_cmd_v6,
+ .open_inst_cmd = s5p_mfc_open_inst_cmd_v6,
+ .close_inst_cmd = s5p_mfc_close_inst_cmd_v6,
+};
+
+struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v6(void)
+{
+ return &s5p_mfc_cmds_v6;
+}
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h
new file mode 100644
index 0000000..b7a8e57
--- /dev/null
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h
@@ -0,0 +1,20 @@
+/*
+ * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h
+ *
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef S5P_MFC_CMD_V6_H_
+#define S5P_MFC_CMD_V6_H_
+
+#include "s5p_mfc_common.h"
+
+struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v6(void);
+
+#endif /* S5P_MFC_CMD_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
index e9e89ac..3371f8a 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
@@ -16,13 +16,14 @@
#ifndef S5P_MFC_COMMON_H_
#define S5P_MFC_COMMON_H_
-#include "regs-mfc.h"
#include <linux/platform_device.h>
#include <linux/videodev2.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
#include <media/videobuf2-core.h>
+#include "regs-mfc.h"
+#include "regs-mfc-v6.h"
/* Definitions related to MFC memory */
@@ -203,6 +204,14 @@ struct s5p_mfc_buf_size_v5 {
unsigned int shm;
};
+struct s5p_mfc_buf_size_v6 {
+ unsigned int dev_ctx;
+ unsigned int h264_dec_ctx;
+ unsigned int other_dec_ctx;
+ unsigned int h264_enc_ctx;
+ unsigned int other_enc_ctx;
+};
+
struct s5p_mfc_buf_size {
unsigned int fw;
unsigned int cpb;
@@ -218,6 +227,8 @@ struct s5p_mfc_variant {
unsigned int port_num;
struct s5p_mfc_buf_size *buf_size;
struct s5p_mfc_buf_align *buf_align;
+ char *mclk_name;
+ char *fw_name;
};
/**
@@ -274,6 +285,7 @@ struct s5p_mfc_priv_buf {
* @watchdog_work: worker for the watchdog
* @alloc_ctx: videobuf2 allocator contexts for two memory banks
* @enter_suspend: flag set when entering suspend
+ * @ctx_buf: common context memory (MFCv6)
* @warn_start: hardware error code from which warnings start
* @mfc_ops: ops structure holding HW operation function pointers
* @mfc_cmds: cmd structure holding HW commands function pointers
@@ -315,6 +327,7 @@ struct s5p_mfc_dev {
void *alloc_ctx[2];
unsigned long enter_suspend;
+ struct s5p_mfc_priv_buf ctx_buf;
int warn_start;
struct s5p_mfc_hw_ops *mfc_ops;
struct s5p_mfc_hw_cmds *mfc_cmds;
@@ -351,6 +364,22 @@ struct s5p_mfc_h264_enc_params {
int level;
u16 cpb_size;
int interlace;
+ u8 hier_qp;
+ u8 hier_qp_type;
+ u8 hier_qp_layer;
+ u8 hier_qp_layer_qp[7];
+ u8 sei_frame_packing;
+ u8 sei_fp_curr_frame_0;
+ u8 sei_fp_arrangement_type;
+
+ u8 fmo;
+ u8 fmo_map_type;
+ u8 fmo_slice_grp;
+ u8 fmo_chg_dir;
+ u32 fmo_chg_rate;
+ u32 fmo_run_len[4];
+ u8 aso;
+ u32 aso_slice_order[8];
};
/**
@@ -393,6 +422,7 @@ struct s5p_mfc_enc_params {
u32 rc_bitrate;
u16 rc_reaction_coeff;
u16 vbv_size;
+ u32 vbv_delay;
enum v4l2_mpeg_video_header_mode seq_hdr_mode;
enum v4l2_mpeg_mfc51_video_frame_skip_mode frame_skip_mode;
@@ -458,6 +488,8 @@ struct s5p_mfc_codec_ops {
* decoding buffer
* @dpb_flush_flag: flag used to indicate that a DPB buffers are being
* flushed
+ * @head_processed: flag mentioning whether the header data is processed
+ * completely or not
* @bank1_buf: handle to memory allocated for temporary buffers from
* memory bank 1
* @bank1_phys: address of the temporary buffers from memory bank 1
@@ -482,14 +514,20 @@ struct s5p_mfc_codec_ops {
* @display_delay_enable: display delay for H264 enable flag
* @after_packed_pb: flag used to track buffer when stream is in
* Packed PB format
+ * @sei_fp_parse: enable/disable parsing of frame packing SEI information
* @dpb_count: count of the DPB buffers required by MFC hw
* @total_dpb_count: count of DPB buffers with additional buffers
* requested by the application
* @ctx: context buffer information
* @dsc: descriptor buffer information
* @shm: shared memory buffer information
+ * @mv_count: number of MV buffers allocated for decoding
* @enc_params: encoding parameters for MFC
* @enc_dst_buf_size: size of the buffers for encoder output
+ * @luma_dpb_size: dpb buffer size for luma
+ * @chroma_dpb_size: dpb buffer size for chroma
+ * @me_buffer_size: size of the motion estimation buffer
+ * @tmv_buffer_size: size of temporal predictor motion vector buffer
* @frame_type: used to force the type of the next encoded frame
* @ref_queue: list of the reference buffers for encoding
* @ref_queue_cnt: number of the buffers in the reference list
@@ -538,6 +576,7 @@ struct s5p_mfc_ctx {
unsigned long consumed_stream;
unsigned int dpb_flush_flag;
+ unsigned int head_processed;
/* Buffers */
void *bank1_buf;
@@ -567,10 +606,11 @@ struct s5p_mfc_ctx {
int display_delay;
int display_delay_enable;
int after_packed_pb;
+ int sei_fp_parse;
int dpb_count;
int total_dpb_count;
-
+ int mv_count;
/* Buffers */
struct s5p_mfc_priv_buf ctx;
struct s5p_mfc_priv_buf dsc;
@@ -579,16 +619,28 @@ struct s5p_mfc_ctx {
struct s5p_mfc_enc_params enc_params;
size_t enc_dst_buf_size;
+ size_t luma_dpb_size;
+ size_t chroma_dpb_size;
+ size_t me_buffer_size;
+ size_t tmv_buffer_size;
enum v4l2_mpeg_mfc51_video_force_frame_type force_frame_type;
struct list_head ref_queue;
unsigned int ref_queue_cnt;
+ enum v4l2_mpeg_video_multi_slice_mode slice_mode;
+ union {
+ unsigned int mb;
+ unsigned int bits;
+ } slice_size;
+
struct s5p_mfc_codec_ops *c_ops;
struct v4l2_ctrl *ctrls[MFC_MAX_CTRLS];
struct v4l2_ctrl_handler ctrl_handler;
+ unsigned int frame_tag;
+ size_t scratch_buf_size;
};
/*
@@ -629,4 +681,9 @@ struct mfc_control {
#define ctrl_to_ctx(__ctrl) \
container_of((__ctrl)->handler, struct s5p_mfc_ctx, ctrl_handler)
+#define HAS_PORTNUM(dev) (dev ? (dev->variant ? \
+ (dev->variant->port_num ? 1 : 0) : 0) : 0)
+#define IS_TWOPORT(dev) (dev->variant->port_num == 2 ? 1 : 0)
+#define IS_MFCV6(dev) (dev->variant->version >= 0x60 ? 1 : 0)
+
#endif /* S5P_MFC_COMMON_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
index 524380c..9e3f45f 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
@@ -37,8 +37,9 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev)
/* Firmare has to be present as a separate file or compiled
* into kernel. */
mfc_debug_enter();
+
err = request_firmware((const struct firmware **)&fw_blob,
- "s5p-mfc.fw", dev->v4l2_dev.dev);
+ dev->variant->fw_name, dev->v4l2_dev.dev);
if (err != 0) {
mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
return -EINVAL;
@@ -82,28 +83,33 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev)
return -EIO;
}
dev->bank1 = s5p_mfc_bitproc_phys;
- b_base = vb2_dma_contig_memops.alloc(
- dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], 1 << MFC_BANK2_ALIGN_ORDER);
- if (IS_ERR(b_base)) {
- vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
- s5p_mfc_bitproc_phys = 0;
- s5p_mfc_bitproc_buf = NULL;
- mfc_err("Allocating bank2 base failed\n");
- release_firmware(fw_blob);
- return -ENOMEM;
- }
- bank2_base_phys = s5p_mfc_mem_cookie(
- dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], b_base);
- vb2_dma_contig_memops.put(b_base);
- if (bank2_base_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
- mfc_err("The base memory for bank 2 is not aligned to 128KB\n");
- vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
- s5p_mfc_bitproc_phys = 0;
- s5p_mfc_bitproc_buf = NULL;
- release_firmware(fw_blob);
- return -EIO;
+ if (HAS_PORTNUM(dev) && IS_TWOPORT(dev)) {
+ b_base = vb2_dma_contig_memops.alloc(
+ dev->alloc_ctx[MFC_BANK2_ALLOC_CTX],
+ 1 << MFC_BANK2_ALIGN_ORDER);
+ if (IS_ERR(b_base)) {
+ vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
+ s5p_mfc_bitproc_phys = 0;
+ s5p_mfc_bitproc_buf = 0;
+ mfc_err("Allocating bank2 base failed\n");
+ release_firmware(fw_blob);
+ return -ENOMEM;
+ }
+ bank2_base_phys = s5p_mfc_mem_cookie(
+ dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], b_base);
+ vb2_dma_contig_memops.put(b_base);
+ if (bank2_base_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
+ mfc_err("The base memory for bank 2 is not aligned to 128KB\n");
+ vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
+ s5p_mfc_bitproc_phys = 0;
+ s5p_mfc_bitproc_buf = 0;
+ release_firmware(fw_blob);
+ return -EIO;
+ }
+ dev->bank2 = bank2_base_phys;
+ } else {
+ dev->bank2 = dev->bank1;
}
- dev->bank2 = bank2_base_phys;
memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size);
wmb();
release_firmware(fw_blob);
@@ -120,8 +126,9 @@ int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev)
/* Firmare has to be present as a separate file or compiled
* into kernel. */
mfc_debug_enter();
+
err = request_firmware((const struct firmware **)&fw_blob,
- "s5p-mfc.fw", dev->v4l2_dev.dev);
+ dev->variant->fw_name, dev->v4l2_dev.dev);
if (err != 0) {
mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
return -EINVAL;
@@ -162,46 +169,81 @@ int s5p_mfc_reset(struct s5p_mfc_dev *dev)
{
unsigned int mc_status;
unsigned long timeout;
+ int i;
mfc_debug_enter();
- /* Stop procedure */
- /* reset RISC */
- mfc_write(dev, 0x3f6, S5P_FIMV_SW_RESET);
- /* All reset except for MC */
- mfc_write(dev, 0x3e2, S5P_FIMV_SW_RESET);
- mdelay(10);
-
- timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
- /* Check MC status */
- do {
- if (time_after(jiffies, timeout)) {
- mfc_err("Timeout while resetting MFC\n");
- return -EIO;
- }
- mc_status = mfc_read(dev, S5P_FIMV_MC_STATUS);
+ if (IS_MFCV6(dev)) {
+ /* Reset IP */
+ /* except RISC, reset */
+ mfc_write(dev, 0xFEE, S5P_FIMV_MFC_RESET_V6);
+ /* reset release */
+ mfc_write(dev, 0x0, S5P_FIMV_MFC_RESET_V6);
+
+ /* Zero Initialization of MFC registers */
+ mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD_V6);
+ mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD_V6);
+ mfc_write(dev, 0, S5P_FIMV_FW_VERSION_V6);
+
+ for (i = 0; i < S5P_FIMV_REG_CLEAR_COUNT_V6; i++)
+ mfc_write(dev, 0, S5P_FIMV_REG_CLEAR_BEGIN_V6 + (i*4));
+
+ /* Reset */
+ mfc_write(dev, 0, S5P_FIMV_RISC_ON_V6);
+ mfc_write(dev, 0x1FFF, S5P_FIMV_MFC_RESET_V6);
+ mfc_write(dev, 0, S5P_FIMV_MFC_RESET_V6);
+ } else {
+ /* Stop procedure */
+ /* reset RISC */
+ mfc_write(dev, 0x3f6, S5P_FIMV_SW_RESET);
+ /* All reset except for MC */
+ mfc_write(dev, 0x3e2, S5P_FIMV_SW_RESET);
+ mdelay(10);
- } while (mc_status & 0x3);
+ timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
+ /* Check MC status */
+ do {
+ if (time_after(jiffies, timeout)) {
+ mfc_err("Timeout while resetting MFC\n");
+ return -EIO;
+ }
+
+ mc_status = mfc_read(dev, S5P_FIMV_MC_STATUS);
+
+ } while (mc_status & 0x3);
+
+ mfc_write(dev, 0x0, S5P_FIMV_SW_RESET);
+ mfc_write(dev, 0x3fe, S5P_FIMV_SW_RESET);
+ }
- mfc_write(dev, 0x0, S5P_FIMV_SW_RESET);
- mfc_write(dev, 0x3fe, S5P_FIMV_SW_RESET);
mfc_debug_leave();
return 0;
}
static inline void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev)
{
- mfc_write(dev, dev->bank1, S5P_FIMV_MC_DRAMBASE_ADR_A);
- mfc_write(dev, dev->bank2, S5P_FIMV_MC_DRAMBASE_ADR_B);
- mfc_debug(2, "Bank1: %08x, Bank2: %08x\n", dev->bank1, dev->bank2);
+ if (IS_MFCV6(dev)) {
+ mfc_write(dev, dev->bank1, S5P_FIMV_RISC_BASE_ADDRESS_V6);
+ mfc_debug(2, "Base Address : %08x\n", dev->bank1);
+ } else {
+ mfc_write(dev, dev->bank1, S5P_FIMV_MC_DRAMBASE_ADR_A);
+ mfc_write(dev, dev->bank2, S5P_FIMV_MC_DRAMBASE_ADR_B);
+ mfc_debug(2, "Bank1: %08x, Bank2: %08x\n",
+ dev->bank1, dev->bank2);
+ }
}
static inline void s5p_mfc_clear_cmds(struct s5p_mfc_dev *dev)
{
- mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH0_INST_ID);
- mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH1_INST_ID);
- mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
- mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD);
+ if (IS_MFCV6(dev)) {
+ /* Zero initialization should be done before RESET.
+ * Nothing to do here. */
+ } else {
+ mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH0_INST_ID);
+ mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH1_INST_ID);
+ mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
+ mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD);
+ }
}
/* Initialize hardware */
@@ -229,7 +271,10 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
s5p_mfc_clear_cmds(dev);
/* 3. Release reset signal to the RISC */
s5p_mfc_clean_dev_int_flags(dev);
- mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
+ if (IS_MFCV6(dev))
+ mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6);
+ else
+ mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
mfc_debug(2, "Will now wait for completion of firmware transfer\n");
if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_FW_STATUS_RET)) {
mfc_err("Failed to load firmware\n");
@@ -263,7 +308,11 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
s5p_mfc_clock_off();
return -EIO;
}
- ver = mfc_read(dev, S5P_FIMV_FW_VERSION);
+ if (IS_MFCV6(dev))
+ ver = mfc_read(dev, S5P_FIMV_FW_VERSION_V6);
+ else
+ ver = mfc_read(dev, S5P_FIMV_FW_VERSION);
+
mfc_debug(2, "MFC F/W version : %02xyy, %02xmm, %02xdd\n",
(ver >> 16) & 0xFF, (ver >> 8) & 0xFF, ver & 0xFF);
s5p_mfc_clock_off();
@@ -338,7 +387,10 @@ int s5p_mfc_wakeup(struct s5p_mfc_dev *dev)
return ret;
}
/* 4. Release reset signal to the RISC */
- mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
+ if (IS_MFCV6(dev))
+ mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6);
+ else
+ mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
mfc_debug(2, "Ok, now will write a command to wakeup the system\n");
if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_WAKEUP_RET)) {
mfc_err("Failed to load firmware\n");
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
index 8133a4c..e27c994 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
@@ -31,10 +31,17 @@
#include "s5p_mfc_pm.h"
#define DEF_SRC_FMT_DEC V4L2_PIX_FMT_H264
-#define DEF_DST_FMT_DEC V4L2_PIX_FMT_NV12MT
+#define DEF_DST_FMT_DEC V4L2_PIX_FMT_NV12MT_16X16
static struct s5p_mfc_fmt formats[] = {
{
+ .name = "4:2:0 2 Planes 16x16 Tiles",
+ .fourcc = V4L2_PIX_FMT_NV12MT_16X16,
+ .codec_mode = S5P_MFC_CODEC_NONE,
+ .type = MFC_FMT_RAW,
+ .num_planes = 2,
+ },
+ {
.name = "4:2:0 2 Planes 64x32 Tiles",
.fourcc = V4L2_PIX_FMT_NV12MT,
.codec_mode = S5P_MFC_CODEC_NONE,
@@ -42,67 +49,88 @@ static struct s5p_mfc_fmt formats[] = {
.num_planes = 2,
},
{
- .name = "4:2:0 2 Planes",
- .fourcc = V4L2_PIX_FMT_NV12M,
- .codec_mode = S5P_MFC_CODEC_NONE,
- .type = MFC_FMT_RAW,
- .num_planes = 2,
+ .name = "4:2:0 2 Planes Y/CbCr",
+ .fourcc = V4L2_PIX_FMT_NV12M,
+ .codec_mode = S5P_MFC_CODEC_NONE,
+ .type = MFC_FMT_RAW,
+ .num_planes = 2,
+ },
+ {
+ .name = "4:2:0 2 Planes Y/CrCb",
+ .fourcc = V4L2_PIX_FMT_NV21M,
+ .codec_mode = S5P_MFC_CODEC_NONE,
+ .type = MFC_FMT_RAW,
+ .num_planes = 2,
+ },
+ {
+ .name = "H264 Encoded Stream",
+ .fourcc = V4L2_PIX_FMT_H264,
+ .codec_mode = S5P_MFC_CODEC_H264_DEC,
+ .type = MFC_FMT_DEC,
+ .num_planes = 1,
},
{
- .name = "H264 Encoded Stream",
- .fourcc = V4L2_PIX_FMT_H264,
- .codec_mode = S5P_MFC_CODEC_H264_DEC,
- .type = MFC_FMT_DEC,
- .num_planes = 1,
+ .name = "H264/MVC Encoded Stream",
+ .fourcc = V4L2_PIX_FMT_H264_MVC,
+ .codec_mode = S5P_MFC_CODEC_H264_MVC_DEC,
+ .type = MFC_FMT_DEC,
+ .num_planes = 1,
},
{
- .name = "H263 Encoded Stream",
- .fourcc = V4L2_PIX_FMT_H263,
- .codec_mode = S5P_MFC_CODEC_H263_DEC,
- .type = MFC_FMT_DEC,
- .num_planes = 1,
+ .name = "H263 Encoded Stream",
+ .fourcc = V4L2_PIX_FMT_H263,
+ .codec_mode = S5P_MFC_CODEC_H263_DEC,
+ .type = MFC_FMT_DEC,
+ .num_planes = 1,
},
{
- .name = "MPEG1 Encoded Stream",
- .fourcc = V4L2_PIX_FMT_MPEG1,
- .codec_mode = S5P_MFC_CODEC_MPEG2_DEC,
- .type = MFC_FMT_DEC,
- .num_planes = 1,
+ .name = "MPEG1 Encoded Stream",
+ .fourcc = V4L2_PIX_FMT_MPEG1,
+ .codec_mode = S5P_MFC_CODEC_MPEG2_DEC,
+ .type = MFC_FMT_DEC,
+ .num_planes = 1,
},
{
- .name = "MPEG2 Encoded Stream",
- .fourcc = V4L2_PIX_FMT_MPEG2,
- .codec_mode = S5P_MFC_CODEC_MPEG2_DEC,
- .type = MFC_FMT_DEC,
- .num_planes = 1,
+ .name = "MPEG2 Encoded Stream",
+ .fourcc = V4L2_PIX_FMT_MPEG2,
+ .codec_mode = S5P_MFC_CODEC_MPEG2_DEC,
+ .type = MFC_FMT_DEC,
+ .num_planes = 1,
},
{
- .name = "MPEG4 Encoded Stream",
- .fourcc = V4L2_PIX_FMT_MPEG4,
- .codec_mode = S5P_MFC_CODEC_MPEG4_DEC,
- .type = MFC_FMT_DEC,
- .num_planes = 1,
+ .name = "MPEG4 Encoded Stream",
+ .fourcc = V4L2_PIX_FMT_MPEG4,
+ .codec_mode = S5P_MFC_CODEC_MPEG4_DEC,
+ .type = MFC_FMT_DEC,
+ .num_planes = 1,
},
{
- .name = "XviD Encoded Stream",
- .fourcc = V4L2_PIX_FMT_XVID,
- .codec_mode = S5P_MFC_CODEC_MPEG4_DEC,
- .type = MFC_FMT_DEC,
- .num_planes = 1,
+ .name = "XviD Encoded Stream",
+ .fourcc = V4L2_PIX_FMT_XVID,
+ .codec_mode = S5P_MFC_CODEC_MPEG4_DEC,
+ .type = MFC_FMT_DEC,
+ .num_planes = 1,
},
{
- .name = "VC1 Encoded Stream",
- .fourcc = V4L2_PIX_FMT_VC1_ANNEX_G,
- .codec_mode = S5P_MFC_CODEC_VC1_DEC,
- .type = MFC_FMT_DEC,
- .num_planes = 1,
+ .name = "VC1 Encoded Stream",
+ .fourcc = V4L2_PIX_FMT_VC1_ANNEX_G,
+ .codec_mode = S5P_MFC_CODEC_VC1_DEC,
+ .type = MFC_FMT_DEC,
+ .num_planes = 1,
},
{
- .name = "VC1 RCV Encoded Stream",
- .fourcc = V4L2_PIX_FMT_VC1_ANNEX_L,
- .codec_mode = S5P_MFC_CODEC_VC1RCV_DEC,
- .type = MFC_FMT_DEC,
- .num_planes = 1,
+ .name = "VC1 RCV Encoded Stream",
+ .fourcc = V4L2_PIX_FMT_VC1_ANNEX_L,
+ .codec_mode = S5P_MFC_CODEC_VC1RCV_DEC,
+ .type = MFC_FMT_DEC,
+ .num_planes = 1,
+ },
+ {
+ .name = "VP8 Encoded Stream",
+ .fourcc = V4L2_PIX_FMT_VP8,
+ .codec_mode = S5P_MFC_CODEC_VP8_DEC,
+ .type = MFC_FMT_DEC,
+ .num_planes = 1,
},
};
@@ -343,21 +371,36 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
/* Try format */
static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
{
+ struct s5p_mfc_dev *dev = video_drvdata(file);
struct s5p_mfc_fmt *fmt;
- if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- mfc_err("This node supports decoding only\n");
- return -EINVAL;
- }
- fmt = find_format(f, MFC_FMT_DEC);
- if (!fmt) {
- mfc_err("Unsupported format\n");
- return -EINVAL;
- }
- if (fmt->type != MFC_FMT_DEC) {
- mfc_err("\n");
- return -EINVAL;
+ mfc_debug(2, "Type is %d\n", f->type);
+ if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ fmt = find_format(f, MFC_FMT_DEC);
+ if (!fmt) {
+ mfc_err("Unsupported format for source.\n");
+ return -EINVAL;
+ }
+ if (!IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_VP8)) {
+ mfc_err("Not supported format.\n");
+ return -EINVAL;
+ }
+ } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ fmt = find_format(f, MFC_FMT_RAW);
+ if (!fmt) {
+ mfc_err("Unsupported format for destination.\n");
+ return -EINVAL;
+ }
+ if (IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) {
+ mfc_err("Not supported format.\n");
+ return -EINVAL;
+ } else if (!IS_MFCV6(dev) &&
+ (fmt->fourcc != V4L2_PIX_FMT_NV12MT)) {
+ mfc_err("Not supported format.\n");
+ return -EINVAL;
+ }
}
+
return 0;
}
@@ -380,6 +423,27 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
ret = -EBUSY;
goto out;
}
+ if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ fmt = find_format(f, MFC_FMT_RAW);
+ if (!fmt) {
+ mfc_err("Unsupported format for source.\n");
+ return -EINVAL;
+ }
+ if (!IS_MFCV6(dev) && (fmt->fourcc != V4L2_PIX_FMT_NV12MT)) {
+ mfc_err("Not supported format.\n");
+ return -EINVAL;
+ } else if (IS_MFCV6(dev) &&
+ (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) {
+ mfc_err("Not supported format.\n");
+ return -EINVAL;
+ }
+ ctx->dst_fmt = fmt;
+ mfc_debug_leave();
+ return ret;
+ } else if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ mfc_err("Wrong type error for S_FMT : %d", f->type);
+ return -EINVAL;
+ }
fmt = find_format(f, MFC_FMT_DEC);
if (!fmt || fmt->codec_mode == S5P_MFC_CODEC_NONE) {
mfc_err("Unknown codec\n");
@@ -392,6 +456,10 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
ret = -EINVAL;
goto out;
}
+ if (!IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_VP8)) {
+ mfc_err("Not supported format.\n");
+ return -EINVAL;
+ }
ctx->src_fmt = fmt;
ctx->codec_mode = fmt->codec_mode;
mfc_debug(2, "The codec number is: %d\n", ctx->codec_mode);
@@ -763,6 +831,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
void *allocators[])
{
struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
+ struct s5p_mfc_dev *dev = ctx->dev;
/* Video output for decoding (source)
* this can be set after getting an instance */
@@ -798,7 +867,13 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
psize[0] = ctx->luma_size;
psize[1] = ctx->chroma_size;
- allocators[0] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
+
+ if (IS_MFCV6(dev))
+ allocators[0] =
+ ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
+ else
+ allocators[0] =
+ ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
allocators[1] = ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
} else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
ctx->state == MFCINST_INIT) {
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
index fe34f17..da96017 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
@@ -35,39 +35,53 @@
static struct s5p_mfc_fmt formats[] = {
{
- .name = "4:2:0 2 Planes 64x32 Tiles",
- .fourcc = V4L2_PIX_FMT_NV12MT,
- .codec_mode = S5P_MFC_CODEC_NONE,
- .type = MFC_FMT_RAW,
- .num_planes = 2,
+ .name = "4:2:0 2 Planes 16x16 Tiles",
+ .fourcc = V4L2_PIX_FMT_NV12MT_16X16,
+ .codec_mode = S5P_MFC_CODEC_NONE,
+ .type = MFC_FMT_RAW,
+ .num_planes = 2,
},
{
- .name = "4:2:0 2 Planes",
- .fourcc = V4L2_PIX_FMT_NV12M,
- .codec_mode = S5P_MFC_CODEC_NONE,
- .type = MFC_FMT_RAW,
- .num_planes = 2,
+ .name = "4:2:0 2 Planes 64x32 Tiles",
+ .fourcc = V4L2_PIX_FMT_NV12MT,
+ .codec_mode = S5P_MFC_CODEC_NONE,
+ .type = MFC_FMT_RAW,
+ .num_planes = 2,
},
{
- .name = "H264 Encoded Stream",
- .fourcc = V4L2_PIX_FMT_H264,
- .codec_mode = S5P_MFC_CODEC_H264_ENC,
- .type = MFC_FMT_ENC,
- .num_planes = 1,
+ .name = "4:2:0 2 Planes Y/CbCr",
+ .fourcc = V4L2_PIX_FMT_NV12M,
+ .codec_mode = S5P_MFC_CODEC_NONE,
+ .type = MFC_FMT_RAW,
+ .num_planes = 2,
},
{
- .name = "MPEG4 Encoded Stream",
- .fourcc = V4L2_PIX_FMT_MPEG4,
- .codec_mode = S5P_MFC_CODEC_MPEG4_ENC,
- .type = MFC_FMT_ENC,
- .num_planes = 1,
+ .name = "4:2:0 2 Planes Y/CrCb",
+ .fourcc = V4L2_PIX_FMT_NV21M,
+ .codec_mode = S5P_MFC_CODEC_NONE,
+ .type = MFC_FMT_RAW,
+ .num_planes = 2,
},
{
- .name = "H263 Encoded Stream",
- .fourcc = V4L2_PIX_FMT_H263,
- .codec_mode = S5P_MFC_CODEC_H263_ENC,
- .type = MFC_FMT_ENC,
- .num_planes = 1,
+ .name = "H264 Encoded Stream",
+ .fourcc = V4L2_PIX_FMT_H264,
+ .codec_mode = S5P_MFC_CODEC_H264_ENC,
+ .type = MFC_FMT_ENC,
+ .num_planes = 1,
+ },
+ {
+ .name = "MPEG4 Encoded Stream",
+ .fourcc = V4L2_PIX_FMT_MPEG4,
+ .codec_mode = S5P_MFC_CODEC_MPEG4_ENC,
+ .type = MFC_FMT_ENC,
+ .num_planes = 1,
+ },
+ {
+ .name = "H263 Encoded Stream",
+ .fourcc = V4L2_PIX_FMT_H263,
+ .codec_mode = S5P_MFC_CODEC_H263_ENC,
+ .type = MFC_FMT_ENC,
+ .num_planes = 1,
},
};
@@ -575,7 +589,8 @@ static int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx)
if (ctx->state == MFCINST_GOT_INST && ctx->dst_queue_cnt >= 1)
return 1;
/* context is ready to encode a frame */
- if (ctx->state == MFCINST_RUNNING &&
+ if ((ctx->state == MFCINST_RUNNING ||
+ ctx->state == MFCINST_HEAD_PARSED) &&
ctx->src_queue_cnt >= 1 && ctx->dst_queue_cnt >= 1)
return 1;
/* context is ready to encode remain frames */
@@ -644,13 +659,23 @@ static int enc_post_seq_start(struct s5p_mfc_ctx *ctx)
vb2_buffer_done(dst_mb->b, VB2_BUF_STATE_DONE);
spin_unlock_irqrestore(&dev->irqlock, flags);
}
- ctx->state = MFCINST_RUNNING;
- if (s5p_mfc_ctx_ready(ctx)) {
- spin_lock_irqsave(&dev->condlock, flags);
- set_bit(ctx->num, &dev->ctx_work_bits);
- spin_unlock_irqrestore(&dev->condlock, flags);
+
+ if (IS_MFCV6(dev)) {
+ ctx->state = MFCINST_HEAD_PARSED; /* for INIT_BUFFER cmd */
+ } else {
+ ctx->state = MFCINST_RUNNING;
+ if (s5p_mfc_ctx_ready(ctx)) {
+ spin_lock_irqsave(&dev->condlock, flags);
+ set_bit(ctx->num, &dev->ctx_work_bits);
+ spin_unlock_irqrestore(&dev->condlock, flags);
+ }
+ s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
}
- s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
+
+ if (IS_MFCV6(dev))
+ ctx->dpb_count = s5p_mfc_hw_call(dev->mfc_ops,
+ get_enc_dpb_count, dev);
+
return 0;
}
@@ -973,6 +998,17 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
mfc_err("failed to set output format\n");
return -EINVAL;
}
+
+ if (!IS_MFCV6(dev) &&
+ (fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16)) {
+ mfc_err("Not supported format.\n");
+ return -EINVAL;
+ } else if (IS_MFCV6(dev) &&
+ (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) {
+ mfc_err("Not supported format.\n");
+ return -EINVAL;
+ }
+
if (fmt->num_planes != pix_fmt_mp->num_planes) {
mfc_err("failed to set output format\n");
ret = -EINVAL;
@@ -1006,6 +1042,7 @@ out:
static int vidioc_reqbufs(struct file *file, void *priv,
struct v4l2_requestbuffers *reqbufs)
{
+ struct s5p_mfc_dev *dev = video_drvdata(file);
struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
int ret = 0;
@@ -1025,13 +1062,16 @@ static int vidioc_reqbufs(struct file *file, void *priv,
return ret;
}
ctx->capture_state = QUEUE_BUFS_REQUESTED;
- ret = s5p_mfc_hw_call(ctx->dev->mfc_ops, alloc_codec_buffers,
- ctx);
- if (ret) {
- mfc_err("Failed to allocate encoding buffers\n");
- reqbufs->count = 0;
- ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
- return -ENOMEM;
+
+ if (!IS_MFCV6(dev)) {
+ ret = s5p_mfc_hw_call(ctx->dev->mfc_ops,
+ alloc_codec_buffers, ctx);
+ if (ret) {
+ mfc_err("Failed to allocate encoding buffers\n");
+ reqbufs->count = 0;
+ ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
+ return -ENOMEM;
+ }
}
} else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
if (ctx->output_state != QUEUE_FREE) {
@@ -1278,6 +1318,13 @@ static int s5p_mfc_enc_s_ctrl(struct v4l2_ctrl *ctrl)
p->codec.h264.profile =
S5P_FIMV_ENC_PROFILE_H264_BASELINE;
break;
+ case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
+ if (IS_MFCV6(dev))
+ p->codec.h264.profile =
+ S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_BASELINE;
+ else
+ ret = -EINVAL;
+ break;
default:
ret = -EINVAL;
}
@@ -1497,6 +1544,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
unsigned int psize[], void *allocators[])
{
struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
+ struct s5p_mfc_dev *dev = ctx->dev;
if (ctx->state != MFCINST_GOT_INST) {
mfc_err("inavlid state: %d\n", ctx->state);
@@ -1525,8 +1573,17 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
*buf_count = MFC_MAX_BUFFERS;
psize[0] = ctx->luma_size;
psize[1] = ctx->chroma_size;
- allocators[0] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
- allocators[1] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
+ if (IS_MFCV6(dev)) {
+ allocators[0] =
+ ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
+ allocators[1] =
+ ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
+ } else {
+ allocators[0] =
+ ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
+ allocators[1] =
+ ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
+ }
} else {
mfc_err("inavlid queue type: %d\n", vq->type);
return -EINVAL;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
index ef8683e..d69248b 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
@@ -14,12 +14,18 @@
#include "s5p_mfc_opr.h"
#include "s5p_mfc_opr_v5.h"
+#include "s5p_mfc_opr_v6.h"
static struct s5p_mfc_hw_ops *s5p_mfc_ops;
void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev)
{
- s5p_mfc_ops = s5p_mfc_init_hw_ops_v5();
- dev->warn_start = S5P_FIMV_ERR_WARNINGS_START;
+ if (IS_MFCV6(dev)) {
+ s5p_mfc_ops = s5p_mfc_init_hw_ops_v6();
+ dev->warn_start = S5P_FIMV_ERR_WARNINGS_START_V6;
+ } else {
+ s5p_mfc_ops = s5p_mfc_init_hw_ops_v5();
+ dev->warn_start = S5P_FIMV_ERR_WARNINGS_START;
+ }
dev->mfc_ops = s5p_mfc_ops;
}
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
new file mode 100644
index 0000000..7fb905b
--- /dev/null
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
@@ -0,0 +1,1956 @@
+/*
+ * drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
+ *
+ * Samsung MFC (Multi Function Codec - FIMV) driver
+ * This file contains hw related functions.
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#undef DEBUG
+
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/firmware.h>
+#include <linux/err.h>
+#include <linux/sched.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/cacheflush.h>
+
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_cmd.h"
+#include "s5p_mfc_intr.h"
+#include "s5p_mfc_pm.h"
+#include "s5p_mfc_debug.h"
+#include "s5p_mfc_opr.h"
+#include "s5p_mfc_opr_v6.h"
+
+/* #define S5P_MFC_DEBUG_REGWRITE */
+#ifdef S5P_MFC_DEBUG_REGWRITE
+#undef writel
+#define writel(v, r) \
+ do { \
+ pr_err("MFCWRITE(%p): %08x\n", r, (unsigned int)v); \
+ __raw_writel(v, r); \
+ } while (0)
+#endif /* S5P_MFC_DEBUG_REGWRITE */
+
+#define READL(offset) readl(dev->regs_base + (offset))
+#define WRITEL(data, offset) writel((data), dev->regs_base + (offset))
+#define OFFSETA(x) (((x) - dev->port_a) >> S5P_FIMV_MEM_OFFSET)
+#define OFFSETB(x) (((x) - dev->port_b) >> S5P_FIMV_MEM_OFFSET)
+
+/* Allocate temporary buffers for decoding */
+int s5p_mfc_alloc_dec_temp_buffers_v6(struct s5p_mfc_ctx *ctx)
+{
+ /* NOP */
+
+ return 0;
+}
+
+/* Release temproary buffers for decoding */
+void s5p_mfc_release_dec_desc_buffer_v6(struct s5p_mfc_ctx *ctx)
+{
+ /* NOP */
+}
+
+int s5p_mfc_get_dec_status_v6(struct s5p_mfc_dev *dev)
+{
+ /* NOP */
+ return -1;
+}
+
+/* Allocate codec buffers */
+int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ unsigned int mb_width, mb_height;
+
+ mb_width = MB_WIDTH(ctx->img_width);
+ mb_height = MB_HEIGHT(ctx->img_height);
+
+ if (ctx->type == MFCINST_DECODER) {
+ mfc_debug(2, "Luma size:%d Chroma size:%d MV size:%d\n",
+ ctx->luma_size, ctx->chroma_size, ctx->mv_size);
+ mfc_debug(2, "Totals bufs: %d\n", ctx->total_dpb_count);
+ } else if (ctx->type == MFCINST_ENCODER) {
+ ctx->tmv_buffer_size = S5P_FIMV_NUM_TMV_BUFFERS_V6 *
+ ALIGN(S5P_FIMV_TMV_BUFFER_SIZE_V6(mb_width, mb_height),
+ S5P_FIMV_TMV_BUFFER_ALIGN_V6);
+ ctx->luma_dpb_size = ALIGN((mb_width * mb_height) *
+ S5P_FIMV_LUMA_MB_TO_PIXEL_V6,
+ S5P_FIMV_LUMA_DPB_BUFFER_ALIGN_V6);
+ ctx->chroma_dpb_size = ALIGN((mb_width * mb_height) *
+ S5P_FIMV_CHROMA_MB_TO_PIXEL_V6,
+ S5P_FIMV_CHROMA_DPB_BUFFER_ALIGN_V6);
+ ctx->me_buffer_size = ALIGN(S5P_FIMV_ME_BUFFER_SIZE_V6(
+ ctx->img_width, ctx->img_height,
+ mb_width, mb_height),
+ S5P_FIMV_ME_BUFFER_ALIGN_V6);
+
+ mfc_debug(2, "recon luma size: %d chroma size: %d\n",
+ ctx->luma_dpb_size, ctx->chroma_dpb_size);
+ } else {
+ return -EINVAL;
+ }
+
+ /* Codecs have different memory requirements */
+ switch (ctx->codec_mode) {
+ case S5P_MFC_CODEC_H264_DEC:
+ case S5P_MFC_CODEC_H264_MVC_DEC:
+ ctx->scratch_buf_size =
+ S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V6(
+ mb_width,
+ mb_height);
+ ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
+ S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
+ ctx->bank1_size =
+ ctx->scratch_buf_size +
+ (ctx->mv_count * ctx->mv_size);
+ break;
+ case S5P_MFC_CODEC_MPEG4_DEC:
+ ctx->scratch_buf_size =
+ S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V6(
+ mb_width,
+ mb_height);
+ ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
+ S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
+ ctx->bank1_size = ctx->scratch_buf_size;
+ break;
+ case S5P_MFC_CODEC_VC1RCV_DEC:
+ case S5P_MFC_CODEC_VC1_DEC:
+ ctx->scratch_buf_size =
+ S5P_FIMV_SCRATCH_BUF_SIZE_VC1_DEC_V6(
+ mb_width,
+ mb_height);
+ ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
+ S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
+ ctx->bank1_size = ctx->scratch_buf_size;
+ break;
+ case S5P_MFC_CODEC_MPEG2_DEC:
+ ctx->bank1_size = 0;
+ ctx->bank2_size = 0;
+ break;
+ case S5P_MFC_CODEC_H263_DEC:
+ ctx->scratch_buf_size =
+ S5P_FIMV_SCRATCH_BUF_SIZE_H263_DEC_V6(
+ mb_width,
+ mb_height);
+ ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
+ S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
+ ctx->bank1_size = ctx->scratch_buf_size;
+ break;
+ case S5P_MFC_CODEC_VP8_DEC:
+ ctx->scratch_buf_size =
+ S5P_FIMV_SCRATCH_BUF_SIZE_VP8_DEC_V6(
+ mb_width,
+ mb_height);
+ ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
+ S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
+ ctx->bank1_size = ctx->scratch_buf_size;
+ break;
+ case S5P_MFC_CODEC_H264_ENC:
+ ctx->scratch_buf_size =
+ S5P_FIMV_SCRATCH_BUF_SIZE_H264_ENC_V6(
+ mb_width,
+ mb_height);
+ ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
+ S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
+ ctx->bank1_size =
+ ctx->scratch_buf_size + ctx->tmv_buffer_size +
+ (ctx->dpb_count * (ctx->luma_dpb_size +
+ ctx->chroma_dpb_size + ctx->me_buffer_size));
+ ctx->bank2_size = 0;
+ break;
+ case S5P_MFC_CODEC_MPEG4_ENC:
+ case S5P_MFC_CODEC_H263_ENC:
+ ctx->scratch_buf_size =
+ S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_ENC_V6(
+ mb_width,
+ mb_height);
+ ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
+ S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
+ ctx->bank1_size =
+ ctx->scratch_buf_size + ctx->tmv_buffer_size +
+ (ctx->dpb_count * (ctx->luma_dpb_size +
+ ctx->chroma_dpb_size + ctx->me_buffer_size));
+ ctx->bank2_size = 0;
+ break;
+ default:
+ break;
+ }
+
+ /* Allocate only if memory from bank 1 is necessary */
+ if (ctx->bank1_size > 0) {
+ ctx->bank1_buf = vb2_dma_contig_memops.alloc(
+ dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_size);
+ if (IS_ERR(ctx->bank1_buf)) {
+ ctx->bank1_buf = 0;
+ pr_err("Buf alloc for decoding failed (port A)\n");
+ return -ENOMEM;
+ }
+ ctx->bank1_phys = s5p_mfc_mem_cookie(
+ dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_buf);
+ BUG_ON(ctx->bank1_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
+ }
+
+ return 0;
+}
+
+/* Release buffers allocated for codec */
+void s5p_mfc_release_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
+{
+ if (ctx->bank1_buf) {
+ vb2_dma_contig_memops.put(ctx->bank1_buf);
+ ctx->bank1_buf = 0;
+ ctx->bank1_phys = 0;
+ ctx->bank1_size = 0;
+ }
+}
+
+/* Allocate memory for instance data buffer */
+int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv;
+
+ mfc_debug_enter();
+
+ switch (ctx->codec_mode) {
+ case S5P_MFC_CODEC_H264_DEC:
+ case S5P_MFC_CODEC_H264_MVC_DEC:
+ ctx->ctx.size = buf_size->h264_dec_ctx;
+ break;
+ case S5P_MFC_CODEC_MPEG4_DEC:
+ case S5P_MFC_CODEC_H263_DEC:
+ case S5P_MFC_CODEC_VC1RCV_DEC:
+ case S5P_MFC_CODEC_VC1_DEC:
+ case S5P_MFC_CODEC_MPEG2_DEC:
+ case S5P_MFC_CODEC_VP8_DEC:
+ ctx->ctx.size = buf_size->other_dec_ctx;
+ break;
+ case S5P_MFC_CODEC_H264_ENC:
+ ctx->ctx.size = buf_size->h264_enc_ctx;
+ break;
+ case S5P_MFC_CODEC_MPEG4_ENC:
+ case S5P_MFC_CODEC_H263_ENC:
+ ctx->ctx.size = buf_size->other_enc_ctx;
+ break;
+ default:
+ ctx->ctx.size = 0;
+ mfc_err("Codec type(%d) should be checked!\n", ctx->codec_mode);
+ break;
+ }
+
+ ctx->ctx.alloc = vb2_dma_contig_memops.alloc(
+ dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx.size);
+ if (IS_ERR(ctx->ctx.alloc)) {
+ mfc_err("Allocating context buffer failed.\n");
+ return PTR_ERR(ctx->ctx.alloc);
+ }
+
+ ctx->ctx.dma = s5p_mfc_mem_cookie(
+ dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx.alloc);
+
+ ctx->ctx.virt = vb2_dma_contig_memops.vaddr(ctx->ctx.alloc);
+ if (!ctx->ctx.virt) {
+ vb2_dma_contig_memops.put(ctx->ctx.alloc);
+ ctx->ctx.alloc = NULL;
+ ctx->ctx.dma = 0;
+ ctx->ctx.virt = NULL;
+
+ mfc_err("Remapping context buffer failed.\n");
+ return -ENOMEM;
+ }
+
+ memset(ctx->ctx.virt, 0, ctx->ctx.size);
+ wmb();
+
+ mfc_debug_leave();
+
+ return 0;
+}
+
+/* Release instance buffer */
+void s5p_mfc_release_instance_buffer_v6(struct s5p_mfc_ctx *ctx)
+{
+ mfc_debug_enter();
+
+ if (ctx->ctx.alloc) {
+ vb2_dma_contig_memops.put(ctx->ctx.alloc);
+ ctx->ctx.alloc = NULL;
+ ctx->ctx.dma = 0;
+ ctx->ctx.virt = NULL;
+ }
+
+ mfc_debug_leave();
+}
+
+/* Allocate context buffers for SYS_INIT */
+int s5p_mfc_alloc_dev_context_buffer_v6(struct s5p_mfc_dev *dev)
+{
+ struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv;
+
+ mfc_debug_enter();
+
+ dev->ctx_buf.alloc = vb2_dma_contig_memops.alloc(
+ dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], buf_size->dev_ctx);
+ if (IS_ERR(dev->ctx_buf.alloc)) {
+ mfc_err("Allocating DESC buffer failed.\n");
+ return PTR_ERR(dev->ctx_buf.alloc);
+ }
+
+ dev->ctx_buf.dma = s5p_mfc_mem_cookie(
+ dev->alloc_ctx[MFC_BANK1_ALLOC_CTX],
+ dev->ctx_buf.alloc);
+
+ dev->ctx_buf.virt = vb2_dma_contig_memops.vaddr(dev->ctx_buf.alloc);
+ if (!dev->ctx_buf.virt) {
+ vb2_dma_contig_memops.put(dev->ctx_buf.alloc);
+ dev->ctx_buf.alloc = NULL;
+ dev->ctx_buf.dma = 0;
+
+ mfc_err("Remapping DESC buffer failed.\n");
+ return -ENOMEM;
+ }
+
+ memset(dev->ctx_buf.virt, 0, buf_size->dev_ctx);
+ wmb();
+
+ mfc_debug_leave();
+
+ return 0;
+}
+
+/* Release context buffers for SYS_INIT */
+void s5p_mfc_release_dev_context_buffer_v6(struct s5p_mfc_dev *dev)
+{
+ if (dev->ctx_buf.alloc) {
+ vb2_dma_contig_memops.put(dev->ctx_buf.alloc);
+ dev->ctx_buf.alloc = NULL;
+ dev->ctx_buf.dma = 0;
+ dev->ctx_buf.virt = NULL;
+ }
+}
+
+static int calc_plane(int width, int height)
+{
+ int mbX, mbY;
+
+ mbX = DIV_ROUND_UP(width, S5P_FIMV_NUM_PIXELS_IN_MB_ROW_V6);
+ mbY = DIV_ROUND_UP(height, S5P_FIMV_NUM_PIXELS_IN_MB_COL_V6);
+
+ if (width * height < S5P_FIMV_MAX_FRAME_SIZE_V6)
+ mbY = (mbY + 1) / 2 * 2;
+
+ return (mbX * S5P_FIMV_NUM_PIXELS_IN_MB_COL_V6) *
+ (mbY * S5P_FIMV_NUM_PIXELS_IN_MB_ROW_V6);
+}
+
+void s5p_mfc_dec_calc_dpb_size_v6(struct s5p_mfc_ctx *ctx)
+{
+ ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN_V6);
+ ctx->buf_height = ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN_V6);
+ mfc_debug(2, "SEQ Done: Movie dimensions %dx%d,\n"
+ "buffer dimensions: %dx%d\n", ctx->img_width,
+ ctx->img_height, ctx->buf_width, ctx->buf_height);
+
+ ctx->luma_size = calc_plane(ctx->img_width, ctx->img_height);
+ ctx->chroma_size = calc_plane(ctx->img_width, (ctx->img_height >> 1));
+ if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC ||
+ ctx->codec_mode == S5P_MFC_CODEC_H264_MVC_DEC) {
+ ctx->mv_size = S5P_MFC_DEC_MV_SIZE_V6(ctx->img_width,
+ ctx->img_height);
+ ctx->mv_size = ALIGN(ctx->mv_size, 16);
+ } else {
+ ctx->mv_size = 0;
+ }
+}
+
+void s5p_mfc_enc_calc_src_size_v6(struct s5p_mfc_ctx *ctx)
+{
+ unsigned int mb_width, mb_height;
+
+ mb_width = MB_WIDTH(ctx->img_width);
+ mb_height = MB_HEIGHT(ctx->img_height);
+
+ ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN_V6);
+ ctx->luma_size = ALIGN((mb_width * mb_height) * 256, 256);
+ ctx->chroma_size = ALIGN((mb_width * mb_height) * 128, 256);
+}
+
+/* Set registers for decoding stream buffer */
+int s5p_mfc_set_dec_stream_buffer_v6(struct s5p_mfc_ctx *ctx, int buf_addr,
+ unsigned int start_num_byte, unsigned int strm_size)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ struct s5p_mfc_buf_size *buf_size = dev->variant->buf_size;
+
+ mfc_debug_enter();
+ mfc_debug(2, "inst_no: %d, buf_addr: 0x%08x,\n"
+ "buf_size: 0x%08x (%d)\n",
+ ctx->inst_no, buf_addr, strm_size, strm_size);
+ WRITEL(strm_size, S5P_FIMV_D_STREAM_DATA_SIZE_V6);
+ WRITEL(buf_addr, S5P_FIMV_D_CPB_BUFFER_ADDR_V6);
+ WRITEL(buf_size->cpb, S5P_FIMV_D_CPB_BUFFER_SIZE_V6);
+ WRITEL(start_num_byte, S5P_FIMV_D_CPB_BUFFER_OFFSET_V6);
+
+ mfc_debug_leave();
+ return 0;
+}
+
+/* Set decoding frame buffer */
+int s5p_mfc_set_dec_frame_buffer_v6(struct s5p_mfc_ctx *ctx)
+{
+ unsigned int frame_size, i;
+ unsigned int frame_size_ch, frame_size_mv;
+ struct s5p_mfc_dev *dev = ctx->dev;
+ size_t buf_addr1;
+ int buf_size1;
+ int align_gap;
+
+ buf_addr1 = ctx->bank1_phys;
+ buf_size1 = ctx->bank1_size;
+
+ mfc_debug(2, "Buf1: %p (%d)\n", (void *)buf_addr1, buf_size1);
+ mfc_debug(2, "Total DPB COUNT: %d\n", ctx->total_dpb_count);
+ mfc_debug(2, "Setting display delay to %d\n", ctx->display_delay);
+
+ WRITEL(ctx->total_dpb_count, S5P_FIMV_D_NUM_DPB_V6);
+ WRITEL(ctx->luma_size, S5P_FIMV_D_LUMA_DPB_SIZE_V6);
+ WRITEL(ctx->chroma_size, S5P_FIMV_D_CHROMA_DPB_SIZE_V6);
+
+ WRITEL(buf_addr1, S5P_FIMV_D_SCRATCH_BUFFER_ADDR_V6);
+ WRITEL(ctx->scratch_buf_size, S5P_FIMV_D_SCRATCH_BUFFER_SIZE_V6);
+ buf_addr1 += ctx->scratch_buf_size;
+ buf_size1 -= ctx->scratch_buf_size;
+
+ if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC ||
+ ctx->codec_mode == S5P_FIMV_CODEC_H264_MVC_DEC){
+ WRITEL(ctx->mv_size, S5P_FIMV_D_MV_BUFFER_SIZE_V6);
+ WRITEL(ctx->mv_count, S5P_FIMV_D_NUM_MV_V6);
+ }
+
+ frame_size = ctx->luma_size;
+ frame_size_ch = ctx->chroma_size;
+ frame_size_mv = ctx->mv_size;
+ mfc_debug(2, "Frame size: %d ch: %d mv: %d\n",
+ frame_size, frame_size_ch, frame_size_mv);
+
+ for (i = 0; i < ctx->total_dpb_count; i++) {
+ /* Bank2 */
+ mfc_debug(2, "Luma %d: %x\n", i,
+ ctx->dst_bufs[i].cookie.raw.luma);
+ WRITEL(ctx->dst_bufs[i].cookie.raw.luma,
+ S5P_FIMV_D_LUMA_DPB_V6 + i * 4);
+ mfc_debug(2, "\tChroma %d: %x\n", i,
+ ctx->dst_bufs[i].cookie.raw.chroma);
+ WRITEL(ctx->dst_bufs[i].cookie.raw.chroma,
+ S5P_FIMV_D_CHROMA_DPB_V6 + i * 4);
+ }
+ if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC ||
+ ctx->codec_mode == S5P_MFC_CODEC_H264_MVC_DEC) {
+ for (i = 0; i < ctx->mv_count; i++) {
+ /* To test alignment */
+ align_gap = buf_addr1;
+ buf_addr1 = ALIGN(buf_addr1, 16);
+ align_gap = buf_addr1 - align_gap;
+ buf_size1 -= align_gap;
+
+ mfc_debug(2, "\tBuf1: %x, size: %d\n",
+ buf_addr1, buf_size1);
+ WRITEL(buf_addr1, S5P_FIMV_D_MV_BUFFER_V6 + i * 4);
+ buf_addr1 += frame_size_mv;
+ buf_size1 -= frame_size_mv;
+ }
+ }
+
+ mfc_debug(2, "Buf1: %u, buf_size1: %d (frames %d)\n",
+ buf_addr1, buf_size1, ctx->total_dpb_count);
+ if (buf_size1 < 0) {
+ mfc_debug(2, "Not enough memory has been allocated.\n");
+ return -ENOMEM;
+ }
+
+ WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
+ s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
+ S5P_FIMV_CH_INIT_BUFS_V6, NULL);
+
+ mfc_debug(2, "After setting buffers.\n");
+ return 0;
+}
+
+/* Set registers for encoding stream buffer */
+int s5p_mfc_set_enc_stream_buffer_v6(struct s5p_mfc_ctx *ctx,
+ unsigned long addr, unsigned int size)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+
+ WRITEL(addr, S5P_FIMV_E_STREAM_BUFFER_ADDR_V6); /* 16B align */
+ WRITEL(size, S5P_FIMV_E_STREAM_BUFFER_SIZE_V6);
+
+ mfc_debug(2, "stream buf addr: 0x%08lx, size: 0x%d",
+ addr, size);
+
+ return 0;
+}
+
+void s5p_mfc_set_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx,
+ unsigned long y_addr, unsigned long c_addr)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+
+ WRITEL(y_addr, S5P_FIMV_E_SOURCE_LUMA_ADDR_V6); /* 256B align */
+ WRITEL(c_addr, S5P_FIMV_E_SOURCE_CHROMA_ADDR_V6);
+
+ mfc_debug(2, "enc src y buf addr: 0x%08lx", y_addr);
+ mfc_debug(2, "enc src c buf addr: 0x%08lx", c_addr);
+}
+
+void s5p_mfc_get_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx,
+ unsigned long *y_addr, unsigned long *c_addr)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ unsigned long enc_recon_y_addr, enc_recon_c_addr;
+
+ *y_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_LUMA_ADDR_V6);
+ *c_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_CHROMA_ADDR_V6);
+
+ enc_recon_y_addr = READL(S5P_FIMV_E_RECON_LUMA_DPB_ADDR_V6);
+ enc_recon_c_addr = READL(S5P_FIMV_E_RECON_CHROMA_DPB_ADDR_V6);
+
+ mfc_debug(2, "recon y addr: 0x%08lx", enc_recon_y_addr);
+ mfc_debug(2, "recon c addr: 0x%08lx", enc_recon_c_addr);
+}
+
+/* Set encoding ref & codec buffer */
+int s5p_mfc_set_enc_ref_buffer_v6(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ size_t buf_addr1, buf_size1;
+ int i;
+
+ mfc_debug_enter();
+
+ buf_addr1 = ctx->bank1_phys;
+ buf_size1 = ctx->bank1_size;
+
+ mfc_debug(2, "Buf1: %p (%d)\n", (void *)buf_addr1, buf_size1);
+
+ for (i = 0; i < ctx->dpb_count; i++) {
+ WRITEL(buf_addr1, S5P_FIMV_E_LUMA_DPB_V6 + (4 * i));
+ buf_addr1 += ctx->luma_dpb_size;
+ WRITEL(buf_addr1, S5P_FIMV_E_CHROMA_DPB_V6 + (4 * i));
+ buf_addr1 += ctx->chroma_dpb_size;
+ WRITEL(buf_addr1, S5P_FIMV_E_ME_BUFFER_V6 + (4 * i));
+ buf_addr1 += ctx->me_buffer_size;
+ buf_size1 -= (ctx->luma_dpb_size + ctx->chroma_dpb_size +
+ ctx->me_buffer_size);
+ }
+
+ WRITEL(buf_addr1, S5P_FIMV_E_SCRATCH_BUFFER_ADDR_V6);
+ WRITEL(ctx->scratch_buf_size, S5P_FIMV_E_SCRATCH_BUFFER_SIZE_V6);
+ buf_addr1 += ctx->scratch_buf_size;
+ buf_size1 -= ctx->scratch_buf_size;
+
+ WRITEL(buf_addr1, S5P_FIMV_E_TMV_BUFFER0_V6);
+ buf_addr1 += ctx->tmv_buffer_size >> 1;
+ WRITEL(buf_addr1, S5P_FIMV_E_TMV_BUFFER1_V6);
+ buf_addr1 += ctx->tmv_buffer_size >> 1;
+ buf_size1 -= ctx->tmv_buffer_size;
+
+ mfc_debug(2, "Buf1: %u, buf_size1: %d (ref frames %d)\n",
+ buf_addr1, buf_size1, ctx->dpb_count);
+ if (buf_size1 < 0) {
+ mfc_debug(2, "Not enough memory has been allocated.\n");
+ return -ENOMEM;
+ }
+
+ WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
+ s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
+ S5P_FIMV_CH_INIT_BUFS_V6, NULL);
+
+ mfc_debug_leave();
+
+ return 0;
+}
+
+static int s5p_mfc_set_slice_mode(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+
+ /* multi-slice control */
+ /* multi-slice MB number or bit size */
+ WRITEL(ctx->slice_mode, S5P_FIMV_E_MSLICE_MODE_V6);
+ if (ctx->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) {
+ WRITEL(ctx->slice_size.mb, S5P_FIMV_E_MSLICE_SIZE_MB_V6);
+ } else if (ctx->slice_mode ==
+ V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) {
+ WRITEL(ctx->slice_size.bits, S5P_FIMV_E_MSLICE_SIZE_BITS_V6);
+ } else {
+ WRITEL(0x0, S5P_FIMV_E_MSLICE_SIZE_MB_V6);
+ WRITEL(0x0, S5P_FIMV_E_MSLICE_SIZE_BITS_V6);
+ }
+
+ return 0;
+}
+
+static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ struct s5p_mfc_enc_params *p = &ctx->enc_params;
+ unsigned int reg = 0;
+
+ mfc_debug_enter();
+
+ /* width */
+ WRITEL(ctx->img_width, S5P_FIMV_E_FRAME_WIDTH_V6); /* 16 align */
+ /* height */
+ WRITEL(ctx->img_height, S5P_FIMV_E_FRAME_HEIGHT_V6); /* 16 align */
+
+ /* cropped width */
+ WRITEL(ctx->img_width, S5P_FIMV_E_CROPPED_FRAME_WIDTH_V6);
+ /* cropped height */
+ WRITEL(ctx->img_height, S5P_FIMV_E_CROPPED_FRAME_HEIGHT_V6);
+ /* cropped offset */
+ WRITEL(0x0, S5P_FIMV_E_FRAME_CROP_OFFSET_V6);
+
+ /* pictype : IDR period */
+ reg = 0;
+ reg |= p->gop_size & 0xFFFF;
+ WRITEL(reg, S5P_FIMV_E_GOP_CONFIG_V6);
+
+ /* multi-slice control */
+ /* multi-slice MB number or bit size */
+ ctx->slice_mode = p->slice_mode;
+ reg = 0;
+ if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) {
+ reg |= (0x1 << 3);
+ WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
+ ctx->slice_size.mb = p->slice_mb;
+ } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) {
+ reg |= (0x1 << 3);
+ WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
+ ctx->slice_size.bits = p->slice_bit;
+ } else {
+ reg &= ~(0x1 << 3);
+ WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
+ }
+
+ s5p_mfc_set_slice_mode(ctx);
+
+ /* cyclic intra refresh */
+ WRITEL(p->intra_refresh_mb, S5P_FIMV_E_IR_SIZE_V6);
+ reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6);
+ if (p->intra_refresh_mb == 0)
+ reg &= ~(0x1 << 4);
+ else
+ reg |= (0x1 << 4);
+ WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
+
+ /* 'NON_REFERENCE_STORE_ENABLE' for debugging */
+ reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6);
+ reg &= ~(0x1 << 9);
+ WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
+
+ /* memory structure cur. frame */
+ if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) {
+ /* 0: Linear, 1: 2D tiled*/
+ reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6);
+ reg &= ~(0x1 << 7);
+ WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
+ /* 0: NV12(CbCr), 1: NV21(CrCb) */
+ WRITEL(0x0, S5P_FIMV_PIXEL_FORMAT_V6);
+ } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV21M) {
+ /* 0: Linear, 1: 2D tiled*/
+ reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6);
+ reg &= ~(0x1 << 7);
+ WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
+ /* 0: NV12(CbCr), 1: NV21(CrCb) */
+ WRITEL(0x1, S5P_FIMV_PIXEL_FORMAT_V6);
+ } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16) {
+ /* 0: Linear, 1: 2D tiled*/
+ reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6);
+ reg |= (0x1 << 7);
+ WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
+ /* 0: NV12(CbCr), 1: NV21(CrCb) */
+ WRITEL(0x0, S5P_FIMV_PIXEL_FORMAT_V6);
+ }
+
+ /* memory structure recon. frame */
+ /* 0: Linear, 1: 2D tiled */
+ reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6);
+ reg |= (0x1 << 8);
+ WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
+
+ /* padding control & value */
+ WRITEL(0x0, S5P_FIMV_E_PADDING_CTRL_V6);
+ if (p->pad) {
+ reg = 0;
+ /** enable */
+ reg |= (1 << 31);
+ /** cr value */
+ reg |= ((p->pad_cr & 0xFF) << 16);
+ /** cb value */
+ reg |= ((p->pad_cb & 0xFF) << 8);
+ /** y value */
+ reg |= p->pad_luma & 0xFF;
+ WRITEL(reg, S5P_FIMV_E_PADDING_CTRL_V6);
+ }
+
+ /* rate control config. */
+ reg = 0;
+ /* frame-level rate control */
+ reg |= ((p->rc_frame & 0x1) << 9);
+ WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6);
+
+ /* bit rate */
+ if (p->rc_frame)
+ WRITEL(p->rc_bitrate,
+ S5P_FIMV_E_RC_BIT_RATE_V6);
+ else
+ WRITEL(1, S5P_FIMV_E_RC_BIT_RATE_V6);
+
+ /* reaction coefficient */
+ if (p->rc_frame) {
+ if (p->rc_reaction_coeff < TIGHT_CBR_MAX) /* tight CBR */
+ WRITEL(1, S5P_FIMV_E_RC_RPARAM_V6);
+ else /* loose CBR */
+ WRITEL(2, S5P_FIMV_E_RC_RPARAM_V6);
+ }
+
+ /* seq header ctrl */
+ reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6);
+ reg &= ~(0x1 << 2);
+ reg |= ((p->seq_hdr_mode & 0x1) << 2);
+
+ /* frame skip mode */
+ reg &= ~(0x3);
+ reg |= (p->frame_skip_mode & 0x3);
+ WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
+
+ /* 'DROP_CONTROL_ENABLE', disable */
+ reg = READL(S5P_FIMV_E_RC_CONFIG_V6);
+ reg &= ~(0x1 << 10);
+ WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6);
+
+ /* setting for MV range [16, 256] */
+ reg = 0;
+ reg &= ~(0x3FFF);
+ reg = 256;
+ WRITEL(reg, S5P_FIMV_E_MV_HOR_RANGE_V6);
+
+ reg = 0;
+ reg &= ~(0x3FFF);
+ reg = 256;
+ WRITEL(reg, S5P_FIMV_E_MV_VER_RANGE_V6);
+
+ WRITEL(0x0, S5P_FIMV_E_FRAME_INSERTION_V6);
+ WRITEL(0x0, S5P_FIMV_E_ROI_BUFFER_ADDR_V6);
+ WRITEL(0x0, S5P_FIMV_E_PARAM_CHANGE_V6);
+ WRITEL(0x0, S5P_FIMV_E_RC_ROI_CTRL_V6);
+ WRITEL(0x0, S5P_FIMV_E_PICTURE_TAG_V6);
+
+ WRITEL(0x0, S5P_FIMV_E_BIT_COUNT_ENABLE_V6);
+ WRITEL(0x0, S5P_FIMV_E_MAX_BIT_COUNT_V6);
+ WRITEL(0x0, S5P_FIMV_E_MIN_BIT_COUNT_V6);
+
+ WRITEL(0x0, S5P_FIMV_E_METADATA_BUFFER_ADDR_V6);
+ WRITEL(0x0, S5P_FIMV_E_METADATA_BUFFER_SIZE_V6);
+
+ mfc_debug_leave();
+
+ return 0;
+}
+
+static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ struct s5p_mfc_enc_params *p = &ctx->enc_params;
+ struct s5p_mfc_h264_enc_params *p_h264 = &p->codec.h264;
+ unsigned int reg = 0;
+ int i;
+
+ mfc_debug_enter();
+
+ s5p_mfc_set_enc_params(ctx);
+
+ /* pictype : number of B */
+ reg = READL(S5P_FIMV_E_GOP_CONFIG_V6);
+ reg &= ~(0x3 << 16);
+ reg |= ((p->num_b_frame & 0x3) << 16);
+ WRITEL(reg, S5P_FIMV_E_GOP_CONFIG_V6);
+
+ /* profile & level */
+ reg = 0;
+ /** level */
+ reg |= ((p_h264->level & 0xFF) << 8);
+ /** profile - 0 ~ 3 */
+ reg |= p_h264->profile & 0x3F;
+ WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE_V6);
+
+ /* rate control config. */
+ reg = READL(S5P_FIMV_E_RC_CONFIG_V6);
+ /** macroblock level rate control */
+ reg &= ~(0x1 << 8);
+ reg |= ((p->rc_mb & 0x1) << 8);
+ WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6);
+ /** frame QP */
+ reg &= ~(0x3F);
+ reg |= p_h264->rc_frame_qp & 0x3F;
+ WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6);
+
+ /* max & min value of QP */
+ reg = 0;
+ /** max QP */
+ reg |= ((p_h264->rc_max_qp & 0x3F) << 8);
+ /** min QP */
+ reg |= p_h264->rc_min_qp & 0x3F;
+ WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_V6);
+
+ /* other QPs */
+ WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP_V6);
+ if (!p->rc_frame && !p->rc_mb) {
+ reg = 0;
+ reg |= ((p_h264->rc_b_frame_qp & 0x3F) << 16);
+ reg |= ((p_h264->rc_p_frame_qp & 0x3F) << 8);
+ reg |= p_h264->rc_frame_qp & 0x3F;
+ WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP_V6);
+ }
+
+ /* frame rate */
+ if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) {
+ reg = 0;
+ reg |= ((p->rc_framerate_num & 0xFFFF) << 16);
+ reg |= p->rc_framerate_denom & 0xFFFF;
+ WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE_V6);
+ }
+
+ /* vbv buffer size */
+ if (p->frame_skip_mode ==
+ V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
+ WRITEL(p_h264->cpb_size & 0xFFFF,
+ S5P_FIMV_E_VBV_BUFFER_SIZE_V6);
+
+ if (p->rc_frame)
+ WRITEL(p->vbv_delay, S5P_FIMV_E_VBV_INIT_DELAY_V6);
+ }
+
+ /* interlace */
+ reg = 0;
+ reg |= ((p_h264->interlace & 0x1) << 3);
+ WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+
+ /* height */
+ if (p_h264->interlace) {
+ WRITEL(ctx->img_height >> 1,
+ S5P_FIMV_E_FRAME_HEIGHT_V6); /* 32 align */
+ /* cropped height */
+ WRITEL(ctx->img_height >> 1,
+ S5P_FIMV_E_CROPPED_FRAME_HEIGHT_V6);
+ }
+
+ /* loop filter ctrl */
+ reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
+ reg &= ~(0x3 << 1);
+ reg |= ((p_h264->loop_filter_mode & 0x3) << 1);
+ WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+
+ /* loopfilter alpha offset */
+ if (p_h264->loop_filter_alpha < 0) {
+ reg = 0x10;
+ reg |= (0xFF - p_h264->loop_filter_alpha) + 1;
+ } else {
+ reg = 0x00;
+ reg |= (p_h264->loop_filter_alpha & 0xF);
+ }
+ WRITEL(reg, S5P_FIMV_E_H264_LF_ALPHA_OFFSET_V6);
+
+ /* loopfilter beta offset */
+ if (p_h264->loop_filter_beta < 0) {
+ reg = 0x10;
+ reg |= (0xFF - p_h264->loop_filter_beta) + 1;
+ } else {
+ reg = 0x00;
+ reg |= (p_h264->loop_filter_beta & 0xF);
+ }
+ WRITEL(reg, S5P_FIMV_E_H264_LF_BETA_OFFSET_V6);
+
+ /* entropy coding mode */
+ reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
+ reg &= ~(0x1);
+ reg |= p_h264->entropy_mode & 0x1;
+ WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+
+ /* number of ref. picture */
+ reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
+ reg &= ~(0x1 << 7);
+ reg |= (((p_h264->num_ref_pic_4p - 1) & 0x1) << 7);
+ WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+
+ /* 8x8 transform enable */
+ reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
+ reg &= ~(0x3 << 12);
+ reg |= ((p_h264->_8x8_transform & 0x3) << 12);
+ WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+
+ /* macroblock adaptive scaling features */
+ WRITEL(0x0, S5P_FIMV_E_MB_RC_CONFIG_V6);
+ if (p->rc_mb) {
+ reg = 0;
+ /** dark region */
+ reg |= ((p_h264->rc_mb_dark & 0x1) << 3);
+ /** smooth region */
+ reg |= ((p_h264->rc_mb_smooth & 0x1) << 2);
+ /** static region */
+ reg |= ((p_h264->rc_mb_static & 0x1) << 1);
+ /** high activity region */
+ reg |= p_h264->rc_mb_activity & 0x1;
+ WRITEL(reg, S5P_FIMV_E_MB_RC_CONFIG_V6);
+ }
+
+ /* aspect ratio VUI */
+ reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
+ reg &= ~(0x1 << 5);
+ reg |= ((p_h264->vui_sar & 0x1) << 5);
+ WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+
+ WRITEL(0x0, S5P_FIMV_E_ASPECT_RATIO_V6);
+ WRITEL(0x0, S5P_FIMV_E_EXTENDED_SAR_V6);
+ if (p_h264->vui_sar) {
+ /* aspect ration IDC */
+ reg = 0;
+ reg |= p_h264->vui_sar_idc & 0xFF;
+ WRITEL(reg, S5P_FIMV_E_ASPECT_RATIO_V6);
+ if (p_h264->vui_sar_idc == 0xFF) {
+ /* extended SAR */
+ reg = 0;
+ reg |= (p_h264->vui_ext_sar_width & 0xFFFF) << 16;
+ reg |= p_h264->vui_ext_sar_height & 0xFFFF;
+ WRITEL(reg, S5P_FIMV_E_EXTENDED_SAR_V6);
+ }
+ }
+
+ /* intra picture period for H.264 open GOP */
+ /* control */
+ reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
+ reg &= ~(0x1 << 4);
+ reg |= ((p_h264->open_gop & 0x1) << 4);
+ WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+ /* value */
+ WRITEL(0x0, S5P_FIMV_E_H264_I_PERIOD_V6);
+ if (p_h264->open_gop) {
+ reg = 0;
+ reg |= p_h264->open_gop_size & 0xFFFF;
+ WRITEL(reg, S5P_FIMV_E_H264_I_PERIOD_V6);
+ }
+
+ /* 'WEIGHTED_BI_PREDICTION' for B is disable */
+ reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
+ reg &= ~(0x3 << 9);
+ WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+
+ /* 'CONSTRAINED_INTRA_PRED_ENABLE' is disable */
+ reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
+ reg &= ~(0x1 << 14);
+ WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+
+ /* ASO */
+ reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
+ reg &= ~(0x1 << 6);
+ reg |= ((p_h264->aso & 0x1) << 6);
+ WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+
+ /* hier qp enable */
+ reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
+ reg &= ~(0x1 << 8);
+ reg |= ((p_h264->open_gop & 0x1) << 8);
+ WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+ reg = 0;
+ if (p_h264->hier_qp && p_h264->hier_qp_layer) {
+ reg |= (p_h264->hier_qp_type & 0x1) << 0x3;
+ reg |= p_h264->hier_qp_layer & 0x7;
+ WRITEL(reg, S5P_FIMV_E_H264_NUM_T_LAYER_V6);
+ /* QP value for each layer */
+ for (i = 0; i < (p_h264->hier_qp_layer & 0x7); i++)
+ WRITEL(p_h264->hier_qp_layer_qp[i],
+ S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER0_V6 +
+ i * 4);
+ }
+ /* number of coding layer should be zero when hierarchical is disable */
+ WRITEL(reg, S5P_FIMV_E_H264_NUM_T_LAYER_V6);
+
+ /* frame packing SEI generation */
+ reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
+ reg &= ~(0x1 << 25);
+ reg |= ((p_h264->sei_frame_packing & 0x1) << 25);
+ WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+ if (p_h264->sei_frame_packing) {
+ reg = 0;
+ /** current frame0 flag */
+ reg |= ((p_h264->sei_fp_curr_frame_0 & 0x1) << 2);
+ /** arrangement type */
+ reg |= p_h264->sei_fp_arrangement_type & 0x3;
+ WRITEL(reg, S5P_FIMV_E_H264_FRAME_PACKING_SEI_INFO_V6);
+ }
+
+ if (p_h264->fmo) {
+ switch (p_h264->fmo_map_type) {
+ case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES:
+ if (p_h264->fmo_slice_grp > 4)
+ p_h264->fmo_slice_grp = 4;
+ for (i = 0; i < (p_h264->fmo_slice_grp & 0xF); i++)
+ WRITEL(p_h264->fmo_run_len[i] - 1,
+ S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_0_V6 +
+ i * 4);
+ break;
+ case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_SCATTERED_SLICES:
+ if (p_h264->fmo_slice_grp > 4)
+ p_h264->fmo_slice_grp = 4;
+ break;
+ case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_RASTER_SCAN:
+ case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_WIPE_SCAN:
+ if (p_h264->fmo_slice_grp > 2)
+ p_h264->fmo_slice_grp = 2;
+ WRITEL(p_h264->fmo_chg_dir & 0x1,
+ S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_DIR_V6);
+ /* the valid range is 0 ~ number of macroblocks -1 */
+ WRITEL(p_h264->fmo_chg_rate,
+ S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_RATE_MINUS1_V6);
+ break;
+ default:
+ mfc_err("Unsupported map type for FMO: %d\n",
+ p_h264->fmo_map_type);
+ p_h264->fmo_map_type = 0;
+ p_h264->fmo_slice_grp = 1;
+ break;
+ }
+
+ WRITEL(p_h264->fmo_map_type,
+ S5P_FIMV_E_H264_FMO_SLICE_GRP_MAP_TYPE_V6);
+ WRITEL(p_h264->fmo_slice_grp - 1,
+ S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1_V6);
+ } else {
+ WRITEL(0, S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1_V6);
+ }
+
+ mfc_debug_leave();
+
+ return 0;
+}
+
+static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ struct s5p_mfc_enc_params *p = &ctx->enc_params;
+ struct s5p_mfc_mpeg4_enc_params *p_mpeg4 = &p->codec.mpeg4;
+ unsigned int reg = 0;
+
+ mfc_debug_enter();
+
+ s5p_mfc_set_enc_params(ctx);
+
+ /* pictype : number of B */
+ reg = READL(S5P_FIMV_E_GOP_CONFIG_V6);
+ reg &= ~(0x3 << 16);
+ reg |= ((p->num_b_frame & 0x3) << 16);
+ WRITEL(reg, S5P_FIMV_E_GOP_CONFIG_V6);
+
+ /* profile & level */
+ reg = 0;
+ /** level */
+ reg |= ((p_mpeg4->level & 0xFF) << 8);
+ /** profile - 0 ~ 1 */
+ reg |= p_mpeg4->profile & 0x3F;
+ WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE_V6);
+
+ /* rate control config. */
+ reg = READL(S5P_FIMV_E_RC_CONFIG_V6);
+ /** macroblock level rate control */
+ reg &= ~(0x1 << 8);
+ reg |= ((p->rc_mb & 0x1) << 8);
+ WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6);
+ /** frame QP */
+ reg &= ~(0x3F);
+ reg |= p_mpeg4->rc_frame_qp & 0x3F;
+ WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6);
+
+ /* max & min value of QP */
+ reg = 0;
+ /** max QP */
+ reg |= ((p_mpeg4->rc_max_qp & 0x3F) << 8);
+ /** min QP */
+ reg |= p_mpeg4->rc_min_qp & 0x3F;
+ WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_V6);
+
+ /* other QPs */
+ WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP_V6);
+ if (!p->rc_frame && !p->rc_mb) {
+ reg = 0;
+ reg |= ((p_mpeg4->rc_b_frame_qp & 0x3F) << 16);
+ reg |= ((p_mpeg4->rc_p_frame_qp & 0x3F) << 8);
+ reg |= p_mpeg4->rc_frame_qp & 0x3F;
+ WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP_V6);
+ }
+
+ /* frame rate */
+ if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) {
+ reg = 0;
+ reg |= ((p->rc_framerate_num & 0xFFFF) << 16);
+ reg |= p->rc_framerate_denom & 0xFFFF;
+ WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE_V6);
+ }
+
+ /* vbv buffer size */
+ if (p->frame_skip_mode ==
+ V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
+ WRITEL(p->vbv_size & 0xFFFF, S5P_FIMV_E_VBV_BUFFER_SIZE_V6);
+
+ if (p->rc_frame)
+ WRITEL(p->vbv_delay, S5P_FIMV_E_VBV_INIT_DELAY_V6);
+ }
+
+ /* Disable HEC */
+ WRITEL(0x0, S5P_FIMV_E_MPEG4_OPTIONS_V6);
+ WRITEL(0x0, S5P_FIMV_E_MPEG4_HEC_PERIOD_V6);
+
+ mfc_debug_leave();
+
+ return 0;
+}
+
+static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ struct s5p_mfc_enc_params *p = &ctx->enc_params;
+ struct s5p_mfc_mpeg4_enc_params *p_h263 = &p->codec.mpeg4;
+ unsigned int reg = 0;
+
+ mfc_debug_enter();
+
+ s5p_mfc_set_enc_params(ctx);
+
+ /* profile & level */
+ reg = 0;
+ /** profile */
+ reg |= (0x1 << 4);
+ WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE_V6);
+
+ /* rate control config. */
+ reg = READL(S5P_FIMV_E_RC_CONFIG_V6);
+ /** macroblock level rate control */
+ reg &= ~(0x1 << 8);
+ reg |= ((p->rc_mb & 0x1) << 8);
+ WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6);
+ /** frame QP */
+ reg &= ~(0x3F);
+ reg |= p_h263->rc_frame_qp & 0x3F;
+ WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6);
+
+ /* max & min value of QP */
+ reg = 0;
+ /** max QP */
+ reg |= ((p_h263->rc_max_qp & 0x3F) << 8);
+ /** min QP */
+ reg |= p_h263->rc_min_qp & 0x3F;
+ WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_V6);
+
+ /* other QPs */
+ WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP_V6);
+ if (!p->rc_frame && !p->rc_mb) {
+ reg = 0;
+ reg |= ((p_h263->rc_b_frame_qp & 0x3F) << 16);
+ reg |= ((p_h263->rc_p_frame_qp & 0x3F) << 8);
+ reg |= p_h263->rc_frame_qp & 0x3F;
+ WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP_V6);
+ }
+
+ /* frame rate */
+ if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) {
+ reg = 0;
+ reg |= ((p->rc_framerate_num & 0xFFFF) << 16);
+ reg |= p->rc_framerate_denom & 0xFFFF;
+ WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE_V6);
+ }
+
+ /* vbv buffer size */
+ if (p->frame_skip_mode ==
+ V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
+ WRITEL(p->vbv_size & 0xFFFF, S5P_FIMV_E_VBV_BUFFER_SIZE_V6);
+
+ if (p->rc_frame)
+ WRITEL(p->vbv_delay, S5P_FIMV_E_VBV_INIT_DELAY_V6);
+ }
+
+ mfc_debug_leave();
+
+ return 0;
+}
+
+/* Initialize decoding */
+int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ unsigned int reg = 0;
+ int fmo_aso_ctrl = 0;
+
+ mfc_debug_enter();
+ mfc_debug(2, "InstNo: %d/%d\n", ctx->inst_no,
+ S5P_FIMV_CH_SEQ_HEADER_V6);
+ mfc_debug(2, "BUFs: %08x %08x %08x\n",
+ READL(S5P_FIMV_D_CPB_BUFFER_ADDR_V6),
+ READL(S5P_FIMV_D_CPB_BUFFER_ADDR_V6),
+ READL(S5P_FIMV_D_CPB_BUFFER_ADDR_V6));
+
+ /* FMO_ASO_CTRL - 0: Enable, 1: Disable */
+ reg |= (fmo_aso_ctrl << S5P_FIMV_D_OPT_FMO_ASO_CTRL_MASK_V6);
+
+ /* When user sets desplay_delay to 0,
+ * It works as "display_delay enable" and delay set to 0.
+ * If user wants display_delay disable, It should be
+ * set to negative value. */
+ if (ctx->display_delay >= 0) {
+ reg |= (0x1 << S5P_FIMV_D_OPT_DDELAY_EN_SHIFT_V6);
+ WRITEL(ctx->display_delay, S5P_FIMV_D_DISPLAY_DELAY_V6);
+ }
+ /* Setup loop filter, for decoding this is only valid for MPEG4 */
+ if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_DEC) {
+ mfc_debug(2, "Set loop filter to: %d\n",
+ ctx->loop_filter_mpeg4);
+ reg |= (ctx->loop_filter_mpeg4 <<
+ S5P_FIMV_D_OPT_LF_CTRL_SHIFT_V6);
+ }
+ if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16)
+ reg |= (0x1 << S5P_FIMV_D_OPT_TILE_MODE_SHIFT_V6);
+
+ WRITEL(reg, S5P_FIMV_D_DEC_OPTIONS_V6);
+
+ /* 0: NV12(CbCr), 1: NV21(CrCb) */
+ if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV21M)
+ WRITEL(0x1, S5P_FIMV_PIXEL_FORMAT_V6);
+ else
+ WRITEL(0x0, S5P_FIMV_PIXEL_FORMAT_V6);
+
+ /* sei parse */
+ WRITEL(ctx->sei_fp_parse & 0x1, S5P_FIMV_D_SEI_ENABLE_V6);
+
+ WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
+ s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
+ S5P_FIMV_CH_SEQ_HEADER_V6, NULL);
+
+ mfc_debug_leave();
+ return 0;
+}
+
+static inline void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ unsigned int dpb;
+ if (flush)
+ dpb = READL(S5P_FIMV_SI_CH0_DPB_CONF_CTRL) | (1 << 14);
+ else
+ dpb = READL(S5P_FIMV_SI_CH0_DPB_CONF_CTRL) & ~(1 << 14);
+ WRITEL(dpb, S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
+}
+
+/* Decode a single frame */
+int s5p_mfc_decode_one_frame_v6(struct s5p_mfc_ctx *ctx,
+ enum s5p_mfc_decode_arg last_frame)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+
+ WRITEL(ctx->dec_dst_flag, S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER_V6);
+ WRITEL(ctx->slice_interface & 0x1, S5P_FIMV_D_SLICE_IF_ENABLE_V6);
+
+ WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
+ /* Issue different commands to instance basing on whether it
+ * is the last frame or not. */
+ switch (last_frame) {
+ case 0:
+ s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
+ S5P_FIMV_CH_FRAME_START_V6, NULL);
+ break;
+ case 1:
+ s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
+ S5P_FIMV_CH_LAST_FRAME_V6, NULL);
+ break;
+ default:
+ mfc_err("Unsupported last frame arg.\n");
+ return -EINVAL;
+ }
+
+ mfc_debug(2, "Decoding a usual frame.\n");
+ return 0;
+}
+
+int s5p_mfc_init_encode_v6(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+
+ if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC)
+ s5p_mfc_set_enc_params_h264(ctx);
+ else if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_ENC)
+ s5p_mfc_set_enc_params_mpeg4(ctx);
+ else if (ctx->codec_mode == S5P_MFC_CODEC_H263_ENC)
+ s5p_mfc_set_enc_params_h263(ctx);
+ else {
+ mfc_err("Unknown codec for encoding (%x).\n",
+ ctx->codec_mode);
+ return -EINVAL;
+ }
+
+ WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
+ s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
+ S5P_FIMV_CH_SEQ_HEADER_V6, NULL);
+
+ return 0;
+}
+
+int s5p_mfc_h264_set_aso_slice_order_v6(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ struct s5p_mfc_enc_params *p = &ctx->enc_params;
+ struct s5p_mfc_h264_enc_params *p_h264 = &p->codec.h264;
+ int i;
+
+ if (p_h264->aso) {
+ for (i = 0; i < 8; i++)
+ WRITEL(p_h264->aso_slice_order[i],
+ S5P_FIMV_E_H264_ASO_SLICE_ORDER_0_V6 + i * 4);
+ }
+ return 0;
+}
+
+/* Encode a single frame */
+int s5p_mfc_encode_one_frame_v6(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+
+ mfc_debug(2, "++\n");
+
+ /* memory structure cur. frame */
+
+ if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC)
+ s5p_mfc_h264_set_aso_slice_order_v6(ctx);
+
+ s5p_mfc_set_slice_mode(ctx);
+
+ WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
+ s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
+ S5P_FIMV_CH_FRAME_START_V6, NULL);
+
+ mfc_debug(2, "--\n");
+
+ return 0;
+}
+
+static inline int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev)
+{
+ unsigned long flags;
+ int new_ctx;
+ int cnt;
+
+ spin_lock_irqsave(&dev->condlock, flags);
+ mfc_debug(2, "Previos context: %d (bits %08lx)\n", dev->curr_ctx,
+ dev->ctx_work_bits);
+ new_ctx = (dev->curr_ctx + 1) % MFC_NUM_CONTEXTS;
+ cnt = 0;
+ while (!test_bit(new_ctx, &dev->ctx_work_bits)) {
+ new_ctx = (new_ctx + 1) % MFC_NUM_CONTEXTS;
+ cnt++;
+ if (cnt > MFC_NUM_CONTEXTS) {
+ /* No contexts to run */
+ spin_unlock_irqrestore(&dev->condlock, flags);
+ return -EAGAIN;
+ }
+ }
+ spin_unlock_irqrestore(&dev->condlock, flags);
+ return new_ctx;
+}
+
+static inline void s5p_mfc_run_dec_last_frames(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ struct s5p_mfc_buf *temp_vb;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev->irqlock, flags);
+
+ /* Frames are being decoded */
+ if (list_empty(&ctx->src_queue)) {
+ mfc_debug(2, "No src buffers.\n");
+ spin_unlock_irqrestore(&dev->irqlock, flags);
+ return;
+ }
+ /* Get the next source buffer */
+ temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+ temp_vb->used = 1;
+ s5p_mfc_set_dec_stream_buffer_v6(ctx,
+ vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), 0, 0);
+ spin_unlock_irqrestore(&dev->irqlock, flags);
+
+ dev->curr_ctx = ctx->num;
+ s5p_mfc_clean_ctx_int_flags(ctx);
+ s5p_mfc_decode_one_frame_v6(ctx, 1);
+}
+
+static inline int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ struct s5p_mfc_buf *temp_vb;
+ unsigned long flags;
+ int last_frame = 0;
+ unsigned int index;
+
+ spin_lock_irqsave(&dev->irqlock, flags);
+
+ /* Frames are being decoded */
+ if (list_empty(&ctx->src_queue)) {
+ mfc_debug(2, "No src buffers.\n");
+ spin_unlock_irqrestore(&dev->irqlock, flags);
+ return -EAGAIN;
+ }
+ /* Get the next source buffer */
+ temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+ temp_vb->used = 1;
+ s5p_mfc_set_dec_stream_buffer_v6(ctx,
+ vb2_dma_contig_plane_dma_addr(temp_vb->b, 0),
+ ctx->consumed_stream,
+ temp_vb->b->v4l2_planes[0].bytesused);
+ spin_unlock_irqrestore(&dev->irqlock, flags);
+
+ index = temp_vb->b->v4l2_buf.index;
+
+ dev->curr_ctx = ctx->num;
+ s5p_mfc_clean_ctx_int_flags(ctx);
+ if (temp_vb->b->v4l2_planes[0].bytesused == 0) {
+ last_frame = 1;
+ mfc_debug(2, "Setting ctx->state to FINISHING\n");
+ ctx->state = MFCINST_FINISHING;
+ }
+ s5p_mfc_decode_one_frame_v6(ctx, last_frame);
+
+ return 0;
+}
+
+static inline int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ unsigned long flags;
+ struct s5p_mfc_buf *dst_mb;
+ struct s5p_mfc_buf *src_mb;
+ unsigned long src_y_addr, src_c_addr, dst_addr;
+ /*
+ unsigned int src_y_size, src_c_size;
+ */
+ unsigned int dst_size;
+ unsigned int index;
+
+ spin_lock_irqsave(&dev->irqlock, flags);
+
+ if (list_empty(&ctx->src_queue)) {
+ mfc_debug(2, "no src buffers.\n");
+ spin_unlock_irqrestore(&dev->irqlock, flags);
+ return -EAGAIN;
+ }
+
+ if (list_empty(&ctx->dst_queue)) {
+ mfc_debug(2, "no dst buffers.\n");
+ spin_unlock_irqrestore(&dev->irqlock, flags);
+ return -EAGAIN;
+ }
+
+ src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+ src_mb->used = 1;
+ src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 0);
+ src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1);
+
+ mfc_debug(2, "enc src y addr: 0x%08lx", src_y_addr);
+ mfc_debug(2, "enc src c addr: 0x%08lx", src_c_addr);
+
+ s5p_mfc_set_enc_frame_buffer_v6(ctx, src_y_addr, src_c_addr);
+
+ dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
+ dst_mb->used = 1;
+ dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
+ dst_size = vb2_plane_size(dst_mb->b, 0);
+
+ s5p_mfc_set_enc_stream_buffer_v6(ctx, dst_addr, dst_size);
+
+ spin_unlock_irqrestore(&dev->irqlock, flags);
+
+ index = src_mb->b->v4l2_buf.index;
+
+ dev->curr_ctx = ctx->num;
+ s5p_mfc_clean_ctx_int_flags(ctx);
+ s5p_mfc_encode_one_frame_v6(ctx);
+
+ return 0;
+}
+
+static inline void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ unsigned long flags;
+ struct s5p_mfc_buf *temp_vb;
+
+ /* Initializing decoding - parsing header */
+ spin_lock_irqsave(&dev->irqlock, flags);
+ mfc_debug(2, "Preparing to init decoding.\n");
+ temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+ mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused);
+ s5p_mfc_set_dec_stream_buffer_v6(ctx,
+ vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), 0,
+ temp_vb->b->v4l2_planes[0].bytesused);
+ spin_unlock_irqrestore(&dev->irqlock, flags);
+ dev->curr_ctx = ctx->num;
+ s5p_mfc_clean_ctx_int_flags(ctx);
+ s5p_mfc_init_decode_v6(ctx);
+}
+
+static inline void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ unsigned long flags;
+ struct s5p_mfc_buf *dst_mb;
+ unsigned long dst_addr;
+ unsigned int dst_size;
+
+ spin_lock_irqsave(&dev->irqlock, flags);
+
+ dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
+ dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
+ dst_size = vb2_plane_size(dst_mb->b, 0);
+ s5p_mfc_set_enc_stream_buffer_v6(ctx, dst_addr, dst_size);
+ spin_unlock_irqrestore(&dev->irqlock, flags);
+ dev->curr_ctx = ctx->num;
+ s5p_mfc_clean_ctx_int_flags(ctx);
+ s5p_mfc_init_encode_v6(ctx);
+}
+
+static inline int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ int ret;
+ /* Header was parsed now start processing
+ * First set the output frame buffers
+ * s5p_mfc_alloc_dec_buffers(ctx); */
+
+ if (ctx->capture_state != QUEUE_BUFS_MMAPED) {
+ mfc_err("It seems that not all destionation buffers were\n"
+ "mmaped.MFC requires that all destination are mmaped\n"
+ "before starting processing.\n");
+ return -EAGAIN;
+ }
+
+ dev->curr_ctx = ctx->num;
+ s5p_mfc_clean_ctx_int_flags(ctx);
+ ret = s5p_mfc_set_dec_frame_buffer_v6(ctx);
+ if (ret) {
+ mfc_err("Failed to alloc frame mem.\n");
+ ctx->state = MFCINST_ERROR;
+ }
+ return ret;
+}
+
+static inline int s5p_mfc_run_init_enc_buffers(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ int ret;
+
+ ret = s5p_mfc_alloc_codec_buffers_v6(ctx);
+ if (ret) {
+ mfc_err("Failed to allocate encoding buffers.\n");
+ return -ENOMEM;
+ }
+
+ /* Header was generated now starting processing
+ * First set the reference frame buffers
+ */
+ if (ctx->capture_state != QUEUE_BUFS_REQUESTED) {
+ mfc_err("It seems that destionation buffers were not\n"
+ "requested.MFC requires that header should be generated\n"
+ "before allocating codec buffer.\n");
+ return -EAGAIN;
+ }
+
+ dev->curr_ctx = ctx->num;
+ s5p_mfc_clean_ctx_int_flags(ctx);
+ ret = s5p_mfc_set_enc_ref_buffer_v6(ctx);
+ if (ret) {
+ mfc_err("Failed to alloc frame mem.\n");
+ ctx->state = MFCINST_ERROR;
+ }
+ return ret;
+}
+
+/* Try running an operation on hardware */
+void s5p_mfc_try_run_v6(struct s5p_mfc_dev *dev)
+{
+ struct s5p_mfc_ctx *ctx;
+ int new_ctx;
+ unsigned int ret = 0;
+
+ mfc_debug(1, "Try run dev: %p\n", dev);
+
+ /* Check whether hardware is not running */
+ if (test_and_set_bit(0, &dev->hw_lock) != 0) {
+ /* This is perfectly ok, the scheduled ctx should wait */
+ mfc_debug(1, "Couldn't lock HW.\n");
+ return;
+ }
+
+ /* Choose the context to run */
+ new_ctx = s5p_mfc_get_new_ctx(dev);
+ if (new_ctx < 0) {
+ /* No contexts to run */
+ if (test_and_clear_bit(0, &dev->hw_lock) == 0) {
+ mfc_err("Failed to unlock hardware.\n");
+ return;
+ }
+
+ mfc_debug(1, "No ctx is scheduled to be run.\n");
+ return;
+ }
+
+ mfc_debug(1, "New context: %d\n", new_ctx);
+ ctx = dev->ctx[new_ctx];
+ mfc_debug(1, "Seting new context to %p\n", ctx);
+ /* Got context to run in ctx */
+ mfc_debug(1, "ctx->dst_queue_cnt=%d ctx->dpb_count=%d ctx->src_queue_cnt=%d\n",
+ ctx->dst_queue_cnt, ctx->dpb_count, ctx->src_queue_cnt);
+ mfc_debug(1, "ctx->state=%d\n", ctx->state);
+ /* Last frame has already been sent to MFC
+ * Now obtaining frames from MFC buffer */
+
+ s5p_mfc_clock_on();
+ if (ctx->type == MFCINST_DECODER) {
+ switch (ctx->state) {
+ case MFCINST_FINISHING:
+ s5p_mfc_run_dec_last_frames(ctx);
+ break;
+ case MFCINST_RUNNING:
+ ret = s5p_mfc_run_dec_frame(ctx);
+ break;
+ case MFCINST_INIT:
+ s5p_mfc_clean_ctx_int_flags(ctx);
+ ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
+ ctx);
+ break;
+ case MFCINST_RETURN_INST:
+ s5p_mfc_clean_ctx_int_flags(ctx);
+ ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
+ ctx);
+ break;
+ case MFCINST_GOT_INST:
+ s5p_mfc_run_init_dec(ctx);
+ break;
+ case MFCINST_HEAD_PARSED:
+ ret = s5p_mfc_run_init_dec_buffers(ctx);
+ break;
+ case MFCINST_RES_CHANGE_INIT:
+ s5p_mfc_run_dec_last_frames(ctx);
+ break;
+ case MFCINST_RES_CHANGE_FLUSH:
+ s5p_mfc_run_dec_last_frames(ctx);
+ break;
+ case MFCINST_RES_CHANGE_END:
+ mfc_debug(2, "Finished remaining frames after resolution change.\n");
+ ctx->capture_state = QUEUE_FREE;
+ mfc_debug(2, "Will re-init the codec`.\n");
+ s5p_mfc_run_init_dec(ctx);
+ break;
+ default:
+ ret = -EAGAIN;
+ }
+ } else if (ctx->type == MFCINST_ENCODER) {
+ switch (ctx->state) {
+ case MFCINST_FINISHING:
+ case MFCINST_RUNNING:
+ ret = s5p_mfc_run_enc_frame(ctx);
+ break;
+ case MFCINST_INIT:
+ ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
+ ctx);
+ break;
+ case MFCINST_RETURN_INST:
+ ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
+ ctx);
+ break;
+ case MFCINST_GOT_INST:
+ s5p_mfc_run_init_enc(ctx);
+ break;
+ case MFCINST_HEAD_PARSED: /* Only for MFC6.x */
+ ret = s5p_mfc_run_init_enc_buffers(ctx);
+ break;
+ default:
+ ret = -EAGAIN;
+ }
+ } else {
+ mfc_err("invalid context type: %d\n", ctx->type);
+ ret = -EAGAIN;
+ }
+
+ if (ret) {
+ /* Free hardware lock */
+ if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+ mfc_err("Failed to unlock hardware.\n");
+
+ /* This is in deed imporant, as no operation has been
+ * scheduled, reduce the clock count as no one will
+ * ever do this, because no interrupt related to this try_run
+ * will ever come from hardware. */
+ s5p_mfc_clock_off();
+ }
+}
+
+
+void s5p_mfc_cleanup_queue_v6(struct list_head *lh, struct vb2_queue *vq)
+{
+ struct s5p_mfc_buf *b;
+ int i;
+
+ while (!list_empty(lh)) {
+ b = list_entry(lh->next, struct s5p_mfc_buf, list);
+ for (i = 0; i < b->b->num_planes; i++)
+ vb2_set_plane_payload(b->b, i, 0);
+ vb2_buffer_done(b->b, VB2_BUF_STATE_ERROR);
+ list_del(&b->list);
+ }
+}
+
+void s5p_mfc_clear_int_flags_v6(struct s5p_mfc_dev *dev)
+{
+ mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD_V6);
+ mfc_write(dev, 0, S5P_FIMV_RISC2HOST_INT_V6);
+}
+
+void s5p_mfc_write_info_v6(struct s5p_mfc_ctx *ctx, unsigned int data,
+ unsigned int ofs)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+
+ s5p_mfc_clock_on();
+ WRITEL(data, ofs);
+ s5p_mfc_clock_off();
+}
+
+unsigned int s5p_mfc_read_info_v6(struct s5p_mfc_ctx *ctx, unsigned int ofs)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ int ret;
+
+ s5p_mfc_clock_on();
+ ret = READL(ofs);
+ s5p_mfc_clock_off();
+
+ return ret;
+}
+
+int s5p_mfc_get_dspl_y_adr_v6(struct s5p_mfc_dev *dev)
+{
+ return mfc_read(dev, S5P_FIMV_D_DISPLAY_LUMA_ADDR_V6);
+}
+
+int s5p_mfc_get_dec_y_adr_v6(struct s5p_mfc_dev *dev)
+{
+ return mfc_read(dev, S5P_FIMV_D_DISPLAY_LUMA_ADDR_V6);
+}
+
+int s5p_mfc_get_dspl_status_v6(struct s5p_mfc_dev *dev)
+{
+ return mfc_read(dev, S5P_FIMV_D_DISPLAY_STATUS_V6);
+}
+
+int s5p_mfc_get_decoded_status_v6(struct s5p_mfc_dev *dev)
+{
+ return mfc_read(dev, S5P_FIMV_D_DECODED_STATUS_V6);
+}
+
+int s5p_mfc_get_dec_frame_type_v6(struct s5p_mfc_dev *dev)
+{
+ return mfc_read(dev, S5P_FIMV_D_DECODED_FRAME_TYPE_V6) &
+ S5P_FIMV_DECODE_FRAME_MASK_V6;
+}
+
+int s5p_mfc_get_disp_frame_type_v6(struct s5p_mfc_ctx *ctx)
+{
+ return mfc_read(ctx->dev, S5P_FIMV_D_DISPLAY_FRAME_TYPE_V6) &
+ S5P_FIMV_DECODE_FRAME_MASK_V6;
+}
+
+int s5p_mfc_get_consumed_stream_v6(struct s5p_mfc_dev *dev)
+{
+ return mfc_read(dev, S5P_FIMV_D_DECODED_NAL_SIZE_V6);
+}
+
+int s5p_mfc_get_int_reason_v6(struct s5p_mfc_dev *dev)
+{
+ return mfc_read(dev, S5P_FIMV_RISC2HOST_CMD_V6) &
+ S5P_FIMV_RISC2HOST_CMD_MASK;
+}
+
+int s5p_mfc_get_int_err_v6(struct s5p_mfc_dev *dev)
+{
+ return mfc_read(dev, S5P_FIMV_ERROR_CODE_V6);
+}
+
+int s5p_mfc_err_dec_v6(unsigned int err)
+{
+ return (err & S5P_FIMV_ERR_DEC_MASK_V6) >> S5P_FIMV_ERR_DEC_SHIFT_V6;
+}
+
+int s5p_mfc_err_dspl_v6(unsigned int err)
+{
+ return (err & S5P_FIMV_ERR_DSPL_MASK_V6) >> S5P_FIMV_ERR_DSPL_SHIFT_V6;
+}
+
+int s5p_mfc_get_img_width_v6(struct s5p_mfc_dev *dev)
+{
+ return mfc_read(dev, S5P_FIMV_D_DISPLAY_FRAME_WIDTH_V6);
+}
+
+int s5p_mfc_get_img_height_v6(struct s5p_mfc_dev *dev)
+{
+ return mfc_read(dev, S5P_FIMV_D_DISPLAY_FRAME_HEIGHT_V6);
+}
+
+int s5p_mfc_get_dpb_count_v6(struct s5p_mfc_dev *dev)
+{
+ return mfc_read(dev, S5P_FIMV_D_MIN_NUM_DPB_V6);
+}
+
+int s5p_mfc_get_mv_count_v6(struct s5p_mfc_dev *dev)
+{
+ return mfc_read(dev, S5P_FIMV_D_MIN_NUM_MV_V6);
+}
+
+int s5p_mfc_get_inst_no_v6(struct s5p_mfc_dev *dev)
+{
+ return mfc_read(dev, S5P_FIMV_RET_INSTANCE_ID_V6);
+}
+
+int s5p_mfc_get_enc_dpb_count_v6(struct s5p_mfc_dev *dev)
+{
+ return mfc_read(dev, S5P_FIMV_E_NUM_DPB_V6);
+}
+
+int s5p_mfc_get_enc_strm_size_v6(struct s5p_mfc_dev *dev)
+{
+ return mfc_read(dev, S5P_FIMV_E_STREAM_SIZE_V6);
+}
+
+int s5p_mfc_get_enc_slice_type_v6(struct s5p_mfc_dev *dev)
+{
+ return mfc_read(dev, S5P_FIMV_E_SLICE_TYPE_V6);
+}
+
+int s5p_mfc_get_enc_pic_count_v6(struct s5p_mfc_dev *dev)
+{
+ return mfc_read(dev, S5P_FIMV_E_PICTURE_COUNT_V6);
+}
+
+int s5p_mfc_get_sei_avail_status_v6(struct s5p_mfc_ctx *ctx)
+{
+ return mfc_read(ctx->dev, S5P_FIMV_D_FRAME_PACK_SEI_AVAIL_V6);
+}
+
+int s5p_mfc_get_mvc_num_views_v6(struct s5p_mfc_dev *dev)
+{
+ return mfc_read(dev, S5P_FIMV_D_MVC_NUM_VIEWS_V6);
+}
+
+int s5p_mfc_get_mvc_view_id_v6(struct s5p_mfc_dev *dev)
+{
+ return mfc_read(dev, S5P_FIMV_D_MVC_VIEW_ID_V6);
+}
+
+unsigned int s5p_mfc_get_pic_type_top_v6(struct s5p_mfc_ctx *ctx)
+{
+ return s5p_mfc_read_info_v6(ctx, PIC_TIME_TOP_V6);
+}
+
+unsigned int s5p_mfc_get_pic_type_bot_v6(struct s5p_mfc_ctx *ctx)
+{
+ return s5p_mfc_read_info_v6(ctx, PIC_TIME_BOT_V6);
+}
+
+unsigned int s5p_mfc_get_crop_info_h_v6(struct s5p_mfc_ctx *ctx)
+{
+ return s5p_mfc_read_info_v6(ctx, CROP_INFO_H_V6);
+}
+
+unsigned int s5p_mfc_get_crop_info_v_v6(struct s5p_mfc_ctx *ctx)
+{
+ return s5p_mfc_read_info_v6(ctx, CROP_INFO_V_V6);
+}
+
+/* Initialize opr function pointers for MFC v6 */
+static struct s5p_mfc_hw_ops s5p_mfc_ops_v6 = {
+ .alloc_dec_temp_buffers = s5p_mfc_alloc_dec_temp_buffers_v6,
+ .release_dec_desc_buffer = s5p_mfc_release_dec_desc_buffer_v6,
+ .alloc_codec_buffers = s5p_mfc_alloc_codec_buffers_v6,
+ .release_codec_buffers = s5p_mfc_release_codec_buffers_v6,
+ .alloc_instance_buffer = s5p_mfc_alloc_instance_buffer_v6,
+ .release_instance_buffer = s5p_mfc_release_instance_buffer_v6,
+ .alloc_dev_context_buffer =
+ s5p_mfc_alloc_dev_context_buffer_v6,
+ .release_dev_context_buffer =
+ s5p_mfc_release_dev_context_buffer_v6,
+ .dec_calc_dpb_size = s5p_mfc_dec_calc_dpb_size_v6,
+ .enc_calc_src_size = s5p_mfc_enc_calc_src_size_v6,
+ .set_dec_stream_buffer = s5p_mfc_set_dec_stream_buffer_v6,
+ .set_dec_frame_buffer = s5p_mfc_set_dec_frame_buffer_v6,
+ .set_enc_stream_buffer = s5p_mfc_set_enc_stream_buffer_v6,
+ .set_enc_frame_buffer = s5p_mfc_set_enc_frame_buffer_v6,
+ .get_enc_frame_buffer = s5p_mfc_get_enc_frame_buffer_v6,
+ .set_enc_ref_buffer = s5p_mfc_set_enc_ref_buffer_v6,
+ .init_decode = s5p_mfc_init_decode_v6,
+ .init_encode = s5p_mfc_init_encode_v6,
+ .encode_one_frame = s5p_mfc_encode_one_frame_v6,
+ .try_run = s5p_mfc_try_run_v6,
+ .cleanup_queue = s5p_mfc_cleanup_queue_v6,
+ .clear_int_flags = s5p_mfc_clear_int_flags_v6,
+ .write_info = s5p_mfc_write_info_v6,
+ .read_info = s5p_mfc_read_info_v6,
+ .get_dspl_y_adr = s5p_mfc_get_dspl_y_adr_v6,
+ .get_dec_y_adr = s5p_mfc_get_dec_y_adr_v6,
+ .get_dspl_status = s5p_mfc_get_dspl_status_v6,
+ .get_dec_status = s5p_mfc_get_dec_status_v6,
+ .get_dec_frame_type = s5p_mfc_get_dec_frame_type_v6,
+ .get_disp_frame_type = s5p_mfc_get_disp_frame_type_v6,
+ .get_consumed_stream = s5p_mfc_get_consumed_stream_v6,
+ .get_int_reason = s5p_mfc_get_int_reason_v6,
+ .get_int_err = s5p_mfc_get_int_err_v6,
+ .err_dec = s5p_mfc_err_dec_v6,
+ .err_dspl = s5p_mfc_err_dspl_v6,
+ .get_img_width = s5p_mfc_get_img_width_v6,
+ .get_img_height = s5p_mfc_get_img_height_v6,
+ .get_dpb_count = s5p_mfc_get_dpb_count_v6,
+ .get_mv_count = s5p_mfc_get_mv_count_v6,
+ .get_inst_no = s5p_mfc_get_inst_no_v6,
+ .get_enc_strm_size = s5p_mfc_get_enc_strm_size_v6,
+ .get_enc_slice_type = s5p_mfc_get_enc_slice_type_v6,
+ .get_enc_dpb_count = s5p_mfc_get_enc_dpb_count_v6,
+ .get_enc_pic_count = s5p_mfc_get_enc_pic_count_v6,
+ .get_sei_avail_status = s5p_mfc_get_sei_avail_status_v6,
+ .get_mvc_num_views = s5p_mfc_get_mvc_num_views_v6,
+ .get_mvc_view_id = s5p_mfc_get_mvc_view_id_v6,
+ .get_pic_type_top = s5p_mfc_get_pic_type_top_v6,
+ .get_pic_type_bot = s5p_mfc_get_pic_type_bot_v6,
+ .get_crop_info_h = s5p_mfc_get_crop_info_h_v6,
+ .get_crop_info_v = s5p_mfc_get_crop_info_v_v6,
+};
+
+struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v6(void)
+{
+ return &s5p_mfc_ops_v6;
+}
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h
new file mode 100644
index 0000000..ab164ef
--- /dev/null
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h
@@ -0,0 +1,50 @@
+/*
+ * drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h
+ *
+ * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
+ * Contains declarations of hw related functions.
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef S5P_MFC_OPR_V6_H_
+#define S5P_MFC_OPR_V6_H_
+
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_opr.h"
+
+#define MFC_CTRL_MODE_CUSTOM MFC_CTRL_MODE_SFR
+
+#define MB_WIDTH(x_size) DIV_ROUND_UP(x_size, 16)
+#define MB_HEIGHT(y_size) DIV_ROUND_UP(y_size, 16)
+#define S5P_MFC_DEC_MV_SIZE_V6(x, y) (MB_WIDTH(x) * \
+ (((MB_HEIGHT(y)+1)/2)*2) * 64 + 128)
+
+/* Definition */
+#define ENC_MULTI_SLICE_MB_MAX ((1 << 30) - 1)
+#define ENC_MULTI_SLICE_BIT_MIN 2800
+#define ENC_INTRA_REFRESH_MB_MAX ((1 << 18) - 1)
+#define ENC_VBV_BUF_SIZE_MAX ((1 << 30) - 1)
+#define ENC_H264_LOOP_FILTER_AB_MIN -12
+#define ENC_H264_LOOP_FILTER_AB_MAX 12
+#define ENC_H264_RC_FRAME_RATE_MAX ((1 << 16) - 1)
+#define ENC_H263_RC_FRAME_RATE_MAX ((1 << 16) - 1)
+#define ENC_H264_PROFILE_MAX 3
+#define ENC_H264_LEVEL_MAX 42
+#define ENC_MPEG4_VOP_TIME_RES_MAX ((1 << 16) - 1)
+#define FRAME_DELTA_H264_H263 1
+#define TIGHT_CBR_MAX 10
+
+/* Definitions for shared memory compatibility */
+#define PIC_TIME_TOP_V6 S5P_FIMV_D_RET_PICTURE_TAG_TOP_V6
+#define PIC_TIME_BOT_V6 S5P_FIMV_D_RET_PICTURE_TAG_BOT_V6
+#define CROP_INFO_H_V6 S5P_FIMV_D_DISPLAY_CROP_INFO1_V6
+#define CROP_INFO_V_V6 S5P_FIMV_D_DISPLAY_CROP_INFO2_V6
+
+struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v6(void);
+#endif /* S5P_MFC_OPR_V6_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
index 0503d14..367db75 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
@@ -20,7 +20,6 @@
#include "s5p_mfc_debug.h"
#include "s5p_mfc_pm.h"
-#define MFC_CLKNAME "sclk_mfc"
#define MFC_GATE_CLK_NAME "mfc"
#define CLK_DEBUG
@@ -51,7 +50,7 @@ int s5p_mfc_init_pm(struct s5p_mfc_dev *dev)
goto err_p_ip_clk;
}
- pm->clock = clk_get(&dev->plat_dev->dev, MFC_CLKNAME);
+ pm->clock = clk_get(&dev->plat_dev->dev, dev->variant->mclk_name);
if (IS_ERR(pm->clock)) {
mfc_err("Failed to get MFC clock\n");
ret = PTR_ERR(pm->clock);
--
1.7.0.4
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v9 0/6] Update MFC v4l2 driver to support MFC6.x
2012-10-02 11:16 ` Kamil Debski
@ 2012-10-02 17:10 ` Sylwester Nawrocki
0 siblings, 0 replies; 15+ messages in thread
From: Sylwester Nawrocki @ 2012-10-02 17:10 UTC (permalink / raw)
To: Kamil Debski
Cc: 'Arun Kumar K', linux-media, jtp.park, janghyuck.kim,
jaeryul.oh, ch.naveen, Marek Szyprowski, hverkuil, kmpark, joshi
Hello,
On 10/02/2012 01:16 PM, Kamil Debski wrote:
> Hi Arun,
>
> Thank you for your hard work with these patches.
> I think that they are ready to be merged.
I've just picked up these patches and have sent the pull request.
Thanks,
Sylwester
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2012-10-02 17:10 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-10-02 14:55 [PATCH v9 0/6] Update MFC v4l2 driver to support MFC6.x Arun Kumar K
2012-10-02 11:16 ` Kamil Debski
2012-10-02 17:10 ` Sylwester Nawrocki
2012-10-02 14:55 ` [PATCH v9 1/6] [media] v4l: Add fourcc definitions for new formats Arun Kumar K
2012-10-02 11:16 ` Kamil Debski
2012-10-02 14:55 ` [PATCH v9 2/6] [media] v4l: Add control definitions for new H264 encoder features Arun Kumar K
2012-10-02 11:16 ` Kamil Debski
2012-10-02 14:55 ` [PATCH v9 3/6] [media] s5p-mfc: Update MFCv5 driver for callback based architecture Arun Kumar K
2012-10-02 11:16 ` Kamil Debski
2012-10-02 14:55 ` [PATCH v9 4/6] [media] s5p-mfc: Add MFC variant data to device context Arun Kumar K
2012-10-02 11:16 ` Kamil Debski
2012-10-02 14:55 ` [PATCH v9 5/6] [media] s5p-mfc: MFCv6 register definitions Arun Kumar K
2012-10-02 11:16 ` Kamil Debski
2012-10-02 14:55 ` [PATCH v9 6/6] [media] s5p-mfc: Update MFC v4l2 driver to support MFC6.x Arun Kumar K
2012-10-02 11:16 ` Kamil Debski
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.