* [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* 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 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
* [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
* 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
* [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
* 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
* [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
* 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
* [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
* 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
* [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
* 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
* [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 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
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.