devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] media: Add Gen 3 IP stateful decoder driver
@ 2025-05-11 14:47 Yassine Ouaissa
  2025-05-11 14:47 ` [PATCH 1/3] media: allegro-dvt: Move the current driver to a subdirectory Yassine Ouaissa
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Yassine Ouaissa @ 2025-05-11 14:47 UTC (permalink / raw)
  To: Michael Tretter, Yassine OUAISSA, Pengutronix Kernel Team,
	Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Michal Simek, Neil Armstrong, Heiko Stuebner,
	Aradhya Bhatia, Junhao Xie, Rafał Miłecki,
	Manivannan Sadhasivam, Kever Yang, Hans Verkuil, Joe Hattori,
	Christophe JAILLET, Uwe Kleine-König, Gaosheng Cui,
	Wolfram Sang, Ricardo Ribalda, linux-media, devicetree,
	linux-kernel, linux-arm-kernel

# V4L2 Video Decoder Driver System Description

** Hardware Architecture **

The system implements a heterogeneous computing architecture with two primary components:

- **Host Subsystem**: Linux-based CPU running the V4L2 framework and associated drivers
- **IP Subsystem**: Dedicated hardware containing an MCU and a hardware video CODEC

The communication between the two subsystems uses a shared DDR shared memory with bidirectional interrupt mechanism for synchronization.

The architecture is represented in the following diagram:

```
+---------------------+                  +----------------------+
|       Host          |                  |        IP            |
|                     |                  |                      |
|  +---------------+  |                  |  +----------------+  |
|  |               |  |   DDR Shared     |  |                |  |
|  | Linux Kernel  |<-|----------------->|->|     MCU        |  |
|  | (CPU)         |  |    Memory        |  |                |  |
|  |   +--------+  |  |                  |  +----------------+  |
|  |   |        |  |  |    IRQ when      |           ^          |
|  |   | V4L2   |  |<-|----new message-->|           |          |
|  |   | Drivers|  |  |                  |           |          |
|  |   |        |  |  |                  |           | APB      |
|  |   +--------+  |  |                  |           |          |
|  |               |  |                  |           v          |
|  +---------------+  |                  |  +----------------+  |
|                     |                  |  |                |  |
|                     |                  |  |     CODEC      |  |
|                     |                  |  |                |  |
|                     |                  |  |                |  |
+---------------------+                  +----------------------+
```

** Communication Protocol **

-- Current Implementation - Custom Mailbox --

The host CPU and MCU currently communicate through a custom mailbox protocol implemented over shared memory. The protocol operates as follows:

1. When the host has a new message for the MCU:
   - The host writes data to a dedicated shared memory region
   - The host triggers an interrupt to the MCU
   - The MCU reads the shared memory to obtain the message type and data

2. Similarly, when the MCU has a message for the host:
   - The MCU writes to the shared memory
   - The MCU triggers an interrupt to the host
   - The host reads the shared memory to process the message

-- Migration to RPMSG --

The custom mailbox implementation will be replaced by the standard Linux RPMSG framework.

** Driver Implementation **

This driver implements a V4L2-compliant stateful video decoder with the following characteristics:

-- Technical Specifications --

- **Codec Support**: AVC (H.264), HEVC (H.265), and JPEG
- **Resolution Support**: Up to 4K
- **Pixel Formats**:
  - Currently supported: V4L2_PIX_FMT_NV12, V4L2_PIX_FMT_NV16, V4L2_PIX_FMT_P010
  - Additional formats planned for future releases
- **Buffer Configuration**: Currently supports semi-planar format only; multiplanar support forthcoming

-- Initialization Sequence --

During probe, the driver performs the following operations:

1. Allocates memory for the MCU firmware
2. Loads the firmware into the allocated memory
3. Initializes the MCU by configuring internal registers (e.g BOOT_ADDR)
4. Establishes the shared memory communication interface (to be replaced by RPMSG)
5. Sets up interrupt handlers for MCU communication

-- Processing Model --

The driver implements a stateful decoding model with the following workflow:

-- Stream Initialization --

1. Upon `VIDIOC_STREAMON` on the OUTPUT queue:
   - The driver sends a context creation request to the MCU
   - This operation is blocking; the driver waits until the MCU responds with a context handler
   - The context handler is stored in a driver-maintained list for subsequent operations
   - Each context has its own unique handler to support multiple simultaneous streams

2. Initial stream analysis:
   - The driver submits the first compressed buffer (OUTPUT queue)
   - The MCU analyzes the stream and reports capability via:
     - `resolution_found_event`: Stream is supported, includes stream parameters
     - `error_event`: Stream format is unsupported or invalid

-- Decoding Pipeline --

1. After successful stream initialization and receiving the resolution_found_evt:
   - The driver can begin normal decoding operations
   - V4L2 framework can be informed of format requirements

2. For each compressed buffer (OUTPUT queue):
   - The driver submits buffer to MCU with the appropriate context handler
   - The MCU processes the buffer and sends `release_bitstream_evt` when complete
   - This event signals that the input buffer can be returned to the application

3. For each decoded buffer (CAPTURE queue):
   - The MCU fills the buffer with decoded frame data
   - The MCU sends `frame_buffer_decode_evt` with important metadata including:
     - Original source buffer timestamp
     - Flags
     - Timecode
     - Actual payload size (bytes used in the decoded frame)
   - This enables the driver to properly queue the filled buffer to the application

4. End-of-stream handling:
   - The MCU sends an event with `eos_evt` when reaching the end of stream
   - This allows proper handling of end-of-stream conditions

-- Multi-stream Support --

The driver architecture supports multiple simultaneous decoding contexts with the following characteristics:

1. Each context maintains separate state information
2. The driver manages multiple context handlers returned by the MCU
3. Buffer submissions include the appropriate context handler for routing
4. The system can decode multiple independent streams concurrently

-- Stream Termination --

When `VIDIOC_STREAMOFF` is called:

1. The driver sends a flush command to the MCU for the specific context
2. The driver issues a non-blocking destroy context message
3. All associated resources are released
4. The context handler is removed from the driver's context list

** Error Handling **

The driver implements comprehensive error handling including:

1. Firmware loading failures
2. MCU initialization errors
3. Context creation failures
4. Unsupported stream formats
5. Decoding errors reported by the MCU
6. Timeout handling for unresponsive hardware

** Memory Management **

The system uses the following memory management strategy:

1. Firmware memory is allocated during probe
2. Buffer memory is managed through the V4L2 buffer management interfaces
3. DMA-capable memory is used for buffer transfers between host and MCU
4. The driver properly synchronizes memory access to avoid coherency issues

** Future Enhancements **

Planned future enhancements include:

1. Migration from custom mailbox to RPMSG (in progress)
2. Support for additional pixel formats
3. Implementation of multiplanar buffer support

This comprehensive architecture enables efficient hardware-accelerated video decoding while adhering to standard V4L2 interfaces, making it suitable for upstream inclusion in the Linux kernel.

** Decoder Compliance Testing **

-- AVC and HEVC Fluster Report --

This section contains the compliance test results from Fluster framework for both AVC and HEVC decoders.
The reports validate the decoder's conformance to relevant standards and demonstrate compatibility with a wide range of video streams.

[FLUSTER REPORT FOR THE H.264]
 -- JVT-AVC_V1

| Test                     | FFmpeg-H.264-v4l2m2m |
| ------------------------ | -------------------- |
| TOTAL                    | 79/135               |
| TOTAL TIME               | 437.031s             |
| -                        | -                    |
| AUD_MW_E                 | OK                   |
| BA1_FT_C                 | OK                   |
| BA1_Sony_D               | OK                   |
| BA2_Sony_F               | OK                   |
| BA3_SVA_C                | OK                   |
| BA_MW_D                  | OK                   |
| BAMQ1_JVC_C              | OK                   |
| BAMQ2_JVC_C              | OK                   |
| BANM_MW_D                | OK                   |
| BASQP1_Sony_C            | OK                   |
| CABA1_Sony_D             | OK                   |
| CABA1_SVA_B              | OK                   |
| CABA2_Sony_E             | OK                   |
| CABA2_SVA_B              | OK                   |
| CABA3_Sony_C             | OK                   |
| CABA3_SVA_B              | OK                   |
| CABA3_TOSHIBA_E          | OK                   |
| cabac_mot_fld0_full      | ER                   |
| cabac_mot_frm0_full      | OK                   |
| cabac_mot_mbaff0_full    | ER                   |
| cabac_mot_picaff0_full   | KO                   |
| CABACI3_Sony_B           | OK                   |
| CABAST3_Sony_E           | OK                   |
| CABASTBR3_Sony_B         | OK                   |
| CABREF3_Sand_D           | ER                   |
| CACQP3_Sony_D            | OK                   |
| CAFI1_SVA_C              | ER                   |
| CAMA1_Sony_C             | ER                   |
| CAMA1_TOSHIBA_B          | ER                   |
| cama1_vtc_c              | ER                   |
| cama2_vtc_b              | ER                   |
| CAMA3_Sand_E             | ER                   |
| cama3_vtc_b              | ER                   |
| CAMACI3_Sony_C           | ER                   |
| CAMANL1_TOSHIBA_B        | ER                   |
| CAMANL2_TOSHIBA_B        | ER                   |
| CAMANL3_Sand_E           | ER                   |
| CAMASL3_Sony_B           | ER                   |
| CAMP_MOT_MBAFF_L30       | ER                   |
| CAMP_MOT_MBAFF_L31       | ER                   |
| CANL1_Sony_E             | OK                   |
| CANL1_SVA_B              | OK                   |
| CANL1_TOSHIBA_G          | OK                   |
| CANL2_Sony_E             | OK                   |
| CANL2_SVA_B              | OK                   |
| CANL3_Sony_C             | OK                   |
| CANL3_SVA_B              | OK                   |
| CANL4_SVA_B              | OK                   |
| CANLMA2_Sony_C           | ER                   |
| CANLMA3_Sony_C           | ER                   |
| CAPA1_TOSHIBA_B          | ER                   |
| CAPAMA3_Sand_F           | ER                   |
| CAPCM1_Sand_E            | OK                   |
| CAPCMNL1_Sand_E          | OK                   |
| CAPM3_Sony_D             | OK                   |
| CAQP1_Sony_B             | OK                   |
| cavlc_mot_fld0_full_B    | ER                   |
| cavlc_mot_frm0_full_B    | OK                   |
| cavlc_mot_mbaff0_full_B  | ER                   |
| cavlc_mot_picaff0_full_B | KO                   |
| CAWP1_TOSHIBA_E          | OK                   |
| CAWP5_TOSHIBA_E          | OK                   |
| CI1_FT_B                 | OK                   |
| CI_MW_D                  | OK                   |
| CVBS3_Sony_C             | OK                   |
| CVCANLMA2_Sony_C         | ER                   |
| CVFC1_Sony_C             | OK                   |
| CVFI1_Sony_D             | ER                   |
| CVFI1_SVA_C              | ER                   |
| CVFI2_Sony_H             | ER                   |
| CVFI2_SVA_C              | ER                   |
| CVMA1_Sony_D             | ER                   |
| CVMA1_TOSHIBA_B          | ER                   |
| CVMANL1_TOSHIBA_B        | ER                   |
| CVMANL2_TOSHIBA_B        | ER                   |
| CVMAPAQP3_Sony_E         | ER                   |
| CVMAQP2_Sony_G           | ER                   |
| CVMAQP3_Sony_D           | ER                   |
| CVMP_MOT_FLD_L30_B       | ER                   |
| CVMP_MOT_FRM_L31_B       | ER                   |
| CVNLFI1_Sony_C           | ER                   |
| CVNLFI2_Sony_H           | ER                   |
| CVPA1_TOSHIBA_B          | ER                   |
| CVPCMNL1_SVA_C           | OK                   |
| CVPCMNL2_SVA_C           | OK                   |
| CVSE2_Sony_B             | OK                   |
| CVSE3_Sony_H             | OK                   |
| CVSEFDFT3_Sony_E         | OK                   |
| CVWP1_TOSHIBA_E          | OK                   |
| CVWP2_TOSHIBA_E          | OK                   |
| CVWP3_TOSHIBA_E          | OK                   |
| CVWP5_TOSHIBA_E          | OK                   |
| FI1_Sony_E               | ER                   |
| FM1_BT_B                 | ER                   |
| FM1_FT_E                 | KO                   |
| FM2_SVA_C                | ER                   |
| HCBP1_HHI_A              | OK                   |
| HCBP2_HHI_A              | OK                   |
| HCMP1_HHI_A              | OK                   |
| LS_SVA_D                 | OK                   |
| MIDR_MW_D                | OK                   |
| MPS_MW_A                 | OK                   |
| MR1_BT_A                 | OK                   |
| MR1_MW_A                 | OK                   |
| MR2_MW_A                 | OK                   |
| MR2_TANDBERG_E           | OK                   |
| MR3_TANDBERG_B           | OK                   |
| MR4_TANDBERG_C           | OK                   |
| MR5_TANDBERG_C           | OK                   |
| MR6_BT_B                 | ER                   |
| MR7_BT_B                 | OK                   |
| MR8_BT_B                 | ER                   |
| MR9_BT_B                 | ER                   |
| MV1_BRCM_D               | OK                   |
| NL1_Sony_D               | OK                   |
| NL2_Sony_H               | OK                   |
| NL3_SVA_E                | OK                   |
| NLMQ1_JVC_C              | OK                   |
| NLMQ2_JVC_C              | OK                   |
| NRF_MW_E                 | OK                   |
| Sharp_MP_Field_1_B       | ER                   |
| Sharp_MP_Field_2_B       | ER                   |
| Sharp_MP_Field_3_B       | ER                   |
| Sharp_MP_PAFF_1r2        | ER                   |
| Sharp_MP_PAFF_2r         | ER                   |
| SL1_SVA_B                | OK                   |
| SP1_BT_A                 | ER                   |
| sp2_bt_b                 | ER                   |
| SVA_BA1_B                | OK                   |
| SVA_BA2_D                | OK                   |
| SVA_Base_B               | OK                   |
| SVA_CL1_E                | OK                   |
| SVA_FM1_E                | OK                   |
| SVA_NL1_B                | OK                   |
| SVA_NL2_E                | OK                   |
| -                        | -                    |
| Test                     | FFmpeg-H.264-v4l2m2m |
| TOTAL                    | 79/135               |
| TOTAL TIME               | 439.031s             |

NOTE: The ER (ERROR) streams are not supported by the decoder.
      The driver print error message "Unsupported stream"

- JVT-FR-EXT

| Test                | FFmpeg-H.264-v4l2m2m |
| ------------------- | -------------------- |
| TOTAL               | 23/69                |
| TOTAL TIME          | 182.362s             |
| -                   | -                    |
| alphaconformanceG   | OK                   |
| brcm_freh10         | ER                   |
| brcm_freh11         | ER                   |
| brcm_freh3          | OK                   |
| brcm_freh4          | ER                   |
| brcm_freh5          | ER                   |
| brcm_freh6          | ER                   |
| brcm_freh8          | OK                   |
| brcm_freh9          | OK                   |
| FREH10-1            | ER                   |
| FREH10-2            | ER                   |
| freh12_b            | OK                   |
| freh1_b             | OK                   |
| freh2_b             | OK                   |
| freh7_b             | ER                   |
| FREXT01_JVC_D       | ER                   |
| FREXT02_JVC_C       | ER                   |
| FRExt1_Panasonic_D  | OK                   |
| FREXT1_TANDBERG_A   | ER                   |
| FRExt2_Panasonic_C  | ER                   |
| FREXT2_TANDBERG_A   | ER                   |
| FRExt3_Panasonic_E  | OK                   |
| FREXT3_TANDBERG_A   | ER                   |
| FRExt4_Panasonic_B  | ER                   |
| FRExt_MMCO4_Sony_B  | OK                   |
| HCAFF1_HHI_B        | ER                   |
| HCAFR1_HHI_C        | OK                   |
| HCAFR2_HHI_A        | OK                   |
| HCAFR3_HHI_A        | OK                   |
| HCAFR4_HHI_A        | OK                   |
| HCAMFF1_HHI_B       | ER                   |
| HCHP1_HHI_B         | OK                   |
| HCHP2_HHI_A         | OK                   |
| HCHP3_HHI_A         | ER                   |
| Hi422FR10_SONY_A    | ER                   |
| Hi422FR11_SONY_A    | ER                   |
| Hi422FR12_SONY_A    | ER                   |
| Hi422FR13_SONY_A    | ER                   |
| Hi422FR14_SONY_A    | ER                   |
| Hi422FR15_SONY_A    | ER                   |
| Hi422FR1_SONY_A     | ER                   |
| Hi422FR2_SONY_A     | ER                   |
| Hi422FR3_SONY_A     | ER                   |
| Hi422FR4_SONY_A     | ER                   |
| Hi422FR6_SONY_A     | ER                   |
| Hi422FR7_SONY_A     | ER                   |
| Hi422FR8_SONY_A     | ER                   |
| Hi422FR9_SONY_A     | ER                   |
| Hi422FREXT16_SONY_A | ER                   |
| Hi422FREXT17_SONY_A | ER                   |
| Hi422FREXT18_SONY_A | ER                   |
| Hi422FREXT19_SONY_A | ER                   |
| HPCA_BRCM_C         | OK                   |
| HPCADQ_BRCM_B       | OK                   |
| HPCAFL_BRCM_C       | ER                   |
| HPCAFLNL_BRCM_C     | ER                   |
| HPCALQ_BRCM_B       | OK                   |
| HPCAMAPALQ_BRCM_B   | ER                   |
| HPCAMOLQ_BRCM_B     | ER                   |
| HPCANL_BRCM_C       | OK                   |
| HPCAQ2LQ_BRCM_B     | OK                   |
| HPCV_BRCM_A         | OK                   |
| HPCVFL_BRCM_A       | ER                   |
| HPCVFLNL_BRCM_A     | ER                   |
| HPCVMOLQ_BRCM_B     | ER                   |
| HPCVNL_BRCM_A       | OK                   |
| HVLCFI0_Sony_B      | ER                   |
| HVLCMFF0_Sony_B     | ER                   |
| HVLCPFF0_Sony_B     | ER                   |
| -                   | -                    |
| Test                | FFmpeg-H.264-v4l2m2m |
| TOTAL               | 23/69                |
| TOTAL TIME          | 182.362s             |

NOTE: The ER (ERROR) streams are not supported by the decoder.
      The driver print error message "Unsupported stream"

- JVT-MVC

| Test       | FFmpeg-H.264-v4l2m2m |
| ---------- | -------------------- |
| TOTAL      | 18/20                |
| TOTAL TIME | 147.076s             |
| -          | -                    |
| MVCDS-4    | OK                   |
| MVCDS-5    | OK                   |
| MVCDS-6    | OK                   |
| MVCDS1     | OK                   |
| MVCDS2     | OK                   |
| MVCDS3     | OK                   |
| MVCICT-1   | ER                   |
| MVCICT-2   | ER                   |
| MVCNV-2    | OK                   |
| MVCNV-3    | OK                   |
| MVCNV1     | OK                   |
| MVCNV4     | OK                   |
| MVCRP_1    | OK                   |
| MVCRP_2    | OK                   |
| MVCRP_3    | OK                   |
| MVCRP_4    | OK                   |
| MVCRP_5    | OK                   |
| MVCRP_6    | OK                   |
| MVCSPS-1   | OK                   |
| MVCSPS-2   | OK                   |
| -          | -                    |
| Test       | FFmpeg-H.264-v4l2m2m |
| TOTAL      | 18/20                |
| TOTAL TIME | 147.076s             |

- JVT-SVC


| Test            | FFmpeg-H.264-v4l2m2m |
| --------------- | -------------------- |
| TOTAL           | 75/185               |
| TOTAL TIME      | 727.240s             |
| -               | -                    |
| SVCBC-1-L0      | OK                   |
| SVCBC-1-L1      | KO                   |
| SVCBCT-1-L0     | OK                   |
| SVCBCT-1-L1     | KO                   |
| SVCBCTS-1-r1-L0 | OK                   |
| SVCBCTS-1-r1-L1 | KO                   |
| SVCBCTS-1-r1-L2 | KO                   |
| SVCBCTS-2-r1-L0 | OK                   |
| SVCBCTS-2-r1-L1 | KO                   |
| SVCBCTS-2-r1-L2 | KO                   |
| SVCBCTS-3-L0    | OK                   |
| SVCBCTS-3-L1    | KO                   |
| SVCBCTS-3-L2    | KO                   |
| SVCBM-1-L0      | OK                   |
| SVCBM-1-L1      | KO                   |
| SVCBM-2-L0      | OK                   |
| SVCBM-2-L1      | KO                   |
| SVCBM-3-L0      | OK                   |
| SVCBM-3-L1      | KO                   |
| SVCBM-4-r1-L0   | OK                   |
| SVCBM-4-r1-L1   | KO                   |
| SVCBM-4-r1-L2   | KO                   |
| SVCBM-5-L0      | OK                   |
| SVCBM-5-L1      | KO                   |
| SVCBM-5-L2      | KO                   |
| SVCBM-5-L3      | KO                   |
| SVCBMST-1-L0    | OK                   |
| SVCBMST-1-L1    | KO                   |
| SVCBMST-1-L2    | KO                   |
| SVCBMST-2-L0    | OK                   |
| SVCBMST-2-L1    | KO                   |
| SVCBMST-2-L2    | KO                   |
| SVCBMST-3-L0    | OK                   |
| SVCBMST-3-L1    | KO                   |
| SVCBMST-3-L2    | KO                   |
| SVCBMT-1-L0     | OK                   |
| SVCBMT-1-L1     | KO                   |
| SVCBMT-10-L0    | OK                   |
| SVCBMT-10-L1    | KO                   |
| SVCBMT-11-L0    | OK                   |
| SVCBMT-11-L1    | KO                   |
| SVCBMT-12-L0    | OK                   |
| SVCBMT-12-L1    | KO                   |
| SVCBMT-13-L0    | OK                   |
| SVCBMT-13-L1    | KO                   |
| SVCBMT-13-L2    | KO                   |
| SVCBMT-2-L0     | OK                   |
| SVCBMT-2-L1     | KO                   |
| SVCBMT-3-L0     | OK                   |
| SVCBMT-3-L1     | KO                   |
| SVCBMT-4-L0     | OK                   |
| SVCBMT-4-L1     | KO                   |
| SVCBMT-5-L0     | OK                   |
| SVCBMT-5-L1     | KO                   |
| SVCBMT-6-L0     | OK                   |
| SVCBMT-6-L1     | KO                   |
| SVCBMT-7-L0     | OK                   |
| SVCBMT-7-L1     | KO                   |
| SVCBMT-8-L0     | OK                   |
| SVCBMT-8-L1     | KO                   |
| SVCBMT-9-L0     | OK                   |
| SVCBMT-9-L1     | KO                   |
| SVCBS-1-L0      | OK                   |
| SVCBS-1-L1      | KO                   |
| SVCBS-2-L0      | OK                   |
| SVCBS-2-L1      | KO                   |
| SVCBS-3-r1-L0   | OK                   |
| SVCBS-3-r1-L1   | KO                   |
| SVCBS-4-r1-L0   | OK                   |
| SVCBS-4-r1-L1   | KO                   |
| SVCBS-5-r1-L0   | OK                   |
| SVCBS-5-r1-L1   | KO                   |
| SVCBS-6-r1-L0   | OK                   |
| SVCBS-6-r1-L1   | KO                   |
| SVCBS-6-r1-L2   | KO                   |
| SVCBS-7-L0      | OK                   |
| SVCBS-7-L1      | KO                   |
| SVCBS-8-L0      | OK                   |
| SVCBS-8-L1      | KO                   |
| SVCBST-1-L0     | OK                   |
| SVCBST-1-L1     | KO                   |
| SVCBST-10-r1-L0 | OK                   |
| SVCBST-10-r1-L1 | KO                   |
| SVCBST-11-r1-L0 | OK                   |
| SVCBST-11-r1-L1 | KO                   |
| SVCBST-12-r1-L0 | OK                   |
| SVCBST-12-r1-L1 | KO                   |
| SVCBST-13-L0    | OK                   |
| SVCBST-13-L1    | KO                   |
| SVCBST-14-L0    | OK                   |
| SVCBST-14-L1    | KO                   |
| SVCBST-14-L2    | KO                   |
| SVCBST-15-L0    | OK                   |
| SVCBST-15-L1    | KO                   |
| SVCBST-15-L2    | KO                   |
| SVCBST-16-r1-L0 | OK                   |
| SVCBST-16-r1-L1 | KO                   |
| SVCBST-16-r1-L2 | KO                   |
| SVCBST-17-r1-L0 | OK                   |
| SVCBST-17-r1-L1 | KO                   |
| SVCBST-17-r1-L2 | KO                   |
| SVCBST-18-r1-L0 | OK                   |
| SVCBST-18-r1-L1 | KO                   |
| SVCBST-18-r1-L2 | KO                   |
| SVCBST-19-L0    | OK                   |
| SVCBST-19-L1    | KO                   |
| SVCBST-2-L0     | OK                   |
| SVCBST-2-L1     | KO                   |
| SVCBST-20-L0    | OK                   |
| SVCBST-20-L1    | KO                   |
| SVCBST-3-L0     | OK                   |
| SVCBST-3-L1     | KO                   |
| SVCBST-4-L0     | OK                   |
| SVCBST-4-L1     | KO                   |
| SVCBST-5-L0     | OK                   |
| SVCBST-5-L1     | KO                   |
| SVCBST-6-r1-L0  | OK                   |
| SVCBST-6-r1-L1  | KO                   |
| SVCBST-7-r1-L0  | OK                   |
| SVCBST-7-r1-L1  | KO                   |
| SVCBST-8-r1-L0  | OK                   |
| SVCBST-8-r1-L1  | KO                   |
| SVCBST-9-r1-L0  | OK                   |
| SVCBST-9-r1-L1  | KO                   |
| SVCBSTC-1-L0    | OK                   |
| SVCBSTC-1-L1    | KO                   |
| SVCBSTC-1-L2    | KO                   |
| SVCHCTS-1-r1-L0 | OK                   |
| SVCHCTS-1-r1-L1 | KO                   |
| SVCHCTS-1-r1-L2 | KO                   |
| SVCHCTS-1-r1-L3 | KO                   |
| SVCHCTS-1-r1-L4 | KO                   |
| SVCHCTS-1-r1-L5 | KO                   |
| SVCHCTS-1-r1-L6 | KO                   |
| SVCHCTS-1-r1-L7 | KO                   |
| SVCHICS-1-L0    | OK                   |
| SVCHICS-1-L1    | KO                   |
| SVCHICS-1-L2    | KO                   |
| SVCHICS-1-L3    | KO                   |
| SVCHIS-1-L0     | OK                   |
| SVCHIS-1-L1     | KO                   |
| SVCHIS-1-L2     | KO                   |
| SVCHIS-2-L0     | OK                   |
| SVCHIS-2-L1     | KO                   |
| SVCHIS-2-L2     | KO                   |
| SVCHIS-3-L0     | OK                   |
| SVCHIS-3-L1     | KO                   |
| SVCHIS-3-L2     | KO                   |
| SVCHM-1-L0      | OK                   |
| SVCHM-1-L1      | KO                   |
| SVCHM-1-L2      | KO                   |
| SVCHM-1-L3      | KO                   |
| SVCHM-2-L0      | OK                   |
| SVCHM-2-L1      | OK                   |
| SVCHM-3-L0      | OK                   |
| SVCHM-3-L1      | OK                   |
| SVCHM-4-L0      | OK                   |
| SVCHM-4-L1      | OK                   |
| SVCHM-4-L2      | OK                   |
| SVCHMTS-1-r1-L0 | OK                   |
| SVCHMTS-1-r1-L1 | KO                   |
| SVCHMTS-1-r1-L2 | KO                   |
| SVCHMTS-1-r1-L3 | KO                   |
| SVCHMTS-1-r1-L4 | KO                   |
| SVCHMTS-1-r1-L5 | KO                   |
| SVCHMTS-2-r1-L0 | OK                   |
| SVCHMTS-2-r1-L1 | KO                   |
| SVCHMTS-2-r1-L2 | KO                   |
| SVCHS-1-r1-L0   | OK                   |
| SVCHS-1-r1-L1   | KO                   |
| SVCHS-2-r1-L0   | OK                   |
| SVCHS-2-r1-L1   | KO                   |
| SVCHST-1-r1-L0  | OK                   |
| SVCHST-1-r1-L1  | KO                   |
| SVCHST-1-r1-L2  | KO                   |
| SVCHST-2-r1-L0  | OK                   |
| SVCHST-2-r1-L1  | KO                   |
| SVCHST-2-r1-L2  | KO                   |
| SVCHST-3-r1-L0  | ER                   |
| SVCHST-3-r1-L1  | ER                   |
| SVCHST-4-r1-L0  | ER                   |
| SVCHST-4-r1-L1  | ER                   |
| SVCHSTC-1-r1-L0 | OK                   |
| SVCHSTC-1-r1-L1 | KO                   |
| SVCHSTC-1-r1-L2 | KO                   |
| -               | -                    |
| Test            | FFmpeg-H.264-v4l2m2m |
| TOTAL           | 75/185               |
| TOTAL TIME      | 727.240s             |

NOTE: The current implementation of the decoder only supports Layer 0 (base layer) processing.
When attempting to decode streams that contain multiple layers (such as scalable or multi-view content), the decoding operation fails.
This limitation means that enhanced features requiring layer-based processing beyond the base layer cannot be properly handled by the current decoder.
For successful decoding, input streams must be limited to single-layer content only.

[FLUSTER REPORT FOR THE H.265]

| -                               | -                    |
| AMP_A_Samsung_7                 | OK                   |
| AMP_B_Samsung_7                 | OK                   |
| AMP_D_Hisilicon_3               | OK                   |
| AMP_E_Hisilicon_3               | OK                   |
| AMP_F_Hisilicon_3               | ER                   |
| AMVP_A_MTK_4                    | ER                   |
| AMVP_B_MTK_4                    | OK                   |
| AMVP_C_Samsung_7                | ER                   |
| BUMPING_A_ericsson_1            | OK                   |
| CAINIT_A_SHARP_4                | OK                   |
| CAINIT_B_SHARP_4                | OK                   |
| CAINIT_C_SHARP_3                | OK                   |
| CAINIT_D_SHARP_3                | OK                   |
| CAINIT_E_SHARP_3                | OK                   |
| CAINIT_F_SHARP_3                | OK                   |
| CAINIT_G_SHARP_3                | OK                   |
| CAINIT_H_SHARP_3                | OK                   |
| CIP_A_Panasonic_3               | OK                   |
| cip_B_NEC_3                     | OK                   |
| CIP_C_Panasonic_2               | OK                   |
| CONFWIN_A_Sony_1                | OK                   |
| DBLK_A_MAIN10_VIXS_4            | ER                   |
| DBLK_A_SONY_3                   | OK                   |
| DBLK_B_SONY_3                   | OK                   |
| DBLK_C_SONY_3                   | OK                   |
| DBLK_D_VIXS_2                   | OK                   |
| DBLK_E_VIXS_2                   | OK                   |
| DBLK_F_VIXS_2                   | OK                   |
| DBLK_G_VIXS_2                   | OK                   |
| DELTAQP_A_BRCM_4                | OK                   |
| DELTAQP_B_SONY_3                | OK                   |
| DELTAQP_C_SONY_3                | OK                   |
| DSLICE_A_HHI_5                  | OK                   |
| DSLICE_B_HHI_5                  | OK                   |
| DSLICE_C_HHI_5                  | OK                   |
| ENTP_A_QUALCOMM_1               | OK                   |
| ENTP_B_Qualcomm_1               | OK                   |
| ENTP_C_Qualcomm_1               | OK                   |
| EXT_A_ericsson_4                | OK                   |
| FILLER_A_Sony_1                 | OK                   |
| HRD_A_Fujitsu_3                 | OK                   |
| INITQP_A_Sony_1                 | OK                   |
| INITQP_B_Main10_Sony_1          | ER                   |
| ipcm_A_NEC_3                    | OK                   |
| ipcm_B_NEC_3                    | OK                   |
| ipcm_C_NEC_3                    | OK                   |
| ipcm_D_NEC_3                    | OK                   |
| ipcm_E_NEC_2                    | OK                   |
| IPRED_A_docomo_2                | OK                   |
| IPRED_B_Nokia_3                 | OK                   |
| IPRED_C_Mitsubishi_3            | OK                   |
| LS_A_Orange_2                   | OK                   |
| LS_B_Orange_4                   | OK                   |
| LTRPSPS_A_Qualcomm_1            | KO                   |
| MAXBINS_A_TI_5                  | OK                   |
| MAXBINS_B_TI_5                  | OK                   |
| MAXBINS_C_TI_5                  | OK                   |
| MERGE_A_TI_3                    | OK                   |
| MERGE_B_TI_3                    | OK                   |
| MERGE_C_TI_3                    | OK                   |
| MERGE_D_TI_3                    | OK                   |
| MERGE_E_TI_3                    | OK                   |
| MERGE_F_MTK_4                   | OK                   |
| MERGE_G_HHI_4                   | OK                   |
| MVCLIP_A_qualcomm_3             | OK                   |
| MVDL1ZERO_A_docomo_4            | OK                   |
| MVEDGE_A_qualcomm_3             | OK                   |
| NoOutPrior_A_Qualcomm_1         | OK                   |
| NoOutPrior_B_Qualcomm_1         | OK                   |
| NUT_A_ericsson_5                | OK                   |
| OPFLAG_A_Qualcomm_1             | OK                   |
| OPFLAG_B_Qualcomm_1             | OK                   |
| OPFLAG_C_Qualcomm_1             | OK                   |
| PICSIZE_A_Bossen_1              | OK                   |
| PICSIZE_B_Bossen_1              | ER                   |
| PICSIZE_C_Bossen_1              | OK                   |
| PICSIZE_D_Bossen_1              | ER                   |
| PMERGE_A_TI_3                   | OK                   |
| PMERGE_B_TI_3                   | OK                   |
| PMERGE_C_TI_3                   | OK                   |
| PMERGE_D_TI_3                   | OK                   |
| PMERGE_E_TI_3                   | OK                   |
| POC_A_Bossen_3                  | OK                   |
| PPS_A_qualcomm_7                | OK                   |
| PS_B_VIDYO_3                    | ER                   |
| RAP_A_docomo_6                  | OK                   |
| RAP_B_Bossen_2                  | OK                   |
| RPLM_A_qualcomm_4               | OK                   |
| RPLM_B_qualcomm_4               | OK                   |
| RPS_A_docomo_5                  | OK                   |
| RPS_B_qualcomm_5                | OK                   |
| RPS_C_ericsson_5                | OK                   |
| RPS_D_ericsson_6                | OK                   |
| RPS_E_qualcomm_5                | OK                   |
| RPS_F_docomo_2                  | OK                   |
| RQT_A_HHI_4                     | OK                   |
| RQT_B_HHI_4                     | OK                   |
| RQT_C_HHI_4                     | OK                   |
| RQT_D_HHI_4                     | OK                   |
| RQT_E_HHI_4                     | OK                   |
| RQT_F_HHI_4                     | OK                   |
| RQT_G_HHI_4                     | OK                   |
| SAO_A_MediaTek_4                | OK                   |
| SAO_B_MediaTek_5                | OK                   |
| SAO_C_Samsung_5                 | OK                   |
| SAO_D_Samsung_5                 | OK                   |
| SAO_E_Canon_4                   | OK                   |
| SAO_F_Canon_3                   | OK                   |
| SAO_G_Canon_3                   | OK                   |
| SAO_H_Parabola_1                | OK                   |
| SAODBLK_A_MainConcept_4         | OK                   |
| SAODBLK_B_MainConcept_4         | OK                   |
| SDH_A_Orange_4                  | OK                   |
| SLICES_A_Rovi_3                 | OK                   |
| SLIST_A_Sony_5                  | OK                   |
| SLIST_B_Sony_9                  | OK                   |
| SLIST_C_Sony_4                  | OK                   |
| SLIST_D_Sony_9                  | OK                   |
| SLPPLP_A_VIDYO_2                | ER                   |
| STRUCT_A_Samsung_7              | ER                   |
| STRUCT_B_Samsung_7              | ER                   |
| TILES_A_Cisco_2                 | ER                   |
| TILES_B_Cisco_1                 | ER                   |
| TMVP_A_MS_3                     | OK                   |
| TSCL_A_VIDYO_5                  | OK                   |
| TSCL_B_VIDYO_4                  | ER                   |
| TSKIP_A_MS_3                    | OK                   |
| TSUNEQBD_A_MAIN10_Technicolor_2 | ER                   |
| TUSIZE_A_Samsung_1              | OK                   |
| VPSID_A_VIDYO_2                 | ER                   |
| VPSSPSPPS_A_MainConcept_1       | KO                   |
| WP_A_MAIN10_Toshiba_3           | ER                   |
| WP_A_Toshiba_3                  | ER                   |
| WP_B_Toshiba_3                  | OK                   |
| WP_MAIN10_B_Toshiba_3           | ER                   |
| WPP_A_ericsson_MAIN10_2         | ER                   |
| WPP_A_ericsson_MAIN_2           | OK                   |
| WPP_B_ericsson_MAIN10_2         | ER                   |
| WPP_B_ericsson_MAIN_2           | OK                   |
| WPP_C_ericsson_MAIN10_2         | ER                   |
| WPP_C_ericsson_MAIN_2           | OK                   |
| WPP_D_ericsson_MAIN10_2         | ER                   |
| WPP_D_ericsson_MAIN_2           | OK                   |
| WPP_E_ericsson_MAIN10_2         | ER                   |
| WPP_E_ericsson_MAIN_2           | OK                   |
| WPP_F_ericsson_MAIN10_2         | ER                   |
| WPP_F_ericsson_MAIN_2           | OK                   |
| -                               | -                    |
| Test                            | FFmpeg-H.265-v4l2m2m |
| TOTAL                           | 120/147              |
| TOTAL TIME                      | 12669.641s           |


Failed streams :
 - VPSSPSPPS_A_MainConcept_1 : Failed due to evolutive dynamic resolution increases. The decoder cannot properly handle upward resolution changes within the same stream.
 - LTRPSPS_A_Qualcomm_1

This patch series introduces a new stateful decoder driver for the
allegrodvt GEN 3 IPs.

Yassine Ouaissa (3):
  media: allegro-dvt: Move the current driver to a subdirectory
  media: allegro-dvt: Add Gen 3 IP stateful decoder driver
  media: allegro-dvt: Add DT-bindings for the Gen 3 IP

 .../bindings/media/allegrodvt,al300-vdec.yaml |   86 +
 .../devicetree/bindings/vendor-prefixes.yaml  |    2 +-
 MAINTAINERS                                   |    5 +-
 drivers/media/platform/allegro-dvt/Kconfig    |   17 +-
 drivers/media/platform/allegro-dvt/Makefile   |    6 +-
 .../media/platform/allegro-dvt/al300/Kconfig  |   12 +
 .../media/platform/allegro-dvt/al300/Makefile |    6 +
 .../allegro-dvt/al300/al_codec_common.c       |  781 +++++++++
 .../allegro-dvt/al300/al_codec_common.h       |  226 +++
 .../allegro-dvt/al300/al_codec_util.c         |  179 ++
 .../allegro-dvt/al300/al_codec_util.h         |  186 ++
 .../platform/allegro-dvt/al300/al_vdec_drv.c  | 1536 +++++++++++++++++
 .../platform/allegro-dvt/al300/al_vdec_drv.h  |   94 +
 .../media/platform/allegro-dvt/zynqmp/Kconfig |   17 +
 .../platform/allegro-dvt/zynqmp/Makefile      |    6 +
 .../allegro-dvt/{ => zynqmp}/allegro-core.c   |    0
 .../allegro-dvt/{ => zynqmp}/allegro-mail.c   |    0
 .../allegro-dvt/{ => zynqmp}/allegro-mail.h   |    0
 .../allegro-dvt/{ => zynqmp}/nal-h264.c       |    0
 .../allegro-dvt/{ => zynqmp}/nal-h264.h       |    0
 .../allegro-dvt/{ => zynqmp}/nal-hevc.c       |    0
 .../allegro-dvt/{ => zynqmp}/nal-hevc.h       |    0
 .../allegro-dvt/{ => zynqmp}/nal-rbsp.c       |    0
 .../allegro-dvt/{ => zynqmp}/nal-rbsp.h       |    0
 24 files changed, 3138 insertions(+), 21 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/media/allegrodvt,al300-vdec.yaml
 create mode 100644 drivers/media/platform/allegro-dvt/al300/Kconfig
 create mode 100644 drivers/media/platform/allegro-dvt/al300/Makefile
 create mode 100644 drivers/media/platform/allegro-dvt/al300/al_codec_common.c
 create mode 100644 drivers/media/platform/allegro-dvt/al300/al_codec_common.h
 create mode 100644 drivers/media/platform/allegro-dvt/al300/al_codec_util.c
 create mode 100644 drivers/media/platform/allegro-dvt/al300/al_codec_util.h
 create mode 100644 drivers/media/platform/allegro-dvt/al300/al_vdec_drv.c
 create mode 100644 drivers/media/platform/allegro-dvt/al300/al_vdec_drv.h
 create mode 100644 drivers/media/platform/allegro-dvt/zynqmp/Kconfig
 create mode 100644 drivers/media/platform/allegro-dvt/zynqmp/Makefile
 rename drivers/media/platform/allegro-dvt/{ => zynqmp}/allegro-core.c (100%)
 rename drivers/media/platform/allegro-dvt/{ => zynqmp}/allegro-mail.c (100%)
 rename drivers/media/platform/allegro-dvt/{ => zynqmp}/allegro-mail.h (100%)
 rename drivers/media/platform/allegro-dvt/{ => zynqmp}/nal-h264.c (100%)
 rename drivers/media/platform/allegro-dvt/{ => zynqmp}/nal-h264.h (100%)
 rename drivers/media/platform/allegro-dvt/{ => zynqmp}/nal-hevc.c (100%)
 rename drivers/media/platform/allegro-dvt/{ => zynqmp}/nal-hevc.h (100%)
 rename drivers/media/platform/allegro-dvt/{ => zynqmp}/nal-rbsp.c (100%)
 rename drivers/media/platform/allegro-dvt/{ => zynqmp}/nal-rbsp.h (100%)

-- 
2.30.2

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

* [PATCH 1/3] media: allegro-dvt: Move the current driver to a subdirectory
  2025-05-11 14:47 [PATCH 0/3] media: Add Gen 3 IP stateful decoder driver Yassine Ouaissa
@ 2025-05-11 14:47 ` Yassine Ouaissa
  2025-05-11 14:47 ` [PATCH 2/3] media: allegro-dvt: Add Gen 3 IP stateful decoder driver Yassine Ouaissa
  2025-05-11 14:47 ` [PATCH 3/3] media: allegro-dvt: Add DT-bindings for the Gen 3 IP Yassine Ouaissa
  2 siblings, 0 replies; 13+ messages in thread
From: Yassine Ouaissa @ 2025-05-11 14:47 UTC (permalink / raw)
  To: Michael Tretter, Yassine OUAISSA, Pengutronix Kernel Team,
	Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Michal Simek, Neil Armstrong, Heiko Stuebner,
	Junhao Xie, Rafał Miłecki, Aradhya Bhatia,
	Manivannan Sadhasivam, Kever Yang, Hans Verkuil,
	Andrzej Pietrasiewicz, Joe Hattori, Sebastian Fricke,
	Christophe JAILLET, Uwe Kleine-König, Gaosheng Cui,
	Wolfram Sang, Ricardo Ribalda, linux-media, devicetree,
	linux-kernel, linux-arm-kernel

In preparation for the upcoming driver update, we need to relocate the
current driver.
This will help ensure a clean transition and avoid any potential
conflicts with the new driver.
This patch is crucial for keeping our directory organized and
facilitating a smooth integration of the new driver.

Signed-off-by: Yassine Ouaissa <yassine.ouaissa@allegrodvt.com>
---
 MAINTAINERS                                     |  2 +-
 drivers/media/platform/allegro-dvt/Kconfig      | 16 +---------------
 drivers/media/platform/allegro-dvt/Makefile     |  5 +----
 .../media/platform/allegro-dvt/zynqmp/Kconfig   | 17 +++++++++++++++++
 .../media/platform/allegro-dvt/zynqmp/Makefile  |  6 ++++++
 .../allegro-dvt/{ => zynqmp}/allegro-core.c     |  0
 .../allegro-dvt/{ => zynqmp}/allegro-mail.c     |  0
 .../allegro-dvt/{ => zynqmp}/allegro-mail.h     |  0
 .../allegro-dvt/{ => zynqmp}/nal-h264.c         |  0
 .../allegro-dvt/{ => zynqmp}/nal-h264.h         |  0
 .../allegro-dvt/{ => zynqmp}/nal-hevc.c         |  0
 .../allegro-dvt/{ => zynqmp}/nal-hevc.h         |  0
 .../allegro-dvt/{ => zynqmp}/nal-rbsp.c         |  0
 .../allegro-dvt/{ => zynqmp}/nal-rbsp.h         |  0
 14 files changed, 26 insertions(+), 20 deletions(-)
 create mode 100644 drivers/media/platform/allegro-dvt/zynqmp/Kconfig
 create mode 100644 drivers/media/platform/allegro-dvt/zynqmp/Makefile
 rename drivers/media/platform/allegro-dvt/{ => zynqmp}/allegro-core.c (100%)
 rename drivers/media/platform/allegro-dvt/{ => zynqmp}/allegro-mail.c (100%)
 rename drivers/media/platform/allegro-dvt/{ => zynqmp}/allegro-mail.h (100%)
 rename drivers/media/platform/allegro-dvt/{ => zynqmp}/nal-h264.c (100%)
 rename drivers/media/platform/allegro-dvt/{ => zynqmp}/nal-h264.h (100%)
 rename drivers/media/platform/allegro-dvt/{ => zynqmp}/nal-hevc.c (100%)
 rename drivers/media/platform/allegro-dvt/{ => zynqmp}/nal-hevc.h (100%)
 rename drivers/media/platform/allegro-dvt/{ => zynqmp}/nal-rbsp.c (100%)
 rename drivers/media/platform/allegro-dvt/{ => zynqmp}/nal-rbsp.h (100%)

diff --git a/MAINTAINERS b/MAINTAINERS
index fa1e04e87d1d..d81d2756cb2e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -806,7 +806,7 @@ R:	Pengutronix Kernel Team <kernel@pengutronix.de>
 L:	linux-media@vger.kernel.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/media/allegro,al5e.yaml
-F:	drivers/media/platform/allegro-dvt/
+F:	drivers/media/platform/allegro-dvt/zynqmp
 
 ALLIED VISION ALVIUM CAMERA DRIVER
 M:	Tommaso Merciai <tomm.merciai@gmail.com>
diff --git a/drivers/media/platform/allegro-dvt/Kconfig b/drivers/media/platform/allegro-dvt/Kconfig
index 2182e1277568..e9008614c27b 100644
--- a/drivers/media/platform/allegro-dvt/Kconfig
+++ b/drivers/media/platform/allegro-dvt/Kconfig
@@ -2,18 +2,4 @@
 
 comment "Allegro DVT media platform drivers"
 
-config VIDEO_ALLEGRO_DVT
-	tristate "Allegro DVT Video IP Core"
-	depends on V4L_MEM2MEM_DRIVERS
-	depends on VIDEO_DEV
-	depends on ARCH_ZYNQMP || COMPILE_TEST
-	select V4L2_MEM2MEM_DEV
-	select VIDEOBUF2_DMA_CONTIG
-	select REGMAP_MMIO
-	help
-	  Support for the encoder video IP core by Allegro DVT. This core is
-	  found for example on the Xilinx ZynqMP SoC in the EV family and is
-	  called VCU in the reference manual.
-
-	  To compile this driver as a module, choose M here: the module
-	  will be called allegro.
+source "drivers/media/platform/allegro-dvt/zynqmp/Kconfig"
diff --git a/drivers/media/platform/allegro-dvt/Makefile b/drivers/media/platform/allegro-dvt/Makefile
index 66108a303774..d2aa6875edcf 100644
--- a/drivers/media/platform/allegro-dvt/Makefile
+++ b/drivers/media/platform/allegro-dvt/Makefile
@@ -1,6 +1,3 @@
 # SPDX-License-Identifier: GPL-2.0
 
-allegro-objs := allegro-core.o allegro-mail.o
-allegro-objs += nal-rbsp.o nal-h264.o nal-hevc.o
-
-obj-$(CONFIG_VIDEO_ALLEGRO_DVT) += allegro.o
+obj-y += zynqmp/
diff --git a/drivers/media/platform/allegro-dvt/zynqmp/Kconfig b/drivers/media/platform/allegro-dvt/zynqmp/Kconfig
new file mode 100644
index 000000000000..0a0a697c420d
--- /dev/null
+++ b/drivers/media/platform/allegro-dvt/zynqmp/Kconfig
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config VIDEO_ALLEGRO_DVT
+	tristate "Allegro DVT Video IP Core for ZynqMP"
+	depends on V4L_MEM2MEM_DRIVERS
+	depends on VIDEO_DEV
+	depends on ARCH_ZYNQMP || COMPILE_TEST
+	select V4L2_MEM2MEM_DEV
+	select VIDEOBUF2_DMA_CONTIG
+	select REGMAP_MMIO
+	help
+	  Support for the encoder video IP core by Allegro DVT. This core is
+	  found for example on the Xilinx ZynqMP SoC in the EV family and is
+	  called VCU in the reference manual.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called allegro.
diff --git a/drivers/media/platform/allegro-dvt/zynqmp/Makefile b/drivers/media/platform/allegro-dvt/zynqmp/Makefile
new file mode 100644
index 000000000000..66108a303774
--- /dev/null
+++ b/drivers/media/platform/allegro-dvt/zynqmp/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+
+allegro-objs := allegro-core.o allegro-mail.o
+allegro-objs += nal-rbsp.o nal-h264.o nal-hevc.o
+
+obj-$(CONFIG_VIDEO_ALLEGRO_DVT) += allegro.o
diff --git a/drivers/media/platform/allegro-dvt/allegro-core.c b/drivers/media/platform/allegro-dvt/zynqmp/allegro-core.c
similarity index 100%
rename from drivers/media/platform/allegro-dvt/allegro-core.c
rename to drivers/media/platform/allegro-dvt/zynqmp/allegro-core.c
diff --git a/drivers/media/platform/allegro-dvt/allegro-mail.c b/drivers/media/platform/allegro-dvt/zynqmp/allegro-mail.c
similarity index 100%
rename from drivers/media/platform/allegro-dvt/allegro-mail.c
rename to drivers/media/platform/allegro-dvt/zynqmp/allegro-mail.c
diff --git a/drivers/media/platform/allegro-dvt/allegro-mail.h b/drivers/media/platform/allegro-dvt/zynqmp/allegro-mail.h
similarity index 100%
rename from drivers/media/platform/allegro-dvt/allegro-mail.h
rename to drivers/media/platform/allegro-dvt/zynqmp/allegro-mail.h
diff --git a/drivers/media/platform/allegro-dvt/nal-h264.c b/drivers/media/platform/allegro-dvt/zynqmp/nal-h264.c
similarity index 100%
rename from drivers/media/platform/allegro-dvt/nal-h264.c
rename to drivers/media/platform/allegro-dvt/zynqmp/nal-h264.c
diff --git a/drivers/media/platform/allegro-dvt/nal-h264.h b/drivers/media/platform/allegro-dvt/zynqmp/nal-h264.h
similarity index 100%
rename from drivers/media/platform/allegro-dvt/nal-h264.h
rename to drivers/media/platform/allegro-dvt/zynqmp/nal-h264.h
diff --git a/drivers/media/platform/allegro-dvt/nal-hevc.c b/drivers/media/platform/allegro-dvt/zynqmp/nal-hevc.c
similarity index 100%
rename from drivers/media/platform/allegro-dvt/nal-hevc.c
rename to drivers/media/platform/allegro-dvt/zynqmp/nal-hevc.c
diff --git a/drivers/media/platform/allegro-dvt/nal-hevc.h b/drivers/media/platform/allegro-dvt/zynqmp/nal-hevc.h
similarity index 100%
rename from drivers/media/platform/allegro-dvt/nal-hevc.h
rename to drivers/media/platform/allegro-dvt/zynqmp/nal-hevc.h
diff --git a/drivers/media/platform/allegro-dvt/nal-rbsp.c b/drivers/media/platform/allegro-dvt/zynqmp/nal-rbsp.c
similarity index 100%
rename from drivers/media/platform/allegro-dvt/nal-rbsp.c
rename to drivers/media/platform/allegro-dvt/zynqmp/nal-rbsp.c
diff --git a/drivers/media/platform/allegro-dvt/nal-rbsp.h b/drivers/media/platform/allegro-dvt/zynqmp/nal-rbsp.h
similarity index 100%
rename from drivers/media/platform/allegro-dvt/nal-rbsp.h
rename to drivers/media/platform/allegro-dvt/zynqmp/nal-rbsp.h
-- 
2.30.2


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

* [PATCH 2/3] media: allegro-dvt: Add Gen 3 IP stateful decoder driver
  2025-05-11 14:47 [PATCH 0/3] media: Add Gen 3 IP stateful decoder driver Yassine Ouaissa
  2025-05-11 14:47 ` [PATCH 1/3] media: allegro-dvt: Move the current driver to a subdirectory Yassine Ouaissa
@ 2025-05-11 14:47 ` Yassine Ouaissa
  2025-05-11 20:49   ` kernel test robot
  2025-05-12 22:39   ` kernel test robot
  2025-05-11 14:47 ` [PATCH 3/3] media: allegro-dvt: Add DT-bindings for the Gen 3 IP Yassine Ouaissa
  2 siblings, 2 replies; 13+ messages in thread
From: Yassine Ouaissa @ 2025-05-11 14:47 UTC (permalink / raw)
  To: Michael Tretter, Yassine OUAISSA, Pengutronix Kernel Team,
	Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Michal Simek, Neil Armstrong, Heiko Stuebner,
	Junhao Xie, Aradhya Bhatia, Rafał Miłecki, Kever Yang,
	Manivannan Sadhasivam, Hans Verkuil, Andrzej Pietrasiewicz,
	Joe Hattori, Christophe JAILLET, Uwe Kleine-König,
	Wolfram Sang, Gaosheng Cui, Ricardo Ribalda, linux-media,
	devicetree, linux-kernel, linux-arm-kernel

This commit introduces a new allegro-dvt V4L2 stateful decoder driver
for the Gen 3 IP with support for:
- AVC (H.264), HEVC (H.265), and JPEG decoding
- Output formats: NV12, NV16, I420, and P010 for capture

The allegrodvt is added to the vendor-prefixes.yaml.
Update the MAINTAINERS file by adding the new driver directory.

Signed-off-by: Yassine Ouaissa <yassine.ouaissa@allegrodvt.com>
---
 .../devicetree/bindings/vendor-prefixes.yaml  |    2 +-
 MAINTAINERS                                   |    2 +
 drivers/media/platform/allegro-dvt/Kconfig    |    1 +
 drivers/media/platform/allegro-dvt/Makefile   |    1 +
 .../media/platform/allegro-dvt/al300/Kconfig  |   12 +
 .../media/platform/allegro-dvt/al300/Makefile |    6 +
 .../allegro-dvt/al300/al_codec_common.c       |  781 +++++++++
 .../allegro-dvt/al300/al_codec_common.h       |  226 +++
 .../allegro-dvt/al300/al_codec_util.c         |  179 ++
 .../allegro-dvt/al300/al_codec_util.h         |  186 ++
 .../platform/allegro-dvt/al300/al_vdec_drv.c  | 1536 +++++++++++++++++
 .../platform/allegro-dvt/al300/al_vdec_drv.h  |   94 +
 12 files changed, 3025 insertions(+), 1 deletion(-)
 create mode 100644 drivers/media/platform/allegro-dvt/al300/Kconfig
 create mode 100644 drivers/media/platform/allegro-dvt/al300/Makefile
 create mode 100644 drivers/media/platform/allegro-dvt/al300/al_codec_common.c
 create mode 100644 drivers/media/platform/allegro-dvt/al300/al_codec_common.h
 create mode 100644 drivers/media/platform/allegro-dvt/al300/al_codec_util.c
 create mode 100644 drivers/media/platform/allegro-dvt/al300/al_codec_util.h
 create mode 100644 drivers/media/platform/allegro-dvt/al300/al_vdec_drv.c
 create mode 100644 drivers/media/platform/allegro-dvt/al300/al_vdec_drv.h

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index 86f6a19b28ae..90bc1ec721ed 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -81,7 +81,7 @@ patternProperties:
     description: Aldec, Inc.
   "^alfa-network,.*":
     description: ALFA Network Inc.
-  "^allegro,.*":
+  "^(allegro|allegrodvt),.*":
     description: Allegro DVT
   "^allegromicro,.*":
     description: Allegro MicroSystems, Inc.
diff --git a/MAINTAINERS b/MAINTAINERS
index d81d2756cb2e..313d08cf90e0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -802,10 +802,12 @@ F:	drivers/platform/x86/dell/alienware-wmi*
 
 ALLEGRO DVT VIDEO IP CORE DRIVER
 M:	Michael Tretter <m.tretter@pengutronix.de>
+M:	Yassine OUAISSA <yassine.ouaissa@allegrodvt.com>
 R:	Pengutronix Kernel Team <kernel@pengutronix.de>
 L:	linux-media@vger.kernel.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/media/allegro,al5e.yaml
+F:	drivers/media/platform/allegro-dvt/al300
 F:	drivers/media/platform/allegro-dvt/zynqmp
 
 ALLIED VISION ALVIUM CAMERA DRIVER
diff --git a/drivers/media/platform/allegro-dvt/Kconfig b/drivers/media/platform/allegro-dvt/Kconfig
index e9008614c27b..0d01ed0ad08a 100644
--- a/drivers/media/platform/allegro-dvt/Kconfig
+++ b/drivers/media/platform/allegro-dvt/Kconfig
@@ -2,4 +2,5 @@
 
 comment "Allegro DVT media platform drivers"
 
+source "drivers/media/platform/allegro-dvt/al300/Kconfig"
 source "drivers/media/platform/allegro-dvt/zynqmp/Kconfig"
diff --git a/drivers/media/platform/allegro-dvt/Makefile b/drivers/media/platform/allegro-dvt/Makefile
index d2aa6875edcf..c70ca19a47fb 100644
--- a/drivers/media/platform/allegro-dvt/Makefile
+++ b/drivers/media/platform/allegro-dvt/Makefile
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
 
+obj-y += al300/
 obj-y += zynqmp/
diff --git a/drivers/media/platform/allegro-dvt/al300/Kconfig b/drivers/media/platform/allegro-dvt/al300/Kconfig
new file mode 100644
index 000000000000..74bafb286250
--- /dev/null
+++ b/drivers/media/platform/allegro-dvt/al300/Kconfig
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config VIDEO_ALLEGRO_DVT_D300
+	tristate "Allegro DVT Video IP Decode Gen 3"
+	depends on V4L_MEM2MEM_DRIVERS
+	depends on VIDEO_DEV && OF && HAS_DMA
+	select V4L2_MEM2MEM_DEV
+	select VIDEOBUF2_DMA_CONTIG
+	select REGMAP_MMIO
+	help
+	  This is a video4linux2 driver for the Allegro DVT IP Decode Gen 3,
+	  that support codecs : AVC (H.264), HEVC (H.265), and JPEG.
diff --git a/drivers/media/platform/allegro-dvt/al300/Makefile b/drivers/media/platform/allegro-dvt/al300/Makefile
new file mode 100644
index 000000000000..3c50caccb731
--- /dev/null
+++ b/drivers/media/platform/allegro-dvt/al300/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+
+al300-vdec-objs := al_codec_common.o al_codec_util.o
+al300-vdec-objs += al_vdec_drv.o
+
+obj-$(CONFIG_VIDEO_ALLEGRO_DVT_D300) += al300-vdec.o
diff --git a/drivers/media/platform/allegro-dvt/al300/al_codec_common.c b/drivers/media/platform/allegro-dvt/al300/al_codec_common.c
new file mode 100644
index 000000000000..9c137b1da113
--- /dev/null
+++ b/drivers/media/platform/allegro-dvt/al300/al_codec_common.c
@@ -0,0 +1,781 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Core MCU functionality including firmware loading,
+ * memory allocation, and general MCU interaction interfaces
+ *
+ * Copyright (c) 2025 Allegro DVT.
+ * Author: Yassine OUAISSA <yassine.ouaissa@allegrodvt.fr>
+ */
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/firmware.h>
+#include <linux/interrupt.h>
+#include <linux/of_reserved_mem.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include "al_codec_common.h"
+
+#define AL_CODEC_UID 0x0000
+#define AL_CODEC_UID_ID 0x30AB6E51
+#define AL_CODEC_RESET 0x0010
+#define AL_CODEC_RESET_CMD BIT(0)
+#define AL_CODEC_COMM_MASK BIT(0)
+#define AL_CODEC_IRQ_MASK 0x0014
+#define AL_CODEC_IRQ_STATUS_CLEAR 0x0018
+#define AL_CODEC_IRQ_MCU_2_CPU BIT(30)
+#define AL_CODEC_MCU_CLK 0x0400
+#define AL_CODEC_MCU_CLK_ENABLE BIT(0)
+#define AL_CODEC_MCU_CLK_DISABLE 0
+#define AL_CODEC_MCU_RST 0x0404
+#define AL_CODEC_MCU_RST_ENABLE BIT(0)
+#define AL_CODEC_MCU_RST_DISABLE 0
+#define AL_CODEC_MCU_IRQ 0x040C
+#define AL_CODEC_MCU_BOOT_ADDR 0x0410
+#define AL_CODEC_MCU_APB_ADDR 0x0418
+#define AL_CODEC_MCU_PERIPHERAL_ADDR 0x0428
+#define AL_CODEC_MCU_IP_INTERRUPT_MASK 0x0440
+#define AL_CODEC_INSTRUCTION_DATA_OFFSET 0x0450
+#define AL_CODEC_IP_OFFSET GENMASK(26, 25)
+#define AL_CODEC_APB_MASK GENMASK(26, 0)
+#define AL_CODEC_MAX_ADDR GENMASK_ULL(38, 0)
+
+#define AL_CODEC_MCU_BOOT_RESET_WAIT 2000 /* in us */
+
+/*
+ * struct codec_dma_buf - Allocated dma buffer
+ *
+ * @list: list head for buffer queue
+ * @paddr: physical address of the allcated DMA buffer
+ * @vaddr: virtual address of the allocated DMA buffer
+ * @size: Size of allocated dma memory
+ */
+struct codec_dma_buf {
+	void *vaddr;
+	dma_addr_t paddr;
+	u32 size;
+	struct list_head list;
+};
+
+struct mb_header {
+	u64 start;
+	u64 end;
+} __packed;
+
+struct boot_header {
+	u32 bh_version;
+	u32 fw_version;
+	char model[16];
+	u64 vaddr_start;
+	u64 vaddr_end;
+	u64 vaddr_boot;
+	struct mb_header h2m;
+	struct mb_header m2h;
+	u64 machine_id;
+	/* fill by driver before fw boot */
+	u64 ip_start;
+	u64 ip_end;
+	u64 mcu_clk_rate;
+} __packed;
+
+/* Regmap config */
+static const struct regmap_config al_regmap_config = {
+	.name = "regs",
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+	.max_register = 0xfff,
+	.fast_io = true,
+	.cache_type = REGCACHE_NONE,
+	.can_multi_write = true,
+};
+
+static inline int al_common_read(struct al_common_dev *dev, u32 offset,
+				 u32 *val)
+{
+	return regmap_read(dev->regmap, offset, val);
+}
+
+static inline int al_common_write(struct al_common_dev *dev, u32 offset,
+				  u32 val)
+{
+	return regmap_write(dev->regmap, offset, val);
+}
+
+static inline int al_common_write_multiple(struct al_common_dev *dev,
+					   u32 offset, const void *val,
+					   u32 num_regs)
+{
+	return regmap_bulk_write(dev->regmap, offset, val, num_regs);
+}
+
+static inline int common_update_bits(struct al_common_dev *dev, u32 offset,
+				     u32 mask, u32 val)
+{
+	return regmap_update_bits(dev->regmap, offset, mask, val);
+}
+
+static void common_trigger_mcu_irq(void *arg)
+{
+	struct al_common_dev *dev = arg;
+
+	common_update_bits(dev, AL_CODEC_MCU_IRQ, AL_CODEC_COMM_MASK, BIT(0));
+}
+
+static void common_reset(struct al_common_dev *dev)
+{
+	/* reset ip */
+	common_update_bits(dev, AL_CODEC_RESET, AL_CODEC_COMM_MASK,
+			   AL_CODEC_RESET_CMD);
+
+	/* reset and stop mcu */
+	al_common_write(dev, AL_CODEC_MCU_CLK, AL_CODEC_MCU_CLK_ENABLE);
+	al_common_write(dev, AL_CODEC_MCU_RST, AL_CODEC_MCU_RST_ENABLE);
+	/* time to reset the mct */
+	udelay(AL_CODEC_MCU_BOOT_RESET_WAIT);
+	al_common_write(dev, AL_CODEC_MCU_CLK, AL_CODEC_MCU_CLK_DISABLE);
+
+	common_update_bits(dev, AL_CODEC_MCU_IRQ, AL_CODEC_COMM_MASK, 0);
+	al_common_write(dev, AL_CODEC_MCU_IP_INTERRUPT_MASK, 0);
+
+	udelay(AL_CODEC_MCU_BOOT_RESET_WAIT * 5);
+	common_update_bits(dev, AL_CODEC_MCU_RST, AL_CODEC_COMM_MASK,
+			   AL_CODEC_MCU_RST_DISABLE);
+}
+
+static int common_probe_check_and_setup_hw(struct al_common_dev *dev)
+{
+	unsigned int id;
+	int ret;
+
+	/* Check regmap */
+	if (WARN_ON(!dev->regmap))
+		return -EINVAL;
+
+	ret = al_common_read(dev, AL_CODEC_UID, &id);
+
+	if (ret)
+		return ret;
+
+	if (id != AL_CODEC_UID_ID) {
+		al_codec_err(dev, "bad device id, expected 0x%08x, got 0x%08x",
+			     AL_CODEC_UID_ID, id);
+		return -ENODEV;
+	}
+
+	common_reset(dev);
+	al_common_write(dev, AL_CODEC_IRQ_MASK, AL_CODEC_IRQ_MCU_2_CPU);
+
+	return 0;
+}
+
+static void common_dma_buf_insert(struct al_common_dev *dev,
+				  struct codec_dma_buf *buf)
+{
+	mutex_lock(&dev->buf_lock);
+	list_add(&buf->list, &dev->alloc_buffers);
+	mutex_unlock(&dev->buf_lock);
+}
+
+static void common_dma_buf_remove(struct al_common_dev *dev,
+				  struct codec_dma_buf *buf)
+{
+	mutex_lock(&dev->buf_lock);
+	list_del(&buf->list);
+	mutex_unlock(&dev->buf_lock);
+}
+
+static struct codec_dma_buf *common_dma_buf_lookup(struct al_common_dev *dev,
+						   dma_addr_t buf_paddr)
+{
+	struct codec_dma_buf *buf = NULL;
+
+	mutex_lock(&dev->buf_lock);
+	list_for_each_entry(buf, &dev->alloc_buffers, list)
+		if (likely(buf->paddr == buf_paddr))
+			break;
+
+	mutex_unlock(&dev->buf_lock);
+
+	return list_entry_is_head(buf, &dev->alloc_buffers, list) ? NULL : buf;
+}
+
+static void common_dma_buf_cleanup(struct al_common_dev *dev)
+{
+	struct codec_dma_buf *buf, *tmp;
+
+	mutex_lock(&dev->buf_lock);
+	list_for_each_entry_safe(buf, tmp, &dev->alloc_buffers, list) {
+		dma_free_coherent(&dev->pdev->dev, buf->size, buf->vaddr,
+				  buf->paddr);
+		list_del(&buf->list);
+		kfree(buf);
+	}
+	mutex_unlock(&dev->buf_lock);
+}
+
+static void *common_dma_alloc(struct al_common_dev *dev, size_t size,
+			      dma_addr_t *paddr, gfp_t flag)
+{
+	void *vaddr;
+
+	vaddr = dma_alloc_coherent(&dev->pdev->dev, size, paddr, flag);
+
+	if (!vaddr)
+		return NULL;
+
+	/* PADDR <= (2^39 - 1) (39-bit MCU PADDR) */
+	if ((*paddr + size) > AL_CODEC_MAX_ADDR) {
+		al_codec_err(dev, "mem check failed for 0x%16llx of size %zu",
+			     *paddr, size);
+		dma_free_coherent(&dev->pdev->dev, size, vaddr, *paddr);
+		return NULL;
+	}
+
+	return vaddr;
+}
+
+void al_common_remove(struct al_common_dev *dev)
+{
+	common_dma_buf_cleanup(dev);
+	if (dev->fw_cpu_mem)
+		dma_free_coherent(&dev->pdev->dev, dev->fw_size,
+				  dev->fw_cpu_mem, dev->fw_phys_addr);
+
+	/* reset device */
+	common_reset(dev);
+}
+
+static void handle_alloc_memory_req(struct al_common_dev *dev,
+				    struct msg_itf_header *hdr)
+{
+	struct msg_itf_alloc_mem_reply_full reply;
+	struct msg_itf_alloc_mem_req req;
+	struct codec_dma_buf *buf;
+	int ret;
+
+	reply.reply.phyAddr = 0;
+	ret = al_common_get_data(dev, (char *)&req, hdr->payload_len);
+	if (ret) {
+		al_codec_err(dev, "Unable to get cma req");
+		return;
+	}
+
+	buf = kmalloc(sizeof(*buf), GFP_KERNEL);
+	if (!buf)
+		goto send_reply;
+
+	buf->size = req.uSize;
+	buf->vaddr = common_dma_alloc(dev, req.uSize, &buf->paddr, GFP_KERNEL);
+	if (!buf->vaddr)
+		goto send_reply;
+
+	reply.reply.phyAddr = (u64)buf->paddr;
+	common_dma_buf_insert(dev, buf);
+
+send_reply:
+	reply.hdr.type = MSG_ITF_TYPE_ALLOC_MEM_REPLY;
+	/* both fields embed info need to finish request */
+	reply.hdr.drv_ctx_hdl = hdr->drv_ctx_hdl;
+	reply.hdr.drv_cmd_hdl = hdr->drv_cmd_hdl;
+	reply.hdr.payload_len = sizeof(reply.reply);
+
+	ret = al_common_send(dev, &reply.hdr);
+	if (ret) {
+		al_codec_err(dev, "Unable to reply to cma alloc");
+		common_dma_buf_remove(dev, buf);
+	}
+}
+
+static void handle_free_memory_req(struct al_common_dev *dev,
+				   struct msg_itf_header *hdr)
+{
+	struct msg_itf_free_mem_reply_full reply;
+	struct msg_itf_free_mem_req req;
+	struct codec_dma_buf *buf;
+	int ret;
+
+	reply.reply.ret = -1;
+	ret = al_common_get_data(dev, (char *)&req, hdr->payload_len);
+	if (ret) {
+		al_codec_err(dev, "Unable to put cma req");
+		return;
+	}
+
+	buf = common_dma_buf_lookup(dev, req.phyAddr);
+	al_codec_dbg(3, "req.phyAddr = %p => %p, Size %d",
+		     (void *)(long)req.phyAddr, buf, buf->size);
+	if (!buf) {
+		al_codec_err(dev, "Unable to get dma handle for %p",
+			     (void *)(long)req.phyAddr);
+		reply.reply.ret = -EINVAL;
+		goto send_reply;
+	}
+
+	dma_free_coherent(&dev->pdev->dev, buf->size, buf->vaddr, buf->paddr);
+	common_dma_buf_remove(dev, buf);
+	reply.reply.ret = 0;
+
+send_reply:
+	reply.hdr.type = MSG_ITF_TYPE_FREE_MEM_REPLY;
+	/* both fields embed info need to hinish request */
+	reply.hdr.drv_ctx_hdl = hdr->drv_ctx_hdl;
+	reply.hdr.drv_cmd_hdl = hdr->drv_cmd_hdl;
+	reply.hdr.payload_len = sizeof(reply.reply);
+
+	ret = al_common_send(dev, &reply.hdr);
+	if (ret)
+		al_codec_err(dev, "Unable to reply to cma free");
+}
+
+static void handle_mcu_console_print(struct al_common_dev *dev,
+				     struct msg_itf_header *hdr)
+{
+#if defined(DEBUG)
+	struct msg_itf_write_req *req;
+	int ret;
+
+	/* one more byte to be sure to have a zero terminated string */
+	req = kzalloc(hdr->payload_len + 1, GFP_KERNEL);
+	if (!req) {
+		al_common_skip_data(dev, hdr->payload_len);
+		al_codec_err(dev, "Unable to alloc memory");
+		return;
+	}
+
+	ret = al_codec_msg_get_data(&dev->mb_m2h, (char *)req,
+				    hdr->payload_len);
+	if (ret) {
+		al_codec_err(dev, "Unable to get request");
+		kfree(req);
+		return;
+	}
+
+	al_mcu_dbg("%s", (char *)(req + 1));
+	kfree(req);
+#else
+	al_common_skip_data(dev, hdr->payload_len);
+#endif
+}
+
+static void process_one_message(struct al_common_dev *dev,
+				struct msg_itf_header *hdr)
+{
+	if (hdr->type == MSG_ITF_TYPE_ALLOC_MEM_REQ)
+		handle_alloc_memory_req(dev, hdr);
+	else if (hdr->type == MSG_ITF_TYPE_FREE_MEM_REQ)
+		handle_free_memory_req(dev, hdr);
+	else if (hdr->type == MSG_ITF_TYPE_WRITE_REQ)
+		handle_mcu_console_print(dev, hdr);
+	else if (hdr->type == MSG_ITF_TYPE_MCU_ALIVE)
+		complete(&dev->completion);
+	else
+		dev->process_msg_cb(dev->cb_arg, hdr);
+}
+
+static void common_reply_handle(struct al_common_dev *dev)
+{
+	struct msg_itf_header hdr;
+	int ret;
+
+	while (1) {
+		ret = al_codec_msg_get_header(&dev->mb_m2h, &hdr);
+		if (ret)
+			break;
+
+		process_one_message(dev, &hdr);
+	}
+}
+
+static irqreturn_t common_irq_handler(int irq, void *data)
+{
+	struct al_common_dev *dev = data;
+
+	/* poll all messages */
+	common_reply_handle(dev);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t common_hardirq_handler(int irq, void *data)
+{
+	struct al_common_dev *dev = data;
+	u32 irq_status;
+	int ret;
+
+	ret = al_common_read(dev, AL_CODEC_IRQ_STATUS_CLEAR, &irq_status);
+	if (ret || !irq_status)
+		return IRQ_NONE;
+
+	al_common_write(dev, AL_CODEC_IRQ_STATUS_CLEAR, AL_CODEC_IRQ_MCU_2_CPU);
+
+	return IRQ_WAKE_THREAD;
+}
+
+static inline u64 get_machine_boot_addr(struct al_common_dev *dev,
+					struct boot_header *bh)
+{
+	return dev->fw_phys_addr + bh->vaddr_boot - bh->vaddr_start;
+}
+
+static int common_start_fw(struct al_common_dev *dev, struct boot_header *bh)
+{
+	u64 boot_addr;
+	u32 regbuf[2] = { 0 };
+	int ret;
+
+	boot_addr = get_machine_boot_addr(dev, bh);
+	regbuf[0] = upper_32_bits(boot_addr);
+	regbuf[1] = lower_32_bits(boot_addr);
+
+	ret = al_common_write_multiple(dev, AL_CODEC_MCU_BOOT_ADDR, regbuf,
+				       ARRAY_SIZE(regbuf));
+	if (ret) {
+		al_codec_err(dev, "Unable to set the MCU boot address");
+		return ret;
+	}
+
+	al_codec_dbg(3, "boot_addr = %pad\n", &boot_addr);
+
+	/* Enable the MCU clock */
+	ret = common_update_bits(dev, AL_CODEC_MCU_CLK, AL_CODEC_COMM_MASK,
+				 AL_CODEC_MCU_CLK_ENABLE);
+
+	if (ret) {
+		al_codec_err(dev, " failed to enable the MCU clock");
+		return ret;
+	}
+
+	return !wait_for_completion_timeout(&dev->completion, HZ);
+}
+
+static inline u64 common_get_periph_addr(struct al_common_dev *dev)
+{
+	struct resource *res;
+
+	res = platform_get_resource_byname(dev->pdev, IORESOURCE_MEM, "apb");
+	if (!res) {
+		al_codec_err(dev, "Unable to find APB start address");
+		return 0;
+	}
+
+	if (res->start & AL_CODEC_APB_MASK) {
+		al_codec_err(dev, "APB start address is invalid");
+		return 0;
+	}
+
+	return res->start;
+}
+
+static int common_alloc_and_setup_fw_memory(struct al_common_dev *dev,
+					    struct boot_header *bh)
+{
+	u64 periph_addr;
+	u32 regbuf[4] = { 0 };
+	int ret;
+
+	dev->fw_cpu_mem = common_dma_alloc(dev, dev->fw_size,
+					   &dev->fw_phys_addr, GFP_KERNEL);
+	if (!dev->fw_cpu_mem)
+		return -ENOMEM;
+
+	ret = al_common_write_multiple(dev, AL_CODEC_INSTRUCTION_DATA_OFFSET,
+				       regbuf, ARRAY_SIZE(regbuf));
+	if (ret) {
+		al_codec_err(dev, "failed to set the (i/d)Cache address");
+		return ret;
+	}
+
+	periph_addr = common_get_periph_addr(dev);
+
+	regbuf[0] = upper_32_bits(periph_addr);
+	regbuf[1] = lower_32_bits(periph_addr);
+	ret = al_common_write_multiple(dev, AL_CODEC_MCU_PERIPHERAL_ADDR,
+				       regbuf, 2);
+	if (ret) {
+		al_codec_err(dev, "failed to set the periph address");
+		return ret;
+	}
+
+	al_codec_dbg(3, "fw phys_addr = %pad", &dev->fw_phys_addr);
+	al_codec_dbg(3, "fw virt_addr = 0x%p", dev->fw_cpu_mem);
+	al_codec_dbg(3, "periph_addr  = %pad", &periph_addr);
+
+	return 0;
+}
+
+static void common_fw_callback(const struct firmware *fw, void *context)
+{
+	struct al_common_dev *dev = context;
+	struct boot_header bh, *bhw;
+	u64 periph_addr = 0;
+	int ret;
+
+	if (!fw) {
+		al_codec_err(dev, "The MCU firmware not found!");
+		return;
+	}
+
+	/* Copy the Firmware header */
+	memcpy(&bh, fw->data, sizeof(bh));
+	dev->fw_size = bh.vaddr_end - bh.vaddr_start;
+
+	if (bh.bh_version < AL_BOOT_VERSION(2, 0, 0) ||
+	    bh.bh_version >= AL_BOOT_VERSION(3, 0, 0)) {
+		al_codec_err(dev, "bad boot header version");
+		goto fw_release;
+	}
+
+	if (WARN(bh.machine_id != 2, "Wrong machine ID"))
+		goto fw_release;
+
+	periph_addr = common_get_periph_addr(dev);
+
+	if (!periph_addr) {
+		al_codec_err(dev, "Unable to get the periph addr");
+		goto fw_release;
+	}
+
+	al_codec_dbg(3, "bh version     = 0x%08x", bh.bh_version);
+	al_codec_dbg(3, "fw version     = 0x%08x", bh.fw_version);
+	al_codec_dbg(3, "fw model       = %s", bh.model);
+	al_codec_dbg(3, "vaddress start = 0x%016llx", bh.vaddr_start);
+	al_codec_dbg(3, "vaddress end   = 0x%016llx", bh.vaddr_end);
+	al_codec_dbg(3, "boot address   = 0x%016llx", bh.vaddr_boot);
+	al_codec_dbg(3, "machineid      = %lld", bh.machine_id);
+	al_codec_dbg(3, "periph address = 0x%016llx", periph_addr);
+
+	ret = common_alloc_and_setup_fw_memory(dev, &bh);
+	if (ret) {
+		al_codec_err(dev, "out of memory %d", ret);
+		goto fw_release;
+	}
+
+	al_codec_dbg(2, "Copy %zu bytes of fw", fw->size);
+	memcpy(dev->fw_cpu_mem, fw->data, fw->size);
+
+	al_codec_mb_init(&dev->mb_h2m,
+			 dev->fw_cpu_mem + bh.h2m.start - bh.vaddr_start,
+			 bh.h2m.end - bh.h2m.start, MB_IFT_MAGIC_H2M);
+	al_codec_mb_init(&dev->mb_m2h,
+			 dev->fw_cpu_mem + bh.m2h.start - bh.vaddr_start,
+			 bh.m2h.end - bh.m2h.start, MB_IFT_MAGIC_M2H);
+
+	/* give fw information about registers location */
+	bhw = dev->fw_cpu_mem;
+	bhw->ip_start = periph_addr + AL_CODEC_IP_OFFSET;
+	bhw->ip_end = bhw->ip_start + resource_size(&dev->regs_info);
+
+	al_codec_dbg(3, "ip start     = 0x%016llx", bhw->ip_start);
+	al_codec_dbg(3, "ip end       =   0x%016llx", bhw->ip_end);
+
+	if (dev->mcu_clk_rate)
+		bhw->mcu_clk_rate = dev->mcu_clk_rate;
+
+	al_codec_dbg(3, "mcu clock rate is %llu", bhw->mcu_clk_rate);
+
+	ret = common_start_fw(dev, &bh);
+	if (ret) {
+		al_codec_err(dev, "fw start has failed");
+		goto fw_release;
+	}
+
+	dev_info(&dev->pdev->dev, "mcu has boot successfully !\n");
+	dev->fw_ready_cb(dev->cb_arg);
+
+fw_release:
+	release_firmware(fw);
+}
+
+static int common_firmware_request_nowait(struct al_common_dev *dev)
+{
+	al_codec_dbg(2, "request fw %s", dev->fw_name);
+
+	return request_firmware_nowait(THIS_MODULE, true, dev->fw_name,
+				       &dev->pdev->dev, GFP_KERNEL, dev,
+				       common_fw_callback);
+}
+
+static int common_setup_dma(struct al_common_dev *dev)
+{
+	int ret;
+
+	/* setup dma memory mask */
+	ret = dma_set_mask_and_coherent(&dev->pdev->dev, DMA_BIT_MASK(64));
+	if (ret) {
+		al_codec_err(dev, "failed to set dma");
+		return -EINVAL;
+	}
+
+	/* Try to use reserved memory if we got one */
+	ret = of_reserved_mem_device_init(&dev->pdev->dev);
+	if (ret && ret != ENODEV)
+		dev_warn(&dev->pdev->dev,
+			 "No reserved memory, use cma instead\n");
+
+	return 0;
+}
+
+int al_common_probe(struct platform_device *pdev, struct al_common_dev *dev)
+{
+	struct resource *res;
+	void __iomem *regs;
+	struct clk *clk;
+	int irq;
+	int ret;
+
+	dev->pdev = pdev;
+	dev->mcu_clk_rate = 0;
+	mutex_init(&dev->buf_lock);
+	INIT_LIST_HEAD(&dev->alloc_buffers);
+	init_completion(&dev->completion);
+
+	clk = devm_clk_get(&pdev->dev, "mcu_clk");
+	if (IS_ERR(clk))
+		al_codec_dbg(1, "Cannot get mcu clock, keep the default value");
+	else if (clk_prepare_enable(clk))
+		al_codec_dbg(
+			1,
+			"Failed to enable the mcu clk, keep the default value");
+	else
+		dev->mcu_clk_rate = clk_get_rate(clk);
+
+	/* setup dma memory */
+	ret = common_setup_dma(dev);
+	if (ret)
+		return ret;
+
+	/* Hw registers */
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
+	if (!res) {
+		al_codec_err(dev, "regs resource missing from device tree");
+		return -EINVAL;
+	}
+
+	dev->regs_info = *res;
+
+	regs = devm_ioremap_resource(&pdev->dev, res);
+	if (!regs) {
+		al_codec_err(dev, "failed to map registers");
+		return -ENOMEM;
+	}
+
+	dev->regmap =
+		devm_regmap_init_mmio(&pdev->dev, regs, &al_regmap_config);
+
+	if (IS_ERR(dev->regmap)) {
+		al_codec_err(dev, "init regmap failed");
+		return PTR_ERR(dev->regmap);
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		al_codec_err(dev, "Failed to get IRQ");
+		return -EINVAL;
+	}
+
+	ret = devm_request_threaded_irq(&pdev->dev, irq, common_hardirq_handler,
+					common_irq_handler, IRQF_SHARED,
+					dev_name(&pdev->dev), dev);
+	if (ret) {
+		al_codec_err(dev, "Unable to register irq handler");
+		return ret;
+	}
+
+	ret = common_probe_check_and_setup_hw(dev);
+	if (ret) {
+		al_codec_err(dev, "Unable to setup hw");
+		return ret;
+	}
+
+	/* ok so request the fw */
+	ret = common_firmware_request_nowait(dev);
+	if (ret) {
+		al_codec_err(dev, "failed to request firmware");
+		return ret;
+	}
+
+	return 0;
+}
+
+int al_common_send(struct al_common_dev *dev, struct msg_itf_header *hdr)
+{
+	return al_codec_msg_send(&dev->mb_h2m, hdr, common_trigger_mcu_irq,
+				 dev);
+}
+
+int al_common_send_req_reply(struct al_codec_dev *dev,
+			     struct list_head *cmd_list,
+			     struct msg_itf_header *hdr,
+			     struct al_common_mcu_req *req)
+{
+	struct al_codec_cmd *cmd = NULL;
+	int ret;
+
+	hdr->drv_cmd_hdl = 0;
+
+	if (req->reply_size && req->reply) {
+		cmd = al_codec_cmd_create(req->reply_size);
+		if (!cmd)
+			return -ENOMEM;
+
+		hdr->drv_cmd_hdl = al_virt_to_phys(cmd);
+	}
+
+	hdr->drv_ctx_hdl = req->pCtx;
+	hdr->type = req->req_type;
+	hdr->payload_len = req->req_size;
+
+	/* Add the list to the cmd list */
+	if (cmd)
+		list_add(&cmd->list, cmd_list);
+
+	ret = al_common_send(&dev->common, hdr);
+	if (ret)
+		goto remove_cmd;
+
+	al_v4l2_dbg(3, "Send req to mcu %d : %ld ", req->req_type,
+		    req->req_size);
+
+	if (!cmd)
+		return 0;
+
+	ret = wait_for_completion_timeout(&cmd->done, 5 * HZ);
+	if (ret <= 0) {
+		al_v4l2_err(dev, "cmd %p has %d (%s)", cmd, ret,
+			    (ret == 0) ? "failed" : "timedout");
+		ret = -ETIMEDOUT;
+		goto remove_cmd;
+	}
+
+	ret = 0;
+	memcpy(req->reply, cmd->reply, req->reply_size);
+
+remove_cmd:
+
+	if (cmd) {
+		list_del(&cmd->list);
+		al_codec_cmd_put(cmd);
+	}
+	return ret;
+}
+
+bool al_common_mcu_is_alive(struct al_codec_dev *dev)
+{
+	static const struct msg_itf_header hdr = {
+		.type = MSG_ITF_TYPE_MCU_ALIVE,
+		.payload_len = 0,
+	};
+	struct al_common_dev *cdev = &dev->common;
+	int ret;
+
+	ret = al_common_send(cdev, (struct msg_itf_header *)&hdr);
+	if (ret)
+		return false;
+
+	ret = wait_for_completion_timeout(&cdev->completion, 5 * HZ);
+	if (ret <= 0)
+		return false;
+
+	return true;
+}
diff --git a/drivers/media/platform/allegro-dvt/al300/al_codec_common.h b/drivers/media/platform/allegro-dvt/al300/al_codec_common.h
new file mode 100644
index 000000000000..aa2bb3d8b7b6
--- /dev/null
+++ b/drivers/media/platform/allegro-dvt/al300/al_codec_common.h
@@ -0,0 +1,226 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2025 Allegro DVT.
+ * Author: Yassine OUAISSA <yassine.ouaissa@allegrodvt.fr>
+ */
+
+#ifndef __AL_CODEC_COMMON__
+#define __AL_CODEC_COMMON__
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <media/v4l2-device.h>
+
+#include "al_codec_util.h"
+
+#define fh_to_ctx(ptr, type) container_of(ptr, type, fh)
+
+enum {
+	MSG_ITF_TYPE_CREATE_INST_REQ = MSG_ITF_TYPE_NEXT_REQ,
+	MSG_ITF_TYPE_DESTROY_INST_REQ,
+	MSG_ITF_TYPE_PUSH_BITSTREAM_BUFFER_REQ,
+	MSG_ITF_TYPE_PUT_DISPLAY_PICTURE_REQ,
+	MSG_ITF_TYPE_FLUSH_REQ,
+	MSG_ITF_TYPE_INFO_REQ,
+	MSG_ITF_TYPE_CREATE_INST_REPLY = MSG_ITF_TYPE_NEXT_REPLY,
+	MSG_ITF_TYPE_DESTROY_INST_REPLY,
+	MSG_ITF_TYPE_PUSH_BITSTREAM_BUFFER_REPLY,
+	MSG_ITF_TYPE_PUT_DISPLAY_PICTURE_REPLY,
+	MSG_ITF_TYPE_FLUSH_REPLY,
+	MSG_ITF_TYPE_INFO_REPLY,
+	MSG_ITF_TYPE_EVT_ERROR = MSG_ITF_TYPE_NEXT_EVT,
+};
+
+struct msg_itf_write_req {
+	u32 fd;
+	u32 len;
+	/* payload follow */
+} __packed;
+DECLARE_FULL_REQ(msg_itf_write_req);
+
+struct msg_itf_free_mem_req {
+	phys_addr_t phyAddr;
+} __packed;
+DECLARE_FULL_REQ(msg_itf_free_mem_req);
+
+struct msg_itf_alloc_mem_req {
+	u64 uSize;
+} __packed;
+DECLARE_FULL_REQ(msg_itf_alloc_mem_req);
+
+struct msg_itf_alloc_mem_reply {
+	phys_addr_t phyAddr;
+} __packed;
+DECLARE_FULL_REPLY(msg_itf_alloc_mem_reply);
+
+struct msg_itf_free_mem_reply {
+	s64 ret;
+};
+DECLARE_FULL_REPLY(msg_itf_free_mem_reply);
+
+struct msg_itf_create_codec_reply {
+	phys_addr_t hCodec;
+	s32 ret;
+} __packed;
+DECLARE_FULL_REPLY(msg_itf_create_codec_reply);
+
+struct msg_itf_destroy_codec_req {
+	phys_addr_t hCodec;
+} __packed;
+DECLARE_FULL_REQ(msg_itf_destroy_codec_req);
+
+/*
+ * Note : no need to know the status of this request
+ * The codec should be destroyed, in case of the mcu
+ * hasn't received any request with the codec handler
+ */
+struct msg_itf_destroy_codec_reply {
+	u32 unused;
+} __packed;
+DECLARE_FULL_REPLY(msg_itf_destroy_codec_reply);
+
+struct al_buffer_meta {
+	u64 timestamp;
+	struct v4l2_timecode timecode;
+	bool last;
+};
+
+struct msg_itf_push_src_buf_req {
+	phys_addr_t hCodec;
+	phys_addr_t bufferHandle;
+	phys_addr_t phyAddr;
+	u64 size;
+	struct al_buffer_meta meta;
+} __packed;
+DECLARE_FULL_REQ(msg_itf_push_src_buf_req);
+
+struct msg_itf_push_dst_buf_req {
+	phys_addr_t hCodec;
+	phys_addr_t bufferHandle;
+	phys_addr_t phyAddr;
+	u64 size;
+} __packed;
+DECLARE_FULL_REQ(msg_itf_push_dst_buf_req);
+
+struct msg_itf_push_buffer_req {
+	phys_addr_t hCodec;
+	phys_addr_t bufferHandle;
+	phys_addr_t phyAddr;
+	u64 size;
+} __packed;
+DECLARE_FULL_REQ(msg_itf_push_buffer_req);
+
+struct msg_itf_push_buffer_reply {
+	s32 res;
+} __packed;
+DECLARE_FULL_REPLY(msg_itf_push_buffer_reply);
+
+struct msg_itf_info_req {
+	u64 unused;
+} __packed;
+DECLARE_FULL_REQ(msg_itf_info_req);
+
+struct msg_itf_flush_req {
+	phys_addr_t hCodec;
+} __packed;
+DECLARE_FULL_REQ(msg_itf_flush_req);
+
+struct msg_itf_flush_reply {
+	int32_t unused;
+} __packed;
+DECLARE_FULL_REPLY(msg_itf_flush_reply);
+
+struct msg_itf_evt_error {
+	uint32_t errno;
+} __packed;
+DECLARE_FULL_EVENT(msg_itf_evt_error);
+
+struct al_match_data {
+	const char *fw_name;
+};
+
+struct al_common_mcu_req {
+	phys_addr_t pCtx;
+	int req_type;
+	size_t req_size;
+	size_t reply_size;
+	void *reply;
+} __packed;
+
+struct al_common_dev {
+	struct platform_device *pdev;
+	void *fw_cpu_mem;
+	phys_addr_t fw_phys_addr;
+	const char *fw_name;
+	size_t fw_size;
+	unsigned long mcu_clk_rate;
+
+	struct al_codec_mb mb_h2m;
+	struct al_codec_mb mb_m2h;
+	struct completion completion;
+
+	struct resource regs_info;
+	struct regmap *regmap;
+
+	struct list_head alloc_buffers;
+	struct mutex buf_lock;
+
+	/* callbacks set by client before common_probe */
+	void *cb_arg;
+	void (*process_msg_cb)(void *cb_arg, struct msg_itf_header *hdr);
+	void (*fw_ready_cb)(void *cb_arg);
+};
+
+struct al_codec_dev {
+	struct v4l2_device v4l2_dev;
+	struct v4l2_m2m_dev *m2m_dev;
+	struct video_device video_dev;
+	struct al_common_dev common;
+
+	/* mutex protecting vb2_queue structure */
+	struct mutex lock;
+
+	/* list of ctx (aka decoder) */
+	struct mutex ctx_mlock;
+	struct list_head ctx_q_list;
+	int is_video_init_done;
+
+	struct completion res_done;
+	/* list of cap/out supported formats */
+	struct list_head codec_q_list;
+	struct al_codec_cmd *codec_info_cmd;
+};
+
+static inline int al_common_get_header(struct al_common_dev *dev,
+				       struct msg_itf_header *hdr)
+{
+	return al_codec_msg_get_header(&dev->mb_m2h, hdr);
+}
+
+static inline int al_common_get_data(struct al_common_dev *dev, char *data,
+				     int len)
+{
+	return al_codec_msg_get_data(&dev->mb_m2h, data, len);
+}
+
+static inline int al_common_skip_data(struct al_common_dev *dev, int len)
+{
+	return al_common_get_data(dev, NULL, len);
+}
+
+int al_common_send(struct al_common_dev *dev, struct msg_itf_header *hdr);
+int al_common_send_req_reply(struct al_codec_dev *dev,
+			     struct list_head *cmd_list,
+			     struct msg_itf_header *hdr,
+			     struct al_common_mcu_req *req);
+bool al_common_mcu_is_alive(struct al_codec_dev *dev);
+
+int al_common_probe(struct platform_device *pdev, struct al_common_dev *dev);
+void al_common_remove(struct al_common_dev *dev);
+
+#endif /*__AL_CODEC_COMMON__*/
diff --git a/drivers/media/platform/allegro-dvt/al300/al_codec_util.c b/drivers/media/platform/allegro-dvt/al300/al_codec_util.c
new file mode 100644
index 000000000000..eb468e467747
--- /dev/null
+++ b/drivers/media/platform/allegro-dvt/al300/al_codec_util.c
@@ -0,0 +1,179 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Mailbox communication utilities for command creation
+ * and message exchange with the MCU
+ *
+ * Copyright (c) 2025 Allegro DVT.
+ * Author: Yassine OUAISSA <yassine.ouaissa@allegrodvt.fr>
+ */
+
+#include <asm-generic/errno.h>
+#include <linux/errno.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include "al_codec_util.h"
+
+static int al_get_used_space(struct al_codec_mb *mb)
+{
+	u32 head = mb->hdr->head;
+	u32 tail = mb->hdr->tail;
+
+	return head >= tail ? head - tail : mb->size - (tail - head);
+}
+
+static int al_get_free_space(struct al_codec_mb *mb)
+{
+	return mb->size - al_get_used_space(mb) - 1;
+}
+
+static int al_has_enough_space(struct al_codec_mb *mb, int len)
+{
+	return al_get_free_space(mb) >= len;
+}
+
+static inline void al_copy_to_mb(struct al_codec_mb *mb, char *data, int len)
+{
+	u32 head = mb->hdr->head;
+	int copy_len = min(mb->size - head, (unsigned int)len);
+	int copied_len = len;
+
+	memcpy(&mb->data[head], data, copy_len);
+	len -= copy_len;
+	if (len)
+		memcpy(&mb->data[0], &data[copy_len], len);
+
+	/* Make sure that all messages are written before updating the head */
+	dma_wmb();
+	mb->hdr->head = (head + copied_len) % mb->size;
+	/* Make sure that the head is updated in DDR instead of cache */
+	dma_wmb();
+}
+
+static inline void al_copy_from_mb(struct al_codec_mb *mb, char *data, int len)
+{
+	u32 tail = mb->hdr->tail;
+	int copy_len = min(mb->size - tail, (unsigned int)len);
+	int copied_len = len;
+
+	if (!data)
+		goto update_tail;
+
+	memcpy(data, &mb->data[tail], copy_len);
+	len -= copy_len;
+	if (len)
+		memcpy(&data[copy_len], &mb->data[0], len);
+
+update_tail:
+	mb->hdr->tail = (tail + copied_len) % mb->size;
+	/* Make sure that the head is updated in DDR instead of cache */
+	dma_wmb();
+}
+
+static int al_codec_mb_send(struct al_codec_mb *mb, char *data, int len)
+{
+	if (!al_has_enough_space(mb, len))
+		return -ENOMEM;
+
+	al_copy_to_mb(mb, data, len);
+
+	return 0;
+}
+
+static int al_codec_mb_receive(struct al_codec_mb *mb, char *data, int len)
+{
+	if (al_get_used_space(mb) < len)
+		return -ENOMEM;
+
+	al_copy_from_mb(mb, data, len);
+
+	return 0;
+}
+
+void al_codec_mb_init(struct al_codec_mb *mb, char *addr, int size, u32 magic)
+{
+	mb->hdr = (struct al_mb_itf *)addr;
+	mb->hdr->magic = magic;
+	mb->hdr->version = MB_IFT_VERSION;
+	mb->hdr->head = 0;
+	mb->hdr->tail = 0;
+	mb->data = addr + sizeof(struct al_mb_itf);
+	mb->size = size - sizeof(struct al_mb_itf);
+	mutex_init(&mb->lock);
+}
+
+int al_codec_msg_get_header(struct al_codec_mb *mb, struct msg_itf_header *hdr)
+{
+	return al_codec_mb_receive(mb, (char *)hdr, sizeof(*hdr));
+}
+
+int al_codec_msg_get_data(struct al_codec_mb *mb, char *data, int len)
+{
+	return al_codec_mb_receive(mb, data, len);
+}
+
+int al_codec_msg_send(struct al_codec_mb *mb, struct msg_itf_header *hdr,
+		      void (*trigger)(void *), void *trigger_arg)
+{
+	unsigned long timeout;
+	int ret;
+
+	timeout = jiffies + HZ;
+	mutex_lock(&mb->lock);
+	do {
+		if (time_after(jiffies, timeout)) {
+			mutex_unlock(&mb->lock);
+			return -ETIMEDOUT;
+		}
+		ret = al_codec_mb_send(mb, (char *)hdr,
+				       hdr->payload_len +
+					       sizeof(struct msg_itf_header));
+
+	} while (ret);
+	mutex_unlock(&mb->lock);
+
+	trigger(trigger_arg);
+
+	return 0;
+}
+
+static void al_codec_cmd_cleanup(struct kref *ref)
+{
+	struct al_codec_cmd *cmd =
+		container_of(ref, struct al_codec_cmd, refcount);
+	if (cmd) {
+		kfree(cmd->reply);
+		kfree(cmd);
+	}
+}
+
+void al_codec_cmd_put(struct al_codec_cmd *cmd)
+{
+	if (WARN_ON(!cmd))
+		return;
+
+	kref_put(&cmd->refcount, al_codec_cmd_cleanup);
+}
+
+struct al_codec_cmd *al_codec_cmd_create(int reply_size)
+{
+	struct al_codec_cmd *cmd;
+
+	cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd)
+		return NULL;
+
+	cmd->reply = kmalloc(reply_size, GFP_KERNEL);
+	if (!cmd->reply) {
+		kfree(cmd);
+		return NULL;
+	}
+
+	kref_init(&cmd->refcount);
+	cmd->reply_size = reply_size;
+	init_completion(&cmd->done);
+
+	return cmd;
+}
diff --git a/drivers/media/platform/allegro-dvt/al300/al_codec_util.h b/drivers/media/platform/allegro-dvt/al300/al_codec_util.h
new file mode 100644
index 000000000000..6806820bdb8a
--- /dev/null
+++ b/drivers/media/platform/allegro-dvt/al300/al_codec_util.h
@@ -0,0 +1,186 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2025 Allegro DVT.
+ * Author: Yassine OUAISSA <yassine.ouaissa@allegrodvt.fr>
+ */
+
+#ifndef __AL_CODEC_UTIL__
+#define __AL_CODEC_UTIL__
+
+#include <linux/mutex.h>
+#include <linux/types.h>
+#include <linux/v4l2-common.h>
+
+#include <media/v4l2-mem2mem.h>
+#include <media/videobuf2-v4l2.h>
+
+#define MB_IFT_MAGIC_H2M 0xabcd1230
+#define MB_IFT_MAGIC_M2H 0xabcd1231
+#define MB_IFT_VERSION 0x00010000
+
+#define MAJOR_SHIFT 20
+#define MAJOR_MASK 0xfff
+#define MINOR_SHIFT 8
+#define MINOR_MASK 0xfff
+#define PATCH_SHIFT 0
+#define PATCH_MASK 0xff
+
+/*
+ * AL_BOOT_VERSION() - Version format 32-bit, 12 bits for the major,
+ * the same for minor, 8bits for the patch
+ */
+#define AL_BOOT_VERSION(major, minor, patch)       \
+	((((major) & MAJOR_MASK) << MAJOR_SHIFT) | \
+	 (((minor) & MINOR_MASK) << MINOR_SHIFT) | \
+	 (((patch) & PATCH_MASK) << PATCH_SHIFT))
+
+#define al_phys_to_virt(x) ((void *)(uintptr_t)x)
+#define al_virt_to_phys(x) ((phys_addr_t)(uintptr_t)x)
+
+#define DECLARE_FULL_REQ(s)                \
+	struct s##_full {                  \
+		struct msg_itf_header hdr; \
+		struct s req;              \
+	} __packed
+
+#define DECLARE_FULL_REPLY(s)              \
+	struct s##_full {                  \
+		struct msg_itf_header hdr; \
+		struct s reply;            \
+	} __packed
+
+#define DECLARE_FULL_EVENT(s)              \
+	struct s##_full {                  \
+		struct msg_itf_header hdr; \
+		struct s event;            \
+	} __packed
+
+struct al_mb_itf {
+	u32 magic;
+	u32 version;
+	u32 head;
+	u32 tail;
+} __packed;
+
+struct al_codec_mb {
+	struct al_mb_itf *hdr;
+	struct mutex lock;
+	char *data;
+	int size;
+};
+
+struct al_codec_cmd {
+	struct kref refcount;
+	struct list_head list;
+	struct completion done;
+	int reply_size;
+	void *reply;
+};
+
+#if defined(DEBUG)
+
+extern int debug;
+/* Common logs */
+#define al_codec_err(dev, fmt, args...)                                     \
+	pr_err("[ALG_CODEC][ERROR] %s():%d: " fmt "\n", __func__, __LINE__, \
+	       ##args)
+
+#define al_codec_dbg(level, fmt, args...)                                  \
+	do {                                                               \
+		if (debug >= level)                                        \
+			pr_info("[ALG_CODEC] level=%d %s(),%d: " fmt "\n", \
+				level, __func__, __LINE__, ##args);        \
+	} while (0)
+
+/* V4L2 logs */
+#define al_v4l2_err(dev, fmt, args...)                                     \
+	pr_err("[ALG_V4L2][ERROR] %s():%d: " fmt "\n", __func__, __LINE__, \
+	       ##args)
+
+#define al_v4l2_dbg(level, fmt, args...)                                  \
+	do {                                                              \
+		if (debug >= level)                                       \
+			pr_info("[ALG_V4L2] level=%d %s(),%d: " fmt "\n", \
+				level, __func__, __LINE__, ##args);       \
+	} while (0)
+
+/* MCU debug */
+#define al_mcu_dbg(fmt, args...) pr_info("[ALG_MCU]: " fmt, ##args);
+
+#else
+
+#define al_codec_err(_dev, fmt, args...) \
+	dev_err(&_dev->pdev->dev, fmt "\n", ##args)
+
+#define al_v4l2_err(_dev, fmt, args...) \
+	dev_err(&_dev->common.pdev->dev, fmt "\n", ##args)
+
+#define al_codec_dbg(level, fmt, args...)
+#define al_v4l2_dbg(level, fmt, args...)
+#define al_mcu_dbg(fmt, args...)
+
+#endif
+
+#define MSG_ITF_TYPE_LIMIT BIT(10)
+
+/* Message types host <-> mcu */
+enum {
+	MSG_ITF_TYPE_MCU_ALIVE = 0x0,
+	MSG_ITF_TYPE_WRITE_REQ = 0x02,
+	MSG_ITF_TYPE_FIRST_REQ = 1024,
+	MSG_ITF_TYPE_NEXT_REQ,
+	MSG_ITF_TYPE_FIRST_REPLY = 2048,
+	MSG_ITF_TYPE_NEXT_REPLY,
+	MSG_ITF_TYPE_ALLOC_MEM_REQ = 3072,
+	MSG_ITF_TYPE_FREE_MEM_REQ,
+	MSG_ITF_TYPE_ALLOC_MEM_REPLY = 4096,
+	MSG_ITF_TYPE_FREE_MEM_REPLY,
+	MSG_ITF_TYPE_FIRST_EVT = 5120,
+	MSG_ITF_TYPE_NEXT_EVT = MSG_ITF_TYPE_FIRST_EVT
+};
+
+struct msg_itf_header {
+	u64 drv_ctx_hdl;
+	u64 drv_cmd_hdl;
+	u16 type;
+	u16 payload_len;
+	u16 padding[2];
+} __packed;
+
+void al_codec_mb_init(struct al_codec_mb *mb, char *addr, int size, u32 magic);
+int al_codec_msg_get_header(struct al_codec_mb *mb, struct msg_itf_header *hdr);
+int al_codec_msg_get_data(struct al_codec_mb *mb, char *data, int len);
+int al_codec_msg_send(struct al_codec_mb *mb, struct msg_itf_header *hdr,
+		      void (*trigger)(void *), void *trigger_arg);
+
+static inline bool is_type_reply(uint16_t type)
+{
+	return type >= MSG_ITF_TYPE_FIRST_REPLY &&
+	       type < MSG_ITF_TYPE_FIRST_REPLY + MSG_ITF_TYPE_LIMIT;
+}
+
+static inline bool is_type_event(uint16_t type)
+{
+	return type >= MSG_ITF_TYPE_FIRST_EVT &&
+	       type < MSG_ITF_TYPE_FIRST_EVT + MSG_ITF_TYPE_LIMIT;
+}
+
+void al_codec_cmd_put(struct al_codec_cmd *cmd);
+
+struct al_codec_cmd *al_codec_cmd_create(int reply_size);
+
+static inline struct al_codec_cmd *al_codec_cmd_get(struct list_head *cmd_list,
+						    uint64_t hdl)
+{
+	struct al_codec_cmd *cmd = NULL;
+
+	list_for_each_entry(cmd, cmd_list, list) {
+		if (likely(cmd == al_phys_to_virt(hdl))) {
+			kref_get(&cmd->refcount);
+			break;
+		}
+	}
+	return list_entry_is_head(cmd, cmd_list, list) ? NULL : cmd;
+}
+
+#endif /* __AL_CODEC_UTIL__ */
diff --git a/drivers/media/platform/allegro-dvt/al300/al_vdec_drv.c b/drivers/media/platform/allegro-dvt/al300/al_vdec_drv.c
new file mode 100644
index 000000000000..70546af410d8
--- /dev/null
+++ b/drivers/media/platform/allegro-dvt/al300/al_vdec_drv.c
@@ -0,0 +1,1536 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2025 Allegro DVT.
+ * Author: Yassine OUAISSA <yassine.ouaissa@allegrodvt.fr>
+ *
+ * Allegro DVT stateful video decoder driver for the IP Gen 3
+ */
+
+#include <asm-generic/errno-base.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/string.h>
+#include <linux/v4l2-controls.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "al_codec_common.h"
+#include "al_vdec_drv.h"
+
+#if defined(DEBUG)
+/* Log level */
+int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Debug level (0-3)");
+#endif
+
+/* default decoder params */
+#define DECODER_WIDTH_DEFAULT 640
+#define DECODER_HEIGHT_DEFAULT 480
+#define DECODER_WIDTH_MAX 3840
+#define DECODER_HEIGHT_MAX 2160
+#define DECODER_WIDTH_MIN 16
+#define DECODER_HEIGHT_MIN 16
+#define DEC_REQ_TIMEOUT msecs_to_jiffies(1000)
+#define DEC_RES_EVT_TIMEOUT DEC_REQ_TIMEOUT
+
+/* Supported formats */
+static const struct al_fmt al_src_formats[] = {
+	{
+		.pixelformat = V4L2_PIX_FMT_H264,
+		.bpp = 20,
+	},
+	{
+		.pixelformat = V4L2_PIX_FMT_HEVC,
+		.bpp = 20,
+	},
+	{
+		.pixelformat = V4L2_PIX_FMT_JPEG,
+		.bpp = 8,
+	}
+};
+
+static const struct al_fmt al_dst_formats[] = {
+	{
+		.pixelformat = V4L2_PIX_FMT_NV12,
+		.bpp = 12,
+	},
+	{
+		.pixelformat = V4L2_PIX_FMT_P010,
+		.bpp = 12,
+	},
+	{
+		.pixelformat = V4L2_PIX_FMT_NV16,
+		.bpp = 16,
+	},
+	{
+		.pixelformat = V4L2_PIX_FMT_YUV420, /* YUV 4:2:0 */
+		.bpp = 12,
+	},
+	{
+		.pixelformat = V4L2_PIX_FMT_YVU420, /* YVU 4:2:0 */
+		.bpp = 12,
+	},
+};
+
+/* Default format */
+static const struct al_frame al_default_fmt = {
+
+	.width = DECODER_WIDTH_DEFAULT,
+	.height = DECODER_HEIGHT_DEFAULT,
+	.bytesperline = DECODER_WIDTH_MAX * 4,
+	.sizeimage = DECODER_WIDTH_DEFAULT * DECODER_HEIGHT_DEFAULT * 4,
+	.nbuffers = 1,
+	.fmt = &al_dst_formats[0],
+	.field = V4L2_FIELD_NONE,
+	.colorspace = V4L2_COLORSPACE_REC709,
+	.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT,
+	.quantization = V4L2_QUANTIZATION_DEFAULT,
+	.xfer_func = V4L2_XFER_FUNC_DEFAULT
+};
+
+static struct al_frame *al_get_frame(struct al_dec_ctx *ctx,
+				     enum v4l2_buf_type type)
+{
+	if (WARN_ON(!ctx))
+		return ERR_PTR(-EINVAL);
+
+	if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+		return &ctx->src;
+	else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return &ctx->dst;
+
+	al_v4l2_err(ctx->dev, "Unsupported type (%d)", type);
+
+	return ERR_PTR(-EINVAL);
+}
+
+static const struct al_fmt *al_find_fmt(u32 pixelformat)
+{
+	const struct al_fmt *fmt;
+	unsigned int i;
+
+	/* check if the pixelformat exist in the src formats list */
+	for (i = 0; i < ARRAY_SIZE(al_src_formats); i++) {
+		fmt = &al_src_formats[i];
+		if (fmt->pixelformat == pixelformat)
+			return fmt;
+	}
+
+	/* check if the pixelformat exist in the dst formats list */
+	for (i = 0; i < ARRAY_SIZE(al_dst_formats); i++) {
+		fmt = &al_dst_formats[i];
+		if (fmt->pixelformat == pixelformat)
+			return fmt;
+	}
+
+	return NULL;
+}
+
+static int dec_fw_create_decoder(struct al_dec_ctx *ctx)
+{
+	struct msg_itf_create_decoder_req_full req;
+	struct msg_itf_create_codec_reply reply;
+	struct al_common_mcu_req mreq;
+	int ret;
+
+	if (ctx->hDec) {
+		al_v4l2_dbg(3, "fw decoder already exist\n");
+		return 0;
+	}
+
+	req.req.codec = ctx->codec;
+
+	mreq.pCtx = al_virt_to_phys(ctx);
+	mreq.req_type = MSG_ITF_TYPE_CREATE_INST_REQ;
+	mreq.req_size = sizeof(req.req);
+	mreq.reply_size = sizeof(reply);
+	mreq.reply = &reply;
+
+	ret = al_common_send_req_reply(ctx->dev, &ctx->cmd_q_list, &req.hdr,
+				       &mreq);
+
+	if (!ret && !reply.ret)
+		ctx->hDec = reply.hCodec;
+	else if (reply.ret)
+		ret = -ENODEV;
+
+	return ret;
+}
+
+static void dec_fw_destroy_decoder(struct al_dec_ctx *ctx)
+{
+	struct msg_itf_destroy_codec_req_full req;
+	struct msg_itf_destroy_codec_reply reply;
+	struct al_common_mcu_req mreq;
+	int ret;
+
+	if (!ctx->hDec) {
+		al_v4l2_dbg(3, "fw decoder doesn't exist");
+		return;
+	}
+	al_v4l2_dbg(3, "Destroy decoder %lld ", ctx->hDec);
+
+	req.req.hCodec = ctx->hDec;
+
+	mreq.pCtx = al_virt_to_phys(ctx);
+	mreq.req_type = MSG_ITF_TYPE_DESTROY_INST_REQ;
+	mreq.req_size = sizeof(req.req);
+	mreq.reply_size = sizeof(reply);
+	mreq.reply = &reply;
+
+	ret = al_common_send_req_reply(ctx->dev, &ctx->cmd_q_list, &req.hdr,
+				       &mreq);
+
+	if (!ret)
+		ctx->hDec = 0;
+}
+
+static int al_dec_fw_push_frame_buf(struct al_dec_ctx *ctx,
+				    struct vb2_v4l2_buffer *vbuf)
+{
+	struct msg_itf_push_dst_buf_req_full req;
+	struct v4l2_m2m_buffer *m2m_buf;
+	struct al_common_mcu_req mreq = { 0 };
+	int ret;
+
+	if (WARN(!vbuf, "NULL frame Buffer to push!!"))
+		return -EINVAL;
+
+	req.req.hCodec = ctx->hDec;
+	m2m_buf = container_of(vbuf, struct v4l2_m2m_buffer, vb);
+	req.req.bufferHandle = al_virt_to_phys(m2m_buf);
+	req.req.phyAddr = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0);
+	req.req.size = vb2_plane_size(&vbuf->vb2_buf, 0);
+
+	mreq.pCtx = al_virt_to_phys(ctx);
+	mreq.req_type = MSG_ITF_TYPE_PUT_DISPLAY_PICTURE_REQ;
+	mreq.req_size = sizeof(req.req);
+
+	ret = al_common_send_req_reply(ctx->dev, &ctx->cmd_q_list, &req.hdr,
+				       &mreq);
+	if (ret)
+		al_v4l2_err(ctx->dev, "Failed to push frame buffer %p %d",
+			    m2m_buf, ret);
+
+	return ret;
+}
+
+static int al_dec_fw_push_bitstream_buf(struct al_dec_ctx *ctx,
+					struct vb2_v4l2_buffer *vbuf)
+{
+	struct msg_itf_push_src_buf_req_full req;
+	struct v4l2_m2m_buffer *m2m_buf;
+	struct al_common_mcu_req mreq = { 0 };
+	int ret;
+
+	if (WARN(!vbuf, "NULL Buffer to push!!"))
+		return -EINVAL;
+
+	req.req.hCodec = ctx->hDec;
+	m2m_buf = container_of(vbuf, struct v4l2_m2m_buffer, vb);
+	req.req.bufferHandle = al_virt_to_phys(m2m_buf);
+	req.req.phyAddr = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0);
+	req.req.size = vb2_plane_size(&vbuf->vb2_buf, 0);
+
+	/* Fill the v4l2 metadata*/
+	req.req.meta.timestamp = vbuf->vb2_buf.timestamp;
+	req.req.meta.timecode = vbuf->timecode;
+	req.req.meta.last = vbuf->flags & V4L2_BUF_FLAG_LAST;
+
+	mreq.pCtx = al_virt_to_phys(ctx);
+	mreq.req_type = MSG_ITF_TYPE_PUSH_BITSTREAM_BUFFER_REQ;
+	mreq.req_size = sizeof(req.req);
+
+	ret = al_common_send_req_reply(ctx->dev, &ctx->cmd_q_list, &req.hdr,
+				       &mreq);
+	if (ret)
+		al_v4l2_err(ctx->dev, "Failed to push bitstream buffer %p %d",
+			    m2m_buf, ret);
+
+	return ret;
+}
+
+static int dec_fw_flush_req(struct al_dec_ctx *ctx)
+{
+	struct msg_itf_flush_req_full req;
+	struct msg_itf_flush_reply reply;
+	struct al_common_mcu_req mreq;
+	int ret;
+
+	req.req.hCodec = ctx->hDec;
+
+	mreq.pCtx = al_virt_to_phys(ctx);
+	mreq.req_type = MSG_ITF_TYPE_FLUSH_REQ;
+	mreq.req_size = sizeof(req.req);
+	mreq.reply_size = sizeof(reply);
+	mreq.reply = &reply;
+
+	ret = al_common_send_req_reply(ctx->dev, &ctx->cmd_q_list, &req.hdr,
+				       &mreq);
+
+	if (ret)
+		al_v4l2_err(ctx->dev, "Failed to flush the decoder %d", ret);
+
+	return ret;
+}
+
+static inline struct vb2_v4l2_buffer *
+al_dec_dequeue_buf(struct al_dec_ctx *ctx, uint64_t hdl,
+		   struct list_head *buffer_list)
+{
+	struct v4l2_m2m_buffer *buf, *tmp;
+	struct vb2_v4l2_buffer *ret = NULL;
+
+	mutex_lock(&ctx->buf_q_mlock);
+	list_for_each_entry_safe(buf, tmp, buffer_list, list) {
+		if (buf == al_phys_to_virt(hdl)) {
+			list_del(&buf->list);
+			ret = &buf->vb;
+			break;
+		}
+	}
+	mutex_unlock(&ctx->buf_q_mlock);
+
+	return ret;
+}
+
+static struct vb2_v4l2_buffer *al_dec_dequeue_src_buf(struct al_dec_ctx *ctx,
+						      uint64_t hdl)
+{
+	return al_dec_dequeue_buf(ctx, hdl, &ctx->stream_q_list);
+}
+
+static struct vb2_v4l2_buffer *al_dec_dequeue_dst_buf(struct al_dec_ctx *ctx,
+						      uint64_t hdl)
+{
+	return al_dec_dequeue_buf(ctx, hdl, &ctx->frame_q_list);
+}
+
+static void al_ctx_cleanup(struct kref *ref)
+{
+	struct al_dec_ctx *ctx = container_of(ref, struct al_dec_ctx, refcount);
+
+	kfree(ctx);
+}
+
+static inline struct al_dec_ctx *al_ctx_get(struct al_codec_dev *dev,
+					    uint64_t hdl)
+{
+	struct al_dec_ctx *ctx;
+	struct al_dec_ctx *ret = NULL;
+
+	mutex_lock(&dev->ctx_mlock);
+	list_for_each_entry(ctx, &dev->ctx_q_list, list) {
+		if (ctx == al_phys_to_virt(hdl)) {
+			kref_get(&ctx->refcount);
+			ret = ctx;
+			break;
+		}
+	}
+	mutex_unlock(&dev->ctx_mlock);
+
+	return ret;
+}
+
+static void al_ctx_put(struct al_dec_ctx *ctx)
+{
+	kref_put(&ctx->refcount, al_ctx_cleanup);
+}
+
+static int al_dec_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+	struct al_dec_ctx *ctx = vb2_get_drv_priv(q);
+	struct al_codec_dev *dev = ctx->dev;
+
+	v4l2_m2m_update_start_streaming_state(ctx->fh.m2m_ctx, q);
+
+	if (V4L2_TYPE_IS_OUTPUT(q->type)) {
+		struct v4l2_m2m_buffer *buf;
+		int ret;
+
+		if (list_empty(&ctx->stream_q_list)) {
+			al_v4l2_dbg(0, "Empty stream list.");
+			return -EINVAL;
+		}
+		if (!al_common_mcu_is_alive(dev)) {
+			al_v4l2_err(dev, "Unable to ping the mcu");
+			return -ENODEV;
+		}
+
+		ret = dec_fw_create_decoder(ctx);
+		if (ret) {
+			al_v4l2_err(dev, "Unable to create the fw decoder %d",
+				    ret);
+			return ret;
+		}
+
+		/* Get the first vid-out queued buffer */
+		buf = list_first_entry(&ctx->stream_q_list,
+				       struct v4l2_m2m_buffer, list);
+
+		if (!buf) {
+			al_v4l2_err(
+				dev,
+				"Unable to get the first buffer from the stream list");
+			return -EINVAL;
+		}
+
+		if (al_dec_fw_push_bitstream_buf(ctx, &buf->vb)) {
+			al_v4l2_err(ctx->dev,
+				    "Unable to push the bitstream buffer");
+			return -EINVAL;
+		}
+
+		/* Wait until the mcu detect the resolution of the stream */
+		ret = wait_for_completion_timeout(&ctx->res_done,
+						  DEC_RES_EVT_TIMEOUT);
+		if (!ret) {
+			al_v4l2_err(ctx->dev, "unsupported stream");
+			ctx->aborting = true;
+		}
+
+		ctx->osequence = 0;
+	} else
+		ctx->csequence = 0;
+
+	return 0;
+}
+
+static void al_dec_stop_streaming_cap(struct al_dec_ctx *ctx)
+{
+	struct vb2_v4l2_buffer *vbuf;
+	struct v4l2_m2m_buffer *entry, *tmp;
+
+	mutex_lock(&ctx->buf_q_mlock);
+	if (!list_empty(&ctx->frame_q_list))
+		list_for_each_entry_safe(entry, tmp, &ctx->frame_q_list, list) {
+			list_del(&entry->list);
+			vbuf = &entry->vb;
+			vb2_set_plane_payload(&vbuf->vb2_buf, 0, 0);
+			v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
+		}
+	mutex_unlock(&ctx->buf_q_mlock);
+
+	while (v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx)) {
+		vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+		if (vbuf) {
+			vb2_set_plane_payload(&vbuf->vb2_buf, 0, 0);
+			v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
+		}
+	}
+
+	v4l2_m2m_mark_stopped(ctx->fh.m2m_ctx);
+}
+
+static void al_dec_stop_streaming_out(struct al_dec_ctx *ctx)
+{
+	struct vb2_v4l2_buffer *vbuf;
+	struct v4l2_m2m_buffer *entry, *tmp;
+
+	mutex_lock(&ctx->buf_q_mlock);
+	if (!list_empty(&ctx->stream_q_list))
+		list_for_each_entry_safe(entry, tmp, &ctx->stream_q_list,
+					 list) {
+			list_del(&entry->list);
+			v4l2_m2m_buf_done(&entry->vb, VB2_BUF_STATE_ERROR);
+		}
+	mutex_unlock(&ctx->buf_q_mlock);
+
+	if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx)) {
+		while ((vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx)))
+			if (vbuf->vb2_buf.state == VB2_BUF_STATE_ACTIVE)
+				v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
+	}
+
+	dec_fw_destroy_decoder(ctx);
+}
+
+static void al_dec_stop_streaming(struct vb2_queue *q)
+{
+	struct al_dec_ctx *ctx = vb2_get_drv_priv(q);
+
+	v4l2_m2m_update_stop_streaming_state(ctx->fh.m2m_ctx, q);
+
+	/* Releasing the dst and src buffers */
+	ctx->stopped = true;
+
+	if (V4L2_TYPE_IS_OUTPUT(q->type))
+		al_dec_stop_streaming_out(ctx);
+	else
+		al_dec_stop_streaming_cap(ctx);
+}
+
+static int al_dec_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
+			      unsigned int *nplanes, unsigned int sizes[],
+			      struct device *alloc_devs[])
+{
+	struct al_dec_ctx *ctx = vb2_get_drv_priv(vq);
+	struct al_frame *format = al_get_frame(ctx, vq->type);
+
+	if (IS_ERR(format)) {
+		al_v4l2_err(ctx->dev, "Invalid format %p", format);
+		return PTR_ERR(format);
+	}
+
+	if (*nplanes)
+		return ((sizes[0] < format->sizeimage) ? -EINVAL : 0);
+
+	/* update queue num buffers */
+	format->nbuffers = max(*nbuffers, format->nbuffers);
+
+	*nplanes = 1;
+	sizes[0] = format->sizeimage;
+	*nbuffers = format->nbuffers;
+
+	al_v4l2_dbg(2, "%s: Get %d buffers of size %d each ",
+		    (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) ? "OUT" : "CAP",
+		    *nbuffers, sizes[0]);
+
+	return 0;
+}
+
+static int al_dec_buf_prepare(struct vb2_buffer *vb)
+{
+	struct al_dec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+
+	if (ctx->aborting)
+		return -EINVAL;
+
+	if (V4L2_TYPE_IS_CAPTURE(vb->type)) {
+		if (vbuf->field == V4L2_FIELD_ANY)
+			vbuf->field = V4L2_FIELD_NONE;
+		if (vbuf->field != V4L2_FIELD_NONE)
+			return -EINVAL;
+	}
+
+	al_v4l2_dbg(3, "%s : Buffer (%p) prepared ",
+		    (V4L2_TYPE_IS_OUTPUT(vb->type) ? "OUT" : "CAP"), vbuf);
+
+	return 0;
+}
+
+static inline void al_dec_fill_bitstream(struct al_dec_ctx *ctx)
+{
+	struct vb2_v4l2_buffer *src_buf;
+	struct v4l2_m2m_buffer *m2m_buf;
+	struct vb2_queue *src_vq;
+
+	lockdep_assert_held(&ctx->buf_q_mlock);
+
+	if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) > 0) {
+		src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+		if (!src_buf)
+			return;
+
+		/* Dump empty buffers */
+		if (!vb2_get_plane_payload(&src_buf->vb2_buf, 0)) {
+			src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+			v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
+			return;
+		}
+
+		src_vq = v4l2_m2m_get_src_vq(ctx->fh.m2m_ctx);
+		src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+
+		if (src_buf) {
+			src_buf->sequence = ctx->osequence++;
+
+			if (vb2_is_streaming(src_vq) &&
+			    al_dec_fw_push_bitstream_buf(ctx, src_buf)) {
+				v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR);
+				return;
+			}
+
+			m2m_buf = container_of(src_buf, struct v4l2_m2m_buffer,
+					       vb);
+			list_add_tail(&m2m_buf->list, &ctx->stream_q_list);
+		}
+	}
+}
+
+static void al_dec_buf_queue(struct vb2_buffer *vb)
+{
+	struct al_dec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+
+	v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
+
+	if (V4L2_TYPE_IS_OUTPUT(vb->type)) {
+		mutex_lock(&ctx->buf_q_mlock);
+		al_dec_fill_bitstream(ctx);
+		mutex_unlock(&ctx->buf_q_mlock);
+	}
+
+	al_v4l2_dbg(3, "%s queued (%p) - (%d)",
+		    V4L2_TYPE_IS_OUTPUT(vb->type) ? "OUT" : "CAP", vbuf,
+		    vb->num_planes);
+}
+
+static const struct vb2_ops dec_queue_ops = {
+	.queue_setup = al_dec_queue_setup,
+	.buf_prepare = al_dec_buf_prepare,
+	.buf_queue = al_dec_buf_queue,
+	.start_streaming = al_dec_start_streaming,
+	.stop_streaming = al_dec_stop_streaming,
+	.wait_prepare = vb2_ops_wait_prepare,
+	.wait_finish = vb2_ops_wait_finish,
+};
+
+static int al_dec_queue_init(void *priv, struct vb2_queue *src_vq,
+			     struct vb2_queue *dst_vq)
+{
+	struct al_dec_ctx *ctx = priv;
+	int ret;
+
+	src_vq->dev = &ctx->dev->common.pdev->dev;
+	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+	src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+	src_vq->non_coherent_mem = false;
+	src_vq->dma_attrs |= DMA_ATTR_FORCE_CONTIGUOUS;
+	src_vq->mem_ops = &vb2_dma_contig_memops;
+	src_vq->drv_priv = ctx;
+	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	src_vq->ops = &dec_queue_ops;
+	src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+	src_vq->lock = &ctx->dev->lock;
+	ret = vb2_queue_init(src_vq);
+	if (ret)
+		return ret;
+
+	dst_vq->dev = &ctx->dev->common.pdev->dev;
+	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+	dst_vq->non_coherent_mem = false;
+	dst_vq->dma_attrs |= DMA_ATTR_FORCE_CONTIGUOUS;
+	dst_vq->mem_ops = &vb2_dma_contig_memops;
+	dst_vq->drv_priv = ctx;
+	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	dst_vq->ops = &dec_queue_ops;
+	dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+	dst_vq->lock = &ctx->dev->lock;
+	ret = vb2_queue_init(dst_vq);
+	if (ret) {
+		vb2_queue_release(src_vq);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int al_dec_querycap(struct file *file, void *fh,
+			   struct v4l2_capability *cap)
+{
+	struct al_codec_dev *dev = video_drvdata(file);
+
+	strscpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
+	strscpy(cap->card, "Allegro DVT Video Decoder", sizeof(cap->card));
+	snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
+		 dev_name(&dev->common.pdev->dev));
+
+	return 0;
+}
+
+static int al_dec_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f)
+{
+	const struct al_fmt *fmt;
+
+	if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+	    f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	if (V4L2_TYPE_IS_OUTPUT(f->type)) {
+		if (f->index >= ARRAY_SIZE(al_src_formats))
+			return -EINVAL;
+
+		fmt = &al_src_formats[f->index];
+	} else {
+		if (f->index >= ARRAY_SIZE(al_dst_formats))
+			return -EINVAL;
+
+		fmt = &al_dst_formats[f->index];
+	}
+
+	f->pixelformat = fmt->pixelformat;
+	return 0;
+}
+
+static int al_dec_try_fmt(struct file *file, void *fh, struct v4l2_format *f)
+{
+	struct al_dec_ctx *ctx = fh_to_ctx(fh, struct al_dec_ctx);
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+	const struct al_fmt *v_fmt;
+	struct al_frame *pix_fmt;
+
+	v_fmt = al_find_fmt(pix->pixelformat);
+	if (!v_fmt) {
+		al_v4l2_dbg(2, "Unknown format 0x%x", pix->pixelformat);
+		return -EINVAL;
+	}
+
+	pix_fmt = al_get_frame(ctx, f->type);
+	if (!pix_fmt) {
+		al_v4l2_dbg(2, "Unknown pix format 0x%x", pix->pixelformat);
+		return -EINVAL;
+	}
+
+	pix_fmt->fmt = v_fmt;
+	pix->field = V4L2_FIELD_NONE;
+	pix->width = clamp_t(__u32, pix->width, DECODER_WIDTH_MIN,
+			     DECODER_WIDTH_MAX);
+	pix->height = clamp_t(__u32, pix->height, DECODER_HEIGHT_MIN,
+			      DECODER_HEIGHT_MAX);
+
+	pix->bytesperline = pix->width;
+	pix->sizeimage = (pix->width * pix->height * v_fmt->bpp) / 8;
+
+	if (V4L2_TYPE_IS_CAPTURE(f->type))
+		if (pix->sizeimage < pix_fmt->sizeimage)
+			pix->sizeimage = pix_fmt->sizeimage;
+
+	al_v4l2_dbg(
+		3,
+		"%s : width (%d) , height (%d), bytesperline (%d), sizeimage (%d) ",
+		(f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) ? "CAP" : "OUT",
+		pix->width, pix->height, pix->bytesperline, pix->sizeimage);
+
+	return 0;
+}
+
+static int al_dec_g_fmt(struct file *file, void *fh, struct v4l2_format *f)
+{
+	struct al_dec_ctx *ctx = fh_to_ctx(fh, struct al_dec_ctx);
+	struct al_frame *pix_fmt = al_get_frame(ctx, f->type);
+	struct v4l2_pix_format *pix;
+
+	if (IS_ERR(pix_fmt)) {
+		al_v4l2_err(ctx->dev, "Invalid pixel format %p", pix_fmt);
+		return PTR_ERR(pix_fmt);
+	}
+
+	if (!pix_fmt->fmt) {
+		al_v4l2_err(ctx->dev, "Unknown format for %d", f->type);
+		return -EINVAL;
+	}
+
+	pix = &f->fmt.pix;
+	pix->width = pix_fmt->width;
+	pix->height = pix_fmt->height;
+	pix->bytesperline = pix_fmt->bytesperline;
+	pix->sizeimage = pix_fmt->sizeimage;
+	pix->pixelformat = pix_fmt->fmt->pixelformat;
+	pix->field = V4L2_FIELD_NONE;
+
+	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+		pix->bytesperline = 0;
+		pix->pixelformat = ctx->codec;
+	}
+
+	pix->ycbcr_enc = pix_fmt->ycbcr_enc;
+	pix->quantization = pix_fmt->quantization;
+	pix->xfer_func = pix_fmt->xfer_func;
+	pix->colorspace = pix_fmt->colorspace;
+
+	al_v4l2_dbg(
+		3,
+		"%s : width (%d) , height (%d), bytesperline (%d) , sizeimage (%d)",
+		(f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) ? "CAP" : "OUT",
+		pix->width, pix->height, pix->bytesperline, pix->sizeimage);
+
+	return 0;
+}
+
+static int al_dec_s_fmt(struct file *file, void *fh, struct v4l2_format *f)
+{
+	struct al_dec_ctx *ctx = fh_to_ctx(fh, struct al_dec_ctx);
+	struct v4l2_pix_format *pix;
+	struct al_frame *frame;
+	struct vb2_queue *vq;
+	int ret;
+
+	ret = al_dec_try_fmt(file, fh, f);
+	if (ret) {
+		al_v4l2_err(ctx->dev, "Cannot set format (%d)", f->type);
+		return ret;
+	}
+
+	frame = (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) ? &ctx->src : &ctx->dst;
+
+	pix = &f->fmt.pix;
+	frame->fmt = al_find_fmt(pix->pixelformat);
+	if (!frame->fmt) {
+		al_v4l2_err(ctx->dev, "Unknown format for %d",
+			    pix->pixelformat);
+		return -EINVAL;
+	}
+
+	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
+	if (vb2_is_streaming(vq)) {
+		al_v4l2_err(ctx->dev, "queue %d busy", f->type);
+		return -EBUSY;
+	}
+
+	frame->width = pix->width;
+	frame->height = pix->height;
+	frame->bytesperline = pix->bytesperline;
+	frame->sizeimage = pix->sizeimage;
+	frame->field = pix->field;
+
+	frame->ycbcr_enc = pix->ycbcr_enc;
+	frame->quantization = pix->quantization;
+	frame->xfer_func = pix->xfer_func;
+	frame->colorspace = pix->colorspace;
+
+	/* Set decoder pixelformat */
+	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+		ctx->codec = pix->pixelformat;
+
+	al_v4l2_dbg(
+		3,
+		" %s : width (%d) , height (%d), bytesperline (%d), sizeimage (%d)",
+		(f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) ? "CAP" : "OUT",
+		pix->width, pix->height, pix->bytesperline, pix->sizeimage);
+
+	return 0;
+}
+
+static void al_queue_eos_event(struct al_dec_ctx *ctx)
+{
+	const struct v4l2_event eos_event = {
+		.id = 0,
+		.type = V4L2_EVENT_EOS,
+	};
+
+	v4l2_event_queue_fh(&ctx->fh, &eos_event);
+}
+
+static void al_queue_res_chg_event(struct al_dec_ctx *ctx)
+{
+	static const struct v4l2_event ev_src_ch = {
+		.id = 0,
+		.type = V4L2_EVENT_SOURCE_CHANGE,
+		.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
+	};
+
+	v4l2_event_queue_fh(&ctx->fh, &ev_src_ch);
+}
+
+static int al_dec_decoder_cmd(struct file *file, void *fh,
+			      struct v4l2_decoder_cmd *dcmd)
+{
+	struct al_dec_ctx *ctx = fh_to_ctx(fh, struct al_dec_ctx);
+	struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
+	struct vb2_v4l2_buffer *vbuf;
+	struct vb2_queue *dst_vq;
+	int ret;
+
+	ret = v4l2_m2m_ioctl_try_decoder_cmd(file, fh, dcmd);
+	if (ret)
+		return ret;
+
+	/* Get the vb2 queue for the Capture */
+	dst_vq = v4l2_m2m_get_dst_vq(m2m_ctx);
+
+	switch (dcmd->cmd) {
+	case V4L2_DEC_CMD_START:
+		vb2_clear_last_buffer_dequeued(dst_vq);
+		break;
+	case V4L2_DEC_CMD_STOP:
+		vbuf = v4l2_m2m_last_src_buf(m2m_ctx);
+		if (vbuf) {
+			al_v4l2_dbg(1, "marking last pending buffer");
+
+			vbuf->flags |= V4L2_BUF_FLAG_LAST;
+			if (v4l2_m2m_num_src_bufs_ready(m2m_ctx) == 0) {
+				al_v4l2_dbg(1, "all remaining buffers queued");
+				v4l2_m2m_try_schedule(m2m_ctx);
+			}
+		}
+		dec_fw_flush_req(ctx);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int al_dec_enum_framesizes(struct file *file, void *fh,
+				  struct v4l2_frmsizeenum *fsize)
+{
+	if (!al_find_fmt(fsize->pixel_format))
+		return -EINVAL;
+
+	/* FIXME : check step size */
+	fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
+	fsize->stepwise.min_width = DECODER_WIDTH_MIN;
+	fsize->stepwise.max_width = DECODER_WIDTH_MAX;
+	fsize->stepwise.step_width = 8;
+	fsize->stepwise.min_height = DECODER_HEIGHT_MIN;
+	fsize->stepwise.max_height = DECODER_HEIGHT_MAX;
+	fsize->stepwise.step_height = 8;
+
+	return 0;
+}
+
+static int al_dec_subscribe_event(struct v4l2_fh *fh,
+				  const struct v4l2_event_subscription *sub)
+{
+	switch (sub->type) {
+	case V4L2_EVENT_EOS:
+		return v4l2_event_subscribe(fh, sub, 0, NULL);
+	case V4L2_EVENT_SOURCE_CHANGE:
+		return v4l2_src_change_event_subscribe(fh, sub);
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int al_dec_log_status(struct file *file, void *fh)
+{
+	struct al_codec_dev *al_dev = video_drvdata(file);
+
+	v4l2_device_call_all(&al_dev->v4l2_dev, 0, core, log_status);
+	return 0;
+}
+
+static const struct v4l2_ioctl_ops al_dec_ioctl_ops = {
+	.vidioc_querycap = al_dec_querycap,
+	.vidioc_enum_fmt_vid_cap = al_dec_enum_fmt,
+	.vidioc_enum_fmt_vid_out = al_dec_enum_fmt,
+	.vidioc_g_fmt_vid_cap = al_dec_g_fmt,
+	.vidioc_g_fmt_vid_out = al_dec_g_fmt,
+	.vidioc_try_fmt_vid_cap = al_dec_try_fmt,
+	.vidioc_try_fmt_vid_out = al_dec_try_fmt,
+	.vidioc_s_fmt_vid_cap = al_dec_s_fmt,
+	.vidioc_s_fmt_vid_out = al_dec_s_fmt,
+
+	.vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
+	.vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
+
+	.vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
+	.vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
+	.vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
+	.vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
+	.vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
+
+	.vidioc_streamon = v4l2_m2m_ioctl_streamon,
+	.vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
+	.vidioc_log_status = al_dec_log_status,
+
+	.vidioc_try_decoder_cmd = v4l2_m2m_ioctl_try_decoder_cmd,
+	.vidioc_decoder_cmd = al_dec_decoder_cmd,
+	.vidioc_enum_framesizes = al_dec_enum_framesizes,
+
+	.vidioc_subscribe_event = al_dec_subscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+
+static void al_device_run(void *priv)
+{
+	struct al_dec_ctx *ctx = priv;
+	struct vb2_v4l2_buffer *dst_buf;
+	struct v4l2_m2m_buffer *m2m_buf;
+
+	if (unlikely(!ctx))
+		return;
+
+	if (ctx->aborting) {
+		vb2_queue_error(v4l2_m2m_get_src_vq(ctx->fh.m2m_ctx));
+		vb2_queue_error(v4l2_m2m_get_dst_vq(ctx->fh.m2m_ctx));
+		return;
+	}
+
+	if (!v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx))
+		goto job_finish;
+
+	dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+	if (!dst_buf)
+		goto job_finish;
+
+	if (!al_common_mcu_is_alive(ctx->dev) ||
+	    al_dec_fw_push_frame_buf(ctx, dst_buf)) {
+		vb2_set_plane_payload(&dst_buf->vb2_buf, 0, 0);
+		v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR);
+		goto job_finish;
+	}
+
+	mutex_lock(&ctx->buf_q_mlock);
+	m2m_buf = container_of(dst_buf, struct v4l2_m2m_buffer, vb);
+	list_add_tail(&m2m_buf->list, &ctx->frame_q_list);
+	mutex_unlock(&ctx->buf_q_mlock);
+
+job_finish:
+	v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
+}
+
+static const struct v4l2_m2m_ops al_dec_m2m_ops = {
+	.device_run = al_device_run,
+};
+
+static int al_dec_open(struct file *file)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct al_codec_dev *dev = video_get_drvdata(vdev);
+	struct al_dec_ctx *ctx = NULL;
+	int ret;
+
+	if (mutex_lock_interruptible(&dev->ctx_mlock))
+		return -ERESTARTSYS;
+
+	/* Aloocate memory for the dec ctx */
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx) {
+		ret = -ENOMEM;
+		goto unlock;
+	}
+
+	ctx->dev = dev;
+	/* Init ctx mutex */
+	mutex_init(&ctx->buf_q_mlock);
+	/* Init ctx LISTHEADs*/
+	INIT_LIST_HEAD(&ctx->cmd_q_list);
+	INIT_LIST_HEAD(&ctx->frame_q_list);
+	INIT_LIST_HEAD(&ctx->stream_q_list);
+
+	/* Init the irq queue */
+	init_completion(&ctx->res_done);
+
+	v4l2_fh_init(&ctx->fh, vdev);
+
+	v4l2_ctrl_handler_init(&ctx->ctrl_handler, 0);
+	if (ctx->ctrl_handler.error) {
+		ret = ctx->ctrl_handler.error;
+		al_v4l2_err(dev, "Failed to create control %d", ret);
+		goto handler_error;
+	}
+
+	ctx->fh.ctrl_handler = &ctx->ctrl_handler;
+	v4l2_ctrl_handler_setup(&ctx->ctrl_handler);
+
+	file->private_data = &ctx->fh;
+	v4l2_fh_add(&ctx->fh);
+
+	/* Set default formats */
+	ctx->src = ctx->dst = al_default_fmt;
+
+	ctx->codec = V4L2_PIX_FMT_H264;
+	ctx->stopped = false;
+	ctx->aborting = false;
+
+	/* Setup the ctx for m2m mode */
+	ctx->fh.m2m_ctx =
+		v4l2_m2m_ctx_init(dev->m2m_dev, ctx, al_dec_queue_init);
+	if (IS_ERR(ctx->fh.m2m_ctx)) {
+		ret = PTR_ERR(ctx->fh.m2m_ctx);
+		al_v4l2_err(dev, "Failed to initialize m2m mode %d", ret);
+		goto error_ctrls;
+	}
+
+	v4l2_m2m_set_src_buffered(ctx->fh.m2m_ctx, true);
+	/* v4l2_m2m_set_dst_buffered(ctx->fh.m2m_ctx, true); */
+
+	/* Add ctx to the LIST */
+	kref_init(&ctx->refcount);
+	list_add(&ctx->list, &dev->ctx_q_list);
+
+	mutex_unlock(&dev->ctx_mlock);
+
+	return 0;
+
+error_ctrls:
+	v4l2_fh_del(&ctx->fh);
+handler_error:
+	v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+	v4l2_fh_exit(&ctx->fh);
+	kfree(ctx);
+
+unlock:
+	mutex_unlock(&dev->ctx_mlock);
+	return ret;
+}
+
+static int al_dec_release(struct file *file)
+{
+	struct al_dec_ctx *ctx =
+		fh_to_ctx(file->private_data, struct al_dec_ctx);
+	struct al_codec_dev *dev = ctx->dev;
+
+	mutex_lock(&dev->ctx_mlock);
+
+	/* It is important to do this before removing ctx from dev list.
+	 * Those commands will trigger some traffic towards fw and so we
+	 * need completion to avoid deadlock if cmds can't find ctx.
+	 */
+	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);
+
+	list_del(&ctx->list);
+	al_ctx_put(ctx);
+	mutex_unlock(&dev->ctx_mlock);
+
+	return 0;
+}
+
+static inline bool al_mark_last_dst_buf(struct al_dec_ctx *ctx)
+{
+	struct vb2_v4l2_buffer *buf;
+	struct vb2_buffer *dst_vb;
+	struct vb2_queue *dst_vq;
+	unsigned long flags;
+
+	al_v4l2_dbg(1, "marking last capture buffer");
+
+	dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+	spin_lock_irqsave(&dst_vq->done_lock, flags);
+	if (list_empty(&dst_vq->done_list)) {
+		spin_unlock_irqrestore(&dst_vq->done_lock, flags);
+		return false;
+	}
+
+	dst_vb = list_last_entry(&dst_vq->done_list, struct vb2_buffer,
+				 done_entry);
+	buf = to_vb2_v4l2_buffer(dst_vb);
+	buf->flags |= V4L2_BUF_FLAG_LAST;
+
+	spin_unlock_irqrestore(&dst_vq->done_lock, flags);
+	return true;
+}
+
+static const struct v4l2_file_operations al_dec_file_ops = {
+	.owner = THIS_MODULE,
+	.open = al_dec_open,
+	.release = al_dec_release,
+	.poll = v4l2_m2m_fop_poll,
+	.unlocked_ioctl = video_ioctl2,
+	.mmap = v4l2_m2m_fop_mmap,
+};
+
+static void handle_error_evt(struct al_dec_ctx *ctx, struct msg_itf_header *hdr)
+{
+	struct al_codec_dev *dev = ctx->dev;
+	struct msg_itf_evt_error evt;
+	struct v4l2_m2m_buffer *vbuf;
+
+	if (al_common_get_data(&dev->common, (char *)&evt, hdr->payload_len)) {
+		al_v4l2_err(dev, "Unable to get resolution found event");
+		return;
+	}
+
+	al_v4l2_err(dev, "Decoding error  %d", evt.errno);
+
+	mutex_lock(&ctx->buf_q_mlock);
+	if (!list_empty(&ctx->stream_q_list)) {
+		vbuf = list_last_entry(&ctx->frame_q_list,
+				       struct v4l2_m2m_buffer, list);
+		list_del(&vbuf->list);
+		v4l2_m2m_buf_done(&vbuf->vb, VB2_BUF_STATE_ERROR);
+	}
+	mutex_unlock(&ctx->buf_q_mlock);
+}
+
+static void handle_resolution_found_evt(struct al_dec_ctx *ctx,
+					struct msg_itf_header *hdr)
+{
+	struct msg_itf_evt_resolution_found evt;
+	struct al_codec_dev *dev = ctx->dev;
+	struct al_frame *frame;
+	struct vb2_queue *dst_vq;
+
+	if (al_common_get_data(&dev->common, (char *)&evt, hdr->payload_len)) {
+		al_v4l2_err(dev, "Unable to get resolution found event");
+		return;
+	}
+
+	frame = &ctx->dst;
+
+	if (frame->width != evt.width || frame->height != evt.height ||
+	    frame->nbuffers < evt.buffer_nb) {
+		/* Update frame properties */
+		frame->width = evt.width;
+		frame->height = evt.height;
+		frame->bytesperline = evt.bytesperline;
+		frame->sizeimage = evt.sizeimage;
+		frame->nbuffers = evt.buffer_nb;
+		frame->fmt = al_find_fmt(evt.pixelformat);
+
+		/* This has to be changed */
+		if (!frame->fmt)
+			return;
+
+		al_queue_res_chg_event(ctx);
+	}
+
+	dst_vq = v4l2_m2m_get_dst_vq(ctx->fh.m2m_ctx);
+	if (!vb2_is_streaming(dst_vq))
+		complete(&ctx->res_done);
+
+	al_v4l2_dbg(
+		3,
+		"width(%d) , height(%d), bytesperline(%d), sizeimage(%d), n_bufs(%d)",
+		frame->width, frame->height, frame->bytesperline,
+		frame->sizeimage, frame->nbuffers);
+}
+
+static void handle_bitstream_buffer_release_evt(struct al_dec_ctx *ctx,
+						struct msg_itf_header *hdr)
+{
+	struct msg_itf_evt_bitstream_buffer_release evt;
+	struct al_codec_dev *dev = ctx->dev;
+	struct vb2_v4l2_buffer *vbuf;
+
+	if (al_common_get_data(&dev->common, (char *)&evt, hdr->payload_len)) {
+		al_v4l2_err(dev, "Unable to get buffer release event");
+		return;
+	}
+
+	if (ctx->stopped)
+		return;
+
+	vbuf = al_dec_dequeue_src_buf(ctx, evt.bufferHandle);
+	if (!vbuf) {
+		al_v4l2_err(dev, "Unable to find bitsream buffer 0x%llx",
+			    evt.bufferHandle);
+		return;
+	}
+
+	al_v4l2_dbg(3, "Release bitstream buffer %p", vbuf);
+	v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);
+}
+
+static void handle_eos_evt(struct al_dec_ctx *ctx, struct msg_itf_header *hdr)
+{
+	struct msg_itf_evt_frame_buffer_decode evt;
+	struct al_codec_dev *dev = ctx->dev;
+
+	if (al_common_get_data(&dev->common, (char *)&evt, hdr->payload_len)) {
+		al_v4l2_err(dev, "Unable to get frame buffer event");
+		return;
+	}
+
+	/* set LAST_FLAG to the last done CAPTURE buffer*/
+	al_mark_last_dst_buf(ctx);
+	/* Set eos event */
+	al_queue_eos_event(ctx);
+}
+
+static void handle_frame_buffer_decode_evt(struct al_dec_ctx *ctx,
+					   struct msg_itf_header *hdr)
+{
+	struct msg_itf_evt_frame_buffer_decode evt;
+	struct al_codec_dev *dev = ctx->dev;
+	struct vb2_v4l2_buffer *vbuf;
+	struct al_buffer_meta *meta;
+
+	if (al_common_get_data(&dev->common, (char *)&evt, hdr->payload_len)) {
+		al_v4l2_err(dev, "Unable to get frame buffer event");
+		return;
+	}
+
+	vbuf = al_dec_dequeue_dst_buf(ctx, evt.bufferHandle);
+	if (!vbuf) {
+		al_v4l2_err(dev, "Unable to find frame buffer 0x%llx",
+			    evt.bufferHandle);
+		return;
+	}
+
+	meta = &evt.meta;
+	al_v4l2_dbg(3, "Decoded frame done for buffer %p (%d) (%lld)", vbuf,
+		    meta->last, evt.size);
+
+	vb2_set_plane_payload(&vbuf->vb2_buf, 0, evt.size);
+	vbuf->field = V4L2_FIELD_NONE;
+	vbuf->sequence = ctx->csequence++;
+	vbuf->timecode = meta->timecode;
+	vbuf->vb2_buf.timestamp = meta->timestamp;
+
+	if (meta->last || (vbuf->flags & V4L2_BUF_FLAG_LAST)) {
+		vbuf->flags |= V4L2_BUF_FLAG_LAST;
+		v4l2_m2m_mark_stopped(ctx->fh.m2m_ctx);
+	}
+
+	v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);
+}
+
+static int al_handle_cmd_reply(struct al_codec_dev *dev,
+			       struct msg_itf_header *hdr)
+{
+	struct al_dec_ctx *ctx;
+	struct al_codec_cmd *cmd = NULL;
+	int ret = 0;
+
+	ctx = al_ctx_get(dev, hdr->drv_ctx_hdl);
+	if (IS_ERR_OR_NULL(ctx)) {
+		al_v4l2_err(dev, "Unable to find ctx %p for reply %d",
+			    al_phys_to_virt(hdr->drv_ctx_hdl), hdr->type);
+		return -EINVAL;
+	}
+
+	cmd = al_codec_cmd_get(&ctx->cmd_q_list, hdr->drv_cmd_hdl);
+	if (!cmd) {
+		al_v4l2_err(dev, "Unable to find command %p for reply %d",
+			    al_phys_to_virt(hdr->drv_cmd_hdl), hdr->type);
+		ret = -EINVAL;
+		goto ctx_put;
+	}
+
+	if (cmd->reply_size != hdr->payload_len) {
+		al_v4l2_err(dev, "mismatch size %d %d", cmd->reply_size,
+			    hdr->payload_len);
+		ret = -EINVAL;
+		goto cmd_put;
+	}
+
+	ret = al_common_get_data(&dev->common, cmd->reply, hdr->payload_len);
+	if (ret)
+		al_v4l2_err(dev, "Unable to copy reply");
+
+	complete(&cmd->done);
+	ret = 0;
+
+cmd_put:
+	al_codec_cmd_put(cmd);
+ctx_put:
+	al_ctx_put(ctx);
+
+	return ret;
+}
+
+static int al_handle_cmd_evt(struct al_codec_dev *dev,
+			     struct msg_itf_header *hdr, int type)
+{
+	static u32 evt_sizes[] = {
+		sizeof(struct msg_itf_evt_error),
+		sizeof(struct msg_itf_evt_resolution_found),
+		sizeof(struct msg_itf_evt_bitstream_buffer_release),
+		sizeof(struct msg_itf_evt_frame_buffer_decode),
+		sizeof(struct msg_itf_evt_eos),
+	};
+
+	u32 evt_size;
+	struct al_dec_ctx *ctx = NULL;
+	int ret = 0;
+
+	if (type < MSG_ITF_TYPE_NEXT_EVT || type > MSG_ITF_TYPE_END_EVT) {
+		al_v4l2_err(dev, "Unsupporting event type %d", type);
+		return -EINVAL;
+	}
+
+	ctx = al_ctx_get(dev, hdr->drv_ctx_hdl);
+	if (!ctx) {
+		al_v4l2_err(dev, "Unable to find ctx %p for evt %d",
+			    al_phys_to_virt(hdr->drv_ctx_hdl), type);
+		return -EINVAL;
+	}
+
+	// Check the received event size and the expected one
+	evt_size = evt_sizes[type - MSG_ITF_TYPE_NEXT_EVT];
+	if (hdr->payload_len != evt_size) {
+		al_v4l2_err(
+			dev,
+			"Invalid event size for client (%p) for evt (%d) : Got (%d), expected (%d)",
+			al_phys_to_virt(hdr->drv_ctx_hdl), type,
+			hdr->payload_len, evt_size);
+		ret = -EINVAL;
+		goto clean_ctx;
+	}
+
+	al_v4l2_dbg(3, "Event received from MCU (%d)", type);
+
+	switch (type) {
+	case MSG_ITF_TYPE_EVT_ERROR:
+		handle_error_evt(ctx, hdr);
+		break;
+	case MSG_ITF_TYPE_EVT_RESOLUTION_FOUND:
+		handle_resolution_found_evt(ctx, hdr);
+		break;
+	case MSG_ITF_TYPE_EVT_BITSTREAM_BUFFER_RELEASE:
+		handle_bitstream_buffer_release_evt(ctx, hdr);
+		break;
+	case MSG_ITF_TYPE_EVT_FRAME_BUFFER_DECODE:
+		handle_frame_buffer_decode_evt(ctx, hdr);
+		break;
+	case MSG_ITF_TYPE_EVT_EOS:
+		handle_eos_evt(ctx, hdr);
+		break;
+	default:
+		break;
+	}
+
+clean_ctx:
+	al_ctx_put(ctx);
+	return ret;
+}
+
+static void al_dec_process_msg(void *cb_arg, struct msg_itf_header *hdr)
+{
+	struct al_codec_dev *dev = cb_arg;
+	int ret;
+
+	if (is_type_reply(hdr->type))
+		ret = al_handle_cmd_reply(dev, hdr);
+	else if (is_type_event(hdr->type))
+		ret = al_handle_cmd_evt(dev, hdr, hdr->type);
+	else {
+		al_v4l2_err(dev, "Unsupported message type %d", hdr->type);
+		ret = -EINVAL;
+	}
+
+	if (ret) {
+		al_v4l2_err(dev, "Skip received data");
+		al_common_skip_data(&dev->common, hdr->payload_len);
+	}
+}
+
+static const struct video_device al_videodev = {
+	.name = "allegro-decoder",
+	.fops = &al_dec_file_ops,
+	.ioctl_ops = &al_dec_ioctl_ops,
+	.minor = -1,
+	.release = video_device_release_empty,
+	.vfl_dir = VFL_DIR_M2M,
+	.device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING,
+};
+
+static void al_dec_register_v4l2(void *cb_arg)
+{
+	struct al_codec_dev *dev = cb_arg;
+	struct video_device *video_dev = NULL;
+	int ret;
+
+	ret = v4l2_device_register(&dev->common.pdev->dev, &dev->v4l2_dev);
+	if (ret) {
+		al_v4l2_err(dev, "Unable to register v4l2 device %d", ret);
+		return;
+	}
+
+	dev->m2m_dev = v4l2_m2m_init(&al_dec_m2m_ops);
+	if (IS_ERR(dev->m2m_dev)) {
+		ret = PTR_ERR(dev->m2m_dev);
+		al_v4l2_err(dev, "failed to init mem2mem device %d", ret);
+		goto v4l2_m2m_init_error;
+	}
+
+	video_dev = &dev->video_dev;
+	*video_dev = al_videodev;
+
+	video_dev->lock = &dev->lock;
+	video_dev->v4l2_dev = &dev->v4l2_dev;
+
+	video_set_drvdata(video_dev, dev);
+	ret = video_register_device(video_dev, VFL_TYPE_VIDEO, -1);
+	if (ret) {
+		al_v4l2_err(dev, "failed to register video device %d", ret);
+		goto video_register_device_error;
+	}
+
+	v4l2_info(&dev->v4l2_dev, "registered as /dev/video%d\n",
+		  dev->video_dev.num);
+
+	dev->is_video_init_done = 1;
+
+	return;
+
+video_register_device_error:
+	v4l2_m2m_release(dev->m2m_dev);
+v4l2_m2m_init_error:
+	v4l2_device_unregister(&dev->v4l2_dev);
+}
+
+static int al_dec_probe(struct platform_device *pdev)
+{
+	struct al_codec_dev *al_dev;
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	const struct al_match_data *match_data;
+	int ret;
+
+	dev_info(dev, "Probing ...\n");
+
+	match_data = device_get_match_data(dev);
+	if (!match_data) {
+		dev_err(dev, "Missing device match data\n");
+		return -EINVAL;
+	}
+
+	al_dev = devm_kzalloc(dev, sizeof(*al_dev), GFP_KERNEL);
+	if (!al_dev)
+		return -ENOMEM;
+
+	al_dev->is_video_init_done = 0;
+	mutex_init(&al_dev->lock);
+	mutex_init(&al_dev->ctx_mlock);
+	INIT_LIST_HEAD(&al_dev->ctx_q_list);
+
+	al_dev->common.cb_arg = al_dev;
+	al_dev->common.process_msg_cb = al_dec_process_msg;
+	al_dev->common.fw_ready_cb = al_dec_register_v4l2;
+
+	/* firmware-name is optional in DT */
+	of_property_read_string(np, "firmware-name", &al_dev->common.fw_name);
+	if (!al_dev->common.fw_name)
+		al_dev->common.fw_name = match_data->fw_name;
+
+	ret = al_common_probe(pdev, &al_dev->common);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, al_dev);
+	dev_info(dev, "Probing done successfully %p\n", al_dev);
+
+	return 0;
+}
+
+static void al_dec_remove(struct platform_device *pdev)
+{
+	struct al_codec_dev *dev = platform_get_drvdata(pdev);
+
+	dev_info(&pdev->dev, "remove %p\n", dev);
+
+	if (dev->is_video_init_done) {
+		video_unregister_device(&dev->video_dev);
+		if (dev->m2m_dev)
+			v4l2_m2m_release(dev->m2m_dev);
+		v4l2_device_unregister(&dev->v4l2_dev);
+	}
+
+	al_common_remove(&dev->common);
+}
+
+static const struct al_match_data ald300_data = {
+	.fw_name = "al300-vdec.fw",
+};
+
+static const struct of_device_id v4l2_al_dec_dt_match[] = {
+	{ .compatible = "allegrodvt,al300-vdec", .data = &ald300_data },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, v4l2_al_dec_dt_match);
+
+static struct platform_driver al300_vdec_drv = {
+	.probe = al_dec_probe,
+	.remove = al_dec_remove,
+	.driver = {
+		.name = "al300_vdec",
+		.of_match_table = of_match_ptr(v4l2_al_dec_dt_match),
+	},
+};
+
+module_platform_driver(al300_vdec_drv);
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:al300-vdec");
+MODULE_AUTHOR("Yassine OUAISSA <yassine.ouaissa@allegrodvt.com>");
+MODULE_DESCRIPTION("Allegro DVT V4l2 decoder driver gen 3");
diff --git a/drivers/media/platform/allegro-dvt/al300/al_vdec_drv.h b/drivers/media/platform/allegro-dvt/al300/al_vdec_drv.h
new file mode 100644
index 000000000000..ec1a7c450300
--- /dev/null
+++ b/drivers/media/platform/allegro-dvt/al300/al_vdec_drv.h
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2025 Allegro DVT.
+ * Author: Yassine OUAISSA <yassine.ouaissa@allegrodvt.fr>
+ */
+
+#ifndef __AL_VDEC_DRV__
+#define __AL_VDEC_DRV__
+
+#include "al_codec_util.h"
+
+enum {
+	MSG_ITF_TYPE_EVT_RESOLUTION_FOUND = MSG_ITF_TYPE_NEXT_EVT + 1,
+	MSG_ITF_TYPE_EVT_BITSTREAM_BUFFER_RELEASE,
+	MSG_ITF_TYPE_EVT_FRAME_BUFFER_DECODE,
+	MSG_ITF_TYPE_EVT_EOS,
+	/* Mark the end of the events list.*/
+	MSG_ITF_TYPE_END_EVT,
+};
+
+struct msg_itf_create_decoder_req {
+	unsigned int codec;
+} __packed;
+DECLARE_FULL_REQ(msg_itf_create_decoder_req);
+
+struct msg_itf_evt_resolution_found {
+	u16 buffer_nb;
+	u16 width;
+	u16 height;
+	u32 pixelformat;
+	u32 sizeimage;
+	u32 bytesperline;
+} __packed;
+DECLARE_FULL_EVENT(msg_itf_evt_resolution_found);
+
+struct msg_itf_evt_bitstream_buffer_release {
+	u64 bufferHandle;
+} __packed;
+DECLARE_FULL_EVENT(msg_itf_evt_bitstream_buffer_release);
+
+struct msg_itf_evt_frame_buffer_decode {
+	u64 bufferHandle;
+	u64 size;
+	struct al_buffer_meta meta;
+} __packed;
+DECLARE_FULL_EVENT(msg_itf_evt_frame_buffer_decode);
+
+struct msg_itf_evt_eos {
+	u32 unused;
+} __packed;
+DECLARE_FULL_EVENT(msg_itf_evt_eos);
+
+struct al_fmt {
+	u32 pixelformat;
+	u8 bpp;
+};
+
+struct al_frame {
+	u32 width;
+	u32 height;
+	u32 bytesperline;
+	u32 sizeimage;
+	u32 nbuffers;
+	const struct al_fmt *fmt;
+	enum v4l2_field field;
+	enum v4l2_colorspace colorspace;
+	enum v4l2_ycbcr_encoding ycbcr_enc;
+	enum v4l2_quantization quantization;
+	enum v4l2_xfer_func xfer_func;
+};
+
+struct al_dec_ctx {
+	struct al_codec_dev *dev;
+	struct v4l2_fh fh;
+	struct v4l2_ctrl_handler ctrl_handler;
+	struct kref refcount;
+	struct list_head list;
+	/* CAP and OUT frames */
+	struct al_frame src;
+	struct al_frame dst;
+	struct completion res_done; /* Resolution found event */
+	u32 codec;
+	u64 hDec;
+	struct list_head cmd_q_list; /* Store active commands */
+	struct mutex buf_q_mlock;
+	struct list_head frame_q_list;
+	struct list_head stream_q_list;
+	u32 csequence;
+	u32 osequence;
+	bool stopped;
+	bool aborting;
+};
+
+#endif /*__AL_VDEC_DRV__*/
-- 
2.30.2


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

* [PATCH 3/3] media: allegro-dvt: Add DT-bindings for the Gen 3 IP
  2025-05-11 14:47 [PATCH 0/3] media: Add Gen 3 IP stateful decoder driver Yassine Ouaissa
  2025-05-11 14:47 ` [PATCH 1/3] media: allegro-dvt: Move the current driver to a subdirectory Yassine Ouaissa
  2025-05-11 14:47 ` [PATCH 2/3] media: allegro-dvt: Add Gen 3 IP stateful decoder driver Yassine Ouaissa
@ 2025-05-11 14:47 ` Yassine Ouaissa
  2025-05-11 16:38   ` Rob Herring (Arm)
  2025-05-11 20:03   ` Krzysztof Kozlowski
  2 siblings, 2 replies; 13+ messages in thread
From: Yassine Ouaissa @ 2025-05-11 14:47 UTC (permalink / raw)
  To: Michael Tretter, Yassine OUAISSA, Pengutronix Kernel Team,
	Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Michal Simek, Neil Armstrong, Heiko Stuebner,
	Aradhya Bhatia, Rafał Miłecki, Junhao Xie,
	Manivannan Sadhasivam, Kever Yang, Hans Verkuil,
	Christophe JAILLET, Andrzej Pietrasiewicz, Joe Hattori,
	Gaosheng Cui, Wolfram Sang, Uwe Kleine-König,
	Ricardo Ribalda, linux-media, devicetree, linux-kernel,
	linux-arm-kernel

Add the device-tree bindings for the allegro-dvt Gen 3 IP decoders, and
update the MAINTAINERS file.

Signed-off-by: Yassine Ouaissa <yassine.ouaissa@allegrodvt.com>
---
 .../bindings/media/allegrodvt,al300-vdec.yaml | 86 +++++++++++++++++++
 MAINTAINERS                                   |  1 +
 2 files changed, 87 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/media/allegrodvt,al300-vdec.yaml

diff --git a/Documentation/devicetree/bindings/media/allegrodvt,al300-vdec.yaml b/Documentation/devicetree/bindings/media/allegrodvt,al300-vdec.yaml
new file mode 100644
index 000000000000..ea4a55de570c
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/allegrodvt,al300-vdec.yaml
@@ -0,0 +1,86 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/allegrodvt,al300-vdec.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Allegro DVT Video IP Decoder Gen 3
+
+maintainers:
+  - Yassine OUAISSA <yassine.ouaissa@allegrodvt.com>
+
+description: |-
+  The al300-vdec represents the latest generation of Allegro DVT IP decoding technology, offering
+  significant advancements over its predecessors. This new decoder features
+  enhanced processing capabilities with improved throughput and reduced latency.
+
+  Communication between the host driver software and the MCU is implemented through
+  a specialized mailbox interface mechanism. This mailbox system provides a
+  structured channel for exchanging commands, parameters, and status information
+  between the host CPU and the MCU controlling the codec engines.
+
+properties:
+  compatible:
+    const: allegrodvt,al300-vdec
+
+  reg:
+    items:
+      - description: The registers
+      - description: the MCU APB register
+
+  reg-names:
+    items:
+      - const: regs
+      - const: apb
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: MCU clock
+
+  clock-names:
+    items:
+      - const: mcu_clk
+
+  memory-region:
+    items:
+      - description: Used to allocate memory for the MCU firmware,
+      and is also used for various operational buffers required by the MCU during codec operations.
+
+  firmware-name:
+    $ref: /schemas/types.yaml#/definitions/string
+    description:
+      If present, name of the file within the firmware search path containing
+      the MCU firmware.
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - interrupts
+  - clocks
+  - clock-names
+
+additionalProperties: False
+
+examples:
+  - |
+    axi {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        ald300: ald300@a0120000 {
+            compatible = "allegrodvt,al300-vdec";
+            reg = <0 0xa0120000 0 0x80000>,
+            <0x01 0x8000000 0x00 0x8000000>;
+            reg-names = "regs", "apb";
+            interrupts = <0 96 4>;
+            clocks = <&mcu_clock_dec>;
+            clock-names = "mcu_clk";
+            firmware-name = "al300_vdec.fw";
+        };
+    };
+
+...
diff --git a/MAINTAINERS b/MAINTAINERS
index 313d08cf90e0..8912fabab6ed 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -807,6 +807,7 @@ R:	Pengutronix Kernel Team <kernel@pengutronix.de>
 L:	linux-media@vger.kernel.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/media/allegro,al5e.yaml
+F:	Documentation/devicetree/bindings/media/allegrodvt,al300-vdec.yaml
 F:	drivers/media/platform/allegro-dvt/al300
 F:	drivers/media/platform/allegro-dvt/zynqmp
 
-- 
2.30.2


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

* Re: [PATCH 3/3] media: allegro-dvt: Add DT-bindings for the Gen 3 IP
  2025-05-11 14:47 ` [PATCH 3/3] media: allegro-dvt: Add DT-bindings for the Gen 3 IP Yassine Ouaissa
@ 2025-05-11 16:38   ` Rob Herring (Arm)
  2025-05-11 20:03   ` Krzysztof Kozlowski
  1 sibling, 0 replies; 13+ messages in thread
From: Rob Herring (Arm) @ 2025-05-11 16:38 UTC (permalink / raw)
  To: Yassine Ouaissa
  Cc: linux-arm-kernel, Andrzej Pietrasiewicz, Krzysztof Kozlowski,
	linux-media, devicetree, Conor Dooley, Hans Verkuil,
	Christophe JAILLET, Junhao Xie, Rafał Miłecki,
	Heiko Stuebner, Aradhya Bhatia, linux-kernel, Michael Tretter,
	Gaosheng Cui, Joe Hattori, Pengutronix Kernel Team,
	Mauro Carvalho Chehab, Ricardo Ribalda, Wolfram Sang,
	Uwe Kleine-König, Neil Armstrong, Manivannan Sadhasivam,
	Kever Yang, Michal Simek


On Sun, 11 May 2025 16:47:34 +0200, Yassine Ouaissa wrote:
> Add the device-tree bindings for the allegro-dvt Gen 3 IP decoders, and
> update the MAINTAINERS file.
> 
> Signed-off-by: Yassine Ouaissa <yassine.ouaissa@allegrodvt.com>
> ---
>  .../bindings/media/allegrodvt,al300-vdec.yaml | 86 +++++++++++++++++++
>  MAINTAINERS                                   |  1 +
>  2 files changed, 87 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/media/allegrodvt,al300-vdec.yaml
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:
./Documentation/devicetree/bindings/media/allegrodvt,al300-vdec.yaml:52:3: [error] syntax error: could not find expected ':' (syntax)

dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/media/allegrodvt,al300-vdec.yaml: ignoring, error parsing file
./Documentation/devicetree/bindings/media/allegrodvt,al300-vdec.yaml:52:3: could not find expected ':'
make[2]: *** Deleting file 'Documentation/devicetree/bindings/media/allegrodvt,al300-vdec.example.dts'
Documentation/devicetree/bindings/media/allegrodvt,al300-vdec.yaml:52:3: could not find expected ':'
make[2]: *** [Documentation/devicetree/bindings/Makefile:26: Documentation/devicetree/bindings/media/allegrodvt,al300-vdec.example.dts] Error 1
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [/builds/robherring/dt-review-ci/linux/Makefile:1527: dt_binding_check] Error 2
make: *** [Makefile:248: __sub-make] Error 2

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250511144752.504162-4-yassine.ouaissa@allegrodvt.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.


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

* Re: [PATCH 3/3] media: allegro-dvt: Add DT-bindings for the Gen 3 IP
  2025-05-11 14:47 ` [PATCH 3/3] media: allegro-dvt: Add DT-bindings for the Gen 3 IP Yassine Ouaissa
  2025-05-11 16:38   ` Rob Herring (Arm)
@ 2025-05-11 20:03   ` Krzysztof Kozlowski
  2025-05-12  8:23     ` Yassine Ouaissa
  1 sibling, 1 reply; 13+ messages in thread
From: Krzysztof Kozlowski @ 2025-05-11 20:03 UTC (permalink / raw)
  To: Yassine Ouaissa, Michael Tretter, Pengutronix Kernel Team,
	Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Michal Simek, Neil Armstrong, Heiko Stuebner,
	Aradhya Bhatia, Rafał Miłecki, Junhao Xie,
	Manivannan Sadhasivam, Kever Yang, Hans Verkuil,
	Christophe JAILLET, Andrzej Pietrasiewicz, Joe Hattori,
	Gaosheng Cui, Wolfram Sang, Uwe Kleine-König,
	Ricardo Ribalda, linux-media, devicetree, linux-kernel,
	linux-arm-kernel

On 11/05/2025 16:47, Yassine Ouaissa wrote:
> Add the device-tree bindings for the allegro-dvt Gen 3 IP decoders, and
> update the MAINTAINERS file.
> 
> Signed-off-by: Yassine Ouaissa <yassine.ouaissa@allegrodvt.com>
> ---
>  .../bindings/media/allegrodvt,al300-vdec.yaml | 86 +++++++++++++++++++

Looks untested so limited review follows.

A nit, subject: drop second/last, redundant "DT bindings". The
"dt-bindings" prefix is already stating that these are DT bindings.
See also:
https://elixir.bootlin.com/linux/v6.7-rc8/source/Documentation/devicetree/bindings/submitting-patches.rst#L18

>  MAINTAINERS                                   |  1 +
>  2 files changed, 87 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/media/allegrodvt,al300-vdec.yaml
> 

Please organize the patch documenting compatible (DT bindings) before
their user.
See also:
https://elixir.bootlin.com/linux/v6.14-rc6/source/Documentation/devicetree/bindings/submitting-patches.rst#L46

> diff --git a/Documentation/devicetree/bindings/media/allegrodvt,al300-vdec.yaml b/Documentation/devicetree/bindings/media/allegrodvt,al300-vdec.yaml
> new file mode 100644
> index 000000000000..ea4a55de570c
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/media/allegrodvt,al300-vdec.yaml
> @@ -0,0 +1,86 @@
> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/media/allegrodvt,al300-vdec.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Allegro DVT Video IP Decoder Gen 3
> +
> +maintainers:
> +  - Yassine OUAISSA <yassine.ouaissa@allegrodvt.com>
> +
> +description: |-
> +  The al300-vdec represents the latest generation of Allegro DVT IP decoding technology, offering

Wrap at 80, see Linux coding style.

> +  significant advancements over its predecessors. This new decoder features
> +  enhanced processing capabilities with improved throughput and reduced latency.
> +
> +  Communication between the host driver software and the MCU is implemented through
> +  a specialized mailbox interface mechanism. This mailbox system provides a
> +  structured channel for exchanging commands, parameters, and status information
> +  between the host CPU and the MCU controlling the codec engines.
> +
> +properties:
> +  compatible:
> +    const: allegrodvt,al300-vdec

Undocumented prefix.

What is the actual device name? al300? Can you have al300-adec? or
al300-dec?


> +
> +  reg:
> +    items:
> +      - description: The registers
> +      - description: the MCU APB register
> +
> +  reg-names:
> +    items:
> +      - const: regs
> +      - const: apb
> +
> +  interrupts:
> +    maxItems: 1
> +
> +  clocks:
> +    items:
> +      - description: MCU clock
> +
> +  clock-names:
> +    items:
> +      - const: mcu_clk

Drop clock-names, pretty obvious

> +
> +  memory-region:
> +    items:
> +      - description: Used to allocate memory for the MCU firmware,
> +      and is also used for various operational buffers required by the MCU during codec operations.
> +
> +  firmware-name:
> +    $ref: /schemas/types.yaml#/definitions/string

Drop, type is already fixed.

missing maxItems: 1

> +    description:
> +      If present, name of the file within the firmware search path containing
> +      the MCU firmware.
> +
> +required:
> +  - compatible
> +  - reg
> +  - reg-names
> +  - interrupts
> +  - clocks
> +  - clock-names
> +
> +additionalProperties: False
> +
> +examples:
> +  - |
> +    axi {
> +        #address-cells = <2>;
> +        #size-cells = <2>;
> +
> +        ald300: ald300@a0120000 {

Drop unused label.

Node names should be generic. See also an explanation and list of
examples (not exhaustive) in DT specification:
https://devicetree-specification.readthedocs.io/en/latest/chapter2-devicetree-basics.html#generic-names-recommendation


> +            compatible = "allegrodvt,al300-vdec";
> +            reg = <0 0xa0120000 0 0x80000>,

Here 0 is not hex

> +            <0x01 0x8000000 0x00 0x8000000>;

but here is hex?

Also misaligned.

Also: very odd large address space.

>  


Best regards,
Krzysztof

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

* Re: [PATCH 2/3] media: allegro-dvt: Add Gen 3 IP stateful decoder driver
  2025-05-11 14:47 ` [PATCH 2/3] media: allegro-dvt: Add Gen 3 IP stateful decoder driver Yassine Ouaissa
@ 2025-05-11 20:49   ` kernel test robot
  2025-05-12 22:39   ` kernel test robot
  1 sibling, 0 replies; 13+ messages in thread
From: kernel test robot @ 2025-05-11 20:49 UTC (permalink / raw)
  To: Yassine Ouaissa, Michael Tretter, Pengutronix Kernel Team,
	Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Michal Simek, Neil Armstrong, Heiko Stuebner,
	Junhao Xie, Aradhya Bhatia, Rafał Miłecki, Kever Yang,
	Manivannan Sadhasivam, Hans Verkuil, Andrzej Pietrasiewicz,
	Joe Hattori, Christophe JAILLET, Uwe Kleine-König,
	Wolfram Sang, Gaosheng Cui, Ricardo Ribalda, devicetree,
	linux-kernel, linux-arm-kernel
  Cc: oe-kbuild-all, linux-media

Hi Yassine,

kernel test robot noticed the following build warnings:

[auto build test WARNING on robh/for-next]
[also build test WARNING on linus/master v6.15-rc5 next-20250509]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Yassine-Ouaissa/media-allegro-dvt-Move-the-current-driver-to-a-subdirectory/20250511-225629
base:   https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
patch link:    https://lore.kernel.org/r/20250511144752.504162-3-yassine.ouaissa%40allegrodvt.com
patch subject: [PATCH 2/3] media: allegro-dvt: Add Gen 3 IP stateful decoder driver
config: sparc-allmodconfig (https://download.01.org/0day-ci/archive/20250512/202505120421.Mdk0nEDm-lkp@intel.com/config)
compiler: sparc64-linux-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250512/202505120421.Mdk0nEDm-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202505120421.Mdk0nEDm-lkp@intel.com/

All warnings (new ones prefixed by >>):

   In file included from include/uapi/linux/errno.h:1,
                    from include/linux/errno.h:5,
                    from drivers/media/platform/allegro-dvt/al300/al_codec_util.c:11:
>> arch/sparc/include/uapi/asm/errno.h:10:9: warning: "EINPROGRESS" redefined
      10 | #define EINPROGRESS     36      /* Operation now in progress */
         |         ^~~~~~~~~~~
   In file included from drivers/media/platform/allegro-dvt/al300/al_codec_util.c:10:
   include/uapi/asm-generic/errno.h:98:9: note: this is the location of the previous definition
      98 | #define EINPROGRESS     115     /* Operation now in progress */
         |         ^~~~~~~~~~~
>> arch/sparc/include/uapi/asm/errno.h:11:9: warning: "EALREADY" redefined
      11 | #define EALREADY        37      /* Operation already in progress */
         |         ^~~~~~~~
   include/uapi/asm-generic/errno.h:97:9: note: this is the location of the previous definition
      97 | #define EALREADY        114     /* Operation already in progress */
         |         ^~~~~~~~
>> arch/sparc/include/uapi/asm/errno.h:12:9: warning: "ENOTSOCK" redefined
      12 | #define ENOTSOCK        38      /* Socket operation on non-socket */
         |         ^~~~~~~~
   include/uapi/asm-generic/errno.h:71:9: note: this is the location of the previous definition
      71 | #define ENOTSOCK        88      /* Socket operation on non-socket */
         |         ^~~~~~~~
>> arch/sparc/include/uapi/asm/errno.h:13:9: warning: "EDESTADDRREQ" redefined
      13 | #define EDESTADDRREQ    39      /* Destination address required */
         |         ^~~~~~~~~~~~
   include/uapi/asm-generic/errno.h:72:9: note: this is the location of the previous definition
      72 | #define EDESTADDRREQ    89      /* Destination address required */
         |         ^~~~~~~~~~~~
>> arch/sparc/include/uapi/asm/errno.h:14:9: warning: "EMSGSIZE" redefined
      14 | #define EMSGSIZE        40      /* Message too long */
         |         ^~~~~~~~
   include/uapi/asm-generic/errno.h:73:9: note: this is the location of the previous definition
      73 | #define EMSGSIZE        90      /* Message too long */
         |         ^~~~~~~~
>> arch/sparc/include/uapi/asm/errno.h:15:9: warning: "EPROTOTYPE" redefined
      15 | #define EPROTOTYPE      41      /* Protocol wrong type for socket */
         |         ^~~~~~~~~~
   include/uapi/asm-generic/errno.h:74:9: note: this is the location of the previous definition
      74 | #define EPROTOTYPE      91      /* Protocol wrong type for socket */
         |         ^~~~~~~~~~
>> arch/sparc/include/uapi/asm/errno.h:16:9: warning: "ENOPROTOOPT" redefined
      16 | #define ENOPROTOOPT     42      /* Protocol not available */
         |         ^~~~~~~~~~~
   include/uapi/asm-generic/errno.h:75:9: note: this is the location of the previous definition
      75 | #define ENOPROTOOPT     92      /* Protocol not available */
         |         ^~~~~~~~~~~
>> arch/sparc/include/uapi/asm/errno.h:17:9: warning: "EPROTONOSUPPORT" redefined
      17 | #define EPROTONOSUPPORT 43      /* Protocol not supported */
         |         ^~~~~~~~~~~~~~~
   include/uapi/asm-generic/errno.h:76:9: note: this is the location of the previous definition
      76 | #define EPROTONOSUPPORT 93      /* Protocol not supported */
         |         ^~~~~~~~~~~~~~~
>> arch/sparc/include/uapi/asm/errno.h:18:9: warning: "ESOCKTNOSUPPORT" redefined
      18 | #define ESOCKTNOSUPPORT 44      /* Socket type not supported */
         |         ^~~~~~~~~~~~~~~
   include/uapi/asm-generic/errno.h:77:9: note: this is the location of the previous definition
      77 | #define ESOCKTNOSUPPORT 94      /* Socket type not supported */
         |         ^~~~~~~~~~~~~~~
>> arch/sparc/include/uapi/asm/errno.h:19:9: warning: "EOPNOTSUPP" redefined
      19 | #define EOPNOTSUPP      45      /* Op not supported on transport endpoint */
         |         ^~~~~~~~~~
   include/uapi/asm-generic/errno.h:78:9: note: this is the location of the previous definition
      78 | #define EOPNOTSUPP      95      /* Operation not supported on transport endpoint */
         |         ^~~~~~~~~~
>> arch/sparc/include/uapi/asm/errno.h:20:9: warning: "EPFNOSUPPORT" redefined
      20 | #define EPFNOSUPPORT    46      /* Protocol family not supported */
         |         ^~~~~~~~~~~~
   include/uapi/asm-generic/errno.h:79:9: note: this is the location of the previous definition
      79 | #define EPFNOSUPPORT    96      /* Protocol family not supported */
         |         ^~~~~~~~~~~~
>> arch/sparc/include/uapi/asm/errno.h:21:9: warning: "EAFNOSUPPORT" redefined
      21 | #define EAFNOSUPPORT    47      /* Address family not supported by protocol */
         |         ^~~~~~~~~~~~
   include/uapi/asm-generic/errno.h:80:9: note: this is the location of the previous definition
      80 | #define EAFNOSUPPORT    97      /* Address family not supported by protocol */
         |         ^~~~~~~~~~~~
>> arch/sparc/include/uapi/asm/errno.h:22:9: warning: "EADDRINUSE" redefined
      22 | #define EADDRINUSE      48      /* Address already in use */
         |         ^~~~~~~~~~
   include/uapi/asm-generic/errno.h:81:9: note: this is the location of the previous definition
      81 | #define EADDRINUSE      98      /* Address already in use */
         |         ^~~~~~~~~~
>> arch/sparc/include/uapi/asm/errno.h:23:9: warning: "EADDRNOTAVAIL" redefined
      23 | #define EADDRNOTAVAIL   49      /* Cannot assign requested address */
         |         ^~~~~~~~~~~~~
   include/uapi/asm-generic/errno.h:82:9: note: this is the location of the previous definition
      82 | #define EADDRNOTAVAIL   99      /* Cannot assign requested address */
         |         ^~~~~~~~~~~~~
>> arch/sparc/include/uapi/asm/errno.h:24:9: warning: "ENETDOWN" redefined
      24 | #define ENETDOWN        50      /* Network is down */
         |         ^~~~~~~~
   include/uapi/asm-generic/errno.h:83:9: note: this is the location of the previous definition
      83 | #define ENETDOWN        100     /* Network is down */
         |         ^~~~~~~~
>> arch/sparc/include/uapi/asm/errno.h:25:9: warning: "ENETUNREACH" redefined
      25 | #define ENETUNREACH     51      /* Network is unreachable */
         |         ^~~~~~~~~~~
   include/uapi/asm-generic/errno.h:84:9: note: this is the location of the previous definition
      84 | #define ENETUNREACH     101     /* Network is unreachable */
         |         ^~~~~~~~~~~
>> arch/sparc/include/uapi/asm/errno.h:26:9: warning: "ENETRESET" redefined
      26 | #define ENETRESET       52      /* Net dropped connection because of reset */
         |         ^~~~~~~~~
   include/uapi/asm-generic/errno.h:85:9: note: this is the location of the previous definition
      85 | #define ENETRESET       102     /* Network dropped connection because of reset */
         |         ^~~~~~~~~
>> arch/sparc/include/uapi/asm/errno.h:27:9: warning: "ECONNABORTED" redefined
      27 | #define ECONNABORTED    53      /* Software caused connection abort */
         |         ^~~~~~~~~~~~
   include/uapi/asm-generic/errno.h:86:9: note: this is the location of the previous definition
      86 | #define ECONNABORTED    103     /* Software caused connection abort */
         |         ^~~~~~~~~~~~
>> arch/sparc/include/uapi/asm/errno.h:28:9: warning: "ECONNRESET" redefined
      28 | #define ECONNRESET      54      /* Connection reset by peer */
         |         ^~~~~~~~~~
   include/uapi/asm-generic/errno.h:87:9: note: this is the location of the previous definition
      87 | #define ECONNRESET      104     /* Connection reset by peer */
         |         ^~~~~~~~~~
>> arch/sparc/include/uapi/asm/errno.h:29:9: warning: "ENOBUFS" redefined
      29 | #define ENOBUFS         55      /* No buffer space available */
         |         ^~~~~~~
   include/uapi/asm-generic/errno.h:88:9: note: this is the location of the previous definition
      88 | #define ENOBUFS         105     /* No buffer space available */
         |         ^~~~~~~
   arch/sparc/include/uapi/asm/errno.h:30:9: warning: "EISCONN" redefined
      30 | #define EISCONN         56      /* Transport endpoint is already connected */
         |         ^~~~~~~
   include/uapi/asm-generic/errno.h:89:9: note: this is the location of the previous definition
      89 | #define EISCONN         106     /* Transport endpoint is already connected */
         |         ^~~~~~~
   arch/sparc/include/uapi/asm/errno.h:31:9: warning: "ENOTCONN" redefined
      31 | #define ENOTCONN        57      /* Transport endpoint is not connected */
         |         ^~~~~~~~
   include/uapi/asm-generic/errno.h:90:9: note: this is the location of the previous definition
      90 | #define ENOTCONN        107     /* Transport endpoint is not connected */
         |         ^~~~~~~~
   arch/sparc/include/uapi/asm/errno.h:32:9: warning: "ESHUTDOWN" redefined
      32 | #define ESHUTDOWN       58      /* No send after transport endpoint shutdown */
         |         ^~~~~~~~~
   include/uapi/asm-generic/errno.h:91:9: note: this is the location of the previous definition
      91 | #define ESHUTDOWN       108     /* Cannot send after transport endpoint shutdown */
         |         ^~~~~~~~~
   arch/sparc/include/uapi/asm/errno.h:33:9: warning: "ETOOMANYREFS" redefined
      33 | #define ETOOMANYREFS    59      /* Too many references: cannot splice */
         |         ^~~~~~~~~~~~
   include/uapi/asm-generic/errno.h:92:9: note: this is the location of the previous definition
      92 | #define ETOOMANYREFS    109     /* Too many references: cannot splice */
         |         ^~~~~~~~~~~~
   arch/sparc/include/uapi/asm/errno.h:34:9: warning: "ETIMEDOUT" redefined
      34 | #define ETIMEDOUT       60      /* Connection timed out */
         |         ^~~~~~~~~
   include/uapi/asm-generic/errno.h:93:9: note: this is the location of the previous definition
      93 | #define ETIMEDOUT       110     /* Connection timed out */
         |         ^~~~~~~~~
   arch/sparc/include/uapi/asm/errno.h:35:9: warning: "ECONNREFUSED" redefined
      35 | #define ECONNREFUSED    61      /* Connection refused */
         |         ^~~~~~~~~~~~
   include/uapi/asm-generic/errno.h:94:9: note: this is the location of the previous definition
      94 | #define ECONNREFUSED    111     /* Connection refused */
         |         ^~~~~~~~~~~~
   arch/sparc/include/uapi/asm/errno.h:36:9: warning: "ELOOP" redefined
      36 | #define ELOOP           62      /* Too many symbolic links encountered */
         |         ^~~~~
   include/uapi/asm-generic/errno.h:21:9: note: this is the location of the previous definition
      21 | #define ELOOP           40      /* Too many symbolic links encountered */
         |         ^~~~~
   arch/sparc/include/uapi/asm/errno.h:37:9: warning: "ENAMETOOLONG" redefined
      37 | #define ENAMETOOLONG    63      /* File name too long */
         |         ^~~~~~~~~~~~
   include/uapi/asm-generic/errno.h:8:9: note: this is the location of the previous definition
       8 | #define ENAMETOOLONG    36      /* File name too long */
         |         ^~~~~~~~~~~~
   arch/sparc/include/uapi/asm/errno.h:38:9: warning: "EHOSTDOWN" redefined
      38 | #define EHOSTDOWN       64      /* Host is down */
         |         ^~~~~~~~~
   include/uapi/asm-generic/errno.h:95:9: note: this is the location of the previous definition
      95 | #define EHOSTDOWN       112     /* Host is down */
         |         ^~~~~~~~~
   arch/sparc/include/uapi/asm/errno.h:39:9: warning: "EHOSTUNREACH" redefined
      39 | #define EHOSTUNREACH    65      /* No route to host */
         |         ^~~~~~~~~~~~
   include/uapi/asm-generic/errno.h:96:9: note: this is the location of the previous definition
      96 | #define EHOSTUNREACH    113     /* No route to host */
         |         ^~~~~~~~~~~~
   arch/sparc/include/uapi/asm/errno.h:40:9: warning: "ENOTEMPTY" redefined
      40 | #define ENOTEMPTY       66      /* Directory not empty */
         |         ^~~~~~~~~
   include/uapi/asm-generic/errno.h:20:9: note: this is the location of the previous definition
      20 | #define ENOTEMPTY       39      /* Directory not empty */
         |         ^~~~~~~~~
   arch/sparc/include/uapi/asm/errno.h:42:9: warning: "EUSERS" redefined
      42 | #define EUSERS          68      /* Too many users */
         |         ^~~~~~
   include/uapi/asm-generic/errno.h:70:9: note: this is the location of the previous definition
      70 | #define EUSERS          87      /* Too many users */
         |         ^~~~~~
   arch/sparc/include/uapi/asm/errno.h:43:9: warning: "EDQUOT" redefined
      43 | #define EDQUOT          69      /* Quota exceeded */
         |         ^~~~~~
   include/uapi/asm-generic/errno.h:105:9: note: this is the location of the previous definition
     105 | #define EDQUOT          122     /* Quota exceeded */
         |         ^~~~~~
   arch/sparc/include/uapi/asm/errno.h:44:9: warning: "ESTALE" redefined
      44 | #define ESTALE          70      /* Stale file handle */
         |         ^~~~~~
   include/uapi/asm-generic/errno.h:99:9: note: this is the location of the previous definition
      99 | #define ESTALE          116     /* Stale file handle */
         |         ^~~~~~
   arch/sparc/include/uapi/asm/errno.h:45:9: warning: "EREMOTE" redefined
      45 | #define EREMOTE         71      /* Object is remote */
         |         ^~~~~~~
   include/uapi/asm-generic/errno.h:49:9: note: this is the location of the previous definition
      49 | #define EREMOTE         66      /* Object is remote */
         |         ^~~~~~~
   arch/sparc/include/uapi/asm/errno.h:46:9: warning: "ENOSTR" redefined
      46 | #define ENOSTR          72      /* Device not a stream */
         |         ^~~~~~
   include/uapi/asm-generic/errno.h:43:9: note: this is the location of the previous definition
      43 | #define ENOSTR          60      /* Device not a stream */


vim +/EINPROGRESS +10 arch/sparc/include/uapi/asm/errno.h

^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16    8  
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16    9  #define	EWOULDBLOCK	EAGAIN	/* Operation would block */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @10  #define	EINPROGRESS	36	/* Operation now in progress */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @11  #define	EALREADY	37	/* Operation already in progress */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @12  #define	ENOTSOCK	38	/* Socket operation on non-socket */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @13  #define	EDESTADDRREQ	39	/* Destination address required */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @14  #define	EMSGSIZE	40	/* Message too long */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @15  #define	EPROTOTYPE	41	/* Protocol wrong type for socket */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @16  #define	ENOPROTOOPT	42	/* Protocol not available */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @17  #define	EPROTONOSUPPORT	43	/* Protocol not supported */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @18  #define	ESOCKTNOSUPPORT	44	/* Socket type not supported */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @19  #define	EOPNOTSUPP	45	/* Op not supported on transport endpoint */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @20  #define	EPFNOSUPPORT	46	/* Protocol family not supported */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @21  #define	EAFNOSUPPORT	47	/* Address family not supported by protocol */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @22  #define	EADDRINUSE	48	/* Address already in use */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @23  #define	EADDRNOTAVAIL	49	/* Cannot assign requested address */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @24  #define	ENETDOWN	50	/* Network is down */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @25  #define	ENETUNREACH	51	/* Network is unreachable */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @26  #define	ENETRESET	52	/* Net dropped connection because of reset */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @27  #define	ECONNABORTED	53	/* Software caused connection abort */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @28  #define	ECONNRESET	54	/* Connection reset by peer */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @29  #define	ENOBUFS		55	/* No buffer space available */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @30  #define	EISCONN		56	/* Transport endpoint is already connected */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @31  #define	ENOTCONN	57	/* Transport endpoint is not connected */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @32  #define	ESHUTDOWN	58	/* No send after transport endpoint shutdown */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @33  #define	ETOOMANYREFS	59	/* Too many references: cannot splice */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @34  #define	ETIMEDOUT	60	/* Connection timed out */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @35  #define	ECONNREFUSED	61	/* Connection refused */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @36  #define	ELOOP		62	/* Too many symbolic links encountered */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @37  #define	ENAMETOOLONG	63	/* File name too long */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @38  #define	EHOSTDOWN	64	/* Host is down */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @39  #define	EHOSTUNREACH	65	/* No route to host */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @40  #define	ENOTEMPTY	66	/* Directory not empty */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16   41  #define EPROCLIM        67      /* SUNOS: Too many processes */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @42  #define	EUSERS		68	/* Too many users */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @43  #define	EDQUOT		69	/* Quota exceeded */
0ca43435188b9f arch/sparc/include/uapi/asm/errno.h Eric Sandeen        2013-11-12  @44  #define	ESTALE		70	/* Stale file handle */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @45  #define	EREMOTE		71	/* Object is remote */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @46  #define	ENOSTR		72	/* Device not a stream */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @47  #define	ETIME		73	/* Timer expired */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @48  #define	ENOSR		74	/* Out of streams resources */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @49  #define	ENOMSG		75	/* No message of desired type */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @50  #define	EBADMSG		76	/* Not a data message */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @51  #define	EIDRM		77	/* Identifier removed */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @52  #define	EDEADLK		78	/* Resource deadlock would occur */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @53  #define	ENOLCK		79	/* No record locks available */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @54  #define	ENONET		80	/* Machine is not on the network */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16   55  #define ERREMOTE        81      /* SunOS: Too many lvls of remote in path */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @56  #define	ENOLINK		82	/* Link has been severed */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @57  #define	EADV		83	/* Advertise error */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @58  #define	ESRMNT		84	/* Srmount error */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @59  #define	ECOMM		85      /* Communication error on send */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @60  #define	EPROTO		86	/* Protocol error */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @61  #define	EMULTIHOP	87	/* Multihop attempted */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @62  #define	EDOTDOT		88	/* RFS specific error */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @63  #define	EREMCHG		89	/* Remote address changed */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @64  #define	ENOSYS		90	/* Function not implemented */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16   65  
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16   66  /* The rest have no SunOS equivalent. */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @67  #define	ESTRPIPE	91	/* Streams pipe error */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @68  #define	EOVERFLOW	92	/* Value too large for defined data type */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @69  #define	EBADFD		93	/* File descriptor in bad state */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @70  #define	ECHRNG		94	/* Channel number out of range */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @71  #define	EL2NSYNC	95	/* Level 2 not synchronized */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @72  #define	EL3HLT		96	/* Level 3 halted */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @73  #define	EL3RST		97	/* Level 3 reset */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @74  #define	ELNRNG		98	/* Link number out of range */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @75  #define	EUNATCH		99	/* Protocol driver not attached */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @76  #define	ENOCSI		100	/* No CSI structure available */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @77  #define	EL2HLT		101	/* Level 2 halted */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @78  #define	EBADE		102	/* Invalid exchange */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @79  #define	EBADR		103	/* Invalid request descriptor */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @80  #define	EXFULL		104	/* Exchange full */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @81  #define	ENOANO		105	/* No anode */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @82  #define	EBADRQC		106	/* Invalid request code */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @83  #define	EBADSLT		107	/* Invalid slot */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @84  #define	EDEADLOCK	108	/* File locking deadlock error */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @85  #define	EBFONT		109	/* Bad font file format */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @86  #define	ELIBEXEC	110	/* Cannot exec a shared library directly */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @87  #define	ENODATA		111	/* No data available */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @88  #define	ELIBBAD		112	/* Accessing a corrupted shared library */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @89  #define	ENOPKG		113	/* Package not installed */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @90  #define	ELIBACC		114	/* Can not access a needed shared library */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @91  #define	ENOTUNIQ	115	/* Name not unique on network */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @92  #define	ERESTART	116	/* Interrupted syscall should be restarted */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16   93  #define	EUCLEAN		117	/* Structure needs cleaning */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16   94  #define	ENOTNAM		118	/* Not a XENIX named type file */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16   95  #define	ENAVAIL		119	/* No XENIX semaphores available */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16   96  #define	EISNAM		120	/* Is a named type file */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16   97  #define	EREMOTEIO	121	/* Remote I/O error */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @98  #define	EILSEQ		122	/* Illegal byte sequence */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  @99  #define	ELIBMAX		123	/* Atmpt to link in too many shared libs */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16 @100  #define	ELIBSCN		124	/* .lib section in a.out corrupted */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  101  
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16 @102  #define	ENOMEDIUM	125	/* No medium found */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16 @103  #define	EMEDIUMTYPE	126	/* Wrong medium type */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16 @104  #define	ECANCELED	127	/* Operation Cancelled */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16 @105  #define	ENOKEY		128	/* Required key not available */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16 @106  #define	EKEYEXPIRED	129	/* Key has expired */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16 @107  #define	EKEYREVOKED	130	/* Key has been revoked */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16 @108  #define	EKEYREJECTED	131	/* Key was rejected by service */
^1da177e4c3f41 include/asm-sparc/errno.h           Linus Torvalds      2005-04-16  109  
4750e2c0c59e0c include/asm-sparc/errno.h           Joe Korty           2005-05-01  110  /* for robust mutexes */
4750e2c0c59e0c include/asm-sparc/errno.h           Joe Korty           2005-05-01 @111  #define	EOWNERDEAD	132	/* Owner died */
4750e2c0c59e0c include/asm-sparc/errno.h           Joe Korty           2005-05-01 @112  #define	ENOTRECOVERABLE	133	/* State not recoverable */
4750e2c0c59e0c include/asm-sparc/errno.h           Joe Korty           2005-05-01  113  
7d217d7ffc3433 arch/sparc/include/asm/errno.h      Alexander Beregalov 2009-06-07 @114  #define	ERFKILL		134	/* Operation not possible due to RF-kill */
7d217d7ffc3433 arch/sparc/include/asm/errno.h      Alexander Beregalov 2009-06-07  115  
69ebb83e13e514 arch/sparc/include/asm/errno.h      Ying Huang          2011-01-30 @116  #define EHWPOISON	135	/* Memory page has hardware error */
69ebb83e13e514 arch/sparc/include/asm/errno.h      Ying Huang          2011-01-30  117  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

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

* Re: [PATCH 3/3] media: allegro-dvt: Add DT-bindings for the Gen 3 IP
  2025-05-11 20:03   ` Krzysztof Kozlowski
@ 2025-05-12  8:23     ` Yassine Ouaissa
  2025-05-12 10:42       ` Krzysztof Kozlowski
  2025-05-14  7:59       ` Krzysztof Kozlowski
  0 siblings, 2 replies; 13+ messages in thread
From: Yassine Ouaissa @ 2025-05-12  8:23 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Michael Tretter, Pengutronix Kernel Team, Mauro Carvalho Chehab,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Michal Simek,
	Neil Armstrong, Heiko Stuebner, Aradhya Bhatia, Rafa?? Mi??ecki,
	Junhao Xie, Manivannan Sadhasivam, Kever Yang, Hans Verkuil,
	Christophe JAILLET, Andrzej Pietrasiewicz, Joe Hattori,
	Gaosheng Cui, Wolfram Sang, Uwe Kleine-K??nig, Ricardo Ribalda,
	linux-media, devicetree, linux-kernel, linux-arm-kernel

On 11.05.2025 22:03, Krzysztof Kozlowski wrote:
>On 11/05/2025 16:47, Yassine Ouaissa wrote:
>> Add the device-tree bindings for the allegro-dvt Gen 3 IP decoders, and
>> update the MAINTAINERS file.
>>
>> Signed-off-by: Yassine Ouaissa <yassine.ouaissa@allegrodvt.com>
>> ---
>>  .../bindings/media/allegrodvt,al300-vdec.yaml | 86 +++++++++++++++++++

Hi Kozlowski,

Thanks for the review.
>
>Looks untested so limited review follows.
>
>A nit, subject: drop second/last, redundant "DT bindings". The
>"dt-bindings" prefix is already stating that these are DT bindings.
>See also:
>https://elixir.bootlin.com/linux/v6.7-rc8/source/Documentation/devicetree/bindings/submitting-patches.rst#L18
>
I'll fix this issue in the next version.

>>  MAINTAINERS                                   |  1 +
>>  2 files changed, 87 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/media/allegrodvt,al300-vdec.yaml
>>
>
>Please organize the patch documenting compatible (DT bindings) before
>their user.
>See also:
>https://elixir.bootlin.com/linux/v6.14-rc6/source/Documentation/devicetree/bindings/submitting-patches.rst#L46
>

I'll fix this issue in the next version.

>> diff --git a/Documentation/devicetree/bindings/media/allegrodvt,al300-vdec.yaml b/Documentation/devicetree/bindings/media/allegrodvt,al300-vdec.yaml
>> new file mode 100644
>> index 000000000000..ea4a55de570c
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/media/allegrodvt,al300-vdec.yaml
>> @@ -0,0 +1,86 @@
>> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/media/allegrodvt,al300-vdec.yaml#
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: Allegro DVT Video IP Decoder Gen 3
>> +
>> +maintainers:
>> +  - Yassine OUAISSA <yassine.ouaissa@allegrodvt.com>
>> +
>> +description: |-
>> +  The al300-vdec represents the latest generation of Allegro DVT IP decoding technology, offering
>
>Wrap at 80, see Linux coding style.
>
issue fixed also, thanks.
>> +  significant advancements over its predecessors. This new decoder features
>> +  enhanced processing capabilities with improved throughput and reduced latency.
>> +
>> +  Communication between the host driver software and the MCU is implemented through
>> +  a specialized mailbox interface mechanism. This mailbox system provides a
>> +  structured channel for exchanging commands, parameters, and status information
>> +  between the host CPU and the MCU controlling the codec engines.
>> +
>> +properties:
>> +  compatible:
>> +    const: allegrodvt,al300-vdec
>
>Undocumented prefix.
>
>What is the actual device name? al300? Can you have al300-adec? or
>al300-dec?
>
>

the device name is al300, the vdec is for decoder driver.

>> +
>> +  reg:
>> +    items:
>> +      - description: The registers
>> +      - description: the MCU APB register
>> +
>> +  reg-names:
>> +    items:
>> +      - const: regs
>> +      - const: apb
>> +
>> +  interrupts:
>> +    maxItems: 1
>> +
>> +  clocks:
>> +    items:
>> +      - description: MCU clock
>> +
>> +  clock-names:
>> +    items:
>> +      - const: mcu_clk
>
>Drop clock-names, pretty obvious
>
the clock-name is a require item, it used by the driver.
>> +
>> +  memory-region:
>> +    items:
>> +      - description: Used to allocate memory for the MCU firmware,
>> +      and is also used for various operational buffers required by the MCU during codec operations.
>> +
>> +  firmware-name:
>> +    $ref: /schemas/types.yaml#/definitions/string
>
>Drop, type is already fixed.
>
>missing maxItems: 1
>

The next version will have the maxItem, and drop the ref type.

>> +    description:
>> +      If present, name of the file within the firmware search path containing
>> +      the MCU firmware.
>> +
>> +required:
>> +  - compatible
>> +  - reg
>> +  - reg-names
>> +  - interrupts
>> +  - clocks
>> +  - clock-names
>> +
>> +additionalProperties: False
>> +
>> +examples:
>> +  - |
>> +    axi {
>> +        #address-cells = <2>;
>> +        #size-cells = <2>;
>> +
>> +        ald300: ald300@a0120000 {
>
>Drop unused label.
>
>Node names should be generic. See also an explanation and list of
>examples (not exhaustive) in DT specification:
>https://devicetree-specification.readthedocs.io/en/latest/chapter2-devicetree-basics.html#generic-names-recommendation
>
>
>> +            compatible = "allegrodvt,al300-vdec";
>> +            reg = <0 0xa0120000 0 0x80000>,
>
>Here 0 is not hex
>
>> +            <0x01 0x8000000 0x00 0x8000000>;
>
>but here is hex?
>
>Also misaligned.
>
>Also: very odd large address space.
>

Nice catch, the misaligned issue is fixed.
>>
>
>
>Best regards,
>Krzysztof

Best regards
Yassine OUAISSA

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

* Re: [PATCH 3/3] media: allegro-dvt: Add DT-bindings for the Gen 3 IP
  2025-05-12  8:23     ` Yassine Ouaissa
@ 2025-05-12 10:42       ` Krzysztof Kozlowski
  2025-05-12 11:17         ` Yassine Ouaissa
  2025-05-14  7:59       ` Krzysztof Kozlowski
  1 sibling, 1 reply; 13+ messages in thread
From: Krzysztof Kozlowski @ 2025-05-12 10:42 UTC (permalink / raw)
  To: Yassine Ouaissa
  Cc: Michael Tretter, Pengutronix Kernel Team, Mauro Carvalho Chehab,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Michal Simek,
	Neil Armstrong, Heiko Stuebner, Aradhya Bhatia, Rafa?? Mi??ecki,
	Junhao Xie, Manivannan Sadhasivam, Kever Yang, Hans Verkuil,
	Christophe JAILLET, Andrzej Pietrasiewicz, Joe Hattori,
	Gaosheng Cui, Wolfram Sang, Uwe Kleine-K??nig, Ricardo Ribalda,
	linux-media, devicetree, linux-kernel, linux-arm-kernel

On Mon, May 12, 2025 at 08:23:11AM GMT, Yassine Ouaissa wrote:
> issue fixed also, thanks.
> > > +  significant advancements over its predecessors. This new decoder features
> > > +  enhanced processing capabilities with improved throughput and reduced latency.
> > > +
> > > +  Communication between the host driver software and the MCU is implemented through
> > > +  a specialized mailbox interface mechanism. This mailbox system provides a
> > > +  structured channel for exchanging commands, parameters, and status information
> > > +  between the host CPU and the MCU controlling the codec engines.
> > > +
> > > +properties:
> > > +  compatible:
> > > +    const: allegrodvt,al300-vdec
> > 
> > Undocumented prefix.
> > 
> > What is the actual device name? al300? Can you have al300-adec? or
> > al300-dec?
> > 
> > 
> 
> the device name is al300, the vdec is for decoder driver.

So drop vdec. Compatible should reflect device name.

Best regards,
Krzysztof


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

* Re: [PATCH 3/3] media: allegro-dvt: Add DT-bindings for the Gen 3 IP
  2025-05-12 10:42       ` Krzysztof Kozlowski
@ 2025-05-12 11:17         ` Yassine Ouaissa
  2025-05-14  8:01           ` Krzysztof Kozlowski
  0 siblings, 1 reply; 13+ messages in thread
From: Yassine Ouaissa @ 2025-05-12 11:17 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Michael Tretter, Pengutronix Kernel Team, Mauro Carvalho Chehab,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Michal Simek,
	Neil Armstrong, Heiko Stuebner, Aradhya Bhatia, Rafa?? Mi??ecki,
	Junhao Xie, Manivannan Sadhasivam, Kever Yang, Hans Verkuil,
	Christophe JAILLET, Andrzej Pietrasiewicz, Joe Hattori,
	Gaosheng Cui, Wolfram Sang, Uwe Kleine-K??nig, Ricardo Ribalda,
	linux-media, devicetree, linux-kernel, linux-arm-kernel

On 12.05.2025 12:42, Krzysztof Kozlowski wrote:
>On Mon, May 12, 2025 at 08:23:11AM GMT, Yassine Ouaissa wrote:
>> issue fixed also, thanks.
>> > > +  significant advancements over its predecessors. This new decoder features
>> > > +  enhanced processing capabilities with improved throughput and reduced latency.
>> > > +
>> > > +  Communication between the host driver software and the MCU is implemented through
>> > > +  a specialized mailbox interface mechanism. This mailbox system provides a
>> > > +  structured channel for exchanging commands, parameters, and status information
>> > > +  between the host CPU and the MCU controlling the codec engines.
>> > > +
>> > > +properties:
>> > > +  compatible:
>> > > +    const: allegrodvt,al300-vdec
>> >
>> > Undocumented prefix.
>> >
>> > What is the actual device name? al300? Can you have al300-adec? or
>> > al300-dec?
>> >
>> >
>>
>> the device name is al300, the vdec is for decoder driver.
>
>So drop vdec. Compatible should reflect device name.
>

We cannot, the IP could have the encode and decode in the same time.
the al300 is for the IP gen, and vdec/venc for the driver compatible.

I'll discuss with the team, about other naming.

>Best regards,
>Krzysztof
>

Best regards
Yassine OUAISSA

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

* Re: [PATCH 2/3] media: allegro-dvt: Add Gen 3 IP stateful decoder driver
  2025-05-11 14:47 ` [PATCH 2/3] media: allegro-dvt: Add Gen 3 IP stateful decoder driver Yassine Ouaissa
  2025-05-11 20:49   ` kernel test robot
@ 2025-05-12 22:39   ` kernel test robot
  1 sibling, 0 replies; 13+ messages in thread
From: kernel test robot @ 2025-05-12 22:39 UTC (permalink / raw)
  To: Yassine Ouaissa, Michael Tretter, Pengutronix Kernel Team,
	Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Michal Simek, Neil Armstrong, Heiko Stuebner,
	Junhao Xie, Aradhya Bhatia, Rafał Miłecki, Kever Yang,
	Manivannan Sadhasivam, Hans Verkuil, Andrzej Pietrasiewicz,
	Joe Hattori, Christophe JAILLET, Uwe Kleine-König,
	Wolfram Sang, Gaosheng Cui, Ricardo Ribalda, devicetree,
	linux-kernel, linux-arm-kernel
  Cc: oe-kbuild-all, linux-media

Hi Yassine,

kernel test robot noticed the following build errors:

[auto build test ERROR on robh/for-next]
[also build test ERROR on linus/master v6.15-rc6]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Yassine-Ouaissa/media-allegro-dvt-Move-the-current-driver-to-a-subdirectory/20250511-225629
base:   https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
patch link:    https://lore.kernel.org/r/20250511144752.504162-3-yassine.ouaissa%40allegrodvt.com
patch subject: [PATCH 2/3] media: allegro-dvt: Add Gen 3 IP stateful decoder driver
config: arm-allmodconfig (https://download.01.org/0day-ci/archive/20250513/202505130610.joo2DpuX-lkp@intel.com/config)
compiler: arm-linux-gnueabi-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250513/202505130610.joo2DpuX-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202505130610.joo2DpuX-lkp@intel.com/

All errors (new ones prefixed by >>, old ones prefixed by <<):

WARNING: modpost: missing MODULE_DESCRIPTION() in arch/arm/probes/kprobes/test-kprobes.o
WARNING: modpost: missing MODULE_DESCRIPTION() in mm/kasan/kasan_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in lib/tests/slub_kunit.o
>> ERROR: modpost: "__bad_udelay" [drivers/media/platform/allegro-dvt/al300/al300-vdec.ko] undefined!

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

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

* Re: [PATCH 3/3] media: allegro-dvt: Add DT-bindings for the Gen 3 IP
  2025-05-12  8:23     ` Yassine Ouaissa
  2025-05-12 10:42       ` Krzysztof Kozlowski
@ 2025-05-14  7:59       ` Krzysztof Kozlowski
  1 sibling, 0 replies; 13+ messages in thread
From: Krzysztof Kozlowski @ 2025-05-14  7:59 UTC (permalink / raw)
  To: Yassine Ouaissa
  Cc: Michael Tretter, Pengutronix Kernel Team, Mauro Carvalho Chehab,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Michal Simek,
	Neil Armstrong, Heiko Stuebner, Aradhya Bhatia, Rafa?? Mi??ecki,
	Junhao Xie, Manivannan Sadhasivam, Kever Yang, Hans Verkuil,
	Christophe JAILLET, Andrzej Pietrasiewicz, Joe Hattori,
	Gaosheng Cui, Wolfram Sang, Uwe Kleine-K??nig, Ricardo Ribalda,
	linux-media, devicetree, linux-kernel, linux-arm-kernel

On 12/05/2025 10:23, Yassine Ouaissa wrote:
>>> +    items:
>>> +      - description: MCU clock
>>> +
>>> +  clock-names:
>>> +    items:
>>> +      - const: mcu_clk
>>
>> Drop clock-names, pretty obvious
>>
> the clock-name is a require item, it used by the driver.

Then fix your driver.



Best regards,
Krzysztof

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

* Re: [PATCH 3/3] media: allegro-dvt: Add DT-bindings for the Gen 3 IP
  2025-05-12 11:17         ` Yassine Ouaissa
@ 2025-05-14  8:01           ` Krzysztof Kozlowski
  0 siblings, 0 replies; 13+ messages in thread
From: Krzysztof Kozlowski @ 2025-05-14  8:01 UTC (permalink / raw)
  To: Yassine Ouaissa
  Cc: Michael Tretter, Pengutronix Kernel Team, Mauro Carvalho Chehab,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Michal Simek,
	Neil Armstrong, Heiko Stuebner, Aradhya Bhatia, Rafa?? Mi??ecki,
	Junhao Xie, Manivannan Sadhasivam, Kever Yang, Hans Verkuil,
	Christophe JAILLET, Andrzej Pietrasiewicz, Joe Hattori,
	Gaosheng Cui, Wolfram Sang, Uwe Kleine-K??nig, Ricardo Ribalda,
	linux-media, devicetree, linux-kernel, linux-arm-kernel

On 12/05/2025 13:17, Yassine Ouaissa wrote:
> On 12.05.2025 12:42, Krzysztof Kozlowski wrote:
>> On Mon, May 12, 2025 at 08:23:11AM GMT, Yassine Ouaissa wrote:
>>> issue fixed also, thanks.
>>>>> +  significant advancements over its predecessors. This new decoder features
>>>>> +  enhanced processing capabilities with improved throughput and reduced latency.
>>>>> +
>>>>> +  Communication between the host driver software and the MCU is implemented through
>>>>> +  a specialized mailbox interface mechanism. This mailbox system provides a
>>>>> +  structured channel for exchanging commands, parameters, and status information
>>>>> +  between the host CPU and the MCU controlling the codec engines.
>>>>> +
>>>>> +properties:
>>>>> +  compatible:
>>>>> +    const: allegrodvt,al300-vdec
>>>>
>>>> Undocumented prefix.
>>>>
>>>> What is the actual device name? al300? Can you have al300-adec? or
>>>> al300-dec?
>>>>
>>>>
>>>
>>> the device name is al300, the vdec is for decoder driver.
>>
>> So drop vdec. Compatible should reflect device name.
>>
> 
> We cannot, the IP could have the encode and decode in the same time.
> the al300 is for the IP gen, and vdec/venc for the driver compatible.
> 
> I'll discuss with the team, about other naming.
Do not send next version - like you did now - before we finish
discussion. You just sent the same bypassing this entire discussion.

Explain what is the device name, what is the device so we can understand it.

I also expect all other comments to be implemented - including
clock-names and incorrect device node name.

Best regards,
Krzysztof

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

end of thread, other threads:[~2025-05-14  8:01 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-11 14:47 [PATCH 0/3] media: Add Gen 3 IP stateful decoder driver Yassine Ouaissa
2025-05-11 14:47 ` [PATCH 1/3] media: allegro-dvt: Move the current driver to a subdirectory Yassine Ouaissa
2025-05-11 14:47 ` [PATCH 2/3] media: allegro-dvt: Add Gen 3 IP stateful decoder driver Yassine Ouaissa
2025-05-11 20:49   ` kernel test robot
2025-05-12 22:39   ` kernel test robot
2025-05-11 14:47 ` [PATCH 3/3] media: allegro-dvt: Add DT-bindings for the Gen 3 IP Yassine Ouaissa
2025-05-11 16:38   ` Rob Herring (Arm)
2025-05-11 20:03   ` Krzysztof Kozlowski
2025-05-12  8:23     ` Yassine Ouaissa
2025-05-12 10:42       ` Krzysztof Kozlowski
2025-05-12 11:17         ` Yassine Ouaissa
2025-05-14  8:01           ` Krzysztof Kozlowski
2025-05-14  7:59       ` Krzysztof Kozlowski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).