All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/3] Add support for MPEG-2 in DELTA video decoder
@ 2017-02-08 15:37 Hugues Fruchet
  2017-02-08 15:37 ` [PATCH v2 1/3] [media] v4l: add parsed MPEG-2 support Hugues Fruchet
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Hugues Fruchet @ 2017-02-08 15:37 UTC (permalink / raw)
  To: linux-media, Hans Verkuil
  Cc: kernel, Benjamin Gaignard, Hugues Fruchet, Jean-Christophe Trotin

The patchset implements the MPEG-2 part of V4L2 unified low-level decoder
API RFC [0] needed by stateless video decoders, ie decoders which requires
specific parsing metadata in addition to video bitstream chunk in order
to complete decoding.
A reference implementation using STMicroelectronics DELTA video decoder
is provided as initial support in this patchset.
In addition to this patchset, a libv4l plugin is also provided which convert
MPEG-2 video bitstream to "parsed MPEG-2" by parsing the user video bitstream
and filling accordingly the dedicated controls, doing so user code remains
unchanged whatever decoder is: stateless or not.

The first patch implements the MPEG-2 part of V4L2 unified low-level decoder
API RFC [0]. A dedicated "parsed MPEG-2" pixel format has been introduced with
its related extended controls in order that user provides both video bitstream
chunk and the associated extra data resulting from this video bitstream chunk
parsing.

The second patch adds the support of "parsed" pixel format inside DELTA video
decoder including handling of the dedicated controls and setting of parsing
metadata required by decoder layer.
Please note that the current implementation has a restriction regarding
the atomicity of S_EXT_CTRL/QBUF that must be guaranteed by user.
This restriction will be removed when V4L2 request API will be implemented [1].
Please also note the failure in v4l2-compliance in controls section, related
to complex compound controls handling, to be discussed to find the right way
to fix it in v4l2-compliance.

The third patch adds the support of DELTA MPEG-2 stateless video decoder back-end.


This driver depends on:
  [PATCH v7 00/10] Add support for DELTA video decoder of STMicroelectronics STiH4xx SoC series https://patchwork.linuxtv.org/patch/39186/

References:
  [0] [RFC] V4L2 unified low-level decoder API https://www.spinics.net/lists/linux-media/msg107150.html
  [1] [ANN] Report of the V4L2 Request API brainstorm meeting https://www.spinics.net/lists/linux-media/msg106699.html

===========
= history =
===========
version 2:
  - rebase on top of DELTA v7, refer to [0]
  - change VIDEO_STI_DELTA_DRIVER to default=y as per Mauro recommendations

version 1:
  - Initial submission

===================
= v4l2-compliance =
===================
Below is the v4l2-compliance report, v4l2-compliance has been build from SHA1:
003f31e59f353b4aecc82e8fb1c7555964da7efa (v4l2-compliance: allow S_SELECTION to return ENOTTY)

root@sti-4:~# v4l2-compliance -d /dev/video3
v4l2-compliance SHA   : 003f31e59f353b4aecc82e8fb1c7555964da7efa


root@sti-lts:~# v4l2-compliance -d /dev/video3 
v4l2-compliance SHA   : not available

Driver Info:
	Driver name   : st-delta
	Card type     : st-delta-21.1-3
	Bus info      : platform:soc:delta0
	Driver version: 4.9.0
	Capabilities  : 0x84208000
		Video Memory-to-Memory
		Streaming
		Extended Pix Format
		Device Capabilities
	Device Caps   : 0x04208000
		Video Memory-to-Memory
		Streaming
		Extended Pix Format

Compliance test for device /dev/video3 (not using libv4l2):

Required ioctls:
	test VIDIOC_QUERYCAP: OK

Allow for multiple opens:
	test second video open: OK
	test VIDIOC_QUERYCAP: OK
	test VIDIOC_G/S_PRIORITY: OK
	test for unlimited opens: OK

Debug ioctls:
	test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
	test VIDIOC_LOG_STATUS: OK (Not Supported)

Input ioctls:
	test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
	test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
	test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
	test VIDIOC_ENUMAUDIO: OK (Not Supported)
	test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
	test VIDIOC_G/S_AUDIO: OK (Not Supported)
	Inputs: 0 Audio Inputs: 0 Tuners: 0

Output ioctls:
	test VIDIOC_G/S_MODULATOR: OK (Not Supported)
	test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
	test VIDIOC_ENUMAUDOUT: OK (Not Supported)
	test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
	test VIDIOC_G/S_AUDOUT: OK (Not Supported)
	Outputs: 0 Audio Outputs: 0 Modulators: 0

Input/Output configuration ioctls:
	test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
	test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
	test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
	test VIDIOC_G/S_EDID: OK (Not Supported)

	Control ioctls:
		test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK
		test VIDIOC_QUERYCTRL: OK
		test VIDIOC_G/S_CTRL: OK
		fail: ../../../../../../../../../sources/v4l-utils/utils/v4l2-compliance/v4l2-test-controls.cpp(585): g_ext_ctrls worked even when no controls are present
		test VIDIOC_G/S/TRY_EXT_CTRLS: FAIL
		test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK (Not Supported)
		test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
		Standard Controls: 0 Private Controls: 0

	Format ioctls:
		test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
		test VIDIOC_G/S_PARM: OK (Not Supported)
		test VIDIOC_G_FBUF: OK (Not Supported)
		test VIDIOC_G_FMT: OK
		warn: ../../../../../../../../../sources/v4l-utils/utils/v4l2-compliance/v4l2-test-formats.cpp(717): TRY_FMT cannot handle an invalid pixelformat.
		warn: ../../../../../../../../../sources/v4l-utils/utils/v4l2-compliance/v4l2-test-formats.cpp(718): This may or may not be a problem. For more information see:
		warn: ../../../../../../../../../sources/v4l-utils/utils/v4l2-compliance/v4l2-test-formats.cpp(719): http://www.mail-archive.com/linux-media@vger.kernel.org/msg56550.html
		test VIDIOC_TRY_FMT: OK
		warn: ../../../../../../../../../sources/v4l-utils/utils/v4l2-compliance/v4l2-test-formats.cpp(977): S_FMT cannot handle an invalid pixelformat.
		warn: ../../../../../../../../../sources/v4l-utils/utils/v4l2-compliance/v4l2-test-formats.cpp(978): This may or may not be a problem. For more information see:
		warn: ../../../../../../../../../sources/v4l-utils/utils/v4l2-compliance/v4l2-test-formats.cpp(979): http://www.mail-archive.com/linux-media@vger.kernel.org/msg56550.html
		test VIDIOC_S_FMT: OK
		test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
		test Cropping: OK (Not Supported)
		test Composing: OK
		test Scaling: OK

	Codec ioctls:
		test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
		test VIDIOC_G_ENC_INDEX: OK (Not Supported)
		test VIDIOC_(TRY_)DECODER_CMD: OK

	Buffer ioctls:
		test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
		test VIDIOC_EXPBUF: OK

Test input 0:


Total: 43, Succeeded: 42, Failed: 1, Warnings: 6

Hugues Fruchet (3):
  [media] v4l: add parsed MPEG-2 support
  [media] st-delta: add parsing metadata controls support
  [media] st-delta: add mpeg2 support

 Documentation/media/uapi/v4l/extended-controls.rst |  363 +++++
 Documentation/media/uapi/v4l/pixfmt-013.rst        |   10 +
 drivers/media/platform/Kconfig                     |   11 +-
 drivers/media/platform/sti/delta/Makefile          |    3 +
 drivers/media/platform/sti/delta/delta-cfg.h       |    5 +
 drivers/media/platform/sti/delta/delta-mpeg2-dec.c | 1392 ++++++++++++++++++++
 drivers/media/platform/sti/delta/delta-mpeg2-fw.h  |  415 ++++++
 drivers/media/platform/sti/delta/delta-v4l2.c      |  129 +-
 drivers/media/platform/sti/delta/delta.h           |   34 +
 drivers/media/v4l2-core/v4l2-ctrls.c               |   53 +
 drivers/media/v4l2-core/v4l2-ioctl.c               |    2 +
 include/uapi/linux/v4l2-controls.h                 |   86 ++
 include/uapi/linux/videodev2.h                     |    8 +
 13 files changed, 2508 insertions(+), 3 deletions(-)
 create mode 100644 drivers/media/platform/sti/delta/delta-mpeg2-dec.c
 create mode 100644 drivers/media/platform/sti/delta/delta-mpeg2-fw.h

-- 
1.9.1


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v2 1/3] [media] v4l: add parsed MPEG-2 support
  2017-02-08 15:37 [PATCH v2 0/3] Add support for MPEG-2 in DELTA video decoder Hugues Fruchet
@ 2017-02-08 15:37 ` Hugues Fruchet
  2017-02-08 15:37 ` [PATCH v2 2/3] [media] st-delta: add parsing metadata controls support Hugues Fruchet
  2017-02-08 15:37 ` [PATCH v2 3/3] [media] st-delta: add mpeg2 support Hugues Fruchet
  2 siblings, 0 replies; 5+ messages in thread
From: Hugues Fruchet @ 2017-02-08 15:37 UTC (permalink / raw)
  To: linux-media, Hans Verkuil
  Cc: kernel, Benjamin Gaignard, Hugues Fruchet, Jean-Christophe Trotin

Add "parsed MPEG-2" pixel format & related controls
needed by stateless video decoders.
In order to decode the video bitstream chunk provided
by user on output queue, stateless decoders require
also some extra data resulting from this video bitstream
chunk parsing.
Those parsed extra data have to be set by user through
control framework using the dedicated mpeg video extended
controls introduced in this patchset.

Signed-off-by: Hugues Fruchet <hugues.fruchet@st.com>
---
 Documentation/media/uapi/v4l/extended-controls.rst | 363 +++++++++++++++++++++
 Documentation/media/uapi/v4l/pixfmt-013.rst        |  10 +
 drivers/media/v4l2-core/v4l2-ctrls.c               |  53 +++
 drivers/media/v4l2-core/v4l2-ioctl.c               |   2 +
 include/uapi/linux/v4l2-controls.h                 |  86 +++++
 include/uapi/linux/videodev2.h                     |   8 +
 6 files changed, 522 insertions(+)

diff --git a/Documentation/media/uapi/v4l/extended-controls.rst b/Documentation/media/uapi/v4l/extended-controls.rst
index abb1057..cd1a8d6 100644
--- a/Documentation/media/uapi/v4l/extended-controls.rst
+++ b/Documentation/media/uapi/v4l/extended-controls.rst
@@ -1827,6 +1827,369 @@ enum v4l2_mpeg_cx2341x_video_median_filter_type -
     not insert, 1 = insert packets.
 
 
+MPEG-2 Parsed Control Reference
+---------------------------------
+
+The MPEG-2 parsed decoding controls are needed by stateless video decoders.
+Those decoders expose :ref:`Compressed formats <compressed-formats>` :ref:`V4L2_PIX_FMT_MPEG1_PARSED<V4L2-PIX-FMT-MPEG1-PARSED>` or :ref:`V4L2_PIX_FMT_MPEG2_PARSED<V4L2-PIX-FMT-MPEG2-PARSED>`.
+In order to decode the video bitstream chunk provided by user on output queue,
+stateless decoders require also some extra data resulting from this video
+bitstream chunk parsing. Those parsed extra data have to be set by user
+through control framework using the mpeg video extended controls defined
+in this section. Those controls have been defined based on MPEG-2 standard
+ISO/IEC 13818-2, and so derive directly from the MPEG-2 video bitstream syntax
+including how it is coded inside bitstream (enumeration values for ex.).
+
+MPEG-2 Parsed Control IDs
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. _mpeg2-parsed-control-id:
+
+``V4L2_CID_MPEG_VIDEO_MPEG2_SEQ_HDR``
+    (enum)
+
+.. tabularcolumns:: |p{4.0cm}|p{2.5cm}|p{11.0cm}|
+
+.. c:type:: v4l2_mpeg_video_mpeg2_seq_hdr
+
+.. cssclass:: longtable
+
+.. flat-table:: struct v4l2_mpeg_video_mpeg2_seq_hdr
+    :header-rows:  0
+    :stub-columns: 0
+    :widths:       1 1 2
+
+    * - __u16
+      - ``width``
+      - Video width in pixels.
+    * - __u16
+      - ``height``
+      - Video height in pixels.
+    * - __u8
+      - ``aspect_ratio_info``
+      - Aspect ratio code as in the bitstream (1: 1:1 square pixels,
+        2: 4:3 display, 3: 16:9 display, 4: 2.21:1 display)
+    * - __u8
+      - ``framerate code``
+      - Framerate code as in the bitstream
+        (1: 24000/1001.0 '23.976 fps, 2: 24.0, 3: 25.0,
+        4: 30000/1001.0 '29.97, 5: 30.0, 6: 50.0, 7: 60000/1001.0,
+        8: 60.0)
+    * - __u32
+      - ``bitrate_value``
+      - Bitrate value as in the bitstream, expressed in 400bps unit
+    * - __u16
+      - ``vbv_buffer_size``
+      -  Video Buffering Verifier size, expressed in 16KBytes unit.
+    * - __u8
+      - ``constrained_parameters_flag``
+      - Set to 1 if this bitstream uses constrained parameters.
+    * - __u8
+      - ``load_intra_quantiser_matrix``
+      - If set to 1, ``intra_quantiser_matrix`` table is to be used for
+        decoding.
+    * - __u8
+      - ``load_non_intra_quantiser_matrix``
+      - If set to 1, ``non_intra_quantiser_matrix`` table is to be used for
+        decoding.
+    * - __u8
+      - ``intra_quantiser_matrix[64]``
+      - Intra quantization table, in zig-zag scan order.
+    * - __u8
+      - ``non_intra_quantiser_matrix[64]``
+      - Non-intra quantization table, in zig-zag scan order.
+    * - __u32
+      - ``par_w``
+      - Pixel aspect ratio width in pixels.
+    * - __u32
+      - ``par_h``
+      - Pixel aspect ratio height in pixels.
+    * - __u32
+      - ``fps_n``
+      - Framerate nominator.
+    * - __u32
+      - ``fps_d``
+      - Framerate denominator.
+    * - __u32
+      - ``bitrate``
+      - Bitrate in bps if constant bitrate, 0 otherwise.
+    * - :cspan:`2`
+
+
+``V4L2_CID_MPEG_VIDEO_MPEG2_SEQ_EXT``
+    (enum)
+
+.. tabularcolumns:: |p{4.0cm}|p{2.5cm}|p{11.0cm}|
+
+.. c:type:: v4l2_mpeg_video_mpeg2_seq_ext
+
+.. cssclass:: longtable
+
+.. flat-table:: struct v4l2_mpeg_video_mpeg2_seq_ext
+    :header-rows:  0
+    :stub-columns: 0
+    :widths:       1 1 2
+
+    * - __u8
+      - ``profile``
+      - Encoding profile used to encode this bitstream.
+        (1: High Profile, 2: Spatially Scalable Profile,
+        3: SNR Scalable Profile, 4: Main Profile, 5: Simple Profile).
+    * - __u8
+      - ``level``
+      - Encoding level used to encode this bitstream
+        (4: High Level, 6: High 1440 Level, 8: Main Level, 10: Low Level).
+    * - __u8
+      - ``progressive``
+      - Set to 1 if frames are progressive (vs interlaced).
+    * - __u8
+      - ``chroma_format``
+      - Chrominance format (1: 420, 2: 422, 3: 444).
+    * - __u8
+      - ``horiz_size_ext``
+      - Horizontal size extension. This value is to be shifted 12 bits left
+        and added to ''seq_hdr->width'' to get the final video width:
+        `width = seq_hdr->width + seq_ext->horiz_size_ext << 12`
+    * - __u8
+      - ``vert_size_ext``
+      - Vertical size extension. This value is to be shifted 12 bits left
+        and added to ''seq_hdr->height'' to get the final video height:
+        `height = seq_hdr->height + seq_ext->vert_size_ext << 12`
+    * - __u16
+      - ``bitrate_ext``
+      -  Bitrate extension. This value, expressed in 400bps unit, is to be
+         shifted 18 bits left and added to ''seq_hdr->bitrate'' to get the
+         final bitrate:
+         `bitrate = seq_hdr->bitrate + (seq_ext->bitrate_ext << 18) * 400`
+    * - __u8
+      - ``vbv_buffer_size_ext``
+      -  Video Buffering Verifier size extension in bits.
+    * - __u8
+      - ``low_delay``
+      -  Low delay. Set to 1 if no B pictures are present.
+    * - __u8
+      - ``fps_n_ext``
+      -  Framerate extension nominator. This value is to be incremented and
+         multiplied by ''seq_hdr->fps_n'' to get the final framerate
+         nominator:
+         `fps_n = seq_hdr->fps_n * (seq_ext->fps_n_ext + 1)`
+    * - __u8
+      - ``fps_d_ext``
+      -  Framerate extension denominator. This value is to be incremented and
+         multiplied by ''seq_hdr->fps_d'' to get the final framerate
+         denominator:
+         `fps_d = seq_hdr->fps_d * (seq_ext->fps_d_ext + 1)`
+    * - :cspan:`2`
+
+
+``V4L2_CID_MPEG_VIDEO_MPEG2_SEQ_DISPLAY_EXT``
+    (enum)
+
+.. tabularcolumns:: |p{4.0cm}|p{2.5cm}|p{11.0cm}|
+
+.. c:type:: v4l2_mpeg_video_mpeg2_seq_display_ext
+
+.. cssclass:: longtable
+
+.. flat-table:: struct v4l2_mpeg_video_mpeg2_seq_ext
+    :header-rows:  0
+    :stub-columns: 0
+    :widths:       1 1 2
+
+    * - __u8
+      - ``video_format``
+      - Video standard (0: Components, 1: PAL, 2: NTSC, 3: SECAM, 4:MAC)
+    * - __u8
+      - ``colour_description_flag``
+      - If set to 1, ''colour_primaries'', ''transfer_characteristics'',
+        ''matrix_coefficients'' are to be used for decoding.
+    * - __u8
+      - ``colour_primaries``
+      - Colour coding standard (1: ITU-R Rec. 709 (1990),
+        4: ITU-R Rec. 624-4 System M, 5: ITU-R Rec. 624-4 System B, G,
+        6: SMPTE 170M, 7: SMPTE 240M (1987))
+    * - __u8
+      - ``transfer_characteristics``
+      - Transfer characteristics coding standard (1: ITU-R Rec. 709 (1990),
+        4: ITU-R Rec. 624-4 System M, 5: ITU-R Rec. 624-4 System B, G,
+        6: SMPTE 170M, 7: SMPTE 240M (1987))
+    * - __u8
+      - ``matrix_coefficients``
+      - Matrix coefficients coding standard (1: ITU-R Rec. 709 (1990),
+        4: FCC, 5: ITU-R Rec. 624-4 System B, G, 6: SMPTE 170M,
+        7: SMPTE 240M (1987))
+    * - __u16
+      - ``display_horizontal_size``, ``display_vertical_size``
+      - Dimensions of the video to be displayed. If those dimensions
+        are smaller than the final video dimensions, only this area
+        must be displayed.
+    * - :cspan:`2`
+
+
+``V4L2_CID_MPEG_VIDEO_MPEG2_SEQ_MATRIX_EXT``
+    (enum)
+
+.. tabularcolumns:: |p{4.0cm}|p{2.5cm}|p{11.0cm}|
+
+.. c:type:: v4l2_mpeg_video_mpeg2_seq_matrix_ext
+
+.. cssclass:: longtable
+
+.. flat-table:: struct v4l2_mpeg_video_mpeg2_seq_matrix_ext
+    :header-rows:  0
+    :stub-columns: 0
+    :widths:       1 1 2
+
+    * - __u8
+      - ``load_intra_quantiser_matrix``
+      - If set to 1, ``intra_quantiser_matrix`` table is to be used for
+        decoding.
+    * - __u8
+      - ``intra_quantiser_matrix[64]``
+      - Intra quantization table, in zig-zag scan order.
+    * - __u8
+      - ``load_non_intra_quantiser_matrix``
+      - If set to 1, ``non_intra_quantiser_matrix`` table is to be used for
+        decoding.
+    * - __u8
+      - ``non_intra_quantiser_matrix[64]``
+      - Non-intra quantization table, in zig-zag scan order.
+    * - __u8
+      - ``load_chroma_intra_quantiser_matrix``
+      - If set to 1, ``chroma_intra_quantiser_matrix`` table is to be used for
+        decoding.
+    * - __u8
+      - ``chroma_intra_quantiser_matrix[64]``
+      - Chroma intra quantization table, in zig-zag scan order.
+    * - __u8
+      - ``load_chroma_non_intra_quantiser_matrix``
+      - If set to 1, ``chroma_non_intra_quantiser_matrix`` table is to be used for
+        decoding.
+    * - __u8
+      - ``chroma_non_intra_quantiser_matrix[64]``
+      - Chroma non-intra quantization table, in zig-zag scan order.
+    * - :cspan:`2`
+
+
+``V4L2_CID_MPEG_VIDEO_MPEG2_PIC_HDR``
+    (enum)
+
+.. tabularcolumns:: |p{4.0cm}|p{2.5cm}|p{11.0cm}|
+
+.. c:type:: v4l2_mpeg_video_mpeg2_pic_hdr
+
+.. cssclass:: longtable
+
+.. flat-table:: struct v4l2_mpeg_video_mpeg2_pic_hdr
+    :header-rows:  0
+    :stub-columns: 0
+    :widths:       1 1 2
+
+    * - __u32
+      - ``offset``
+      - Offset in bytes of the slice data from the beginning of packet.
+    * - __u16
+      - ``tsn``
+      - Temporal Sequence Number: order in which the frames must be displayed.
+    * - __u8
+      - ``pic_type``
+      - Picture coding type (1: Intra, 2: Predictive,
+        3: B, Bidirectionally Predictive, 4: D, DC Intra).
+    * - __u16
+      - ``vbv_delay``
+      - Video Buffering Verifier delay, in 90KHz cycles unit.
+    * - __u8
+      - ``full_pel_forward_vector``
+      - If set to 1, forward vectors are expressed in full pixel unit instead
+        half pixel unit.
+    * - __u8
+      - ``full_pel_backward_vector``
+      - If set to 1, backward vectors are expressed in full pixel unit instead
+        half pixel unit.
+    * - __u8
+      - ``f_code[2][2]``
+      - Motion vectors code.
+    * - :cspan:`2`
+
+
+``V4L2_CID_MPEG_VIDEO_MPEG2_PIC_EXT``
+    (enum)
+
+.. tabularcolumns:: |p{4.0cm}|p{2.5cm}|p{11.0cm}|
+
+.. c:type:: v4l2_mpeg_video_mpeg2_pic_ext
+
+.. cssclass:: longtable
+
+.. flat-table:: struct v4l2_mpeg_video_mpeg2_pic_ext
+    :header-rows:  0
+    :stub-columns: 0
+    :widths:       1 1 2
+
+    * - __u8
+      - ``f_code[2][2]``
+      - Motion vectors code.
+    * - __u8
+      - ``intra_dc_precision``
+      - Precision of Discrete Cosine transform (0: 8 bits precision,
+        1: 9 bits precision, 2: 10 bits precision, 11: 11 bits precision).
+    * - __u8
+      - ``picture_structure``
+      - Picture structure (1: interlaced top field,
+        2: interlaced bottom field, 3: progressive frame).
+    * - __u8
+      - ``top_field_first``
+      - If set to 1 and interlaced stream, top field is output first.
+    * - __u8
+      - ``frame_pred_frame_dct``
+      - If set to 1, only frame-DCT and frame prediction are used.
+    * - __u8
+      - ``concealment_motion_vectors``
+      -  If set to 1, motion vectors are coded for intra macroblocks.
+    * - __u8
+      - ``q_scale_type``
+      - This flag affects the inverse quantisation process.
+    * - __u8
+      - ``intra_vlc_format``
+      - This flag affects the decoding of transform coefficient data.
+    * - __u8
+      - ``alternate_scan``
+      - This flag affects the decoding of transform coefficient data.
+    * - __u8
+      - ``repeat_first_field``
+      - This flag affects how the frames or fields are output by decoder.
+    * - __u8
+      - ``chroma_420_type``
+      - Set the same as ``progressive_frame``. Exists for historical reasons.
+    * - __u8
+      - ``progressive_frame``
+      - If this flag is set to 0, the two fields of a frame are two interlaced fields,
+        ``repeat_first_field`` must be 0 (two field duration). If the flag is set to 1,
+        the two fields are merged into one frame, ``picture_structure`` is so set to "Frame"
+        and ``frame_pred_frame_dct`` to 1.
+    * - __u8
+      - ``composite_display``
+      - This flag is set to 1 if pictures are encoded as (analog) composite video.
+    * - __u8
+      - ``v_axis``
+      - Used only when pictures are encoded according to PAL systems. This flag is set to 1
+        on a positive sign, 0 otherwise.
+    * - __u8
+      - ``field_sequence``
+      - Specifies the number of the field of an eight Field Sequence for a PAL system or
+        a five Field Sequence for a NTSC system
+    * - __u8
+      - ``sub_carrier``
+      - If the flag is set to 0, the sub-carrier/line-frequency relationship is correct.
+    * - __u8
+      - ``burst_amplitude``
+      - Specifies the burst amplitude for PAL and NTSC.
+    * - __u8
+      - ``sub_carrier_phase``
+      - Specifies the phase of the reference sub-carrier for the field synchronization.
+    * - :cspan:`2`
+
+
 VPX Control Reference
 ---------------------
 
diff --git a/Documentation/media/uapi/v4l/pixfmt-013.rst b/Documentation/media/uapi/v4l/pixfmt-013.rst
index 728d7ed..32c9ef7 100644
--- a/Documentation/media/uapi/v4l/pixfmt-013.rst
+++ b/Documentation/media/uapi/v4l/pixfmt-013.rst
@@ -55,11 +55,21 @@ Compressed Formats
       - ``V4L2_PIX_FMT_MPEG1``
       - 'MPG1'
       - MPEG1 video elementary stream.
+    * .. _V4L2-PIX-FMT-MPEG1-PARSED:
+
+      - ``V4L2_PIX_FMT_MPEG1_PARSED``
+      - 'MG1P'
+      - MPEG-1 with parsing metadata given through controls, see :ref:`MPEG-2 Parsed Control IDs<mpeg2-parsed-control-id>`.
     * .. _V4L2-PIX-FMT-MPEG2:
 
       - ``V4L2_PIX_FMT_MPEG2``
       - 'MPG2'
       - MPEG2 video elementary stream.
+    * .. _V4L2-PIX-FMT-MPEG2-PARSED:
+
+      - ``V4L2_PIX_FMT_MPEG2_PARSED``
+      - 'MG2P'
+      - MPEG-2 with parsing metadata given through controls, see :ref:`MPEG-2 Parsed Control IDs<mpeg2-parsed-control-id>`.
     * .. _V4L2-PIX-FMT-MPEG4:
 
       - ``V4L2_PIX_FMT_MPEG4``
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index 47001e2..5d02818 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -760,6 +760,13 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE:		return "Vertical MV Search Range";
 	case V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER:		return "Repeat Sequence Header";
 	case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME:		return "Force Key Frame";
+	/* parsed MPEG-2 controls */
+	case V4L2_CID_MPEG_VIDEO_MPEG2_SEQ_HDR:			return "MPEG-2 sequence header";
+	case V4L2_CID_MPEG_VIDEO_MPEG2_SEQ_EXT:			return "MPEG-2 sequence extension";
+	case V4L2_CID_MPEG_VIDEO_MPEG2_SEQ_DISPLAY_EXT:		return "MPEG-2 sequence display extension";
+	case V4L2_CID_MPEG_VIDEO_MPEG2_SEQ_MATRIX_EXT:		return "MPEG-2 sequence quantization matrix";
+	case V4L2_CID_MPEG_VIDEO_MPEG2_PIC_HDR:			return "MPEG-2 picture header";
+	case V4L2_CID_MPEG_VIDEO_MPEG2_PIC_EXT:			return "MPEG-2 picture extension";
 
 	/* VPX controls */
 	case V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS:		return "VPX Number of Partitions";
@@ -1146,6 +1153,24 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
 	case V4L2_CID_RDS_TX_ALT_FREQS:
 		*type = V4L2_CTRL_TYPE_U32;
 		break;
+	case V4L2_CID_MPEG_VIDEO_MPEG2_SEQ_HDR:
+		*type = V4L2_CTRL_TYPE_MPEG2_SEQ_HDR;
+		break;
+	case V4L2_CID_MPEG_VIDEO_MPEG2_SEQ_EXT:
+		*type = V4L2_CTRL_TYPE_MPEG2_SEQ_EXT;
+		break;
+	case V4L2_CID_MPEG_VIDEO_MPEG2_SEQ_DISPLAY_EXT:
+		*type = V4L2_CTRL_TYPE_MPEG2_SEQ_DISPLAY_EXT;
+		break;
+	case V4L2_CID_MPEG_VIDEO_MPEG2_SEQ_MATRIX_EXT:
+		*type = V4L2_CTRL_TYPE_MPEG2_SEQ_MATRIX_EXT;
+		break;
+	case V4L2_CID_MPEG_VIDEO_MPEG2_PIC_HDR:
+		*type = V4L2_CTRL_TYPE_MPEG2_PIC_HDR;
+		break;
+	case V4L2_CID_MPEG_VIDEO_MPEG2_PIC_EXT:
+		*type = V4L2_CTRL_TYPE_MPEG2_PIC_EXT;
+		break;
 	default:
 		*type = V4L2_CTRL_TYPE_INTEGER;
 		break;
@@ -1456,6 +1481,14 @@ static int std_validate(const struct v4l2_ctrl *ctrl, u32 idx,
 			return -ERANGE;
 		return 0;
 
+	case V4L2_CTRL_TYPE_MPEG2_SEQ_HDR:
+	case V4L2_CTRL_TYPE_MPEG2_SEQ_EXT:
+	case V4L2_CTRL_TYPE_MPEG2_SEQ_DISPLAY_EXT:
+	case V4L2_CTRL_TYPE_MPEG2_SEQ_MATRIX_EXT:
+	case V4L2_CTRL_TYPE_MPEG2_PIC_HDR:
+	case V4L2_CTRL_TYPE_MPEG2_PIC_EXT:
+		return 0;
+
 	default:
 		return -EINVAL;
 	}
@@ -1975,6 +2008,26 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
 	case V4L2_CTRL_TYPE_U32:
 		elem_size = sizeof(u32);
 		break;
+	case V4L2_CTRL_TYPE_MPEG2_SEQ_HDR:
+		elem_size = sizeof(struct v4l2_mpeg_video_mpeg2_seq_hdr);
+		break;
+	case V4L2_CTRL_TYPE_MPEG2_SEQ_EXT:
+		elem_size = sizeof(struct v4l2_mpeg_video_mpeg2_seq_ext);
+		break;
+	case V4L2_CTRL_TYPE_MPEG2_SEQ_DISPLAY_EXT:
+		elem_size =
+			sizeof(struct v4l2_mpeg_video_mpeg2_seq_display_ext);
+		break;
+	case V4L2_CTRL_TYPE_MPEG2_SEQ_MATRIX_EXT:
+		elem_size =
+			sizeof(struct v4l2_mpeg_video_mpeg2_seq_matrix_ext);
+		break;
+	case V4L2_CTRL_TYPE_MPEG2_PIC_HDR:
+		elem_size = sizeof(struct v4l2_mpeg_video_mpeg2_pic_hdr);
+		break;
+	case V4L2_CTRL_TYPE_MPEG2_PIC_EXT:
+		elem_size = sizeof(struct v4l2_mpeg_video_mpeg2_pic_ext);
+		break;
 	default:
 		if (type < V4L2_CTRL_COMPOUND_TYPES)
 			elem_size = sizeof(s32);
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 0c3f238..55be85d 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -1232,7 +1232,9 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
 		case V4L2_PIX_FMT_H264_MVC:	descr = "H.264 MVC"; break;
 		case V4L2_PIX_FMT_H263:		descr = "H.263"; break;
 		case V4L2_PIX_FMT_MPEG1:	descr = "MPEG-1 ES"; break;
+		case V4L2_PIX_FMT_MPEG1_PARSED:	descr = "MPEG-1 with parsing metadata"; break;
 		case V4L2_PIX_FMT_MPEG2:	descr = "MPEG-2 ES"; break;
+		case V4L2_PIX_FMT_MPEG2_PARSED:	descr = "MPEG-2 with parsing metadata"; break;
 		case V4L2_PIX_FMT_MPEG4:	descr = "MPEG-4 part 2 ES"; break;
 		case V4L2_PIX_FMT_XVID:		descr = "Xvid"; break;
 		case V4L2_PIX_FMT_VC1_ANNEX_G:	descr = "VC-1 (SMPTE 412M Annex G)"; break;
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index 0d2e1e0..deff646 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -547,6 +547,92 @@ enum v4l2_mpeg_video_mpeg4_profile {
 };
 #define V4L2_CID_MPEG_VIDEO_MPEG4_QPEL		(V4L2_CID_MPEG_BASE+407)
 
+/* parsed MPEG-2 controls
+ * (needed by stateless video decoders)
+ * Those controls have been defined based on MPEG-2 standard ISO/IEC 13818-2,
+ * and so derive directly from the MPEG-2 video bitstream syntax including
+ * how it is coded inside bitstream (enumeration values for ex.).
+ */
+#define MPEG2_QUANTISER_MATRIX_SIZE	64
+#define V4L2_CID_MPEG_VIDEO_MPEG2_SEQ_HDR		(V4L2_CID_MPEG_BASE+450)
+struct v4l2_mpeg_video_mpeg2_seq_hdr {
+	__u16	width, height;
+	__u8	aspect_ratio_info;
+	__u8	frame_rate_code;
+	__u32	bitrate_value;
+	__u16	vbv_buffer_size;
+	__u8	constrained_parameters_flag;
+	__u8	load_intra_quantiser_matrix, load_non_intra_quantiser_matrix;
+	__u8	intra_quantiser_matrix[MPEG2_QUANTISER_MATRIX_SIZE];
+	__u8	non_intra_quantiser_matrix[MPEG2_QUANTISER_MATRIX_SIZE];
+	__u32	par_w, par_h;
+	__u32	fps_n, fps_d;
+	__u32	bitrate;
+};
+#define V4L2_CID_MPEG_VIDEO_MPEG2_SEQ_EXT		(V4L2_CID_MPEG_BASE+451)
+struct v4l2_mpeg_video_mpeg2_seq_ext {
+	__u8	profile;
+	__u8	level;
+	__u8	progressive;
+	__u8	chroma_format;
+	__u8	horiz_size_ext, vert_size_ext;
+	__u16	bitrate_ext;
+	__u8	vbv_buffer_size_ext;
+	__u8	low_delay;
+	__u8	fps_n_ext, fps_d_ext;
+};
+#define V4L2_CID_MPEG_VIDEO_MPEG2_SEQ_DISPLAY_EXT	(V4L2_CID_MPEG_BASE+452)
+struct v4l2_mpeg_video_mpeg2_seq_display_ext {
+	__u8	video_format;
+	__u8	colour_description_flag;
+	__u8	colour_primaries;
+	__u8	transfer_characteristics;
+	__u8	matrix_coefficients;
+	__u16	display_horizontal_size;
+	__u16	display_vertical_size;
+};
+#define V4L2_CID_MPEG_VIDEO_MPEG2_SEQ_MATRIX_EXT	(V4L2_CID_MPEG_BASE+453)
+struct v4l2_mpeg_video_mpeg2_seq_matrix_ext {
+	__u8	load_intra_quantiser_matrix;
+	__u8	intra_quantiser_matrix[MPEG2_QUANTISER_MATRIX_SIZE];
+	__u8	load_non_intra_quantiser_matrix;
+	__u8	non_intra_quantiser_matrix[MPEG2_QUANTISER_MATRIX_SIZE];
+	__u8	load_chroma_intra_quantiser_matrix;
+	__u8	chroma_intra_quantiser_matrix[MPEG2_QUANTISER_MATRIX_SIZE];
+	__u8	load_chroma_non_intra_quantiser_matrix;
+	__u8	chroma_non_intra_quantiser_matrix[MPEG2_QUANTISER_MATRIX_SIZE];
+};
+#define V4L2_CID_MPEG_VIDEO_MPEG2_PIC_HDR		(V4L2_CID_MPEG_BASE+454)
+struct v4l2_mpeg_video_mpeg2_pic_hdr {
+	__u32	offset;
+	__u16	tsn;
+	__u8	pic_type;
+	__u16	vbv_delay;
+	__u8	full_pel_forward_vector, full_pel_backward_vector;
+	__u8	f_code[2][2];
+};
+#define V4L2_CID_MPEG_VIDEO_MPEG2_PIC_EXT		(V4L2_CID_MPEG_BASE+455)
+struct v4l2_mpeg_video_mpeg2_pic_ext {
+	__u8	f_code[2][2];
+	__u8	intra_dc_precision;
+	__u8	picture_structure;
+	__u8	top_field_first;
+	__u8	frame_pred_frame_dct;
+	__u8	concealment_motion_vectors;
+	__u8	q_scale_type;
+	__u8	intra_vlc_format;
+	__u8	alternate_scan;
+	__u8	repeat_first_field;
+	__u8	chroma_420_type;
+	__u8	progressive_frame;
+	__u8	composite_display;
+	__u8	v_axis;
+	__u8	field_sequence;
+	__u8	sub_carrier;
+	__u8	burst_amplitude;
+	__u8	sub_carrier_phase;
+};
+
 /*  Control IDs for VP8 streams
  *  Although VP8 is not part of MPEG we add these controls to the MPEG class
  *  as that class is already handling other video compression standards
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 46e8a2e3..ada8a62 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -623,7 +623,9 @@ struct v4l2_pix_format {
 #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_MPEG1_PARSED v4l2_fourcc('M', 'G', '1', 'P') /* MPEG1 with parsing metadata given through controls */
 #define V4L2_PIX_FMT_MPEG2    v4l2_fourcc('M', 'P', 'G', '2') /* MPEG-2 ES     */
+#define V4L2_PIX_FMT_MPEG2_PARSED v4l2_fourcc('M', 'G', '2', 'P') /* MPEG2 with parsing metadata given through controls */
 #define V4L2_PIX_FMT_MPEG4    v4l2_fourcc('M', 'P', 'G', '4') /* MPEG-4 part 2 ES */
 #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 */
@@ -1601,6 +1603,12 @@ enum v4l2_ctrl_type {
 	V4L2_CTRL_TYPE_U8	     = 0x0100,
 	V4L2_CTRL_TYPE_U16	     = 0x0101,
 	V4L2_CTRL_TYPE_U32	     = 0x0102,
+	V4L2_CTRL_TYPE_MPEG2_SEQ_HDR  = 0x0109,
+	V4L2_CTRL_TYPE_MPEG2_SEQ_EXT  = 0x010A,
+	V4L2_CTRL_TYPE_MPEG2_SEQ_DISPLAY_EXT  = 0x010B,
+	V4L2_CTRL_TYPE_MPEG2_SEQ_MATRIX_EXT  = 0x010C,
+	V4L2_CTRL_TYPE_MPEG2_PIC_HDR  = 0x010D,
+	V4L2_CTRL_TYPE_MPEG2_PIC_EXT  = 0x010E,
 };
 
 /*  Used in the VIDIOC_QUERYCTRL ioctl for querying controls */
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v2 2/3] [media] st-delta: add parsing metadata controls support
  2017-02-08 15:37 [PATCH v2 0/3] Add support for MPEG-2 in DELTA video decoder Hugues Fruchet
  2017-02-08 15:37 ` [PATCH v2 1/3] [media] v4l: add parsed MPEG-2 support Hugues Fruchet
@ 2017-02-08 15:37 ` Hugues Fruchet
  2017-02-08 15:37 ` [PATCH v2 3/3] [media] st-delta: add mpeg2 support Hugues Fruchet
  2 siblings, 0 replies; 5+ messages in thread
From: Hugues Fruchet @ 2017-02-08 15:37 UTC (permalink / raw)
  To: linux-media, Hans Verkuil
  Cc: kernel, Benjamin Gaignard, Hugues Fruchet, Jean-Christophe Trotin

Install all metadata controls required by registered decoders.
Update the decoding context with the set of metadata received
from user through extended control.
Set the received metadata in access unit prior to call the
decoder decoding ops.

Signed-off-by: Hugues Fruchet <hugues.fruchet@st.com>
---
 drivers/media/platform/sti/delta/delta-v4l2.c | 125 +++++++++++++++++++++++++-
 drivers/media/platform/sti/delta/delta.h      |  34 +++++++
 2 files changed, 158 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/sti/delta/delta-v4l2.c b/drivers/media/platform/sti/delta/delta-v4l2.c
index c6f2e24..1d4436e 100644
--- a/drivers/media/platform/sti/delta/delta-v4l2.c
+++ b/drivers/media/platform/sti/delta/delta-v4l2.c
@@ -339,6 +339,30 @@ static void register_decoders(struct delta_dev *delta)
 	}
 }
 
+static void register_ctrls(struct delta_dev *delta)
+{
+	const struct delta_dec *dec;
+	unsigned int i, j;
+	u32 meta_cid;
+
+	/* decoders optional meta controls */
+	for (i = 0; i < delta->nb_of_decoders; i++) {
+		dec = delta->decoders[i];
+		if (!dec->meta_cids)
+			continue;
+
+		for (j = 0; j < dec->nb_of_metas; j++) {
+			meta_cid = dec->meta_cids[j];
+			if (!meta_cid)
+				continue;
+
+			delta->cids[delta->nb_of_ctrls++] = meta_cid;
+		}
+	}
+
+	/* add here additional controls if needed */
+}
+
 static void delta_lock(void *priv)
 {
 	struct delta_ctx *ctx = priv;
@@ -355,6 +379,79 @@ static void delta_unlock(void *priv)
 	mutex_unlock(&delta->lock);
 }
 
+static int delta_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct delta_ctx *ctx =
+		container_of(ctrl->handler, struct delta_ctx, ctrl_handler);
+	struct delta_dev *delta = ctx->dev;
+
+	if (ctx->nb_of_metas >= DELTA_MAX_METAS) {
+		dev_err(delta->dev, "%s not enough room to set meta control\n",
+			ctx->name);
+		return -EINVAL;
+	}
+
+	dev_dbg(delta->dev, "%s set metas[%d] from control id=%d (%s)\n",
+		ctx->name, ctx->nb_of_metas, ctrl->id, ctrl->name);
+
+	ctx->metas[ctx->nb_of_metas].cid = ctrl->id;
+	ctx->metas[ctx->nb_of_metas].p = ctrl->p_new.p;
+	ctx->nb_of_metas++;
+
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops delta_ctrl_ops = {
+	.s_ctrl = delta_s_ctrl,
+};
+
+static int delta_ctrls_setup(struct delta_ctx *ctx)
+{
+	struct delta_dev *delta = ctx->dev;
+	struct v4l2_ctrl_handler *hdl = &ctx->ctrl_handler;
+	unsigned int i;
+
+	v4l2_ctrl_handler_init(hdl, delta->nb_of_ctrls);
+
+	for (i = 0; i < delta->nb_of_ctrls; i++) {
+		struct v4l2_ctrl *ctrl;
+		u32 cid = delta->cids[i];
+		struct v4l2_ctrl_config cfg;
+
+		/* override static config to set delta_ctrl_ops */
+		memset(&cfg, 0, sizeof(cfg));
+		cfg.id = cid;
+		cfg.ops = &delta_ctrl_ops;
+
+		ctrl = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
+		if (hdl->error) {
+			int err = hdl->error;
+
+			dev_err(delta->dev, "%s failed to setup control '%s' (id=%d, size=%d, err=%d)\n",
+				ctx->name, cfg.name, cfg.id,
+				cfg.elem_size, err);
+			v4l2_ctrl_handler_free(hdl);
+			return err;
+		}
+
+		/* force unconditional execution of s_ctrl() by
+		 * disabling control value evaluation in case of
+		 * meta control (passed by pointer)
+		 */
+		if (ctrl->is_ptr)
+			ctrl->flags |= V4L2_CTRL_FLAG_EXECUTE_ON_WRITE;
+	}
+
+	v4l2_ctrl_handler_setup(hdl);
+	ctx->fh.ctrl_handler = hdl;
+
+	ctx->nb_of_metas = 0;
+	memset(ctx->metas, 0, sizeof(ctx->metas));
+
+	dev_dbg(delta->dev, "%s controls setup done\n", ctx->name);
+	return 0;
+}
+
 static int delta_open_decoder(struct delta_ctx *ctx, u32 streamformat,
 			      u32 pixelformat, const struct delta_dec **pdec)
 {
@@ -964,6 +1061,12 @@ static void delta_run_work(struct work_struct *work)
 	au->size = vb2_get_plane_payload(&vbuf->vb2_buf, 0);
 	au->dts = vbuf->vb2_buf.timestamp;
 
+	/* set access unit meta data in case of decoder requires it */
+	memcpy(au->metas, ctx->metas, ctx->nb_of_metas * sizeof(au->metas[0]));
+	au->nb_of_metas = ctx->nb_of_metas;
+	/* reset context metas for next decoding */
+	ctx->nb_of_metas = 0;
+
 	/* dump access unit */
 	dump_au(ctx, au);
 
@@ -1364,6 +1467,12 @@ static int delta_vb2_au_start_streaming(struct vb2_queue *q,
 	au->size = vb2_get_plane_payload(&vbuf->vb2_buf, 0);
 	au->dts = vbuf->vb2_buf.timestamp;
 
+	/* set access unit meta data in case of decoder requires it */
+	memcpy(au->metas, ctx->metas, ctx->nb_of_metas * sizeof(au->metas[0]));
+	au->nb_of_metas = ctx->nb_of_metas;
+	/* reset context metas for next decoding */
+	ctx->nb_of_metas = 0;
+
 	delta_push_dts(ctx, au->dts);
 
 	/* dump access unit */
@@ -1659,6 +1768,13 @@ static int delta_open(struct file *file)
 	file->private_data = &ctx->fh;
 	v4l2_fh_add(&ctx->fh);
 
+	ret = delta_ctrls_setup(ctx);
+	if (ret) {
+		dev_err(delta->dev, "%s failed to setup controls (%d)\n",
+			DELTA_PREFIX, ret);
+		goto err_fh_del;
+	}
+
 	INIT_WORK(&ctx->run_work, delta_run_work);
 	mutex_init(&ctx->lock);
 
@@ -1668,7 +1784,7 @@ static int delta_open(struct file *file)
 		ret = PTR_ERR(ctx->fh.m2m_ctx);
 		dev_err(delta->dev, "%s failed to initialize m2m context (%d)\n",
 			DELTA_PREFIX, ret);
-		goto err_fh_del;
+		goto err_ctrls;
 	}
 
 	/*
@@ -1703,6 +1819,8 @@ static int delta_open(struct file *file)
 
 	return 0;
 
+err_ctrls:
+	v4l2_ctrl_handler_free(&ctx->ctrl_handler);
 err_fh_del:
 	v4l2_fh_del(&ctx->fh);
 	v4l2_fh_exit(&ctx->fh);
@@ -1732,6 +1850,8 @@ static int delta_release(struct file *file)
 
 	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
 
+	v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+
 	v4l2_fh_del(&ctx->fh);
 	v4l2_fh_exit(&ctx->fh);
 
@@ -1887,6 +2007,9 @@ static int delta_probe(struct platform_device *pdev)
 	/* register all supported formats */
 	register_formats(delta);
 
+	/* register all supported controls */
+	register_ctrls(delta);
+
 	/* register on V4L2 */
 	ret = v4l2_device_register(dev, &delta->v4l2_dev);
 	if (ret) {
diff --git a/drivers/media/platform/sti/delta/delta.h b/drivers/media/platform/sti/delta/delta.h
index 60c07324..0893948 100644
--- a/drivers/media/platform/sti/delta/delta.h
+++ b/drivers/media/platform/sti/delta/delta.h
@@ -8,6 +8,7 @@
 #define DELTA_H
 
 #include <linux/rpmsg.h>
+#include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-mem2mem.h>
 
@@ -86,6 +87,19 @@ struct delta_streaminfo {
 #define DELTA_STREAMINFO_FLAG_OTHER		0x0004
 
 /*
+ * struct delta_meta - access unit metadata structure.
+ *
+ * @cid:	control identifier for this meta
+ * @p:		pointer to control data
+ */
+struct delta_meta {
+	u32 cid;
+	void *p;
+};
+
+#define DELTA_MAX_METAS 20
+
+/*
  * struct delta_au - access unit structure.
  *
  * @vbuf:	video buffer information for V4L2
@@ -106,6 +120,8 @@ struct delta_au {
 	dma_addr_t paddr;
 	u32 flags;
 	u64 dts;
+	struct delta_meta metas[DELTA_MAX_METAS];
+	unsigned int nb_of_metas;
 };
 
 /*
@@ -229,6 +245,9 @@ struct delta_ipc_param {
  * @name:		name of this decoder
  * @streamformat:	input stream format that this decoder support
  * @pixelformat:	pixel format of decoded frame that this decoder support
+ * @meta_cids:		(optional) meta control identifiers if decoder needs
+ *			additional parsing metadata to be able to decode
+ * @nb_of_metas:	(optional) nb of meta controls
  * @max_width:		(optional) maximum width that can decode this decoder
  *			if not set, maximum width is DELTA_MAX_WIDTH
  * @max_height:		(optional) maximum height that can decode this decoder
@@ -251,6 +270,8 @@ struct delta_dec {
 	const char *name;
 	u32 streamformat;
 	u32 pixelformat;
+	const u32 *meta_cids;
+	unsigned int nb_of_metas;
 	u32 max_width;
 	u32 max_height;
 	bool pm;
@@ -396,11 +417,17 @@ struct delta_dec {
 
 struct delta_dev;
 
+#define DELTA_MAX_CTRLS  (DELTA_MAX_DECODERS * DELTA_MAX_METAS)
+
 /*
  * struct delta_ctx - instance structure.
  *
  * @flags:		validity of fields (streaminfo)
  * @fh:			V4L2 file handle
+ * @ctrl_handler:	controls handler
+ * @metas:		set of parsing metadata required to
+ *			decode the current access unit
+ * @nb_of_metas:	number of metatada
  * @dev:		device context
  * @dec:		selected decoder context for this instance
  * @ipc_ctx:		context of IPC communication with firmware
@@ -433,6 +460,9 @@ struct delta_dec {
 struct delta_ctx {
 	u32 flags;
 	struct v4l2_fh fh;
+	struct v4l2_ctrl_handler ctrl_handler;
+	struct delta_meta metas[DELTA_MAX_METAS];
+	unsigned int nb_of_metas;
 	struct delta_dev *dev;
 	const struct delta_dec *dec;
 	struct delta_ipc_ctx ipc_ctx;
@@ -483,6 +513,8 @@ struct delta_ctx {
  * @nb_of_pixelformats:	number of supported umcompressed video formats
  * @streamformats:	supported compressed video formats
  * @nb_of_streamformats:number of supported compressed video formats
+ * @cids:		set of all control identifiers used by device
+ * @nb_of_ctrls:	overall number of controls used by device
  * @instance_id:	rolling counter identifying an instance (debug purpose)
  * @work_queue:		decoding job work queue
  * @rpmsg_driver:	rpmsg IPC driver
@@ -504,6 +536,8 @@ struct delta_dev {
 	u32 nb_of_pixelformats;
 	u32 streamformats[DELTA_MAX_FORMATS];
 	u32 nb_of_streamformats;
+	u32 cids[DELTA_MAX_CTRLS];
+	u32 nb_of_ctrls;
 	u8 instance_id;
 	struct workqueue_struct *work_queue;
 	struct rpmsg_driver rpmsg_driver;
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v2 3/3] [media] st-delta: add mpeg2 support
  2017-02-08 15:37 [PATCH v2 0/3] Add support for MPEG-2 in DELTA video decoder Hugues Fruchet
  2017-02-08 15:37 ` [PATCH v2 1/3] [media] v4l: add parsed MPEG-2 support Hugues Fruchet
  2017-02-08 15:37 ` [PATCH v2 2/3] [media] st-delta: add parsing metadata controls support Hugues Fruchet
@ 2017-02-08 15:37 ` Hugues Fruchet
  2017-02-08 21:56   ` kbuild test robot
  2 siblings, 1 reply; 5+ messages in thread
From: Hugues Fruchet @ 2017-02-08 15:37 UTC (permalink / raw)
  To: linux-media, Hans Verkuil
  Cc: kernel, Benjamin Gaignard, Hugues Fruchet, Jean-Christophe Trotin

Adds support of DELTA MPEG-2 video decoder back-end,
implemented by calling MPEG2_TRANSFORMER0 firmware
using RPMSG IPC communication layer.
MPEG-2 decoder back-end is a stateless decoder which
require specific parsing metadata in access unit
in order to complete decoding.

Signed-off-by: Hugues Fruchet <hugues.fruchet@st.com>
---
 drivers/media/platform/Kconfig                     |   11 +-
 drivers/media/platform/sti/delta/Makefile          |    3 +
 drivers/media/platform/sti/delta/delta-cfg.h       |    5 +
 drivers/media/platform/sti/delta/delta-mpeg2-dec.c | 1392 ++++++++++++++++++++
 drivers/media/platform/sti/delta/delta-mpeg2-fw.h  |  415 ++++++
 drivers/media/platform/sti/delta/delta-v4l2.c      |    4 +
 6 files changed, 1828 insertions(+), 2 deletions(-)
 create mode 100644 drivers/media/platform/sti/delta/delta-mpeg2-dec.c
 create mode 100644 drivers/media/platform/sti/delta/delta-mpeg2-fw.h

diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index 20b26ea..fb04c50 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -326,15 +326,22 @@ config VIDEO_STI_DELTA_MJPEG
 		To compile this driver as a module, choose M here:
 		the module will be called st-delta.
 
+config VIDEO_STI_DELTA_MPEG2
+	bool "STMicroelectronics DELTA MPEG2/MPEG1 support"
+	default y
+	help
+		Enables DELTA MPEG2 hardware support.
+
 config VIDEO_STI_DELTA_DRIVER
 	tristate
 	depends on VIDEO_STI_DELTA
-	depends on VIDEO_STI_DELTA_MJPEG
-	default VIDEO_STI_DELTA_MJPEG
+	depends on VIDEO_STI_DELTA_MJPEG || VIDEO_STI_DELTA_MPEG2
+	default y
 	select VIDEOBUF2_DMA_CONTIG
 	select V4L2_MEM2MEM_DEV
 	select RPMSG
 
+
 endif # VIDEO_STI_DELTA
 
 config VIDEO_SH_VEU
diff --git a/drivers/media/platform/sti/delta/Makefile b/drivers/media/platform/sti/delta/Makefile
index 8d032508..b18ed37 100644
--- a/drivers/media/platform/sti/delta/Makefile
+++ b/drivers/media/platform/sti/delta/Makefile
@@ -4,3 +4,6 @@ st-delta-y := delta-v4l2.o delta-mem.o delta-ipc.o delta-debug.o
 # MJPEG support
 st-delta-$(CONFIG_VIDEO_STI_DELTA_MJPEG) += delta-mjpeg-hdr.o
 st-delta-$(CONFIG_VIDEO_STI_DELTA_MJPEG) += delta-mjpeg-dec.o
+
+# MPEG2 support
+st-delta-$(CONFIG_VIDEO_STI_DELTA_MPEG2) += delta-mpeg2-dec.o
diff --git a/drivers/media/platform/sti/delta/delta-cfg.h b/drivers/media/platform/sti/delta/delta-cfg.h
index c6388f5..bce2c74 100644
--- a/drivers/media/platform/sti/delta/delta-cfg.h
+++ b/drivers/media/platform/sti/delta/delta-cfg.h
@@ -61,4 +61,9 @@
 extern const struct delta_dec mjpegdec;
 #endif
 
+#ifdef CONFIG_VIDEO_STI_DELTA_MPEG2
+extern const struct delta_dec mpeg2dec;
+extern const struct delta_dec mpeg1dec;
+#endif
+
 #endif /* DELTA_CFG_H */
diff --git a/drivers/media/platform/sti/delta/delta-mpeg2-dec.c b/drivers/media/platform/sti/delta/delta-mpeg2-dec.c
new file mode 100644
index 0000000..6ccfdc9
--- /dev/null
+++ b/drivers/media/platform/sti/delta/delta-mpeg2-dec.c
@@ -0,0 +1,1392 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2015
+ * Authors: Hugues Fruchet <hugues.fruchet@st.com>
+ *          Chetan Nanda <chetan.nanda@st.com>
+ *          Jean-Christophe Trotin <jean-christophe.trotin@st.com>
+ *          for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#include <linux/slab.h>
+
+#include "delta.h"
+#include "delta-ipc.h"
+#include "delta-mem.h"
+#include "delta-mpeg2-fw.h"
+
+#define DELTA_MPEG2_MAX_RESO DELTA_MAX_RESO
+
+/* minimal number of frames for decoding = 1 dec + 2 refs frames */
+#define DELTA_MPEG2_DPB_FRAMES_NEEDED     3
+
+struct delta_mpeg2_ctx {
+	/* ipc */
+	void *ipc_hdl;
+	struct delta_buf *ipc_buf;
+
+	/* stream information */
+	struct delta_streaminfo streaminfo;
+
+	bool header_parsed;
+
+	/* reference frames mgt */
+	struct delta_mpeg2_frame *prev_ref;
+	struct delta_mpeg2_frame *next_ref;
+
+	/* output frames reordering management */
+	struct delta_frame *out_frame;
+	struct delta_frame *delayed_frame;
+
+	/* interlaced frame management */
+	struct delta_frame *last_frame;
+	enum mpeg2_picture_structure_t accumulated_picture_structure;
+
+	unsigned char str[3000];
+};
+
+/* codec specific frame struct */
+struct delta_mpeg2_frame {
+	struct delta_frame frame;
+	struct timeval dts;
+	struct delta_buf omega_buf;	/* 420mb buffer for decoding */
+};
+
+#define to_ctx(ctx) ((struct delta_mpeg2_ctx *)ctx->priv)
+#define to_mpeg2_frame(frame) ((struct delta_mpeg2_frame *)frame)
+#define to_frame(mpeg2_frame) ((struct delta_frame *)mpeg2_frame)
+
+/* default intra, zig-zag order */
+static u8 default_intra_matrix[] = {
+	8,
+	16, 16,
+	19, 16, 19,
+	22, 22, 22, 22,
+	22, 22, 26, 24, 26,
+	27, 27, 27, 26, 26, 26,
+	26, 27, 27, 27, 29, 29, 29,
+	34, 34, 34, 29, 29, 29, 27, 27,
+	29, 29, 32, 32, 34, 34, 37,
+	38, 37, 35, 35, 34, 35,
+	38, 38, 40, 40, 40,
+	48, 48, 46, 46,
+	56, 56, 58,
+	69, 69,
+	83
+};
+
+static u8 default_non_intra_matrix[] = {
+	16, 16, 16, 16, 16, 16, 16, 16,
+	16, 16, 16, 16, 16, 16, 16, 16,
+	16, 16, 16, 16, 16, 16, 16, 16,
+	16, 16, 16, 16, 16, 16, 16, 16,
+	16, 16, 16, 16, 16, 16, 16, 16,
+	16, 16, 16, 16, 16, 16, 16, 16,
+	16, 16, 16, 16, 16, 16, 16, 16,
+	16, 16, 16, 16, 16, 16, 16, 16
+};
+
+/* this table translates zig-zag matrix indexes used in coefficient
+ * transmission to natural order indexes required by firmware
+ */
+static u8 to_natural_order[] = {
+	0,   1,  8, 16,  9,  2,  3, 10,
+	17, 24, 32, 25, 18, 11,  4,  5,
+	12, 19, 26, 33, 40, 48, 41, 34,
+	27, 20, 13,  6,  7, 14, 21, 28,
+	35, 42, 49, 56, 57, 50, 43, 36,
+	29, 22, 15, 23, 30, 37, 44, 51,
+	58, 59, 52, 45, 38, 31, 39, 46,
+	53, 60, 61, 54, 47, 55, 62, 63,
+};
+
+static inline const char *profile_str(u32 p)
+{
+	switch (p) {
+	case 1:
+		return "High profile (HP)";
+	case 2:
+		return "Spatially scalable profile (Spatial)";
+	case 3:
+		return "SNR Scalable profile (SNR)";
+	case 4:
+		return "Main profile (MP)";
+	case 5:
+		return "Simple profile (SP)";
+	default:
+		return "unknown profile";
+	}
+}
+
+static inline const char *level_str(u32 l)
+{
+	switch (l) {
+	case 4:
+		return "High level (HL)";
+	case 6:
+		return "High 1440 level (H-14)";
+	case 8:
+		return "Main level (ML)";
+	case 10:
+		return "Low level (LL)";
+	default:
+		return "unknown level";
+	}
+}
+
+static inline const char *chroma_str(u32 c)
+{
+	switch (c) {
+	case MPEG2_CHROMA_4_2_0:
+		return "4:2:0";
+	case MPEG2_CHROMA_4_2_2:
+		return "4:2:2";
+	case MPEG2_CHROMA_4_4_4:
+		return "4:4:4";
+	default:
+		return "unknown chroma";
+	}
+}
+
+static char *ipc_open_param_str(struct mpeg2_init_transformer_param_t *p,
+				char *str, u32 len)
+{
+	if (!p)
+		return NULL;
+
+	snprintf(str, len,
+		 "mpeg2_init_transformer_param_t size=%zu\n"
+		 "input_buffer_begin\t0x%x\n"
+		 "input_buffer_end\t\t0x%x\n",
+		 sizeof(*p),
+		 p->input_buffer_begin,
+		 p->input_buffer_end);
+
+	return str;
+}
+
+static char *ipc_stream_param_str(struct mpeg2_set_global_param_sequence_t *p,
+				  char *str, u32 len)
+{
+	if (!p)
+		return NULL;
+
+	snprintf(str, len,
+		 "mpeg2_set_global_param_sequence_t size=%zu\n"
+		 "mpeg_stream_type_flag\t%d\n"
+		 "horizontal_size\t\t%d\n"
+		 "vertical_size\t\t%d\n"
+		 "progressive_sequence\t%d\n"
+		 "chroma_format\t\t%d\n"
+		 "matrix_flags\t\t0x%x\n"
+		 "intra_quantiser_matrix\t\t\t%02x %02x %02x %02x %02x %02x %02x %02x\n"
+		 "non_intra_quantiser_matrix\t\t%02x %02x %02x %02x %02x %02x %02x %02x\n"
+		 "chroma_intra_quantiser_matrix\t\t%02x %02x %02x %02x %02x %02x %02x %02x\n"
+		 "chroma_non_intra_quantiser_matrix\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
+		 sizeof(*p),
+		 p->mpeg_stream_type_flag,
+		 p->horizontal_size,
+		 p->vertical_size,
+		 p->progressive_sequence,
+		 p->chroma_format,
+		 p->matrix_flags,
+		 p->intra_quantiser_matrix[0],
+		 p->intra_quantiser_matrix[1],
+		 p->intra_quantiser_matrix[2],
+		 p->intra_quantiser_matrix[3],
+		 p->intra_quantiser_matrix[4],
+		 p->intra_quantiser_matrix[5],
+		 p->intra_quantiser_matrix[6],
+		 p->intra_quantiser_matrix[7],
+		 p->non_intra_quantiser_matrix[0],
+		 p->non_intra_quantiser_matrix[1],
+		 p->non_intra_quantiser_matrix[2],
+		 p->non_intra_quantiser_matrix[3],
+		 p->non_intra_quantiser_matrix[4],
+		 p->non_intra_quantiser_matrix[5],
+		 p->non_intra_quantiser_matrix[6],
+		 p->non_intra_quantiser_matrix[7],
+		 p->chroma_intra_quantiser_matrix[0],
+		 p->chroma_intra_quantiser_matrix[1],
+		 p->chroma_intra_quantiser_matrix[2],
+		 p->chroma_intra_quantiser_matrix[3],
+		 p->chroma_intra_quantiser_matrix[4],
+		 p->chroma_intra_quantiser_matrix[5],
+		 p->chroma_intra_quantiser_matrix[6],
+		 p->chroma_intra_quantiser_matrix[7],
+		 p->chroma_non_intra_quantiser_matrix[0],
+		 p->chroma_non_intra_quantiser_matrix[1],
+		 p->chroma_non_intra_quantiser_matrix[2],
+		 p->chroma_non_intra_quantiser_matrix[3],
+		 p->chroma_non_intra_quantiser_matrix[4],
+		 p->chroma_non_intra_quantiser_matrix[5],
+		 p->chroma_non_intra_quantiser_matrix[6],
+		 p->chroma_non_intra_quantiser_matrix[7]);
+
+	return str;
+}
+
+static char *ipc_decode_param_str(struct mpeg2_transform_param_t *p,
+				  char *str, u32 len)
+{
+	if (!p)
+		return NULL;
+
+	snprintf(str, len,
+		 "mpeg2_transform_param_t size=%zu\n"
+		 "picture_start_addr\t\t0x%x\n"
+		 "picture_stop_addr\t\t0x%x\n"
+		 "main_aux_enable\t\t\t0x%x\n"
+		 "decoding_mode\t\t\t%d\n"
+		 "additional_flags\t\t\t0x%x\n"
+		 "[decoded_buffer]\n"
+		 " decoded_luma_p\t\t\t0x%x\n"
+		 " decoded_chroma_p\t\t0x%x\n"
+		 " decoded_temporal_reference\t%x\n"
+		 " display_luma_p\t\t\t0x%x\n"
+		 " display_chroma_p\t\t0x%x\n"
+		 "[ref_pic_list]\n"
+		 " backward_reference_luma_p\t0x%x\n"
+		 " backward_reference_chroma_p\t0x%x\n"
+		 " backward_temporal_reference\t%d\n"
+		 " forward_reference_luma_p\t0x%x\n"
+		 " forward_reference_chroma_p\t0x%x\n"
+		 " forward_temporal_reference\t%d\n"
+		 "[picture_parameters]\n"
+		 " picture_coding_type\t\t%d\n"
+		 " forward_horizontal_f_code\t%d\n"
+		 " forward_vertical_f_code\t\t%d\n"
+		 " backward_horizontal_f_code\t%d\n"
+		 " backward_vertical_f_code\t%d\n"
+		 " intra_dc_precision\t\t%d\n"
+		 " picture_structure\t\t%d\n"
+		 " mpeg_decoding_flags\t\t0x%x\n",
+		 sizeof(*p),
+		 p->picture_start_addr_compressed_buffer_p,
+		 p->picture_stop_addr_compressed_buffer_p,
+		 p->main_aux_enable,
+		 p->decoding_mode,
+		 p->additional_flags,
+		 p->decoded_buffer_address.decoded_luma_p,
+		 p->decoded_buffer_address.decoded_chroma_p,
+		 p->decoded_buffer_address.decoded_temporal_reference_value,
+		 p->display_buffer_address.display_luma_p,
+		 p->display_buffer_address.display_chroma_p,
+		 p->ref_pic_list_address.backward_reference_luma_p,
+		 p->ref_pic_list_address.backward_reference_chroma_p,
+		 p->ref_pic_list_address.backward_temporal_reference_value,
+		 p->ref_pic_list_address.forward_reference_luma_p,
+		 p->ref_pic_list_address.forward_reference_chroma_p,
+		 p->ref_pic_list_address.forward_temporal_reference_value,
+		 p->picture_parameters.picture_coding_type,
+		 p->picture_parameters.forward_horizontal_f_code,
+		 p->picture_parameters.forward_vertical_f_code,
+		 p->picture_parameters.backward_horizontal_f_code,
+		 p->picture_parameters.backward_vertical_f_code,
+		 p->picture_parameters.intra_dc_precision,
+		 p->picture_parameters.picture_structure,
+		 p->picture_parameters.mpeg_decoding_flags);
+
+	return str;
+}
+
+static inline char *picture_coding_type_str(u32 type)
+{
+	switch (type) {
+	case MPEG2_INTRA_PICTURE:
+		return "I";
+	case MPEG2_DC_INTRA_PICTURE:
+		return "I(DC)";
+	case MPEG2_PREDICTIVE_PICTURE:
+		return "P";
+	case MPEG2_BIDIRECTIONAL_PICTURE:
+		return "B";
+	default:
+		return "unknown picture coding type";
+	}
+}
+
+static inline char *picture_structure_str(enum mpeg2_picture_structure_t s)
+{
+	switch (s) {
+	case MPEG2_RESERVED_TYPE:
+		return "X";
+	case MPEG2_TOP_FIELD_TYPE:
+		return "T";
+	case MPEG2_BOTTOM_FIELD_TYPE:
+		return "B";
+	case MPEG2_FRAME_TYPE:
+		return "F";
+	default:
+		return "unknown picture structure";
+	}
+}
+
+static inline void to_v4l2_frame_type(enum mpeg2_picture_coding_type_t type,
+				      __u32 *flags)
+{
+	switch (type) {
+	case MPEG2_INTRA_PICTURE:
+	case MPEG2_DC_INTRA_PICTURE:
+		*flags |= V4L2_BUF_FLAG_KEYFRAME;
+		break;
+	case MPEG2_PREDICTIVE_PICTURE:
+		*flags |= V4L2_BUF_FLAG_PFRAME;
+		break;
+	case MPEG2_BIDIRECTIONAL_PICTURE:
+		*flags |= V4L2_BUF_FLAG_BFRAME;
+		break;
+	default:
+		*flags |= V4L2_BUF_FLAG_ERROR;
+	}
+}
+
+static inline enum v4l2_field to_v4l2_field_type(bool interlaced,
+						 bool top_field_first)
+{
+	if (interlaced)
+		return (top_field_first ? V4L2_FIELD_INTERLACED_TB :
+					  V4L2_FIELD_INTERLACED_BT);
+	else
+		return V4L2_FIELD_NONE;
+}
+
+static inline const char *err_str(enum mpeg2_decoding_error_t err)
+{
+	switch (err) {
+	case MPEG2_DECODER_NO_ERROR:
+		return "MPEG2_DECODER_NO_ERROR";
+	case MPEG2_DECODER_ERROR_TASK_TIMEOUT:
+		return "MPEG2_DECODER_ERROR_TASK_TIMEOUT";
+	case MPEG2_DECODER_ERROR_MB_OVERFLOW:
+		return "MPEG2_DECODER_ERROR_MB_OVERFLOW";
+	case MPEG2_DECODER_ERROR_NOT_RECOVERED:
+		return "MPEG2_DECODER_ERROR_NOT_RECOVERED";
+	case MPEG2_DECODER_ERROR_RECOVERED:
+		return "MPEG2_DECODER_ERROR_RECOVERED";
+	case MPEG2_DECODER_ERROR_FEATURE_NOT_SUPPORTED:
+		return "MPEG2_DECODER_ERROR_FEATURE_NOT_SUPPORTED";
+	default:
+		return "unknown mpeg2 error";
+	}
+}
+
+static inline bool is_stream_error(enum mpeg2_decoding_error_t err)
+{
+	switch (err) {
+	case MPEG2_DECODER_ERROR_MB_OVERFLOW:
+	case MPEG2_DECODER_ERROR_RECOVERED:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static int compute_corrupted_mbs(struct mpeg2_command_status_t *status)
+{
+	u32 i;
+	u32 j;
+	u32 cnt = 0;
+
+	for (i = 0; i < MPEG2_STATUS_PARTITION; i++)
+		for (j = 0; j < MPEG2_STATUS_PARTITION; j++)
+			cnt += status->status[i][j];
+
+	return cnt;
+}
+
+static bool delta_mpeg2_check_status(struct delta_ctx *pctx,
+				     struct mpeg2_command_status_t *status)
+{
+	struct delta_dev *delta = pctx->dev;
+	bool dump = false;
+
+	if (status->error_code == MPEG2_DECODER_NO_ERROR)
+		return dump;
+
+	if (is_stream_error(status->error_code)) {
+		dev_warn_ratelimited(delta->dev,
+				     "%s  firmware: stream error @ frame %d (%s)\n",
+				     pctx->name, pctx->decoded_frames,
+				     err_str(status->error_code));
+		pctx->stream_errors++;
+
+		if (status->error_code & MPEG2_DECODER_ERROR_RECOVERED) {
+			/* errors, but recovered,
+			 * update corrupted MBs stats
+			 */
+			u32 corrupted = compute_corrupted_mbs(status);
+
+			if (corrupted)
+				dev_warn_ratelimited(delta->dev,
+						     "%s  firmware: %d MBs corrupted @ frame %d\n",
+						     pctx->name,
+						     corrupted,
+						     pctx->decoded_frames);
+		}
+	} else {
+		dev_warn_ratelimited(delta->dev,
+				     "%s  firmware: decode error @ frame %d (%s)\n",
+				     pctx->name, pctx->decoded_frames,
+				     err_str(status->error_code));
+		pctx->decode_errors++;
+		dump = true;
+	}
+
+	dev_dbg(delta->dev,
+		"%s  firmware: mean QP=%d variance QP=%d\n", pctx->name,
+		status->picture_mean_qp, status->picture_variance_qp);
+	dev_dbg(delta->dev,
+		"%s  firmware: decoding time(us)=%d\n", pctx->name,
+		status->decode_time_in_micros);
+
+	return dump;
+}
+
+static int delta_mpeg2_ipc_open(struct delta_ctx *pctx)
+{
+	struct delta_dev *delta = pctx->dev;
+	struct delta_mpeg2_ctx *ctx = to_ctx(pctx);
+	int ret = 0;
+	struct mpeg2_init_transformer_param_t params_struct;
+	struct mpeg2_init_transformer_param_t *params = &params_struct;
+	struct delta_ipc_param ipc_param;
+	struct delta_buf *ipc_buf;
+	__u32 ipc_buf_size;
+	void *hdl;
+
+	memset(params, 0, sizeof(*params));
+	params->input_buffer_begin = 0x00000000;
+	params->input_buffer_end = 0xffffffff;
+
+	dev_vdbg(delta->dev,
+		 "%s  %s\n", pctx->name,
+		 ipc_open_param_str(params, ctx->str, sizeof(ctx->str)));
+
+	ipc_param.size = sizeof(*params);
+	ipc_param.data = params;
+	ipc_buf_size = sizeof(struct mpeg2_transform_param_t) +
+		       sizeof(struct mpeg2_command_status_t);
+	ret = delta_ipc_open(pctx, "MPEG2_TRANSFORMER0", &ipc_param,
+			     ipc_buf_size, &ipc_buf, &hdl);
+	if (ret) {
+		dev_err(delta->dev,
+			"%s  dumping command %s\n", pctx->name,
+			ipc_open_param_str(params, ctx->str, sizeof(ctx->str)));
+		return ret;
+	}
+
+	ctx->ipc_buf = ipc_buf;
+	ctx->ipc_hdl = hdl;
+
+	return 0;
+}
+
+static int delta_mpeg2_ipc_set_stream
+		(struct delta_ctx *pctx,
+		 struct v4l2_mpeg_video_mpeg2_seq_hdr *seq_hdr,
+		 struct v4l2_mpeg_video_mpeg2_seq_ext *seq_ext_hdr,
+		 struct v4l2_mpeg_video_mpeg2_seq_display_ext *seq_disp_ext,
+		 struct v4l2_mpeg_video_mpeg2_seq_matrix_ext *seq_matrix_ext)
+{
+	struct delta_dev *delta = pctx->dev;
+	struct delta_mpeg2_ctx *ctx = to_ctx(pctx);
+	const struct delta_dec *dec = pctx->dec;
+	int ret;
+	u32 i;
+	struct mpeg2_set_global_param_sequence_t *params = ctx->ipc_buf->vaddr;
+	struct delta_ipc_param ipc_param;
+	u8 *intra_quantiser_matrix;
+	u8 *non_intra_quantiser_matrix;
+	u8 *chroma_intra_quantiser_matrix;
+	u8 *chroma_non_intra_quantiser_matrix;
+
+	if (!seq_hdr) {
+		dev_err(delta->dev, "%s  failed to set stream on ipc, no header in meta sequence\n",
+			pctx->name);
+		return -EINVAL;
+	}
+
+	memset(params, 0, sizeof(*params));
+	params->struct_size = sizeof(*params);
+
+	/* Sequence header */
+	params->mpeg_stream_type_flag =
+		(dec->streamformat == V4L2_PIX_FMT_MPEG2_PARSED) ? 1 : 0;
+
+	params->horizontal_size = seq_hdr->width;
+	params->vertical_size = seq_hdr->height;
+	params->progressive_sequence = true;
+	params->chroma_format = MPEG2_CHROMA_4_2_0;
+
+	params->matrix_flags =
+		(seq_hdr->load_intra_quantiser_matrix ?
+		 MPEG2_LOAD_INTRA_QUANTISER_MATRIX_FLAG : 0) |
+		(seq_hdr->load_non_intra_quantiser_matrix ?
+		 MPEG2_LOAD_NON_INTRA_QUANTISER_MATRIX_FLAG : 0);
+
+	/* Sequence header, matrix part */
+	intra_quantiser_matrix =
+		seq_hdr->load_intra_quantiser_matrix ?
+			seq_hdr->intra_quantiser_matrix :
+			default_intra_matrix;
+	chroma_intra_quantiser_matrix = intra_quantiser_matrix;
+
+	non_intra_quantiser_matrix =
+		seq_hdr->load_non_intra_quantiser_matrix ?
+			seq_hdr->non_intra_quantiser_matrix :
+			default_non_intra_matrix;
+	chroma_non_intra_quantiser_matrix = non_intra_quantiser_matrix;
+
+	/* Sequence header extension */
+	if (seq_ext_hdr) {
+		params->horizontal_size |=
+		    (seq_ext_hdr->horiz_size_ext << 12);
+		params->vertical_size |= (seq_ext_hdr->vert_size_ext << 12);
+		params->progressive_sequence = seq_ext_hdr->progressive;
+		params->chroma_format = (enum mpeg2_chroma_format_t)
+						seq_ext_hdr->chroma_format;
+	}
+
+	/* Matrix extension */
+	if (seq_matrix_ext) {
+		params->matrix_flags =
+			(seq_matrix_ext->load_intra_quantiser_matrix ?
+			 MPEG2_LOAD_INTRA_QUANTISER_MATRIX_FLAG : 0) |
+			(seq_matrix_ext->load_non_intra_quantiser_matrix ?
+			 MPEG2_LOAD_NON_INTRA_QUANTISER_MATRIX_FLAG : 0);
+
+		intra_quantiser_matrix =
+			seq_matrix_ext->load_intra_quantiser_matrix ?
+			seq_matrix_ext->intra_quantiser_matrix :
+			default_intra_matrix;
+		chroma_intra_quantiser_matrix =
+			seq_matrix_ext->load_chroma_intra_quantiser_matrix ?
+			seq_matrix_ext->chroma_intra_quantiser_matrix :
+			default_intra_matrix;
+
+		non_intra_quantiser_matrix =
+			seq_matrix_ext->load_non_intra_quantiser_matrix ?
+			seq_matrix_ext->non_intra_quantiser_matrix :
+			default_non_intra_matrix;
+		chroma_non_intra_quantiser_matrix =
+			seq_matrix_ext->load_chroma_non_intra_quantiser_matrix ?
+			seq_matrix_ext->chroma_non_intra_quantiser_matrix :
+			default_non_intra_matrix;
+	}
+
+	/* firwmare requires matrix in natural order, not zig-zag order */
+	for (i = 0; i < MPEG2_QUANTISER_MATRIX_SIZE; i++) {
+		params->intra_quantiser_matrix[to_natural_order[i]] =
+			intra_quantiser_matrix[i];
+		params->non_intra_quantiser_matrix[to_natural_order[i]] =
+			non_intra_quantiser_matrix[i];
+		params->chroma_intra_quantiser_matrix[to_natural_order[i]] =
+			chroma_intra_quantiser_matrix[i];
+		params->chroma_non_intra_quantiser_matrix[to_natural_order[i]] =
+			chroma_non_intra_quantiser_matrix[i];
+	}
+
+	dev_vdbg(delta->dev,
+		 "%s  %s\n", pctx->name,
+		 ipc_stream_param_str(params, ctx->str, sizeof(ctx->str)));
+
+	ipc_param.size = sizeof(*params);
+	ipc_param.data = params;
+	ret = delta_ipc_set_stream(ctx->ipc_hdl, &ipc_param);
+	if (ret) {
+		dev_err(delta->dev,
+			"%s  dumping command %s\n", pctx->name,
+			ipc_stream_param_str(params, ctx->str,
+					     sizeof(ctx->str)));
+		return ret;
+	}
+
+	return 0;
+}
+
+static int delta_mpeg2_ipc_decode
+			(struct delta_ctx *pctx, struct delta_au *pau,
+			 struct v4l2_mpeg_video_mpeg2_pic_hdr *pic_hdrs[],
+			 struct v4l2_mpeg_video_mpeg2_pic_ext *pic_exts[])
+{
+	struct delta_dev *delta = pctx->dev;
+	struct delta_mpeg2_ctx *ctx = to_ctx(pctx);
+	struct delta_au au = *pau;
+	struct v4l2_mpeg_video_mpeg2_pic_hdr *pic_hdr = pic_hdrs[0];
+	struct v4l2_mpeg_video_mpeg2_pic_ext *pic_ext = pic_exts[0];
+	int ret = 0;
+	struct delta_mpeg2_frame *mpeg2_frame = NULL;
+	struct delta_frame *frame = NULL;
+	struct delta_mpeg2_frame *next_ref = ctx->next_ref;
+	struct delta_mpeg2_frame *prev_ref = ctx->prev_ref;
+	struct mpeg2_transform_param_t *params = ctx->ipc_buf->vaddr;
+	struct mpeg2_command_status_t *status = ctx->ipc_buf->vaddr +
+						sizeof(*params);
+	struct mpeg2_decoded_buffer_address_t *params_dec;
+	struct mpeg2_param_picture_t *params_pic;
+	struct mpeg2_display_buffer_address_t *params_disp;
+	struct mpeg2_ref_pic_list_address_t *params_ref;
+	struct delta_ipc_param ipc_param, ipc_status;
+	enum mpeg2_picture_structure_t picture_structure = MPEG2_FRAME_TYPE;
+	bool interlaced = false;
+	bool top_field_first = true;
+
+	ctx->out_frame = NULL;
+
+next_field:
+
+	if (!pic_hdr) {
+		dev_err(delta->dev, "%s  failed to decode, no picture header\n",
+			pctx->name);
+		return -EINVAL;
+	}
+
+	if ((au.size <= 0) || (au.size < pic_hdr->offset)) {
+		dev_err(delta->dev, "%s  invalid access unit size (%d) or offset (%d)\n",
+			pctx->name, au.size, pic_hdr->offset);
+		return -EINVAL;
+	}
+
+	dev_dbg(delta->dev, "%s  processing au[%p/%pad, %d], offset=%d\n",
+		pctx->name, au.vaddr, &au.paddr, au.size, pic_hdr->offset);
+
+	au.vaddr = pau->vaddr + pic_hdr->offset;
+	au.paddr = pau->paddr + pic_hdr->offset;
+	au.size = pau->size - pic_hdr->offset;
+
+	/* progressive/interlaced frame,
+	 * if interlaced, picture can be either a frame,
+	 * a top field or a bottom field
+	 */
+	if (pic_ext &&
+	    (pic_ext->picture_structure != MPEG2_RESERVED_TYPE))
+		picture_structure = pic_ext->picture_structure;
+	else
+		picture_structure = MPEG2_FRAME_TYPE;
+	/* store frame, top+bottom or bottom+top fields sequence */
+	ctx->accumulated_picture_structure |= picture_structure;
+
+	if (pic_ext) {
+		interlaced = !pic_ext->progressive_frame;
+		top_field_first = pic_ext->top_field_first;
+	}
+
+	/* recalculate top_field_first as it is always set to false
+	 * in case of field picture decoding...
+	 */
+	if (picture_structure != MPEG2_FRAME_TYPE)
+		top_field_first =
+			((!ctx->last_frame) ==
+			 (picture_structure == MPEG2_TOP_FIELD_TYPE));
+
+	if (!ctx->last_frame) {
+		/* Progressive frame to be decoded or
+		 * first field of an interlaced frame to be decoded
+		 */
+		ret = delta_get_free_frame(pctx, &frame);
+		if (ret)
+			return ret;
+
+		if ((frame->info.aligned_width < ctx->streaminfo.width) ||
+		    (frame->info.aligned_height < ctx->streaminfo.height)) {
+			dev_err(delta->dev, "%s  failed to decode, frame is too small (%dx%d while at least %dx%d expected)\n",
+				pctx->name,
+				frame->info.aligned_width,
+				frame->info.aligned_height,
+				ctx->streaminfo.width,
+				ctx->streaminfo.height);
+			return -EINVAL;
+		}
+
+		mpeg2_frame = to_mpeg2_frame(frame);
+	} else {
+		/* 2 fields decoding are needed to get 1 frame
+		 * and the first field has already been decoded
+		 */
+		frame = ctx->last_frame;
+		mpeg2_frame = to_mpeg2_frame(frame);
+	}
+
+	memset(params, 0, sizeof(*params));
+	params->struct_size = sizeof(*params);
+
+	params->picture_start_addr_compressed_buffer_p =
+		(u32)(au.paddr);
+	params->picture_stop_addr_compressed_buffer_p =
+		(u32)(au.paddr + au.size - 1);
+
+	params->main_aux_enable = MPEG2_REF_MAIN_DISP_MAIN_AUX_EN;
+	params->horizontal_decimation_factor = MPEG2_HDEC_1;
+	params->vertical_decimation_factor = MPEG2_VDEC_1;
+
+	params->decoding_mode = MPEG2_NORMAL_DECODE;
+	params->additional_flags = MPEG2_ADDITIONAL_FLAG_NONE;
+
+	params_dec = &params->decoded_buffer_address;
+	params_dec->struct_size = sizeof(*params_dec);
+	params_dec->decoded_luma_p =
+		(u32)mpeg2_frame->omega_buf.paddr;
+	params_dec->decoded_chroma_p =
+		(u32)(mpeg2_frame->omega_buf.paddr +
+				  (to_frame(mpeg2_frame))->info.aligned_width *
+				  (to_frame(mpeg2_frame))->info.aligned_height);
+
+	params_dec->decoded_temporal_reference_value = pic_hdr->tsn;
+
+	params_disp = &params->display_buffer_address;
+	params_disp->struct_size = sizeof(*params_disp);
+	params_disp->display_luma_p = (u32)frame->paddr;
+	params_disp->display_chroma_p =
+		(u32)(frame->paddr +
+				  frame->info.aligned_width *
+				  frame->info.aligned_height);
+	params_pic = &params->picture_parameters;
+	params_pic->struct_size = sizeof(*params_pic);
+	params_pic->picture_coding_type =
+		(enum mpeg2_picture_coding_type_t)pic_hdr->pic_type;
+
+	/* if not enough ref frames, skip... */
+	if ((params_pic->picture_coding_type == MPEG2_BIDIRECTIONAL_PICTURE) &&
+	    (!(prev_ref && next_ref))) {
+		dev_dbg(delta->dev,
+			"%s  B frame missing references (prev=%p, next=%p) @ frame %d\n",
+			pctx->name,
+			prev_ref, next_ref, pctx->decoded_frames);
+		pctx->dropped_frames++;
+		return 0;
+	}
+
+	if (pic_ext) {
+		params_pic->forward_horizontal_f_code =
+			pic_ext->f_code[0][0];
+		params_pic->forward_vertical_f_code =
+			pic_ext->f_code[0][1];
+		params_pic->backward_horizontal_f_code =
+			pic_ext->f_code[1][0];
+		params_pic->backward_vertical_f_code =
+			pic_ext->f_code[1][1];
+		params_pic->intra_dc_precision =
+			(enum mpeg2_intra_dc_precision_t)
+				pic_ext->intra_dc_precision;
+		params_pic->picture_structure =
+			(enum mpeg2_picture_structure_t)picture_structure;
+		params_pic->mpeg_decoding_flags =
+			(pic_ext->top_field_first << 0) |
+			(pic_ext->frame_pred_frame_dct << 1) |
+			(pic_ext->concealment_motion_vectors << 2) |
+			(pic_ext->q_scale_type << 3) |
+			(pic_ext->intra_vlc_format << 4) |
+			(pic_ext->alternate_scan << 5) |
+			(pic_ext->progressive_frame << 6);
+
+		if (picture_structure == MPEG2_TOP_FIELD_TYPE)
+			params->additional_flags = top_field_first ?
+				MPEG2_ADDITIONAL_FLAG_FIRST_FIELD :
+				MPEG2_ADDITIONAL_FLAG_SECOND_FIELD;
+		else if (picture_structure == MPEG2_BOTTOM_FIELD_TYPE)
+			params->additional_flags = top_field_first ?
+				MPEG2_ADDITIONAL_FLAG_SECOND_FIELD :
+				MPEG2_ADDITIONAL_FLAG_FIRST_FIELD;
+	} else {
+		params_pic->forward_horizontal_f_code =
+			pic_hdr->f_code[0][0];
+		params_pic->forward_vertical_f_code =
+			pic_hdr->f_code[0][1];
+		params_pic->backward_horizontal_f_code =
+			pic_hdr->f_code[1][0];
+		params_pic->backward_vertical_f_code =
+			pic_hdr->f_code[1][1];
+		params_pic->intra_dc_precision =
+			MPEG2_INTRA_DC_PRECISION_8_BITS;
+		params_pic->picture_structure = MPEG2_FRAME_TYPE;
+		params_pic->mpeg_decoding_flags =
+			MPEG_DECODING_FLAGS_TOP_FIELD_FIRST |
+			MPEG_DECODING_FLAGS_PROGRESSIVE_FRAME;
+	}
+
+	params_ref = &params->ref_pic_list_address;
+	params_ref->struct_size = sizeof(*params_ref);
+	/*
+	 * MPEG2 transformer always takes past reference in Forward field (P
+	 * or B frames) and future reference in Backward field (B frames).
+	 */
+	if (params_pic->picture_coding_type == MPEG2_PREDICTIVE_PICTURE) {
+		/*
+		 * a P frame AU needs the most recently decoded reference as
+		 * past ref: this is the one pointed by next_ref
+		 */
+		if (next_ref) {
+			params_ref->forward_reference_luma_p =
+				(u32)next_ref->omega_buf.paddr;
+			params_ref->forward_reference_chroma_p =
+				(u32)(next_ref->omega_buf.paddr +
+				  (to_frame(next_ref))->info.aligned_width *
+				  (to_frame(next_ref))->info.aligned_height);
+			params_ref->forward_temporal_reference_value =
+				pic_hdr->tsn - 1;
+		}
+	}
+
+	if (params_pic->picture_coding_type == MPEG2_BIDIRECTIONAL_PICTURE) {
+		/*
+		 * Most recently decoded ref frame (in next_ref) was
+		 * intended as a future reference frame for the current batch
+		 * of B frames. The related past reference frame is the
+		 * one even before that, in prev_next_frame
+		 */
+		if (prev_ref) {
+			params_ref->forward_reference_luma_p =
+				(u32)prev_ref->omega_buf.paddr;
+			params_ref->forward_reference_chroma_p =
+				(u32)(prev_ref->omega_buf.paddr +
+				  (to_frame(prev_ref))->info.aligned_width *
+				  (to_frame(prev_ref))->info.aligned_height);
+			params_ref->forward_temporal_reference_value =
+				pic_hdr->tsn - 1;
+		}
+		if (next_ref) {
+			params_ref->backward_reference_luma_p =
+				(u32)next_ref->omega_buf.paddr;
+			params_ref->backward_reference_chroma_p =
+				(u32)(next_ref->omega_buf.paddr +
+				  (to_frame(next_ref))->info.aligned_width *
+				  (to_frame(next_ref))->info.aligned_height);
+			params_ref->backward_temporal_reference_value =
+				pic_hdr->tsn + 1;
+		}
+	}
+
+	dev_vdbg(delta->dev,
+		 "%s  %s\n", pctx->name,
+		 ipc_decode_param_str(params, ctx->str, sizeof(ctx->str)));
+
+	/* status */
+	memset(status, 0, sizeof(*status));
+	status->struct_size = sizeof(*status);
+	status->error_code = MPEG2_DECODER_NO_ERROR;
+
+	ipc_param.size = sizeof(*params);
+	ipc_param.data = params;
+	ipc_status.size = sizeof(*status);
+	ipc_status.data = status;
+	ret = delta_ipc_decode(ctx->ipc_hdl, &ipc_param, &ipc_status);
+	if (ret) {
+		dev_err(delta->dev,
+			"%s  dumping command %s\n", pctx->name,
+			ipc_decode_param_str(params, ctx->str,
+					     sizeof(ctx->str)));
+		pctx->sys_errors++;
+		return ret;
+	}
+
+	pctx->decoded_frames++;
+
+	/* check firmware decoding status */
+	if (delta_mpeg2_check_status(pctx, status)) {
+		dev_err(delta->dev,
+			"%s  dumping command %s\n", pctx->name,
+			ipc_decode_param_str(params, ctx->str,
+					     sizeof(ctx->str)));
+	}
+
+	mpeg2_frame->dts.tv_usec = pic_hdr->tsn;
+	frame->state |= DELTA_FRAME_DEC;
+	frame->flags = 0;
+	to_v4l2_frame_type(params_pic->picture_coding_type,
+			   &frame->flags);
+	frame->field = to_v4l2_field_type(interlaced, top_field_first);
+
+	dev_dbg(delta->dev, "%s  dec frame[%d] tref=%03lu type=%s pic=%s cnt=%03d %s\n",
+		pctx->name,
+		(to_frame(mpeg2_frame))->index,
+		mpeg2_frame->dts.tv_usec,
+		picture_coding_type_str(params_pic->picture_coding_type),
+		picture_structure_str(picture_structure),
+		pctx->decoded_frames,
+		frame_state_str(frame->state, ctx->str, sizeof(ctx->str)));
+
+	/* check if the frame has been entirely decoded (progressive frame
+	 * decoded or all fields of an interlaced frame decoded
+	 */
+	if (ctx->accumulated_picture_structure == MPEG2_FRAME_TYPE) {
+		/* Update reference frames & output ordering */
+		switch (params_pic->picture_coding_type) {
+		case MPEG2_INTRA_PICTURE:
+			if ((!ctx->prev_ref) && (!ctx->next_ref)) {
+				/* first I in sequence */
+
+				/* this is a reference frame */
+				ctx->next_ref = mpeg2_frame;
+				(to_frame(ctx->next_ref))->state |=
+					DELTA_FRAME_REF;
+
+				/* immediate output */
+				ctx->out_frame = frame;
+				/* skip Predictive case code */
+				break;
+			}
+			/* If not first frame, do the same for I and P */
+		case MPEG2_PREDICTIVE_PICTURE:
+
+			/* I or P within sequence */
+
+			/* 2 references frames (prev/next) on a sliding window,
+			 * if more, release the oldest frame
+			 * Most recently decoded reference is always in
+			 * next_ref
+			 */
+			if (ctx->prev_ref)
+				(to_frame(ctx->prev_ref))->state &=
+					~DELTA_FRAME_REF;
+			ctx->prev_ref = ctx->next_ref;
+			ctx->next_ref = mpeg2_frame;
+			(to_frame(ctx->next_ref))->state |=
+			    DELTA_FRAME_REF;
+
+			/* delay output on next I/P */
+			ctx->out_frame = ctx->delayed_frame;
+			ctx->delayed_frame = frame;
+			break;
+
+		case MPEG2_BIDIRECTIONAL_PICTURE:
+			/* B frame not used for reference, immediate output */
+			ctx->out_frame = frame;
+			break;
+		default:
+			dev_err(delta->dev, "%s  unknown coding type\n",
+				pctx->name);
+			break;
+		}
+
+		ctx->accumulated_picture_structure = 0;
+		if (ctx->last_frame)
+			ctx->last_frame = NULL;
+	} else {
+		/* switch to next field decoding */
+		pic_hdr = pic_hdrs[1];
+		pic_ext = pic_exts[1];
+		ctx->last_frame = frame;
+		goto next_field;
+	}
+
+	return 0;
+}
+
+static int delta_mpeg2_open(struct delta_ctx *pctx)
+{
+	struct delta_dev *delta = pctx->dev;
+	struct delta_mpeg2_ctx *ctx;
+
+	if (sizeof(struct delta_mpeg2_frame) > (sizeof(struct delta_frame) +
+						DELTA_MAX_FRAME_PRIV_SIZE)) {
+		dev_err(delta->dev,
+			"%s  not enough memory for codec specific data\n",
+			pctx->name);
+		return -ENOMEM;
+	}
+
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	pctx->priv = ctx;
+
+	return 0;
+}
+
+static int delta_mpeg2_close(struct delta_ctx *pctx)
+{
+	struct delta_mpeg2_ctx *ctx = to_ctx(pctx);
+	int i = 0;
+
+	if (ctx->ipc_hdl) {
+		delta_ipc_close(ctx->ipc_hdl);
+		ctx->ipc_hdl = NULL;
+	}
+
+	for (i = 0; i < pctx->nb_of_frames; i++) {
+		struct delta_mpeg2_frame *mpeg2_frame =
+		    to_mpeg2_frame(pctx->frames[i]);
+		if (mpeg2_frame && mpeg2_frame->omega_buf.paddr) {
+			hw_free(pctx, &mpeg2_frame->omega_buf);
+			mpeg2_frame->omega_buf.paddr = 0;
+		}
+	}
+
+	kfree(ctx);
+
+	return 0;
+}
+
+static int delta_mpeg2_setup_frame(struct delta_ctx *pctx,
+				   struct delta_frame *frame)
+{
+	struct delta_dev *delta = pctx->dev;
+	struct delta_mpeg2_frame *mpeg2_frame = to_mpeg2_frame(frame);
+	int size = 0;
+	int ret = 0;
+
+	/* allocate 420mb buffer */
+	size = (frame->info.aligned_width *
+		frame->info.aligned_height * 3) / 2;
+
+	if (mpeg2_frame->omega_buf.paddr) {
+		dev_err(delta->dev,
+			"%s  omega_buf for frame[%d] already allocated !\n",
+			pctx->name, frame->index);
+		return -EINVAL;
+	}
+	ret = hw_alloc(pctx, size, "420mb omega buffer",
+		       &mpeg2_frame->omega_buf);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int delta_mpeg2_get_streaminfo(struct delta_ctx *pctx,
+				      struct delta_streaminfo *streaminfo)
+{
+	struct delta_mpeg2_ctx *ctx = to_ctx(pctx);
+
+	if (!ctx->header_parsed)
+		return -ENODATA;
+
+	*streaminfo = ctx->streaminfo;
+
+	return 0;
+}
+
+static int delta_mpeg2_set_streaminfo
+		(struct delta_ctx *pctx,
+		 struct v4l2_mpeg_video_mpeg2_seq_hdr *seq_hdr,
+		 struct v4l2_mpeg_video_mpeg2_seq_ext *seq_ext_hdr,
+		 struct v4l2_mpeg_video_mpeg2_seq_display_ext *seq_disp_ext)
+{
+	struct delta_dev *delta = pctx->dev;
+	struct delta_mpeg2_ctx *ctx = to_ctx(pctx);
+	const struct delta_dec *dec = pctx->dec;
+	__u32 width, height;
+	struct v4l2_rect crop;
+	__u32 streamformat;
+	__u32 flags = 0;
+	const char *profile = NULL;
+	const char *level = NULL;
+	const char *chroma = NULL;
+	const char *extension = NULL;
+	enum v4l2_field field = V4L2_FIELD_NONE;
+
+	/* stream format */
+	streamformat = dec->streamformat;
+
+	/* width/height */
+	width = seq_hdr->width;
+	height = seq_hdr->height;
+	if (seq_ext_hdr) {
+		width |= seq_ext_hdr->horiz_size_ext << 12;
+		height |= seq_ext_hdr->vert_size_ext << 12;
+	}
+	if ((width * height) > DELTA_MPEG2_MAX_RESO) {
+		dev_err(delta->dev,
+			"%s  stream resolution too large: %dx%d > %d pixels budget\n",
+			pctx->name, width, height, DELTA_MPEG2_MAX_RESO);
+		return -EINVAL;
+	}
+
+	/* crop */
+	crop.top = 0;
+	crop.left = 0;
+	crop.width = 0;
+	crop.height = 0;
+	if (seq_disp_ext &&
+	    (seq_disp_ext->display_horizontal_size != 0) &&
+	    (seq_disp_ext->display_vertical_size != 0)) {
+		/*  As per MPEG2 standard (section 6.3.6)
+		 *
+		 * display_horizontal_size and display_vertical_size together
+		 * define a rectangle which may be considered as the
+		 * "intended display's" active region.
+		 * If this rectangle is smaller than the encoded frame size,
+		 * then the display process may be expected to display only a
+		 * portion of the encoded frame (Crop).
+		 * Conversely if the display rectangle is larger than the
+		 * encoded frame size, then the display process may be expected
+		 * to display the reconstructed frames on a portion of the
+		 * display device rather than on the whole display device.
+		 *
+		 * Thus as per above, crop info valid only if display rectangle
+		 * is smaller than encoded frame size.
+		 */
+		if ((seq_disp_ext->display_horizontal_size < width) ||
+		    (seq_disp_ext->display_vertical_size < height)) {
+			flags |= DELTA_STREAMINFO_FLAG_CROP;
+			crop.width =
+				seq_disp_ext->display_horizontal_size;
+			crop.height =
+				seq_disp_ext->display_vertical_size;
+		}
+	}
+	/* seq_ext_hdr->progressive_sequence set to 1 indicates a
+	 * progressive stream
+	 * Rec. ITU-T H.262 (1995 E): "progressive_sequence -- When set to '1'
+	 * the coded video sequence contains only progressive frame-pictures"
+	 */
+	if (seq_ext_hdr)
+		field = (seq_ext_hdr->progressive) ?
+			V4L2_FIELD_NONE : V4L2_FIELD_INTERLACED;
+
+	/* profile & level */
+	if (seq_ext_hdr) {
+		profile = profile_str(seq_ext_hdr->profile);
+		level = level_str(seq_ext_hdr->level);
+	}
+	/* other... */
+	flags |= DELTA_STREAMINFO_FLAG_OTHER;
+	chroma = chroma_str(MPEG2_CHROMA_4_2_0);
+	if (seq_ext_hdr)
+		chroma = chroma_str((enum mpeg2_chroma_format_t)
+				    seq_ext_hdr->chroma_format);
+	if (seq_ext_hdr && seq_disp_ext)
+		extension = " ext:seq+disp";
+	else if (seq_disp_ext)
+		extension = " ext:disp";
+	else if (seq_ext_hdr)
+		extension = " ext:seq";
+	else
+		extension = "";
+
+	/* update streaminfo */
+	memset(&ctx->streaminfo, 0, sizeof(ctx->streaminfo));
+	ctx->streaminfo.flags = flags;
+	ctx->streaminfo.streamformat = streamformat;
+	ctx->streaminfo.width = width;
+	ctx->streaminfo.height = height;
+	ctx->streaminfo.crop = crop;
+	ctx->streaminfo.field = field;
+
+	ctx->streaminfo.dpb = DELTA_MPEG2_DPB_FRAMES_NEEDED;
+
+	snprintf(ctx->streaminfo.profile,
+		 sizeof(ctx->streaminfo.profile), "%s", profile);
+	snprintf(ctx->streaminfo.level,
+		 sizeof(ctx->streaminfo.level), "%s", level);
+
+	snprintf(ctx->streaminfo.other,
+		 sizeof(ctx->streaminfo.other), "%s%s", chroma, extension);
+
+	ctx->header_parsed = true;
+
+	return 0;
+}
+
+static int delta_mpeg2_decode(struct delta_ctx *pctx, struct delta_au *au)
+{
+	struct delta_dev *delta = pctx->dev;
+	struct delta_mpeg2_ctx *ctx = to_ctx(pctx);
+	int ret;
+	struct v4l2_mpeg_video_mpeg2_seq_hdr *seq_hdr = NULL;
+	struct v4l2_mpeg_video_mpeg2_seq_ext *seq_ext = NULL;
+	struct v4l2_mpeg_video_mpeg2_seq_display_ext *seq_disp_ext = NULL;
+	struct v4l2_mpeg_video_mpeg2_seq_matrix_ext *seq_matrix_ext = NULL;
+	struct v4l2_mpeg_video_mpeg2_pic_hdr *pic_hdrs[2] = {NULL, NULL};
+	struct v4l2_mpeg_video_mpeg2_pic_ext *pic_exts[2] = {NULL, NULL};
+	unsigned int i;
+
+	if (!au->nb_of_metas) {
+		dev_err(delta->dev, "%s  failed to decode, no metadata provided\n",
+			pctx->name);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < au->nb_of_metas; i++) {
+		switch (au->metas[i].cid) {
+		case V4L2_CID_MPEG_VIDEO_MPEG2_SEQ_HDR:
+			seq_hdr = au->metas[i].p;
+			break;
+		case V4L2_CID_MPEG_VIDEO_MPEG2_SEQ_EXT:
+			seq_ext = au->metas[i].p;
+			break;
+		case V4L2_CTRL_TYPE_MPEG2_SEQ_DISPLAY_EXT:
+			seq_disp_ext = au->metas[i].p;
+			break;
+		case V4L2_CID_MPEG_VIDEO_MPEG2_SEQ_MATRIX_EXT:
+			seq_matrix_ext = au->metas[i].p;
+			break;
+		case V4L2_CID_MPEG_VIDEO_MPEG2_PIC_HDR:
+			if (!pic_hdrs[0])
+				pic_hdrs[0] = au->metas[i].p;
+			else
+				/* 2nd field of interlaced stream */
+				pic_hdrs[1] = au->metas[i].p;
+			break;
+		case V4L2_CID_MPEG_VIDEO_MPEG2_PIC_EXT:
+			if (!pic_exts[0])
+				pic_exts[0] = au->metas[i].p;
+			else
+				/* 2nd field of interlaced stream */
+				pic_exts[1] = au->metas[i].p;
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (!ctx->ipc_hdl) {
+		ret = delta_mpeg2_ipc_open(pctx);
+		if (ret)
+			return ret;
+	}
+
+	if (seq_hdr) {
+		/* refresh streaminfo with new sequence header */
+		ret = delta_mpeg2_set_streaminfo(pctx, seq_hdr,
+						 seq_ext, seq_disp_ext);
+		if (ret)
+			return ret;
+
+		/* send new sequence header to firmware */
+		ret = delta_mpeg2_ipc_set_stream(pctx, seq_hdr, seq_ext,
+						 seq_disp_ext, seq_matrix_ext);
+		if (ret)
+			return ret;
+	}
+
+	if (pic_hdrs[0]) {
+		/* send new access unit to decode with its picture header */
+		ret = delta_mpeg2_ipc_decode(pctx, au, pic_hdrs, pic_exts);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int delta_mpeg2_get_frame(struct delta_ctx *pctx,
+				 struct delta_frame **pframe)
+{
+	struct delta_dev *delta = pctx->dev;
+	struct delta_mpeg2_ctx *ctx = to_ctx(pctx);
+	struct delta_frame *frame = NULL;
+
+	if (!ctx->out_frame)
+		return -ENODATA;
+
+	frame = ctx->out_frame;
+
+	*pframe = frame;
+
+	dev_dbg(delta->dev,
+		"%s  out frame[%d] tref=%03lu type=%s field=%s cnt=%03d %s\n",
+		pctx->name,
+		frame->index,
+		to_mpeg2_frame(frame)->dts.tv_usec,
+		frame_type_str(frame->flags),
+		frame_field_str(frame->field),
+		pctx->output_frames + 1,
+		frame_state_str(frame->state, ctx->str, sizeof(ctx->str)));
+
+	ctx->out_frame = NULL;
+
+	return 0;
+}
+
+static int delta_mpeg2_recycle(struct delta_ctx *pctx,
+				struct delta_frame *frame)
+{
+	struct delta_dev *delta = pctx->dev;
+	struct delta_mpeg2_ctx *ctx = to_ctx(pctx);
+	struct delta_mpeg2_frame *mpeg2_frame = to_mpeg2_frame(frame);
+
+	dev_dbg(delta->dev,
+		"%s  rec frame[%d] tref=%03lu %s\n",
+		pctx->name,
+		frame->index,
+		mpeg2_frame->dts.tv_usec,
+		frame_state_str(frame->state, ctx->str, sizeof(ctx->str)));
+
+	frame->state &= ~DELTA_FRAME_DEC;
+
+	return 0;
+}
+
+static int delta_mpeg2_flush(struct delta_ctx *pctx)
+{
+	struct delta_mpeg2_ctx *ctx = to_ctx(pctx);
+
+	ctx->prev_ref = NULL;
+	ctx->next_ref = NULL;
+	ctx->out_frame = NULL;
+	ctx->delayed_frame = NULL;
+
+	return 0;
+}
+
+static int delta_mpeg2_drain(struct delta_ctx *pctx)
+{
+	struct delta_mpeg2_ctx *ctx = to_ctx(pctx);
+	struct delta_frame *prev_ref = to_frame(ctx->prev_ref);
+	struct delta_frame *next_ref = to_frame(ctx->next_ref);
+
+	/* mark any pending buffer as out */
+	if (prev_ref &&
+	    (prev_ref->state & DELTA_FRAME_DEC) &&
+	    !(prev_ref->state & DELTA_FRAME_OUT)) {
+		ctx->out_frame = prev_ref;
+	} else if (next_ref &&
+		   (next_ref->state & DELTA_FRAME_DEC) &&
+		   !(next_ref->state & DELTA_FRAME_OUT)) {
+		ctx->out_frame = next_ref;
+	}
+
+	return 0;
+}
+
+static const u32 delta_mpeg2_meta_cids[] = {
+	V4L2_CID_MPEG_VIDEO_MPEG2_SEQ_HDR,
+	V4L2_CID_MPEG_VIDEO_MPEG2_SEQ_EXT,
+	V4L2_CID_MPEG_VIDEO_MPEG2_SEQ_DISPLAY_EXT,
+	V4L2_CID_MPEG_VIDEO_MPEG2_SEQ_MATRIX_EXT,
+	V4L2_CID_MPEG_VIDEO_MPEG2_PIC_HDR,
+	V4L2_CID_MPEG_VIDEO_MPEG2_PIC_HDR,/* 2nd field of interlaced stream */
+	V4L2_CID_MPEG_VIDEO_MPEG2_PIC_EXT,
+	V4L2_CID_MPEG_VIDEO_MPEG2_PIC_EXT,/* 2nd field of interlaced stream */
+};
+
+/* MPEG2 decoder can decode MPEG2 and MPEG1 contents */
+const struct delta_dec mpeg2dec = {
+	.name = "MPEG2",
+	.streamformat = V4L2_PIX_FMT_MPEG2_PARSED,
+	.pixelformat = V4L2_PIX_FMT_NV12,
+	.meta_cids = delta_mpeg2_meta_cids,
+	.nb_of_metas = sizeof(delta_mpeg2_meta_cids) /
+			sizeof(delta_mpeg2_meta_cids[0]),
+	.open = delta_mpeg2_open,
+	.close = delta_mpeg2_close,
+	.get_streaminfo = delta_mpeg2_get_streaminfo,
+	.get_frameinfo = delta_get_frameinfo_default,
+	.decode = delta_mpeg2_decode,
+	.setup_frame = delta_mpeg2_setup_frame,
+	.get_frame = delta_mpeg2_get_frame,
+	.recycle = delta_mpeg2_recycle,
+	.flush = delta_mpeg2_flush,
+	.drain = delta_mpeg2_drain,
+};
+
+const struct delta_dec mpeg1dec = {
+	.name = "MPEG1",
+	.streamformat = V4L2_PIX_FMT_MPEG1_PARSED,
+	.pixelformat = V4L2_PIX_FMT_NV12,
+	.meta_cids = delta_mpeg2_meta_cids,
+	.nb_of_metas = sizeof(delta_mpeg2_meta_cids) /
+			sizeof(delta_mpeg2_meta_cids[0]),
+	.open = delta_mpeg2_open,
+	.close = delta_mpeg2_close,
+	.setup_frame = delta_mpeg2_setup_frame,
+	.get_streaminfo = delta_mpeg2_get_streaminfo,
+	.get_frameinfo = delta_get_frameinfo_default,
+	.decode = delta_mpeg2_decode,
+	.get_frame = delta_mpeg2_get_frame,
+	.recycle = delta_mpeg2_recycle,
+	.flush = delta_mpeg2_flush,
+	.drain = delta_mpeg2_drain,
+};
diff --git a/drivers/media/platform/sti/delta/delta-mpeg2-fw.h b/drivers/media/platform/sti/delta/delta-mpeg2-fw.h
new file mode 100644
index 0000000..7134514
--- /dev/null
+++ b/drivers/media/platform/sti/delta/delta-mpeg2-fw.h
@@ -0,0 +1,415 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2015
+ * Author: Hugues Fruchet <hugues.fruchet@st.com> for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#ifndef DELTA_MPEG2_FW_H
+#define DELTA_MPEG2_FW_H
+
+#define MPEG2_Q_MATRIX_SIZE	64
+
+#define MPEG2_DECODER_ID	0xCAFE
+#define MPEG2_DECODER_BASE	(MPEG2_DECODER_ID << 16)
+
+#define MPEG2_NUMBER_OF_CEH_INTERVALS 32
+
+enum mpeg_decoding_flags_t {
+	/* used to determine the type of picture */
+	MPEG_DECODING_FLAGS_TOP_FIELD_FIRST = 0x00000001,
+	/* used for parsing progression purpose only */
+	MPEG_DECODING_FLAGS_FRAME_PRED_FRAME_DCT = 0x00000002,
+	/* used for parsing progression purpose only */
+	MPEG_DECODING_FLAGS_CONCEALMENT_MOTION_VECTORS = 0x00000004,
+	/* used for the inverse Quantisation process */
+	MPEG_DECODING_FLAGS_Q_SCALE_TYPE = 0x00000008,
+	/* VLC tables selection when decoding the DCT coefficients */
+	MPEG_DECODING_FLAGS_INTRA_VLC_FORMAT = 0x00000010,
+	/* used for the inverse Scan process */
+	MPEG_DECODING_FLAGS_ALTERNATE_SCAN = 0x00000020,
+	/* used for progressive frame signaling */
+	MPEG_DECODING_FLAGS_PROGRESSIVE_FRAME = 0x00000040
+};
+
+/* additional decoding flags */
+enum mpeg2_additional_flags_t {
+	MPEG2_ADDITIONAL_FLAG_NONE = 0x00000000,
+	MPEG2_ADDITIONAL_FLAG_DEBLOCKING_ENABLE = 0x00000001,
+	MPEG2_ADDITIONAL_FLAG_DERINGING_ENABLE = 0x00000002,
+	MPEG2_ADDITIONAL_FLAG_TRANSCODING_H264 = 0x00000004,
+	MPEG2_ADDITIONAL_FLAG_CEH = 0x00000008,
+	MPEG2_ADDITIONAL_FLAG_FIRST_FIELD = 0x00000010,
+	MPEG2_ADDITIONAL_FLAG_SECOND_FIELD = 0x00000020
+};
+
+/* horizontal decimation factor */
+enum mpeg2_horizontal_deci_factor_t {
+	MPEG2_HDEC_1 = 0x00000000, /* no H resize */
+	MPEG2_HDEC_2 = 0x00000001, /* H/2  resize */
+	MPEG2_HDEC_4 = 0x00000002, /* H/4  resize */
+	/* advanced H/2 resize using improved 8-tap filters */
+	MPEG2_HDEC_ADVANCED_2 = 0x00000101,
+	/* advanced H/4 resize using improved 8-tap filters */
+	MPEG2_HDEC_ADVANCED_4 = 0x00000102
+};
+
+/* vertical decimation factor */
+enum mpeg2_vertical_deci_factor_t {
+	MPEG2_VDEC_1 = 0x00000000, /* no V resize */
+	MPEG2_VDEC_2_PROG = 0x00000004, /* V/2, progressive resize */
+	MPEG2_VDEC_2_INT = 0x00000008, /* V/2, interlaced resize */
+	/* advanced V/2, progressive resize */
+	MPEG2_VDEC_ADVANCED_2_PROG = 0x00000204,
+	/* advanced V/2, interlaced resize */
+	MPEG2_VDEC_ADVANCED_2_INT = 0x00000208
+};
+
+/* used to enable main/aux outputs for both display &
+ * reference reconstruction blocks
+ */
+enum mpeg2_rcn_ref_disp_enable_t {
+	/* enable decimated (for display) reconstruction */
+	MPEG2_DISP_AUX_EN = 0x00000010,
+	/* enable main (for display) reconstruction */
+	MPEG2_DISP_MAIN_EN = 0x00000020,
+	/* enable both main & decimated (for display) reconstruction */
+	MPEG2_DISP_AUX_MAIN_EN = 0x00000030,
+	/* enable only reference output (ex. for trick modes) */
+	MPEG2_REF_MAIN_EN = 0x00000100,
+	/* enable reference output with decimated
+	 * (for display) reconstruction
+	 */
+	MPEG2_REF_MAIN_DISP_AUX_EN = 0x00000110,
+	/* enable reference output with main (for display) reconstruction */
+	MPEG2_REF_MAIN_DISP_MAIN_EN = 0x00000120,
+	/* enable reference output with main & decimated
+	 * (for display) reconstruction
+	 */
+	MPEG2_REF_MAIN_DISP_MAIN_AUX_EN = 0x00000130
+};
+
+/* picture prediction coding type (none, one or two reference pictures) */
+enum mpeg2_picture_coding_type_t {
+	/* forbidden coding type */
+	MPEG2_FORBIDDEN_PICTURE = 0x00000000,
+	/* intra (I) picture coding type */
+	MPEG2_INTRA_PICTURE = 0x00000001,
+	/* predictive (P) picture coding type */
+	MPEG2_PREDICTIVE_PICTURE = 0x00000002,
+	/* bidirectional (B) picture coding type */
+	MPEG2_BIDIRECTIONAL_PICTURE = 0x00000003,
+	/* dc intra (D) picture coding type */
+	MPEG2_DC_INTRA_PICTURE = 0x00000004,
+	/* reserved coding type*/
+	MPEG2_RESERVED_1_PICTURE = 0x00000005,
+	MPEG2_RESERVED_2_PICTURE = 0x00000006,
+	MPEG2_RESERVED_3_PICTURE = 0x00000007
+};
+
+/* picture structure type (progressive, interlaced top/bottom) */
+enum mpeg2_picture_structure_t {
+	MPEG2_RESERVED_TYPE = 0,
+	/* identifies a top field picture type */
+	MPEG2_TOP_FIELD_TYPE = 1,
+	/* identifies a bottom field picture type */
+	MPEG2_BOTTOM_FIELD_TYPE = 2,
+	/* identifies a frame picture type */
+	MPEG2_FRAME_TYPE = 3
+};
+
+/* decoding mode */
+enum mpeg2_decoding_mode_t {
+	MPEG2_NORMAL_DECODE = 0,
+	MPEG2_NORMAL_DECODE_WITHOUT_ERROR_RECOVERY = 1,
+	MPEG2_DOWNGRADED_DECODE_LEVEL1 = 2,
+	MPEG2_DOWNGRADED_DECODE_LEVEL2 = 4
+};
+
+/* quantisation matrix flags */
+enum mpeg2_default_matrix_flags_t {
+	MPEG2_LOAD_INTRA_QUANTISER_MATRIX_FLAG = 0x00000001,
+	MPEG2_LOAD_NON_INTRA_QUANTISER_MATRIX_FLAG = 0x00000002
+};
+
+/*
+ * struct mpeg2_decoded_buffer_address_t
+ *
+ * defines the addresses where the decoded pictures will be stored
+ *
+ * @struct_size:		size of the structure in bytes
+ * @decoded_luma_p:		address of the luma buffer
+ * @decoded_chroma_p:		address of the chroma buffer
+ * @decoded_temporal_reference_value:	temporal_reference value
+ *				of the decoded (current) picture
+ * @mb_descr_p:			buffer where to store data related
+ *				to every MBs of the picture
+ */
+struct mpeg2_decoded_buffer_address_t {
+	u32 struct_size;
+	u32 decoded_luma_p;
+	u32 decoded_chroma_p;
+	u32 decoded_temporal_reference_value;	/*  */
+
+	u32 mb_descr_p;
+};
+
+/*
+ * struct mpeg2_display_buffer_address_t
+ *
+ * defines the addresses (used by the Display Reconstruction block)
+ * where the pictures to be displayed will be stored
+ *
+ * @struct_size:		size of the structure in bytes
+ * @display_luma_p:		address of the luma buffer
+ * @display_chroma_p:		address of the chroma buffer
+ * @display_decimated_luma_p:	address of the decimated luma buffer
+ * @display_decimated_chroma_p:	address of the decimated chroma buffer
+ */
+struct mpeg2_display_buffer_address_t {
+	u32 struct_size;
+	u32 display_luma_p;
+	u32 display_chroma_p;
+	u32 display_decimated_luma_p;
+	u32 display_decimated_chroma_p;
+};
+
+/*
+ * struct mpeg2_display_buffer_address_t
+ *
+ * defines the addresses where the two reference pictures
+ * will be stored
+ *
+ * @struct_size:		size of the structure in bytes
+ * @backward_reference_luma_p:	address of the backward reference luma buffer
+ * @backward_reference_chroma_p:address of the backward reference chroma buffer
+ * @backward_temporal_reference_value:	temporal_reference value of the
+ *				backward reference picture
+ * @forward_reference_luma_p:	address of the forward reference luma buffer
+ * @forward_reference_chroma_p:	address of the forward reference chroma buffer
+ * @forward_temporal_reference_value:	temporal_reference value of the
+ *				forward reference picture
+ */
+struct mpeg2_ref_pic_list_address_t {
+	u32 struct_size;
+	u32 backward_reference_luma_p;
+	u32 backward_reference_chroma_p;
+	u32 backward_temporal_reference_value;
+	u32 forward_reference_luma_p;
+	u32 forward_reference_chroma_p;
+	u32 forward_temporal_reference_value;
+};
+
+/* identifies the type of chroma of the decoded picture */
+enum mpeg2_chroma_format_t {
+	MPEG2_CHROMA_RESERVED = 0,
+	/* chroma type 4:2:0 */
+	MPEG2_CHROMA_4_2_0 = 1,
+	/* chroma type 4:2:2 */
+	MPEG2_CHROMA_4_2_2 = 2,
+	/* chroma type 4:4:4 */
+	MPEG2_CHROMA_4_4_4 = 3
+};
+
+/* identifies the Intra DC Precision */
+enum mpeg2_intra_dc_precision_t {
+	/* 8 bits Intra DC Precision*/
+	MPEG2_INTRA_DC_PRECISION_8_BITS = 0,
+	/* 9 bits Intra DC Precision  */
+	MPEG2_INTRA_DC_PRECISION_9_BITS = 1,
+	/* 10 bits Intra DC Precision */
+	MPEG2_INTRA_DC_PRECISION_10_BITS = 2,
+	/* 11 bits Intra DC Precision */
+	MPEG2_INTRA_DC_PRECISION_11_BITS = 3
+};
+
+/* decoding errors bitfield returned by firmware, several bits can be
+ * raised at the same time to signal several errors.
+ */
+enum mpeg2_decoding_error_t {
+	/* the firmware decoding was successful */
+	MPEG2_DECODER_NO_ERROR = (MPEG2_DECODER_BASE + 0),
+	/* the firmware decoded too much MBs:
+	 * - The mpeg2_command_status_t.status doesn't locate
+	 *   these erroneous MBs because the firmware can't know
+	 *   where are these extra MBs.
+	 * - MPEG2_DECODER_ERROR_RECOVERED could also be set
+	 */
+	MPEG2_DECODER_ERROR_MB_OVERFLOW = (MPEG2_DECODER_BASE + 1),
+	/* the firmware encountered error(s) that were recovered:
+	 * - mpeg2_command_status_t.status locates the erroneous MBs.
+	 * - MPEG2_DECODER_ERROR_MB_OVERFLOW could also be set
+	 */
+	MPEG2_DECODER_ERROR_RECOVERED = (MPEG2_DECODER_BASE + 2),
+	/* the firmware encountered an error that can't be recovered:
+	 * - mpeg2_command_status_t.status has no meaning
+	 */
+	MPEG2_DECODER_ERROR_NOT_RECOVERED = (MPEG2_DECODER_BASE + 4),
+	/* the firmware task is hanged and doesn't get back to watchdog
+	 * task even after maximum time alloted has lapsed:
+	 * - mpeg2_command_status_t.status has no meaning.
+	 */
+	MPEG2_DECODER_ERROR_TASK_TIMEOUT = (MPEG2_DECODER_BASE + 8),
+	/* This feature is not supported by firmware */
+	MPEG2_DECODER_ERROR_FEATURE_NOT_SUPPORTED = (MPEG2_DECODER_BASE + 16)
+};
+
+/*
+ * struct mpeg2_set_global_param_sequence_t
+ *
+ * overall video sequence parameters required
+ * by firmware to prepare picture decoding
+ *
+ * @struct_size:		size of the structure in bytes
+ * @mpeg_stream_type_flag:	type of the bitstream MPEG1/MPEG2:
+ *				 = 0  for MPEG1 coded stream,
+ *				 = 1  for MPEG2 coded stream
+ * @horizontal_size:		horizontal size of the video picture: based
+ *				on the two elements "horizontal_size_value"
+ *				and "horizontal_size_extension"
+ * @vertical_size:		vertical size of the video picture: based
+ *				on the two elements "vertical_size_value"
+ *				and "vertical_size_extension"
+ * @progressive_sequence:	progressive/interlaced sequence
+ * @chroma_format:		type of chroma of the decoded picture
+ * @matrix_flags:		load or not the intra or non-intra
+ *				quantisation matrices
+ * @intra_quantiser_matrix:	intra quantisation matrix
+ * @non_intra_quantiser_matrix:	non-intra quantisation matrix
+ * @chroma_intra_quantiser_matrix:	chroma of intra quantisation matrix
+ * @chroma_non_intra_quantiser_matrix:	chroma of non-intra quantisation matrix
+ */
+struct mpeg2_set_global_param_sequence_t {
+	u32 struct_size;
+	bool mpeg_stream_type_flag;
+	u32 horizontal_size;
+	u32 vertical_size;
+	u32 progressive_sequence;
+	enum mpeg2_chroma_format_t chroma_format;
+	enum mpeg2_default_matrix_flags_t matrix_flags;
+	u8 intra_quantiser_matrix[MPEG2_Q_MATRIX_SIZE];
+	u8 non_intra_quantiser_matrix[MPEG2_Q_MATRIX_SIZE];
+	u8 chroma_intra_quantiser_matrix[MPEG2_Q_MATRIX_SIZE];
+	u8 chroma_non_intra_quantiser_matrix[MPEG2_Q_MATRIX_SIZE];
+};
+
+/*
+ * struct mpeg2_param_picture_t
+ *
+ * picture specific parameters required by firmware to perform a picture decode
+ *
+ * @struct_size:		size of the structure in bytes
+ * @picture_coding_type:	identifies the picture prediction
+ *				(none, one or two reference pictures)
+ * @forward_horizontal_f_code:	motion vector: forward horizontal F code
+ * @forward_vertical_f_code:	motion vector: forward vertical F code
+ * @backward_horizontal_f_code:	motion vector: backward horizontal F code
+ * @backward_vertical_f_code:	motion vector: backward vertical F code
+ * @intra_dc_precision:		inverse quantisation process precision
+ * @picture_structure:		picture structure type (progressive,
+ *				interlaced top/bottom)
+ * @mpeg_decoding_flags:	flags to control decoding process
+ */
+struct mpeg2_param_picture_t {
+	u32 struct_size;
+	enum mpeg2_picture_coding_type_t picture_coding_type;
+	u32 forward_horizontal_f_code;
+	u32 forward_vertical_f_code;
+	u32 backward_horizontal_f_code;
+	u32 backward_vertical_f_code;
+	enum mpeg2_intra_dc_precision_t intra_dc_precision;
+	enum mpeg2_picture_structure_t picture_structure;
+	enum mpeg_decoding_flags_t mpeg_decoding_flags;
+};
+
+/*
+ * struct mpeg2_transform_param_t
+ *
+ * control parameters required by firmware to decode a picture
+ *
+ * @struct_size:		size of the structure in bytes
+ * @picture_start_addr_compressed_buffer_p:	start address of the
+ *						compressed MPEG data
+ * @picture_stop_addr_compressed_buffer_p:	stop address of the
+ *						compressed MPEG data
+ * @decoded_buffer_address:	buffer addresses of decoded frame
+ * @display_buffer_address:	buffer addresses of decoded frame
+ *				to be displayed
+ * @ref_pic_list_address:	buffer addresses where the backward
+ *				and forward reference pictures will
+ *				be stored
+ * @main_aux_enable:		output reconstruction stage control
+ * @horizontal_decimation_factor: horizontal decimation control
+ * @vertical_decimation_factor:	vertical decimation control
+ * @decoding_mode:		decoding control (normal,
+ *				recovery, downgraded...)
+ * @additional_flags:		optional additional decoding controls
+ *				(deblocking, deringing...)
+ * @picture_parameters:		picture specific parameters
+ */
+struct mpeg2_transform_param_t {
+	u32 struct_size;
+	u32 picture_start_addr_compressed_buffer_p;
+	u32 picture_stop_addr_compressed_buffer_p;
+	struct mpeg2_decoded_buffer_address_t decoded_buffer_address;
+	struct mpeg2_display_buffer_address_t display_buffer_address;
+	struct mpeg2_ref_pic_list_address_t ref_pic_list_address;
+	enum mpeg2_rcn_ref_disp_enable_t main_aux_enable;
+	enum mpeg2_horizontal_deci_factor_t horizontal_decimation_factor;
+	enum mpeg2_vertical_deci_factor_t vertical_decimation_factor;
+	enum mpeg2_decoding_mode_t decoding_mode;
+	enum mpeg2_additional_flags_t additional_flags;
+	struct mpeg2_param_picture_t picture_parameters;
+	bool reserved;
+};
+
+/*
+ * struct mpeg2_init_transformer_param_t
+ *
+ * defines the addresses where the decoded pictures will be stored
+ *
+ * @input_buffer_begin:	 start address of the input circular buffer
+ * @input_buffer_end:	stop address of the input circular buffer
+ */
+struct mpeg2_init_transformer_param_t {
+	u32 input_buffer_begin;
+	u32 input_buffer_end;
+	bool reserved;
+};
+
+#define MPEG2_STATUS_PARTITION   6
+
+/*
+ * struct mpeg2_init_transformer_param_t
+ *
+ * @struct_size:	size of the structure in bytes
+ * @status:		decoding quality indicator which can be used
+ *			to assess the level corruption of input
+ *			MPEG bitstream. The picture to decode
+ *			is divided into a maximum of
+ *			MPEG2_STATUS_PARTITION * MPEG2_STATUS_PARTITION
+ *			areas in order to locate the decoding errors.
+ * @error_code:		decoding errors bitfield returned by firmware
+ * @decode_time_in_micros:	stop address of the input circular buffer
+ * @ceh_registers:	array where values of the Contrast Enhancement
+ *			Histogram (CEH) registers will be stored.
+ *			ceh_registers[0] correspond to register MBE_CEH_0_7,
+ *			ceh_registers[1] correspond to register MBE_CEH_8_15,
+ *			ceh_registers[2] correspond to register MBE_CEH_16_23.
+ *			Note that elements of this array will be updated
+ *			only if mpeg2_transform_param_t.additional_flags has
+ *			the flag MPEG2_ADDITIONAL_FLAG_CEH set.
+ *			They will remain unchanged otherwise.
+ * @picture_mean_qp:	picture mean QP factor
+ * @picture_variance_qp:picture variance QP factor
+ */
+struct mpeg2_command_status_t {
+	u32 struct_size;
+	u8 status[MPEG2_STATUS_PARTITION][MPEG2_STATUS_PARTITION];
+	enum mpeg2_decoding_error_t error_code;
+	u32 decode_time_in_micros;
+	u32 ceh_registers[MPEG2_NUMBER_OF_CEH_INTERVALS];
+	u32 picture_mean_qp;
+	u32 picture_variance_qp;
+};
+
+#endif /* DELTA_MPEG2_FW_H */
diff --git a/drivers/media/platform/sti/delta/delta-v4l2.c b/drivers/media/platform/sti/delta/delta-v4l2.c
index 1d4436e..8b00c81 100644
--- a/drivers/media/platform/sti/delta/delta-v4l2.c
+++ b/drivers/media/platform/sti/delta/delta-v4l2.c
@@ -36,6 +36,10 @@
 #ifdef CONFIG_VIDEO_STI_DELTA_MJPEG
 	&mjpegdec,
 #endif
+#ifdef CONFIG_VIDEO_STI_DELTA_MPEG2
+	&mpeg2dec,
+	&mpeg1dec,
+#endif
 };
 
 static inline int frame_size(u32 w, u32 h, u32 fmt)
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 3/3] [media] st-delta: add mpeg2 support
  2017-02-08 15:37 ` [PATCH v2 3/3] [media] st-delta: add mpeg2 support Hugues Fruchet
@ 2017-02-08 21:56   ` kbuild test robot
  0 siblings, 0 replies; 5+ messages in thread
From: kbuild test robot @ 2017-02-08 21:56 UTC (permalink / raw)
  To: Hugues Fruchet
  Cc: kbuild-all, linux-media, Hans Verkuil, kernel, Benjamin Gaignard,
	Hugues Fruchet, Jean-Christophe Trotin

[-- Attachment #1: Type: text/plain, Size: 4571 bytes --]

Hi Hugues,

[auto build test WARNING on linuxtv-media/master]
[cannot apply to v4.10-rc7 next-20170208]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Hugues-Fruchet/Add-support-for-MPEG-2-in-DELTA-video-decoder/20170209-000624
base:   git://linuxtv.org/media_tree.git master
config: parisc-allyesconfig (attached as .config)
compiler: hppa-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=parisc 

All warnings (new ones prefixed by >>):

   In file included from include/linux/printk.h:320:0,
                    from include/linux/kernel.h:13,
                    from arch/parisc/include/asm/bug.h:4,
                    from include/linux/bug.h:4,
                    from include/linux/mmdebug.h:4,
                    from include/linux/gfp.h:4,
                    from include/linux/slab.h:14,
                    from drivers/media/platform/sti/delta/delta-mpeg2-dec.c:10:
   drivers/media/platform/sti/delta/delta-mpeg2-dec.c: In function 'delta_mpeg2_ipc_decode':
>> drivers/media/platform/sti/delta/delta-mpeg2-dec.c:899:22: warning: format '%lu' expects argument of type 'long unsigned int', but argument 6 has type '__kernel_suseconds_t {aka int}' [-Wformat=]
     dev_dbg(delta->dev, "%s  dec frame[%d] tref=%03lu type=%s pic=%s cnt=%03d %s\n",
                         ^
   include/linux/dynamic_debug.h:134:39: note: in definition of macro 'dynamic_dev_dbg'
      __dynamic_dev_dbg(&descriptor, dev, fmt, \
                                          ^~~
>> drivers/media/platform/sti/delta/delta-mpeg2-dec.c:899:2: note: in expansion of macro 'dev_dbg'
     dev_dbg(delta->dev, "%s  dec frame[%d] tref=%03lu type=%s pic=%s cnt=%03d %s\n",
     ^~~~~~~
   drivers/media/platform/sti/delta/delta-mpeg2-dec.c: In function 'delta_mpeg2_get_frame':
   drivers/media/platform/sti/delta/delta-mpeg2-dec.c:1279:3: warning: format '%lu' expects argument of type 'long unsigned int', but argument 6 has type '__kernel_suseconds_t {aka int}' [-Wformat=]
      "%s  out frame[%d] tref=%03lu type=%s field=%s cnt=%03d %s\n",
      ^
   include/linux/dynamic_debug.h:134:39: note: in definition of macro 'dynamic_dev_dbg'
      __dynamic_dev_dbg(&descriptor, dev, fmt, \
                                          ^~~
   drivers/media/platform/sti/delta/delta-mpeg2-dec.c:1278:2: note: in expansion of macro 'dev_dbg'
     dev_dbg(delta->dev,
     ^~~~~~~
   drivers/media/platform/sti/delta/delta-mpeg2-dec.c: In function 'delta_mpeg2_recycle':
   drivers/media/platform/sti/delta/delta-mpeg2-dec.c:1301:3: warning: format '%lu' expects argument of type 'long unsigned int', but argument 6 has type '__kernel_suseconds_t {aka int}' [-Wformat=]
      "%s  rec frame[%d] tref=%03lu %s\n",
      ^
   include/linux/dynamic_debug.h:134:39: note: in definition of macro 'dynamic_dev_dbg'
      __dynamic_dev_dbg(&descriptor, dev, fmt, \
                                          ^~~
   drivers/media/platform/sti/delta/delta-mpeg2-dec.c:1300:2: note: in expansion of macro 'dev_dbg'
     dev_dbg(delta->dev,
     ^~~~~~~

vim +899 drivers/media/platform/sti/delta/delta-mpeg2-dec.c

   883	
   884		/* check firmware decoding status */
   885		if (delta_mpeg2_check_status(pctx, status)) {
   886			dev_err(delta->dev,
   887				"%s  dumping command %s\n", pctx->name,
   888				ipc_decode_param_str(params, ctx->str,
   889						     sizeof(ctx->str)));
   890		}
   891	
   892		mpeg2_frame->dts.tv_usec = pic_hdr->tsn;
   893		frame->state |= DELTA_FRAME_DEC;
   894		frame->flags = 0;
   895		to_v4l2_frame_type(params_pic->picture_coding_type,
   896				   &frame->flags);
   897		frame->field = to_v4l2_field_type(interlaced, top_field_first);
   898	
 > 899		dev_dbg(delta->dev, "%s  dec frame[%d] tref=%03lu type=%s pic=%s cnt=%03d %s\n",
   900			pctx->name,
   901			(to_frame(mpeg2_frame))->index,
   902			mpeg2_frame->dts.tv_usec,
   903			picture_coding_type_str(params_pic->picture_coding_type),
   904			picture_structure_str(picture_structure),
   905			pctx->decoded_frames,
   906			frame_state_str(frame->state, ctx->str, sizeof(ctx->str)));
   907	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 48523 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2017-02-08 21:57 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-08 15:37 [PATCH v2 0/3] Add support for MPEG-2 in DELTA video decoder Hugues Fruchet
2017-02-08 15:37 ` [PATCH v2 1/3] [media] v4l: add parsed MPEG-2 support Hugues Fruchet
2017-02-08 15:37 ` [PATCH v2 2/3] [media] st-delta: add parsing metadata controls support Hugues Fruchet
2017-02-08 15:37 ` [PATCH v2 3/3] [media] st-delta: add mpeg2 support Hugues Fruchet
2017-02-08 21:56   ` kbuild test robot

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.