mbox series

[00/33] Qualcomm video decoder/encoder driver

Message ID 1690550624-14642-1-git-send-email-quic_vgarodia@quicinc.com
Headers show
Series Qualcomm video decoder/encoder driver | expand

Message

Vikash Garodia July 28, 2023, 1:23 p.m. UTC
This patch series introduces support for Qualcomm new video acceleration
hardware architecture, used for video stream decoding/encoding. This driver
is based on new communication protocol between video hardware and application
processor.

This driver comes with below capabilities:
- V4L2 complaint video driver with M2M and STREAMING capability.
- Supports H264, H265, VP9 decoders.
- Supports H264, H265 encoders.

This driver comes with below features:
- Centralized resource and memory management.
- Centralized management of core and instance states.
- Defines platform specific capabilities and features. As a results, it provides
  a single point of control to enable/disable a given feature depending on 
  specific platform capabilities.
- Handles hardware interdependent configurations. For a given configuration from
  client, the driver checks for hardware dependent configuration/s and updates
  the same.
- Handles multiple complex video scenarios involving state transitions - DRC,
  Drain, Seek, back to back DRC, DRC during Drain sequence, DRC during Seek
  sequence.
- Introduces a flexible way for driver to subscribe for any property with
  hardware. Hardware would inform driver with those subscribed property with any
  change in value.
- Introduces performance (clock and bus) model based on new hardware
  architecture.
- Introduces multi thread safe design to handle communication between client and
  hardware.
- Adapts encoder quality improvements available in new hardware architecture.
- Implements asynchronous communication with hardware to achieve better
  experience in low latency usecases.
- Supports multi stage hardware architecture for encode/decode.
- Output and capture planes are controlled independently. Thereby providing a
  way to reconfigure individual plane.
- Hardware packetization layer supports synchronization between configuration
  packet and data packet.
- Introduces a flexibility to receive a hardware response for a given command
  packet.
- Native hardware support of LAST flag which is mandatory to align with port
  reconfiguration and DRAIN sequence as per V4L guidelines.
- Native hardware support for drain sequence.

I think that the driver is in good shape for mainline kernel, and I hope the
review comments will help to improve it, so please do review, and make comments.

Dikshita Agarwal (17):
  iris: vidc: add core functions
  iris: add vidc wrapper file
  iris: vidc: add vb2 ops
  iris: vidc: add helpers for memory management
  iris: vidc: add helper functions for resource management
  iris: vidc: add helper functions for power management
  iris: add helpers for media format
  iris: vidc: add PIL functionality for video firmware
  iris: platform: add platform files
  iris: platform: sm8550: add capability file for sm8550
  iris: variant: add helper functions for register handling
  iris: variant: iris3: add iris3 specific ops
  iris: variant: iris3: add helpers for buffer size calculations
  iris: variant: iris3: add helper for bus and clock calculation
  iris: variant: iris: implement the logic to compute bus bandwidth
  iris: variant: iris3: implement logic to compute clock frequency
  iris: enable building of iris video driver

Vikash Garodia (16):
  MAINTAINERS: Add Qualcomm Iris video accelerator driver
  iris: vidc: add v4l2 wrapper file
  iris: vidc: define video core and instance context
  iris: iris: add video encoder files
  iris: vidc: add video decoder files
  iris: vidc: add control files
  iris: vidc: add helper functions
  iris: vidc: add helpers for state management
  iris: add vidc buffer files
  iris: vidc: define various structures and enum
  iris: vidc: hfi: add Host Firmware Interface (HFI)
  iris: vidc: hfi: add Host Firmware Interface (HFI) response handling
  iris: vidc: hfi: add helpers for handling shared queues
  iris: vidc: hfi: Add packetization layer
  iris: vidc: hfi: defines HFI properties and enums
  iris: vidc: add debug files

 MAINTAINERS                                        |   10 +
 drivers/media/platform/qcom/Kconfig                |    1 +
 drivers/media/platform/qcom/Makefile               |    1 +
 drivers/media/platform/qcom/iris/Kconfig           |   15 +
 drivers/media/platform/qcom/iris/Makefile          |   46 +
 .../iris/platform/common/inc/msm_vidc_platform.h   |  305 ++
 .../iris/platform/common/src/msm_vidc_platform.c   | 2499 ++++++++++++
 .../iris/platform/sm8550/inc/msm_vidc_sm8550.h     |   14 +
 .../iris/platform/sm8550/src/msm_vidc_sm8550.c     | 1727 ++++++++
 .../iris/variant/common/inc/msm_vidc_variant.h     |   22 +
 .../iris/variant/common/src/msm_vidc_variant.c     |  163 +
 .../qcom/iris/variant/iris3/inc/hfi_buffer_iris3.h | 1481 +++++++
 .../iris/variant/iris3/inc/msm_vidc_buffer_iris3.h |   19 +
 .../qcom/iris/variant/iris3/inc/msm_vidc_iris3.h   |   15 +
 .../iris/variant/iris3/inc/msm_vidc_power_iris3.h  |   17 +
 .../iris/variant/iris3/inc/perf_static_model.h     |  229 ++
 .../iris/variant/iris3/src/msm_vidc_buffer_iris3.c |  595 +++
 .../iris/variant/iris3/src/msm_vidc_bus_iris3.c    |  884 ++++
 .../iris/variant/iris3/src/msm_vidc_clock_iris3.c  |  627 +++
 .../qcom/iris/variant/iris3/src/msm_vidc_iris3.c   |  954 +++++
 .../iris/variant/iris3/src/msm_vidc_power_iris3.c  |  345 ++
 .../media/platform/qcom/iris/vidc/inc/firmware.h   |   18 +
 .../platform/qcom/iris/vidc/inc/hfi_command.h      |  190 +
 .../media/platform/qcom/iris/vidc/inc/hfi_packet.h |   52 +
 .../platform/qcom/iris/vidc/inc/hfi_property.h     |  666 +++
 .../platform/qcom/iris/vidc/inc/msm_media_info.h   |  599 +++
 .../media/platform/qcom/iris/vidc/inc/msm_vdec.h   |   40 +
 .../media/platform/qcom/iris/vidc/inc/msm_venc.h   |   34 +
 .../media/platform/qcom/iris/vidc/inc/msm_vidc.h   |   60 +
 .../platform/qcom/iris/vidc/inc/msm_vidc_buffer.h  |   32 +
 .../platform/qcom/iris/vidc/inc/msm_vidc_control.h |   26 +
 .../platform/qcom/iris/vidc/inc/msm_vidc_core.h    |  165 +
 .../platform/qcom/iris/vidc/inc/msm_vidc_debug.h   |  186 +
 .../platform/qcom/iris/vidc/inc/msm_vidc_driver.h  |  352 ++
 .../platform/qcom/iris/vidc/inc/msm_vidc_inst.h    |  207 +
 .../qcom/iris/vidc/inc/msm_vidc_internal.h         |  787 ++++
 .../platform/qcom/iris/vidc/inc/msm_vidc_memory.h  |   83 +
 .../platform/qcom/iris/vidc/inc/msm_vidc_power.h   |   94 +
 .../platform/qcom/iris/vidc/inc/msm_vidc_state.h   |  102 +
 .../platform/qcom/iris/vidc/inc/msm_vidc_v4l2.h    |   77 +
 .../platform/qcom/iris/vidc/inc/msm_vidc_vb2.h     |   39 +
 .../media/platform/qcom/iris/vidc/inc/resources.h  |  259 ++
 .../media/platform/qcom/iris/vidc/inc/venus_hfi.h  |   66 +
 .../platform/qcom/iris/vidc/inc/venus_hfi_queue.h  |   89 +
 .../qcom/iris/vidc/inc/venus_hfi_response.h        |   26 +
 .../media/platform/qcom/iris/vidc/src/firmware.c   |  294 ++
 .../media/platform/qcom/iris/vidc/src/hfi_packet.c |  657 +++
 .../media/platform/qcom/iris/vidc/src/msm_vdec.c   | 2091 ++++++++++
 .../media/platform/qcom/iris/vidc/src/msm_venc.c   | 1484 +++++++
 .../media/platform/qcom/iris/vidc/src/msm_vidc.c   |  841 ++++
 .../platform/qcom/iris/vidc/src/msm_vidc_buffer.c  |  290 ++
 .../platform/qcom/iris/vidc/src/msm_vidc_control.c |  824 ++++
 .../platform/qcom/iris/vidc/src/msm_vidc_debug.c   |  581 +++
 .../platform/qcom/iris/vidc/src/msm_vidc_driver.c  | 4276 ++++++++++++++++++++
 .../platform/qcom/iris/vidc/src/msm_vidc_memory.c  |  448 ++
 .../platform/qcom/iris/vidc/src/msm_vidc_power.c   |  560 +++
 .../platform/qcom/iris/vidc/src/msm_vidc_probe.c   |  660 +++
 .../platform/qcom/iris/vidc/src/msm_vidc_state.c   | 1607 ++++++++
 .../platform/qcom/iris/vidc/src/msm_vidc_v4l2.c    |  953 +++++
 .../platform/qcom/iris/vidc/src/msm_vidc_vb2.c     |  605 +++
 .../media/platform/qcom/iris/vidc/src/resources.c  | 1321 ++++++
 .../media/platform/qcom/iris/vidc/src/venus_hfi.c  | 1503 +++++++
 .../platform/qcom/iris/vidc/src/venus_hfi_queue.c  |  537 +++
 .../qcom/iris/vidc/src/venus_hfi_response.c        | 1607 ++++++++
 64 files changed, 35357 insertions(+)
 create mode 100644 drivers/media/platform/qcom/iris/Kconfig
 create mode 100644 drivers/media/platform/qcom/iris/Makefile
 create mode 100644 drivers/media/platform/qcom/iris/platform/common/inc/msm_vidc_platform.h
 create mode 100644 drivers/media/platform/qcom/iris/platform/common/src/msm_vidc_platform.c
 create mode 100644 drivers/media/platform/qcom/iris/platform/sm8550/inc/msm_vidc_sm8550.h
 create mode 100644 drivers/media/platform/qcom/iris/platform/sm8550/src/msm_vidc_sm8550.c
 create mode 100644 drivers/media/platform/qcom/iris/variant/common/inc/msm_vidc_variant.h
 create mode 100644 drivers/media/platform/qcom/iris/variant/common/src/msm_vidc_variant.c
 create mode 100644 drivers/media/platform/qcom/iris/variant/iris3/inc/hfi_buffer_iris3.h
 create mode 100644 drivers/media/platform/qcom/iris/variant/iris3/inc/msm_vidc_buffer_iris3.h
 create mode 100644 drivers/media/platform/qcom/iris/variant/iris3/inc/msm_vidc_iris3.h
 create mode 100644 drivers/media/platform/qcom/iris/variant/iris3/inc/msm_vidc_power_iris3.h
 create mode 100644 drivers/media/platform/qcom/iris/variant/iris3/inc/perf_static_model.h
 create mode 100644 drivers/media/platform/qcom/iris/variant/iris3/src/msm_vidc_buffer_iris3.c
 create mode 100644 drivers/media/platform/qcom/iris/variant/iris3/src/msm_vidc_bus_iris3.c
 create mode 100644 drivers/media/platform/qcom/iris/variant/iris3/src/msm_vidc_clock_iris3.c
 create mode 100644 drivers/media/platform/qcom/iris/variant/iris3/src/msm_vidc_iris3.c
 create mode 100644 drivers/media/platform/qcom/iris/variant/iris3/src/msm_vidc_power_iris3.c
 create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/firmware.h
 create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/hfi_command.h
 create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/hfi_packet.h
 create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/hfi_property.h
 create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_media_info.h
 create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vdec.h
 create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_venc.h
 create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc.h
 create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_buffer.h
 create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_control.h
 create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_core.h
 create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_debug.h
 create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_driver.h
 create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_inst.h
 create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_internal.h
 create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_memory.h
 create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_power.h
 create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_state.h
 create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_v4l2.h
 create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_vb2.h
 create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/resources.h
 create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/venus_hfi.h
 create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/venus_hfi_queue.h
 create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/venus_hfi_response.h
 create mode 100644 drivers/media/platform/qcom/iris/vidc/src/firmware.c
 create mode 100644 drivers/media/platform/qcom/iris/vidc/src/hfi_packet.c
 create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vdec.c
 create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_venc.c
 create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc.c
 create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_buffer.c
 create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_control.c
 create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_debug.c
 create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_driver.c
 create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_memory.c
 create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_power.c
 create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_probe.c
 create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_state.c
 create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_v4l2.c
 create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_vb2.c
 create mode 100644 drivers/media/platform/qcom/iris/vidc/src/resources.c
 create mode 100644 drivers/media/platform/qcom/iris/vidc/src/venus_hfi.c
 create mode 100644 drivers/media/platform/qcom/iris/vidc/src/venus_hfi_queue.c
 create mode 100644 drivers/media/platform/qcom/iris/vidc/src/venus_hfi_response.c

Comments

Dmitry Baryshkov July 28, 2023, 1:32 p.m. UTC | #1
On 28/07/2023 16:23, Vikash Garodia wrote:
> This patch series introduces support for Qualcomm new video acceleration
> hardware architecture, used for video stream decoding/encoding. This driver
> is based on new communication protocol between video hardware and application
> processor.
> 
> This driver comes with below capabilities:
> - V4L2 complaint video driver with M2M and STREAMING capability.
> - Supports H264, H265, VP9 decoders.
> - Supports H264, H265 encoders.
> 
> This driver comes with below features:
> - Centralized resource and memory management.
> - Centralized management of core and instance states.
> - Defines platform specific capabilities and features. As a results, it provides
>    a single point of control to enable/disable a given feature depending on
>    specific platform capabilities.
> - Handles hardware interdependent configurations. For a given configuration from
>    client, the driver checks for hardware dependent configuration/s and updates
>    the same.
> - Handles multiple complex video scenarios involving state transitions - DRC,
>    Drain, Seek, back to back DRC, DRC during Drain sequence, DRC during Seek
>    sequence.
> - Introduces a flexible way for driver to subscribe for any property with
>    hardware. Hardware would inform driver with those subscribed property with any
>    change in value.
> - Introduces performance (clock and bus) model based on new hardware
>    architecture.
> - Introduces multi thread safe design to handle communication between client and
>    hardware.
> - Adapts encoder quality improvements available in new hardware architecture.
> - Implements asynchronous communication with hardware to achieve better
>    experience in low latency usecases.
> - Supports multi stage hardware architecture for encode/decode.
> - Output and capture planes are controlled independently. Thereby providing a
>    way to reconfigure individual plane.
> - Hardware packetization layer supports synchronization between configuration
>    packet and data packet.
> - Introduces a flexibility to receive a hardware response for a given command
>    packet.
> - Native hardware support of LAST flag which is mandatory to align with port
>    reconfiguration and DRAIN sequence as per V4L guidelines.
> - Native hardware support for drain sequence.
> 
> I think that the driver is in good shape for mainline kernel, and I hope the
> review comments will help to improve it, so please do review, and make comments.

No bindings, no driver. Please post start the series from the bindings.

> 
> Dikshita Agarwal (17):
>    iris: vidc: add core functions
>    iris: add vidc wrapper file
>    iris: vidc: add vb2 ops
>    iris: vidc: add helpers for memory management
>    iris: vidc: add helper functions for resource management
>    iris: vidc: add helper functions for power management
>    iris: add helpers for media format
>    iris: vidc: add PIL functionality for video firmware
>    iris: platform: add platform files
>    iris: platform: sm8550: add capability file for sm8550
>    iris: variant: add helper functions for register handling
>    iris: variant: iris3: add iris3 specific ops
>    iris: variant: iris3: add helpers for buffer size calculations
>    iris: variant: iris3: add helper for bus and clock calculation
>    iris: variant: iris: implement the logic to compute bus bandwidth
>    iris: variant: iris3: implement logic to compute clock frequency
>    iris: enable building of iris video driver
> 
> Vikash Garodia (16):
>    MAINTAINERS: Add Qualcomm Iris video accelerator driver
>    iris: vidc: add v4l2 wrapper file
>    iris: vidc: define video core and instance context
>    iris: iris: add video encoder files
>    iris: vidc: add video decoder files
>    iris: vidc: add control files
>    iris: vidc: add helper functions
>    iris: vidc: add helpers for state management
>    iris: add vidc buffer files
>    iris: vidc: define various structures and enum
>    iris: vidc: hfi: add Host Firmware Interface (HFI)
>    iris: vidc: hfi: add Host Firmware Interface (HFI) response handling
>    iris: vidc: hfi: add helpers for handling shared queues
>    iris: vidc: hfi: Add packetization layer
>    iris: vidc: hfi: defines HFI properties and enums
>    iris: vidc: add debug files
> 
>   MAINTAINERS                                        |   10 +
>   drivers/media/platform/qcom/Kconfig                |    1 +
>   drivers/media/platform/qcom/Makefile               |    1 +
>   drivers/media/platform/qcom/iris/Kconfig           |   15 +
>   drivers/media/platform/qcom/iris/Makefile          |   46 +
>   .../iris/platform/common/inc/msm_vidc_platform.h   |  305 ++
>   .../iris/platform/common/src/msm_vidc_platform.c   | 2499 ++++++++++++
>   .../iris/platform/sm8550/inc/msm_vidc_sm8550.h     |   14 +
>   .../iris/platform/sm8550/src/msm_vidc_sm8550.c     | 1727 ++++++++
>   .../iris/variant/common/inc/msm_vidc_variant.h     |   22 +
>   .../iris/variant/common/src/msm_vidc_variant.c     |  163 +
>   .../qcom/iris/variant/iris3/inc/hfi_buffer_iris3.h | 1481 +++++++
>   .../iris/variant/iris3/inc/msm_vidc_buffer_iris3.h |   19 +
>   .../qcom/iris/variant/iris3/inc/msm_vidc_iris3.h   |   15 +
>   .../iris/variant/iris3/inc/msm_vidc_power_iris3.h  |   17 +
>   .../iris/variant/iris3/inc/perf_static_model.h     |  229 ++
>   .../iris/variant/iris3/src/msm_vidc_buffer_iris3.c |  595 +++
>   .../iris/variant/iris3/src/msm_vidc_bus_iris3.c    |  884 ++++
>   .../iris/variant/iris3/src/msm_vidc_clock_iris3.c  |  627 +++
>   .../qcom/iris/variant/iris3/src/msm_vidc_iris3.c   |  954 +++++
>   .../iris/variant/iris3/src/msm_vidc_power_iris3.c  |  345 ++
>   .../media/platform/qcom/iris/vidc/inc/firmware.h   |   18 +
>   .../platform/qcom/iris/vidc/inc/hfi_command.h      |  190 +
>   .../media/platform/qcom/iris/vidc/inc/hfi_packet.h |   52 +
>   .../platform/qcom/iris/vidc/inc/hfi_property.h     |  666 +++
>   .../platform/qcom/iris/vidc/inc/msm_media_info.h   |  599 +++
>   .../media/platform/qcom/iris/vidc/inc/msm_vdec.h   |   40 +
>   .../media/platform/qcom/iris/vidc/inc/msm_venc.h   |   34 +
>   .../media/platform/qcom/iris/vidc/inc/msm_vidc.h   |   60 +
>   .../platform/qcom/iris/vidc/inc/msm_vidc_buffer.h  |   32 +
>   .../platform/qcom/iris/vidc/inc/msm_vidc_control.h |   26 +
>   .../platform/qcom/iris/vidc/inc/msm_vidc_core.h    |  165 +
>   .../platform/qcom/iris/vidc/inc/msm_vidc_debug.h   |  186 +
>   .../platform/qcom/iris/vidc/inc/msm_vidc_driver.h  |  352 ++
>   .../platform/qcom/iris/vidc/inc/msm_vidc_inst.h    |  207 +
>   .../qcom/iris/vidc/inc/msm_vidc_internal.h         |  787 ++++
>   .../platform/qcom/iris/vidc/inc/msm_vidc_memory.h  |   83 +
>   .../platform/qcom/iris/vidc/inc/msm_vidc_power.h   |   94 +
>   .../platform/qcom/iris/vidc/inc/msm_vidc_state.h   |  102 +
>   .../platform/qcom/iris/vidc/inc/msm_vidc_v4l2.h    |   77 +
>   .../platform/qcom/iris/vidc/inc/msm_vidc_vb2.h     |   39 +
>   .../media/platform/qcom/iris/vidc/inc/resources.h  |  259 ++
>   .../media/platform/qcom/iris/vidc/inc/venus_hfi.h  |   66 +
>   .../platform/qcom/iris/vidc/inc/venus_hfi_queue.h  |   89 +
>   .../qcom/iris/vidc/inc/venus_hfi_response.h        |   26 +
>   .../media/platform/qcom/iris/vidc/src/firmware.c   |  294 ++
>   .../media/platform/qcom/iris/vidc/src/hfi_packet.c |  657 +++
>   .../media/platform/qcom/iris/vidc/src/msm_vdec.c   | 2091 ++++++++++
>   .../media/platform/qcom/iris/vidc/src/msm_venc.c   | 1484 +++++++
>   .../media/platform/qcom/iris/vidc/src/msm_vidc.c   |  841 ++++
>   .../platform/qcom/iris/vidc/src/msm_vidc_buffer.c  |  290 ++
>   .../platform/qcom/iris/vidc/src/msm_vidc_control.c |  824 ++++
>   .../platform/qcom/iris/vidc/src/msm_vidc_debug.c   |  581 +++
>   .../platform/qcom/iris/vidc/src/msm_vidc_driver.c  | 4276 ++++++++++++++++++++
>   .../platform/qcom/iris/vidc/src/msm_vidc_memory.c  |  448 ++
>   .../platform/qcom/iris/vidc/src/msm_vidc_power.c   |  560 +++
>   .../platform/qcom/iris/vidc/src/msm_vidc_probe.c   |  660 +++
>   .../platform/qcom/iris/vidc/src/msm_vidc_state.c   | 1607 ++++++++
>   .../platform/qcom/iris/vidc/src/msm_vidc_v4l2.c    |  953 +++++
>   .../platform/qcom/iris/vidc/src/msm_vidc_vb2.c     |  605 +++
>   .../media/platform/qcom/iris/vidc/src/resources.c  | 1321 ++++++
>   .../media/platform/qcom/iris/vidc/src/venus_hfi.c  | 1503 +++++++
>   .../platform/qcom/iris/vidc/src/venus_hfi_queue.c  |  537 +++
>   .../qcom/iris/vidc/src/venus_hfi_response.c        | 1607 ++++++++
>   64 files changed, 35357 insertions(+)
>   create mode 100644 drivers/media/platform/qcom/iris/Kconfig
>   create mode 100644 drivers/media/platform/qcom/iris/Makefile
>   create mode 100644 drivers/media/platform/qcom/iris/platform/common/inc/msm_vidc_platform.h
>   create mode 100644 drivers/media/platform/qcom/iris/platform/common/src/msm_vidc_platform.c
>   create mode 100644 drivers/media/platform/qcom/iris/platform/sm8550/inc/msm_vidc_sm8550.h
>   create mode 100644 drivers/media/platform/qcom/iris/platform/sm8550/src/msm_vidc_sm8550.c
>   create mode 100644 drivers/media/platform/qcom/iris/variant/common/inc/msm_vidc_variant.h
>   create mode 100644 drivers/media/platform/qcom/iris/variant/common/src/msm_vidc_variant.c
>   create mode 100644 drivers/media/platform/qcom/iris/variant/iris3/inc/hfi_buffer_iris3.h
>   create mode 100644 drivers/media/platform/qcom/iris/variant/iris3/inc/msm_vidc_buffer_iris3.h
>   create mode 100644 drivers/media/platform/qcom/iris/variant/iris3/inc/msm_vidc_iris3.h
>   create mode 100644 drivers/media/platform/qcom/iris/variant/iris3/inc/msm_vidc_power_iris3.h
>   create mode 100644 drivers/media/platform/qcom/iris/variant/iris3/inc/perf_static_model.h
>   create mode 100644 drivers/media/platform/qcom/iris/variant/iris3/src/msm_vidc_buffer_iris3.c
>   create mode 100644 drivers/media/platform/qcom/iris/variant/iris3/src/msm_vidc_bus_iris3.c
>   create mode 100644 drivers/media/platform/qcom/iris/variant/iris3/src/msm_vidc_clock_iris3.c
>   create mode 100644 drivers/media/platform/qcom/iris/variant/iris3/src/msm_vidc_iris3.c
>   create mode 100644 drivers/media/platform/qcom/iris/variant/iris3/src/msm_vidc_power_iris3.c
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/firmware.h
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/hfi_command.h
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/hfi_packet.h
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/hfi_property.h
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_media_info.h
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vdec.h
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_venc.h
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc.h
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_buffer.h
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_control.h
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_core.h
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_debug.h
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_driver.h
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_inst.h
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_internal.h
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_memory.h
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_power.h
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_state.h
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_v4l2.h
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_vb2.h
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/resources.h
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/venus_hfi.h
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/venus_hfi_queue.h
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/venus_hfi_response.h
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/firmware.c
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/hfi_packet.c
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vdec.c
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_venc.c
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc.c
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_buffer.c
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_control.c
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_debug.c
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_driver.c
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_memory.c
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_power.c
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_probe.c
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_state.c
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_v4l2.c
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_vb2.c
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/resources.c
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/venus_hfi.c
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/venus_hfi_queue.c
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/venus_hfi_response.c
>
Konrad Dybcio July 28, 2023, 1:45 p.m. UTC | #2
On 28.07.2023 15:23, Vikash Garodia wrote:
> From: Dikshita Agarwal <quic_dikshita@quicinc.com>
> 
> This implements the platform driver methods, file
> operations and v4l2 registration.
> 
> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
> Signed-off-by: Vikash Garodia <quic_vgarodia@quicinc.com>
> ---
[...]

> +struct msm_vidc_core *g_core;
> +
> +static inline bool is_video_device(struct device *dev)
> +{
> +	return !!(of_device_is_compatible(dev->of_node, "qcom,sm8550-vidc"));
> +}
Are you expecting this to be expanded each time support for new SoC is added?

> +
> +static inline bool is_video_context_bank_device(struct device *dev)
> +{
> +	return !!(of_device_is_compatible(dev->of_node, "qcom,vidc,cb-ns"));
> +}
> +
> +static int msm_vidc_init_resources(struct msm_vidc_core *core)
> +{
> +	struct msm_vidc_resource *res = NULL;
No need to initialize, you use it right after defining.

> +	int rc = 0;
I think 'ret' is more common for a return-value-holding variable.

> +
> +	res = devm_kzalloc(&core->pdev->dev, sizeof(*res), GFP_KERNEL);
> +	if (!res) {
> +		d_vpr_e("%s: failed to alloc memory for resource\n", __func__);
> +		return -ENOMEM;
> +	}
> +	core->resource = res;
I don't think the 'res' variable makes sense.

> +
> +	rc = call_res_op(core, init, core);
> +	if (rc) {
> +		d_vpr_e("%s: Failed to init resources: %d\n", __func__, rc);
> +		return rc;
you can omit this line and return rc/ret at the last line of this func.

> +	}
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id msm_vidc_dt_match[] = {
> +	{.compatible = "qcom,sm8550-vidc"},
{ .compatible = .... " },

> +	{.compatible = "qcom,vidc,cb-ns"},
> +	MSM_VIDC_EMPTY_BRACE
why?

> +};
> +MODULE_DEVICE_TABLE(of, msm_vidc_dt_match);
> +
> +static void msm_vidc_release_video_device(struct video_device *vdev)
> +{
> +	d_vpr_e("%s: video device released\n", __func__);
> +}
Doesn't sound too useful? And definitely not with an error print?

> +
> +static void msm_vidc_unregister_video_device(struct msm_vidc_core *core,
> +					     enum msm_vidc_domain_type type)
> +{
> +	int index;
> +
> +	if (type == MSM_VIDC_DECODER)
I'm not sure this is defined.

> +		index = 0;
> +	else if (type == MSM_VIDC_ENCODER)
Or this.

Can't we just assign index = MSM_VIDC_EN/DECODER?

> +		index = 1;
> +	else
> +		return;
> +
> +	v4l2_m2m_release(core->vdev[index].m2m_dev);
> +
> +	video_set_drvdata(&core->vdev[index].vdev, NULL);
> +	video_unregister_device(&core->vdev[index].vdev);
> +}
> +
> +static int msm_vidc_register_video_device(struct msm_vidc_core *core,
> +					  enum msm_vidc_domain_type type, int nr)
> +{
> +	int rc = 0;
> +	int index;
> +
> +	d_vpr_h("%s: domain %d\n", __func__, type);
> +
> +	if (type == MSM_VIDC_DECODER)
> +		index = 0;
> +	else if (type == MSM_VIDC_ENCODER)
> +		index = 1;
> +	else
> +		return -EINVAL;
> +
> +	core->vdev[index].vdev.release =
> +		msm_vidc_release_video_device;
> +	core->vdev[index].vdev.fops = core->v4l2_file_ops;
> +	if (type == MSM_VIDC_DECODER)
> +		core->vdev[index].vdev.ioctl_ops = core->v4l2_ioctl_ops_dec;
> +	else
> +		core->vdev[index].vdev.ioctl_ops = core->v4l2_ioctl_ops_enc;
> +	core->vdev[index].vdev.vfl_dir = VFL_DIR_M2M;
> +	core->vdev[index].type = type;
> +	core->vdev[index].vdev.v4l2_dev = &core->v4l2_dev;
> +	core->vdev[index].vdev.device_caps = core->capabilities[DEVICE_CAPS].value;
> +	rc = video_register_device(&core->vdev[index].vdev,
> +				   VFL_TYPE_VIDEO, nr);
> +	if (rc) {
> +		d_vpr_e("Failed to register the video device\n");
> +		return rc;
> +	}
> +	video_set_drvdata(&core->vdev[index].vdev, core);
> +
> +	core->vdev[index].m2m_dev = v4l2_m2m_init(core->v4l2_m2m_ops);
> +	if (IS_ERR(core->vdev[index].m2m_dev)) {
> +		d_vpr_e("Failed to initialize V4L2 M2M device\n");
> +		rc = PTR_ERR(core->vdev[index].m2m_dev);
> +		goto m2m_init_failed;
> +	}
> +
> +	return 0;
> +
> +m2m_init_failed:
> +	video_unregister_device(&core->vdev[index].vdev);
> +	return rc;
> +}
> +
> +static int msm_vidc_deinitialize_core(struct msm_vidc_core *core)
> +{
> +	int rc = 0;
> +
> +	if (!core) {
Are we expecting to ever hit this?

> +		d_vpr_e("%s: invalid params\n", __func__);
> +		return -EINVAL;
> +	}
> +
> +	mutex_destroy(&core->lock);
> +	msm_vidc_update_core_state(core, MSM_VIDC_CORE_DEINIT, __func__);
Not defined.

> +
> +	if (core->batch_workq)
> +		destroy_workqueue(core->batch_workq);
> +
> +	if (core->pm_workq)
> +		destroy_workqueue(core->pm_workq);
> +
> +	core->batch_workq = NULL;
> +	core->pm_workq = NULL;
> +
> +	return rc;
> +}
> +
> +static int msm_vidc_initialize_core(struct msm_vidc_core *core)
> +{
> +	int rc = 0;
> +
> +	msm_vidc_update_core_state(core, MSM_VIDC_CORE_DEINIT, __func__);
Not defined.

> +
> +	core->pm_workq = create_singlethread_workqueue("pm_workq");
> +	if (!core->pm_workq) {
> +		d_vpr_e("%s: create pm workq failed\n", __func__);
> +		rc = -EINVAL;
> +		goto exit;
> +	}
> +
> +	core->batch_workq = create_singlethread_workqueue("batch_workq");
> +	if (!core->batch_workq) {
> +		d_vpr_e("%s: create batch workq failed\n", __func__);
> +		rc = -EINVAL;
> +		goto exit;
> +	}
> +
> +	core->packet_size = VIDC_IFACEQ_VAR_HUGE_PKT_SIZE;
> +	core->packet = devm_kzalloc(&core->pdev->dev, core->packet_size, GFP_KERNEL);
> +	if (!core->packet) {
> +		d_vpr_e("%s: failed to alloc core packet\n", __func__);
> +		rc = -ENOMEM;
> +		goto exit;
> +	}
> +
> +	core->response_packet = devm_kzalloc(&core->pdev->dev, core->packet_size, GFP_KERNEL);
> +	if (!core->packet) {
> +		d_vpr_e("%s: failed to alloc core response packet\n", __func__);
> +		rc = -ENOMEM;
> +		goto exit;
> +	}
> +
> +	mutex_init(&core->lock);
> +	INIT_LIST_HEAD(&core->instances);
> +	INIT_LIST_HEAD(&core->dangling_instances);
> +
> +	INIT_DELAYED_WORK(&core->pm_work, venus_hfi_pm_work_handler);
> +	INIT_DELAYED_WORK(&core->fw_unload_work, msm_vidc_fw_unload_handler);
> +
> +	return 0;
Either return rc/ret here or don't initialize it at definition.

> +exit:
> +	if (core->batch_workq)
> +		destroy_workqueue(core->batch_workq);
> +	if (core->pm_workq)
> +		destroy_workqueue(core->pm_workq);
> +	core->batch_workq = NULL;
> +	core->pm_workq = NULL;
> +
> +	return rc;
> +}
[...]

> +
> +static int msm_vidc_pm_suspend(struct device *dev)
> +{
> +	int rc = 0;
> +	struct msm_vidc_core *core;
> +	enum msm_vidc_allow allow = MSM_VIDC_DISALLOW;
> +
> +	/*
> +	 * Bail out if
> +	 * - driver possibly not probed yet
Would the pm callbacks be registered by then?

> +	 * - not the main device. We don't support power management on
> +	 *   subdevices (e.g. context banks)
I'm not sure registering context banks as different kinds of devices
within the same driver is a good idea, this seems rather convoluted.

> +	 */
> +	if (!dev || !dev->driver || !is_video_device(dev))
> +		return 0;
> +
> +	core = dev_get_drvdata(dev);
> +	if (!core) {
> +		d_vpr_e("%s: invalid core\n", __func__);
> +		return -EINVAL;
> +	}
> +
> +	core_lock(core, __func__);
> +	allow = msm_vidc_allow_pm_suspend(core);
> +
> +	if (allow == MSM_VIDC_IGNORE) {
> +		d_vpr_h("%s: pm already suspended\n", __func__);
> +		msm_vidc_change_core_sub_state(core, 0, CORE_SUBSTATE_PM_SUSPEND, __func__);
> +		rc = 0;
> +		goto unlock;
> +	} else if (allow != MSM_VIDC_ALLOW) {
> +		d_vpr_h("%s: pm suspend not allowed\n", __func__);
> +		rc = 0;
> +		goto unlock;
> +	}
> +
> +	rc = msm_vidc_suspend(core);
> +	if (rc == -EOPNOTSUPP)
> +		rc = 0;
> +	else if (rc)
> +		d_vpr_e("Failed to suspend: %d\n", rc);
> +	else
> +		msm_vidc_change_core_sub_state(core, 0, CORE_SUBSTATE_PM_SUSPEND, __func__);
> +
> +unlock:
> +	core_unlock(core, __func__);
> +	return rc;
> +}
> +
> +static int msm_vidc_pm_resume(struct device *dev)
Same comments as in _suspend

Konrad
Dmitry Baryshkov July 28, 2023, 1:49 p.m. UTC | #3
On 28/07/2023 16:23, Vikash Garodia wrote:
> From: Dikshita Agarwal <quic_dikshita@quicinc.com>
> 
> This implements the platform driver methods, file
> operations and v4l2 registration.
> 
> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
> Signed-off-by: Vikash Garodia <quic_vgarodia@quicinc.com>
> ---
>   .../platform/qcom/iris/vidc/src/msm_vidc_probe.c   | 660 +++++++++++++++++++++
>   1 file changed, 660 insertions(+)
>   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_probe.c
> 
> diff --git a/drivers/media/platform/qcom/iris/vidc/src/msm_vidc_probe.c b/drivers/media/platform/qcom/iris/vidc/src/msm_vidc_probe.c
> new file mode 100644
> index 0000000..43439cb
> --- /dev/null
> +++ b/drivers/media/platform/qcom/iris/vidc/src/msm_vidc_probe.c
> @@ -0,0 +1,660 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2020-2022, The Linux Foundation. All rights reserved.
> + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
> + */
> +
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/iommu.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_platform.h>
> +#include <linux/stringify.h>
> +#include <linux/version.h>
> +#include <linux/workqueue.h>
> +
> +#include "msm_vidc_core.h"
> +#include "msm_vidc_debug.h"
> +#include "msm_vidc_driver.h"
> +#include "msm_vidc_internal.h"
> +#include "msm_vidc_memory.h"
> +#include "msm_vidc_platform.h"
> +#include "msm_vidc_state.h"
> +#include "venus_hfi.h"

This files are not present yet, so this commit doesn't have a change of 
being compiled in any way.

> +
> +#define BASE_DEVICE_NUMBER 32
> +
> +struct msm_vidc_core *g_core;
> +
> +static inline bool is_video_device(struct device *dev)
> +{
> +	return !!(of_device_is_compatible(dev->of_node, "qcom,sm8550-vidc"));

Are you going to add future platforms to this list? Please don't 
duplicate of_match_data here.

> +}
> +
> +static inline bool is_video_context_bank_device(struct device *dev)
> +{
> +	return !!(of_device_is_compatible(dev->of_node, "qcom,vidc,cb-ns"));
> +}
> +
> +static int msm_vidc_init_resources(struct msm_vidc_core *core)
> +{
> +	struct msm_vidc_resource *res = NULL;
> +	int rc = 0;
> +
> +	res = devm_kzalloc(&core->pdev->dev, sizeof(*res), GFP_KERNEL);
> +	if (!res) {
> +		d_vpr_e("%s: failed to alloc memory for resource\n", __func__);

Where is this macro defined? Please structure your comments in a logical 
way, so that one can read them from the beginning and understand what is 
going one.

This is not to mention that adding such debugging wrappers doesn't have 
a lot of value.

> +		return -ENOMEM;
> +	}
> +	core->resource = res;
> +
> +	rc = call_res_op(core, init, core);

What is call_res_op?

> +	if (rc) {
> +		d_vpr_e("%s: Failed to init resources: %d\n", __func__, rc);
> +		return rc;
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id msm_vidc_dt_match[] = {
> +	{.compatible = "qcom,sm8550-vidc"},
> +	{.compatible = "qcom,vidc,cb-ns"},
> +	MSM_VIDC_EMPTY_BRACE

NO!!! Please use {} directly.

> +};
> +MODULE_DEVICE_TABLE(of, msm_vidc_dt_match);
> +
> +static void msm_vidc_release_video_device(struct video_device *vdev)
> +{
> +	d_vpr_e("%s: video device released\n", __func__);
> +}
> +
> +static void msm_vidc_unregister_video_device(struct msm_vidc_core *core,
> +					     enum msm_vidc_domain_type type)
> +{
> +	int index;
> +
> +	if (type == MSM_VIDC_DECODER)
> +		index = 0;
> +	else if (type == MSM_VIDC_ENCODER)
> +		index = 1;
> +	else
> +		return;

You can index by the type instead of converting to index.

> +
> +	v4l2_m2m_release(core->vdev[index].m2m_dev);
> +
> +	video_set_drvdata(&core->vdev[index].vdev, NULL);
> +	video_unregister_device(&core->vdev[index].vdev);
> +}
> +
> +static int msm_vidc_register_video_device(struct msm_vidc_core *core,
> +					  enum msm_vidc_domain_type type, int nr)
> +{
> +	int rc = 0;
> +	int index;
> +
> +	d_vpr_h("%s: domain %d\n", __func__, type);
> +
> +	if (type == MSM_VIDC_DECODER)
> +		index = 0;
> +	else if (type == MSM_VIDC_ENCODER)
> +		index = 1;
> +	else
> +		return -EINVAL;
> +
> +	core->vdev[index].vdev.release =
> +		msm_vidc_release_video_device;
> +	core->vdev[index].vdev.fops = core->v4l2_file_ops;
> +	if (type == MSM_VIDC_DECODER)
> +		core->vdev[index].vdev.ioctl_ops = core->v4l2_ioctl_ops_dec;
> +	else
> +		core->vdev[index].vdev.ioctl_ops = core->v4l2_ioctl_ops_enc;
> +	core->vdev[index].vdev.vfl_dir = VFL_DIR_M2M;
> +	core->vdev[index].type = type;
> +	core->vdev[index].vdev.v4l2_dev = &core->v4l2_dev;
> +	core->vdev[index].vdev.device_caps = core->capabilities[DEVICE_CAPS].value;
> +	rc = video_register_device(&core->vdev[index].vdev,
> +				   VFL_TYPE_VIDEO, nr);
> +	if (rc) {
> +		d_vpr_e("Failed to register the video device\n");
> +		return rc;
> +	}
> +	video_set_drvdata(&core->vdev[index].vdev, core);
> +
> +	core->vdev[index].m2m_dev = v4l2_m2m_init(core->v4l2_m2m_ops);
> +	if (IS_ERR(core->vdev[index].m2m_dev)) {
> +		d_vpr_e("Failed to initialize V4L2 M2M device\n");
> +		rc = PTR_ERR(core->vdev[index].m2m_dev);
> +		goto m2m_init_failed;
> +	}
> +
> +	return 0;
> +
> +m2m_init_failed:
> +	video_unregister_device(&core->vdev[index].vdev);
> +	return rc;
> +}
> +
> +static int msm_vidc_deinitialize_core(struct msm_vidc_core *core)
> +{
> +	int rc = 0;
> +
> +	if (!core) {
> +		d_vpr_e("%s: invalid params\n", __func__);
> +		return -EINVAL;
> +	}
> +
> +	mutex_destroy(&core->lock);
> +	msm_vidc_update_core_state(core, MSM_VIDC_CORE_DEINIT, __func__);
> +
> +	if (core->batch_workq)
> +		destroy_workqueue(core->batch_workq);
> +
> +	if (core->pm_workq)
> +		destroy_workqueue(core->pm_workq);
> +
> +	core->batch_workq = NULL;
> +	core->pm_workq = NULL;
> +
> +	return rc;
> +}
> +
> +static int msm_vidc_initialize_core(struct msm_vidc_core *core)
> +{
> +	int rc = 0;
> +
> +	msm_vidc_update_core_state(core, MSM_VIDC_CORE_DEINIT, __func__);
> +
> +	core->pm_workq = create_singlethread_workqueue("pm_workq");
> +	if (!core->pm_workq) {
> +		d_vpr_e("%s: create pm workq failed\n", __func__);
> +		rc = -EINVAL;
> +		goto exit;
> +	}
> +
> +	core->batch_workq = create_singlethread_workqueue("batch_workq");
> +	if (!core->batch_workq) {
> +		d_vpr_e("%s: create batch workq failed\n", __func__);
> +		rc = -EINVAL;
> +		goto exit;
> +	}
> +
> +	core->packet_size = VIDC_IFACEQ_VAR_HUGE_PKT_SIZE;
> +	core->packet = devm_kzalloc(&core->pdev->dev, core->packet_size, GFP_KERNEL);
> +	if (!core->packet) {
> +		d_vpr_e("%s: failed to alloc core packet\n", __func__);
> +		rc = -ENOMEM;
> +		goto exit;
> +	}
> +
> +	core->response_packet = devm_kzalloc(&core->pdev->dev, core->packet_size, GFP_KERNEL);
> +	if (!core->packet) {
> +		d_vpr_e("%s: failed to alloc core response packet\n", __func__);
> +		rc = -ENOMEM;
> +		goto exit;
> +	}
> +
> +	mutex_init(&core->lock);
> +	INIT_LIST_HEAD(&core->instances);
> +	INIT_LIST_HEAD(&core->dangling_instances);
> +
> +	INIT_DELAYED_WORK(&core->pm_work, venus_hfi_pm_work_handler);
> +	INIT_DELAYED_WORK(&core->fw_unload_work, msm_vidc_fw_unload_handler);
> +
> +	return 0;
> +exit:
> +	if (core->batch_workq)
> +		destroy_workqueue(core->batch_workq);
> +	if (core->pm_workq)
> +		destroy_workqueue(core->pm_workq);
> +	core->batch_workq = NULL;
> +	core->pm_workq = NULL;
> +
> +	return rc;
> +}
> +
> +static void msm_vidc_devm_deinit_core(void *res)
> +{
> +	struct msm_vidc_core *core = res;
> +
> +	msm_vidc_deinitialize_core(core);
> +}
> +
> +static int msm_vidc_devm_init_core(struct device *dev, struct msm_vidc_core *core)
> +{
> +	int rc = 0;
> +
> +	if (!dev || !core) {
> +		d_vpr_e("%s: invalid params\n", __func__);
> +		return -EINVAL;
> +	}
> +
> +	rc = msm_vidc_initialize_core(core);
> +	if (rc) {
> +		d_vpr_e("%s: init failed with %d\n", __func__, rc);
> +		return rc;
> +	}
> +
> +	rc = devm_add_action_or_reset(dev, msm_vidc_devm_deinit_core, (void *)core);
> +	if (rc)
> +		return -EINVAL;
> +
> +	return rc;
> +}
> +
> +static void msm_vidc_devm_debugfs_put(void *res)
> +{
> +	struct dentry *parent = res;
> +
> +	debugfs_remove_recursive(parent);
> +}
> +
> +static struct dentry *msm_vidc_devm_debugfs_get(struct device *dev)

Why is it called get?


> +{
> +	struct dentry *parent = NULL;
> +	int rc = 0;
> +
> +	if (!dev) {
> +		d_vpr_e("%s: invalid params\n", __func__);
> +		return NULL;
> +	}
> +
> +	parent = msm_vidc_debugfs_init_drv();
> +	if (!parent)
> +		return NULL;
> +
> +	rc = devm_add_action_or_reset(dev, msm_vidc_devm_debugfs_put, (void *)parent);
> +	if (rc)
> +		return NULL;
> +
> +	return parent;
> +}
> +
> +static int msm_vidc_setup_context_bank(struct msm_vidc_core *core,
> +				       struct device *dev)
> +{
> +	struct context_bank_info *cb = NULL;
> +	int rc = 0;
> +
> +	cb = msm_vidc_get_context_bank_for_device(core, dev);
> +	if (!cb) {
> +		d_vpr_e("%s: Failed to get context bank device for %s\n",
> +			__func__, dev_name(dev));
> +		return -EIO;
> +	}
> +
> +	/* populate dev & domain field */
> +	cb->dev = dev;
> +	cb->domain = iommu_get_domain_for_dev(cb->dev);
> +	if (!cb->domain) {
> +		d_vpr_e("%s: Failed to get iommu domain for %s\n", __func__, dev_name(dev));
> +		return -EIO;
> +	}
> +
> +	if (cb->dma_mask) {
> +		rc = dma_set_mask_and_coherent(cb->dev, cb->dma_mask);
> +		if (rc) {
> +			d_vpr_e("%s: dma_set_mask_and_coherent failed\n", __func__);
> +			return rc;
> +		}
> +	}
> +
> +	/*
> +	 * configure device segment size and segment boundary to ensure
> +	 * iommu mapping returns one mapping (which is required for partial
> +	 * cache operations)
> +	 */
> +	if (!dev->dma_parms)
> +		dev->dma_parms =
> +			devm_kzalloc(dev, sizeof(*dev->dma_parms), GFP_KERNEL);
> +	dma_set_max_seg_size(dev, (unsigned int)DMA_BIT_MASK(32));
> +	dma_set_seg_boundary(dev, (unsigned long)DMA_BIT_MASK(64));
> +
> +	iommu_set_fault_handler(cb->domain, msm_vidc_smmu_fault_handler, (void *)core);
> +
> +	d_vpr_h("%s: name %s addr start %x size %x secure %d\n",
> +		__func__, cb->name, cb->addr_range.start,
> +		cb->addr_range.size, cb->secure);
> +	d_vpr_h("%s: dma_coherant %d region %d dev_name %s domain %pK dma_mask %llu\n",
> +		__func__, cb->dma_coherant, cb->region, dev_name(cb->dev),
> +		cb->domain, cb->dma_mask);
> +
> +	return rc;
> +}
> +
> +static int msm_vidc_remove_video_device(struct platform_device *pdev)
> +{
> +	struct msm_vidc_core *core;
> +
> +	if (!pdev) {
> +		d_vpr_e("%s: invalid input %pK", __func__, pdev);
> +		return -EINVAL;
> +	}
> +
> +	core = dev_get_drvdata(&pdev->dev);
> +	if (!core) {
> +		d_vpr_e("%s: invalid core\n", __func__);
> +		return -EINVAL;
> +	}
> +
> +	msm_vidc_core_deinit(core, true);
> +	venus_hfi_queue_deinit(core);
> +
> +	msm_vidc_unregister_video_device(core, MSM_VIDC_ENCODER);
> +	msm_vidc_unregister_video_device(core, MSM_VIDC_DECODER);
> +
> +	v4l2_device_unregister(&core->v4l2_dev);
> +
> +	d_vpr_h("depopulating sub devices\n");
> +	/*
> +	 * Trigger remove for each sub-device i.e. qcom,context-bank,xxxx
> +	 * When msm_vidc_remove is called for each sub-device, destroy
> +	 * context-bank mappings.
> +	 */
> +	of_platform_depopulate(&pdev->dev);
> +
> +	dev_set_drvdata(&pdev->dev, NULL);
> +	g_core = NULL;
> +	d_vpr_h("%s(): succssful\n", __func__);
> +
> +	return 0;
> +}
> +
> +static int msm_vidc_remove_context_bank(struct platform_device *pdev)
> +{
> +	d_vpr_h("%s(): %s\n", __func__, dev_name(&pdev->dev));
> +
> +	return 0;
> +}
> +
> +static int msm_vidc_remove(struct platform_device *pdev)
> +{
> +	/*
> +	 * Sub devices remove will be triggered by of_platform_depopulate()
> +	 * after core_deinit(). It return immediately after completing
> +	 * sub-device remove.
> +	 */
> +	if (is_video_device(&pdev->dev))
> +		return msm_vidc_remove_video_device(pdev);
> +	else if (is_video_context_bank_device(&pdev->dev))
> +		return msm_vidc_remove_context_bank(pdev);
> +
> +	/* How did we end up here? */
> +	WARN_ON(1);
> +	return -EINVAL;
> +}
> +
> +static int msm_vidc_probe_video_device(struct platform_device *pdev)
> +{
> +	int rc = 0;
> +	struct msm_vidc_core *core = NULL;
> +	int nr = BASE_DEVICE_NUMBER;
> +
> +	d_vpr_h("%s: %s\n", __func__, dev_name(&pdev->dev));
> +
> +	core = devm_kzalloc(&pdev->dev, sizeof(struct msm_vidc_core), GFP_KERNEL);
> +	if (!core) {
> +		d_vpr_e("%s: failed to alloc memory for core\n", __func__);
> +		return -ENOMEM;
> +	}
> +	g_core = core;
> +
> +	core->pdev = pdev;
> +	dev_set_drvdata(&pdev->dev, core);
> +
> +	core->debugfs_parent = msm_vidc_devm_debugfs_get(&pdev->dev);
> +	if (!core->debugfs_parent)
> +		d_vpr_h("Failed to create debugfs for msm_vidc\n");
> +
> +	rc = msm_vidc_devm_init_core(&pdev->dev, core);
> +	if (rc) {
> +		d_vpr_e("%s: init core failed with %d\n", __func__, rc);
> +		goto init_core_failed;
> +	}
> +
> +	rc = msm_vidc_init_platform(core);
> +	if (rc) {
> +		d_vpr_e("%s: init platform failed with %d\n", __func__, rc);
> +		rc = -EINVAL;
> +		goto init_plat_failed;
> +	}
> +
> +	rc = msm_vidc_init_resources(core);
> +	if (rc) {
> +		d_vpr_e("%s: init resource failed with %d\n", __func__, rc);
> +		goto init_res_failed;
> +	}
> +
> +	rc = msm_vidc_init_core_caps(core);
> +	if (rc) {
> +		d_vpr_e("%s: init core caps failed with %d\n", __func__, rc);
> +		goto init_res_failed;
> +	}
> +
> +	rc = msm_vidc_init_instance_caps(core);
> +	if (rc) {
> +		d_vpr_e("%s: init inst cap failed with %d\n", __func__, rc);
> +		goto init_inst_caps_fail;
> +	}
> +
> +	core->debugfs_root = msm_vidc_debugfs_init_core(core);
> +	if (!core->debugfs_root)
> +		d_vpr_h("Failed to init debugfs core\n");
> +
> +	d_vpr_h("populating sub devices\n");
> +	/*
> +	 * Trigger probe for each sub-device i.e. qcom,msm-vidc,context-bank.
> +	 * When msm_vidc_probe is called for each sub-device, parse the
> +	 * context-bank details.
> +	 */
> +	rc = of_platform_populate(pdev->dev.of_node, msm_vidc_dt_match, NULL,
> +				  &pdev->dev);
> +	if (rc) {
> +		d_vpr_e("Failed to trigger probe for sub-devices\n");
> +		goto sub_dev_failed;
> +	}
> +
> +	rc = v4l2_device_register(&pdev->dev, &core->v4l2_dev);
> +	if (rc) {
> +		d_vpr_e("Failed to register v4l2 device\n");
> +		goto v4l2_reg_failed;
> +	}
> +
> +	/* setup the decoder device */
> +	rc = msm_vidc_register_video_device(core, MSM_VIDC_DECODER, nr);
> +	if (rc) {
> +		d_vpr_e("Failed to register video decoder\n");
> +		goto dec_reg_failed;
> +	}
> +
> +	/* setup the encoder device */
> +	rc = msm_vidc_register_video_device(core, MSM_VIDC_ENCODER, nr + 1);
> +	if (rc) {
> +		d_vpr_e("Failed to register video encoder\n");
> +		goto enc_reg_failed;
> +	}
> +
> +	rc = venus_hfi_queue_init(core);
> +	if (rc) {
> +		d_vpr_e("%s: interface queues init failed\n", __func__);
> +		goto queues_init_failed;
> +	}
> +
> +	rc = msm_vidc_core_init(core);
> +	if (rc) {
> +		d_vpr_e("%s: sys init failed\n", __func__);
> +		goto core_init_failed;
> +	}
> +
> +	d_vpr_h("%s(): succssful\n", __func__);
> +
> +	return rc;
> +
> +core_init_failed:
> +	venus_hfi_queue_deinit(core);
> +queues_init_failed:
> +	of_platform_depopulate(&pdev->dev);
> +sub_dev_failed:
> +	msm_vidc_unregister_video_device(core, MSM_VIDC_ENCODER);
> +enc_reg_failed:
> +	msm_vidc_unregister_video_device(core, MSM_VIDC_DECODER);
> +dec_reg_failed:
> +	v4l2_device_unregister(&core->v4l2_dev);
> +v4l2_reg_failed:
> +init_inst_caps_fail:
> +init_res_failed:
> +init_plat_failed:
> +init_core_failed:
> +	dev_set_drvdata(&pdev->dev, NULL);
> +	g_core = NULL;
> +
> +	return rc;
> +}
> +
> +static int msm_vidc_probe_context_bank(struct platform_device *pdev)
> +{
> +	struct msm_vidc_core *core = NULL;
> +	int rc = 0;
> +
> +	if (!pdev) {
> +		d_vpr_e("%s: Invalid platform device %pK", __func__, pdev);
> +		return -EINVAL;
> +	} else if (!pdev->dev.parent) {
> +		d_vpr_e("%s: Failed to find a parent for %s\n",
> +			__func__, dev_name(&pdev->dev));
> +		return -ENODEV;
> +	}
> +
> +	d_vpr_h("%s(): %s\n", __func__, dev_name(&pdev->dev));
> +
> +	core = dev_get_drvdata(pdev->dev.parent);
> +	if (!core) {
> +		d_vpr_e("%s: core not found in device %s",
> +			__func__, dev_name(pdev->dev.parent));
> +		return -EINVAL;
> +	}
> +
> +	rc = msm_vidc_setup_context_bank(core, &pdev->dev);
> +	if (rc) {
> +		d_vpr_e("%s: Failed to probe context bank %s\n",
> +			__func__, dev_name(&pdev->dev));
> +		return rc;
> +	}
> +
> +	return rc;
> +}
> +
> +static int msm_vidc_probe(struct platform_device *pdev)
> +{
> +	if (!pdev) {
> +		d_vpr_e("%s: invalid params\n", __func__);
> +		return -EINVAL;
> +	}
> +
> +	/*
> +	 * Sub devices probe will be triggered by of_platform_populate() towards
> +	 * the end of the probe function after msm-vidc device probe is
> +	 * completed. Return immediately after completing sub-device probe.
> +	 */
> +	if (is_video_device(&pdev->dev))
> +		return msm_vidc_probe_video_device(pdev);
> +	else if (is_video_context_bank_device(&pdev->dev))
> +		return msm_vidc_probe_context_bank(pdev);
> +
> +	/* How did we end up here? */
> +	WARN_ON(1);
> +	return -EINVAL;

No. Please don't hack around the driver infrastructure and register two 
separate drivers. They can even come in two separate commits, 
simplifying the review.

> +}
> +
> +static int msm_vidc_pm_suspend(struct device *dev)
> +{
> +	int rc = 0;
> +	struct msm_vidc_core *core;
> +	enum msm_vidc_allow allow = MSM_VIDC_DISALLOW;
> +
> +	/*
> +	 * Bail out if
> +	 * - driver possibly not probed yet
> +	 * - not the main device. We don't support power management on
> +	 *   subdevices (e.g. context banks)
> +	 */
> +	if (!dev || !dev->driver || !is_video_device(dev))
> +		return 0;
> +
> +	core = dev_get_drvdata(dev);
> +	if (!core) {
> +		d_vpr_e("%s: invalid core\n", __func__);
> +		return -EINVAL;
> +	}
> +
> +	core_lock(core, __func__);
> +	allow = msm_vidc_allow_pm_suspend(core);
> +
> +	if (allow == MSM_VIDC_IGNORE) {
> +		d_vpr_h("%s: pm already suspended\n", __func__);
> +		msm_vidc_change_core_sub_state(core, 0, CORE_SUBSTATE_PM_SUSPEND, __func__);
> +		rc = 0;
> +		goto unlock;
> +	} else if (allow != MSM_VIDC_ALLOW) {
> +		d_vpr_h("%s: pm suspend not allowed\n", __func__);
> +		rc = 0;
> +		goto unlock;
> +	}
> +
> +	rc = msm_vidc_suspend(core);
> +	if (rc == -EOPNOTSUPP)
> +		rc = 0;
> +	else if (rc)
> +		d_vpr_e("Failed to suspend: %d\n", rc);
> +	else
> +		msm_vidc_change_core_sub_state(core, 0, CORE_SUBSTATE_PM_SUSPEND, __func__);
> +
> +unlock:
> +	core_unlock(core, __func__);
> +	return rc;
> +}
> +
> +static int msm_vidc_pm_resume(struct device *dev)
> +{
> +	struct msm_vidc_core *core;
> +
> +	/*
> +	 * Bail out if
> +	 * - driver possibly not probed yet
> +	 * - not the main device. We don't support power management on
> +	 *   subdevices (e.g. context banks)
> +	 */
> +	if (!dev || !dev->driver || !is_video_device(dev))
> +		return 0;
> +
> +	core = dev_get_drvdata(dev);
> +	if (!core) {
> +		d_vpr_e("%s: invalid core\n", __func__);
> +		return -EINVAL;
> +	}
> +
> +	/* remove PM suspend from core sub_state */
> +	core_lock(core, __func__);
> +	msm_vidc_change_core_sub_state(core, CORE_SUBSTATE_PM_SUSPEND, 0, __func__);
> +	core_unlock(core, __func__);
> +
> +	return 0;
> +}
> +
> +static const struct dev_pm_ops msm_vidc_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(msm_vidc_pm_suspend, msm_vidc_pm_resume)

No runtime PM?

> +};
> +
> +struct platform_driver msm_vidc_driver = {
> +	.probe = msm_vidc_probe,
> +	.remove = msm_vidc_remove,
> +	.driver = {
> +		.name = "msm_vidc_v4l2",
> +		.of_match_table = msm_vidc_dt_match,
> +		.pm = &msm_vidc_pm_ops,
> +	},
> +};
> +
> +module_platform_driver(msm_vidc_driver);
> +MODULE_LICENSE("GPL");

Unfortunately, after taking a glance at first two patches, I have to 
stop. It is nearly impossible to review it.

Please start from the beginning, split the driver according to the 
logical functions, not per-file. Ideally something should be compillable 
starting from one of the first patches, if not the very first one. This 
would guarantee that your patchset is structured logically.

Please add DT bindings. New driver series should start from the bindings 
anyway.

Please drop your custom debugging wrappers. Use dev_info, dev_warn, 
dev_err and dev_dbg instead.

Please drop the custom multi-device-single-driver scheme. If there are 
different kinds of devices, there should be different drivers.

Please take a look around. If you are pushing your driver for kernel 
inclusion, it should not stand out by the style and by the typical code 
seuqences.
Dmitry Baryshkov July 28, 2023, 2:13 p.m. UTC | #4
On 28/07/2023 16:23, Vikash Garodia wrote:
> From: Dikshita Agarwal <quic_dikshita@quicinc.com>
> 
> This implements all the capabilities supported by sm8550.
> 
> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
> Signed-off-by: Vikash Garodia <quic_vgarodia@quicinc.com>
> ---
>   .../iris/platform/sm8550/inc/msm_vidc_sm8550.h     |   14 +
>   .../iris/platform/sm8550/src/msm_vidc_sm8550.c     | 1727 ++++++++++++++++++++
>   2 files changed, 1741 insertions(+)
>   create mode 100644 drivers/media/platform/qcom/iris/platform/sm8550/inc/msm_vidc_sm8550.h
>   create mode 100644 drivers/media/platform/qcom/iris/platform/sm8550/src/msm_vidc_sm8550.c
> 
> diff --git a/drivers/media/platform/qcom/iris/platform/sm8550/inc/msm_vidc_sm8550.h b/drivers/media/platform/qcom/iris/platform/sm8550/inc/msm_vidc_sm8550.h
> new file mode 100644
> index 0000000..0a2f172
> --- /dev/null
> +++ b/drivers/media/platform/qcom/iris/platform/sm8550/inc/msm_vidc_sm8550.h
> @@ -0,0 +1,14 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
> + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
> + */
> +
> +#ifndef _MSM_VIDC_SM8550_H_
> +#define _MSM_VIDC_SM8550_H_
> +
> +#include "msm_vidc_core.h"
> +
> +int msm_vidc_init_platform_sm8550(struct msm_vidc_core *core);
> +
> +#endif // _MSM_VIDC_SM8550_H_
> diff --git a/drivers/media/platform/qcom/iris/platform/sm8550/src/msm_vidc_sm8550.c b/drivers/media/platform/qcom/iris/platform/sm8550/src/msm_vidc_sm8550.c
> new file mode 100644
> index 0000000..2408556
> --- /dev/null
> +++ b/drivers/media/platform/qcom/iris/platform/sm8550/src/msm_vidc_sm8550.c
> @@ -0,0 +1,1727 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
> + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
> + */
> +
> +#include <dt-bindings/clock/qcom,sm8550-gcc.h>
> +#include <dt-bindings/clock/qcom,sm8450-videocc.h>
> +
> +#include "hfi_command.h"
> +#include "hfi_property.h"
> +#include "msm_vidc_control.h"
> +#include "msm_vidc_debug.h"
> +#include "msm_vidc_iris3.h"
> +#include "msm_vidc_sm8550.h"
> +#include "msm_vidc_platform.h"
> +
> +/* version: major[24:31], minor[16:23], revision[0:15] */
> +#define DRIVER_VERSION          0x04000000
> +#define DEFAULT_VIDEO_CONCEAL_COLOR_BLACK 0x8020010
> +#define MAX_BASE_LAYER_PRIORITY_ID 63
> +#define MAX_OP_POINT            31
> +#define MAX_BITRATE             245000000
> +#define DEFAULT_BITRATE         20000000
> +#define MINIMUM_FPS             1
> +#define MAXIMUM_FPS             480
> +#define MAXIMUM_DEC_FPS         960
> +#define MAX_QP                  51
> +#define DEFAULT_QP              20
> +#define MAX_CONSTANT_QUALITY    100
> +#define MIN_SLICE_BYTE_SIZE     512
> +#define MAX_SLICE_BYTE_SIZE       \
> +	((MAX_BITRATE) >> 3)
> +#define MAX_SLICE_MB_SIZE         \
> +	(((4096 + 15) >> 4) * ((2304 + 15) >> 4))
> +
> +#define ENC     MSM_VIDC_ENCODER
> +#define DEC     MSM_VIDC_DECODER
> +#define H264    MSM_VIDC_H264
> +#define HEVC    MSM_VIDC_HEVC
> +#define VP9     MSM_VIDC_VP9

Another redefinition. Inline it.

> +#define CODECS_ALL     (H264 | HEVC | VP9)
> +#define MAXIMUM_OVERRIDE_VP9_FPS 200
> +
> +static struct codec_info codec_data_sm8550[] = {
> +	{
> +		.v4l2_codec  = V4L2_PIX_FMT_H264,
> +		.vidc_codec  = MSM_VIDC_H264,
> +		.pixfmt_name = "AVC",

Have you considered using existing code which enumerates formats? For 
example, it is much better to refactor v4l_fill_fmtdesc() to allow 
getting the description instead of adding your own names here.
Not to mention that printk supports %p4cc for printing fourcc values. I 
hope you knew that.

> +	},
> +	{
> +		.v4l2_codec  = V4L2_PIX_FMT_HEVC,
> +		.vidc_codec  = MSM_VIDC_HEVC,
> +		.pixfmt_name = "HEVC",
> +	},
> +	{
> +		.v4l2_codec  = V4L2_PIX_FMT_VP9,
> +		.vidc_codec  = MSM_VIDC_VP9,
> +		.pixfmt_name = "VP9",
> +	},
> +};
> +
> +static struct color_format_info color_format_data_sm8550[] = {
> +	{
> +		.v4l2_color_format = V4L2_PIX_FMT_NV12,
> +		.vidc_color_format = MSM_VIDC_FMT_NV12,
> +		.pixfmt_name       = "NV12",
> +	},
> +	{
> +		.v4l2_color_format = V4L2_PIX_FMT_NV21,
> +		.vidc_color_format = MSM_VIDC_FMT_NV21,
> +		.pixfmt_name       = "NV21",
> +	},
> +	{
> +		.v4l2_color_format = V4L2_PIX_FMT_QC08C,
> +		.vidc_color_format = MSM_VIDC_FMT_NV12C,
> +		.pixfmt_name       = "NV12C",
> +	},
> +	{
> +		.v4l2_color_format = V4L2_PIX_FMT_QC10C,
> +		.vidc_color_format = MSM_VIDC_FMT_TP10C,
> +		.pixfmt_name       = "TP10C",
> +	},
> +	{
> +		.v4l2_color_format = V4L2_PIX_FMT_RGBA32,
> +		.vidc_color_format = MSM_VIDC_FMT_RGBA8888,
> +		.pixfmt_name       = "RGBA",
> +	},
> +};
> +
> +static struct color_primaries_info color_primaries_data_sm8550[] = {
> +	{
> +		.v4l2_color_primaries  = V4L2_COLORSPACE_DEFAULT,
> +		.vidc_color_primaries  = MSM_VIDC_PRIMARIES_RESERVED,
> +	},
> +	{
> +		.v4l2_color_primaries  = V4L2_COLORSPACE_REC709,
> +		.vidc_color_primaries  = MSM_VIDC_PRIMARIES_BT709,
> +	},
> +	{
> +		.v4l2_color_primaries  = V4L2_COLORSPACE_470_SYSTEM_M,
> +		.vidc_color_primaries  = MSM_VIDC_PRIMARIES_BT470_SYSTEM_M,
> +	},
> +	{
> +		.v4l2_color_primaries  = V4L2_COLORSPACE_470_SYSTEM_BG,
> +		.vidc_color_primaries  = MSM_VIDC_PRIMARIES_BT470_SYSTEM_BG,
> +	},
> +	{
> +		.v4l2_color_primaries  = V4L2_COLORSPACE_SMPTE170M,
> +		.vidc_color_primaries  = MSM_VIDC_PRIMARIES_BT601_525,
> +	},
> +	{
> +		.v4l2_color_primaries  = V4L2_COLORSPACE_SMPTE240M,
> +		.vidc_color_primaries  = MSM_VIDC_PRIMARIES_SMPTE_ST240M,
> +	},
> +	{
> +		.v4l2_color_primaries  = V4L2_COLORSPACE_BT2020,
> +		.vidc_color_primaries  = MSM_VIDC_PRIMARIES_BT2020,
> +	},
> +	{
> +		.v4l2_color_primaries  = V4L2_COLORSPACE_DCI_P3,
> +		.vidc_color_primaries  = MSM_VIDC_PRIMARIES_SMPTE_RP431_2,
> +	},
> +};
> +
> +static struct transfer_char_info transfer_char_data_sm8550[] = {
> +	{
> +		.v4l2_transfer_char  = V4L2_XFER_FUNC_DEFAULT,
> +		.vidc_transfer_char  = MSM_VIDC_TRANSFER_RESERVED,
> +	},
> +	{
> +		.v4l2_transfer_char  = V4L2_XFER_FUNC_709,
> +		.vidc_transfer_char  = MSM_VIDC_TRANSFER_BT709,
> +	},
> +	{
> +		.v4l2_transfer_char  = V4L2_XFER_FUNC_SMPTE240M,
> +		.vidc_transfer_char  = MSM_VIDC_TRANSFER_SMPTE_ST240M,
> +	},
> +	{
> +		.v4l2_transfer_char  = V4L2_XFER_FUNC_SRGB,
> +		.vidc_transfer_char  = MSM_VIDC_TRANSFER_SRGB_SYCC,
> +	},
> +	{
> +		.v4l2_transfer_char  = V4L2_XFER_FUNC_SMPTE2084,
> +		.vidc_transfer_char  = MSM_VIDC_TRANSFER_SMPTE_ST2084_PQ,
> +	},
> +};
> +
> +static struct matrix_coeff_info matrix_coeff_data_sm8550[] = {
> +	{
> +		.v4l2_matrix_coeff  = V4L2_YCBCR_ENC_DEFAULT,
> +		.vidc_matrix_coeff  = MSM_VIDC_MATRIX_COEFF_RESERVED,
> +	},
> +	{
> +		.v4l2_matrix_coeff  = V4L2_YCBCR_ENC_709,
> +		.vidc_matrix_coeff  = MSM_VIDC_MATRIX_COEFF_BT709,
> +	},
> +	{
> +		.v4l2_matrix_coeff  = V4L2_YCBCR_ENC_XV709,
> +		.vidc_matrix_coeff  = MSM_VIDC_MATRIX_COEFF_BT709,
> +	},
> +	{
> +		.v4l2_matrix_coeff  = V4L2_YCBCR_ENC_XV601,
> +		.vidc_matrix_coeff  = MSM_VIDC_MATRIX_COEFF_BT470_SYS_BG_OR_BT601_625,
> +	},
> +	{
> +		.v4l2_matrix_coeff  = V4L2_YCBCR_ENC_601,
> +		.vidc_matrix_coeff  = MSM_VIDC_MATRIX_COEFF_BT601_525_BT1358_525_OR_625,
> +	},
> +	{
> +		.v4l2_matrix_coeff  = V4L2_YCBCR_ENC_SMPTE240M,
> +		.vidc_matrix_coeff  = MSM_VIDC_MATRIX_COEFF_SMPTE_ST240,
> +	},
> +	{
> +		.v4l2_matrix_coeff  = V4L2_YCBCR_ENC_BT2020,
> +		.vidc_matrix_coeff  = MSM_VIDC_MATRIX_COEFF_BT2020_NON_CONSTANT,
> +	},
> +	{
> +		.v4l2_matrix_coeff  = V4L2_YCBCR_ENC_BT2020_CONST_LUM,
> +		.vidc_matrix_coeff  = MSM_VIDC_MATRIX_COEFF_BT2020_CONSTANT,
> +	},
> +};

Are you going to say that these tables are platform-specific instead of 
being generic to the driver?

> +
> +static struct msm_platform_core_capability core_data_sm8550[] = {
> +	/* {type, value} */
> +	{ENC_CODECS, H264 | HEVC},
> +	{DEC_CODECS, H264 | HEVC | VP9},
> +	{MAX_SESSION_COUNT, 16},
> +	{MAX_NUM_720P_SESSIONS, 16},
> +	{MAX_NUM_1080P_SESSIONS, 16},
> +	{MAX_NUM_4K_SESSIONS, 8},
> +	{MAX_NUM_8K_SESSIONS, 2},
> +	{MAX_RT_MBPF, 174080},	/* (8192x4352)/256 + (4096x2176)/256*/
> +	{MAX_MBPF, 278528}, /* ((8192x4352)/256) * 2 */
> +	{MAX_MBPS, 7833600},	/* max_load
> +				 * 7680x4320@60fps or 3840x2176@240fps
> +				 * which is greater than 4096x2176@120fps,
> +				 * 8192x4320@48fps
> +				 */
> +	{MAX_MBPF_HQ, 8160}, /* ((1920x1088)/256) */
> +	{MAX_MBPS_HQ, 489600}, /* ((1920x1088)/256)@60fps */
> +	{MAX_MBPF_B_FRAME, 32640}, /* 3840x2176/256 */
> +	{MAX_MBPS_B_FRAME, 1958400}, /* 3840x2176/256 MBs@60fps */
> +	{MAX_MBPS_ALL_INTRA, 1044480}, /* 4096x2176/256 MBs@30fps */
> +	{MAX_ENH_LAYER_COUNT, 5},
> +	{NUM_VPP_PIPE, 4},
> +	{SW_PC, 1},
> +	{FW_UNLOAD, 0},
> +	{HW_RESPONSE_TIMEOUT, HW_RESPONSE_TIMEOUT_VALUE}, /* 1000 ms */
> +	{SW_PC_DELAY,         SW_PC_DELAY_VALUE        }, /* 1500 ms (>HW_RESPONSE_TIMEOUT)*/
> +	{FW_UNLOAD_DELAY,     FW_UNLOAD_DELAY_VALUE    }, /* 3000 ms (>SW_PC_DELAY)*/
> +	{DCVS, 1},
> +	{DECODE_BATCH, 1},
> +	{DECODE_BATCH_TIMEOUT, 200},
> +	{STATS_TIMEOUT_MS, 2000},
> +	{NON_FATAL_FAULTS, 1},
> +	{DEVICE_CAPS, V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING},

Unless there is a good reason, please change this to be a proper data 
structure instead of being a type-value array. With the T-V it is 
impossible to notice if the value is missing or duplicated. This comment 
also applies to the next 'capability' array.

> +};
> +
> +static struct msm_platform_inst_capability instance_cap_data_sm8550[] = {
> +	/* {cap, domain, codec,
> +	 *      min, max, step_or_mask, value,
> +	 *      v4l2_id,
> +	 *      hfi_id,
> +	 *      flags}
> +	 */
> +	{FRAME_WIDTH, DEC, CODECS_ALL, 96, 8192, 1, 1920},
> +
> +	{FRAME_WIDTH, DEC, VP9, 96, 4096, 1, 1920},
> +
> +	{FRAME_WIDTH, ENC, CODECS_ALL, 128, 8192, 1, 1920},
> +
> +	{FRAME_WIDTH, ENC, HEVC, 96, 8192, 1, 1920},
> +
> +	{LOSSLESS_FRAME_WIDTH, ENC, CODECS_ALL, 128, 4096, 1, 1920},
> +
> +	{LOSSLESS_FRAME_WIDTH, ENC, HEVC, 96, 4096, 1, 1920},
> +
> +	{FRAME_HEIGHT, DEC, CODECS_ALL, 96, 8192, 1, 1080},
> +
> +	{FRAME_HEIGHT, DEC, VP9, 96, 4096, 1, 1080},
> +
> +	{FRAME_HEIGHT, ENC, CODECS_ALL, 128, 8192, 1, 1080},
> +
> +	{FRAME_HEIGHT, ENC, HEVC, 96, 8192, 1, 1080},
> +
> +	{LOSSLESS_FRAME_HEIGHT, ENC, CODECS_ALL, 128, 4096, 1, 1080},
> +
> +	{LOSSLESS_FRAME_HEIGHT, ENC, HEVC, 96, 4096, 1, 1080},
> +
> +	{PIX_FMTS, ENC | DEC, H264,
> +		MSM_VIDC_FMT_NV12,
> +		MSM_VIDC_FMT_NV12C,
> +		MSM_VIDC_FMT_NV12 | MSM_VIDC_FMT_NV21 | MSM_VIDC_FMT_NV12C,
> +		MSM_VIDC_FMT_NV12C},
> +
> +	{PIX_FMTS, ENC | DEC, HEVC | VP9,
> +		MSM_VIDC_FMT_NV12,
> +		MSM_VIDC_FMT_TP10C,
> +		MSM_VIDC_FMT_NV12 | MSM_VIDC_FMT_NV21 | MSM_VIDC_FMT_NV12C |
> +		MSM_VIDC_FMT_TP10C,
> +		MSM_VIDC_FMT_NV12C},
> +
> +	{MIN_BUFFERS_INPUT, ENC | DEC, CODECS_ALL, 0, 64, 1, 4,
> +		V4L2_CID_MIN_BUFFERS_FOR_OUTPUT,
> +		0,
> +		CAP_FLAG_VOLATILE},
> +
> +	{MIN_BUFFERS_OUTPUT, ENC | DEC, CODECS_ALL,
> +		0, 64, 1, 4,
> +		V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,
> +		HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_VOLATILE},
> +
> +	/* (8192 * 4320) / 256 */
> +	{MBPF, ENC, CODECS_ALL, 64, 138240, 1, 138240},
> +
> +	{MBPF, ENC, HEVC, 36, 138240, 1, 138240},
> +
> +	{MBPF, DEC, CODECS_ALL, 36, 138240, 1, 138240},
> +
> +	/* (4096 * 2304) / 256 */
> +	{MBPF, DEC, VP9, 36, 36864, 1, 36864},
> +
> +	/* (4096 * 2304) / 256 */
> +	{LOSSLESS_MBPF, ENC, H264 | HEVC, 64, 36864, 1, 36864},
> +
> +	/* Batch Mode Decode */
> +	/* TODO: update with new values based on updated voltage corner */
> +	{BATCH_MBPF, DEC, H264 | HEVC | VP9, 64, 34816, 1, 34816},
> +
> +	/* (4096 * 2304) / 256 */
> +	{BATCH_FPS, DEC, H264 | HEVC | VP9, 1, 120, 1, 120},
> +
> +	{FRAME_RATE, ENC | DEC, CODECS_ALL,
> +		(MINIMUM_FPS << 16), (MAXIMUM_FPS << 16),
> +		1, (DEFAULT_FPS << 16),
> +		0,
> +		HFI_PROP_FRAME_RATE,
> +		CAP_FLAG_OUTPUT_PORT},
> +
> +	{OPERATING_RATE, ENC | DEC, CODECS_ALL,
> +		(MINIMUM_FPS << 16), (MAXIMUM_FPS << 16),
> +		1, (DEFAULT_FPS << 16)},
> +
> +	{INPUT_RATE, ENC | DEC, CODECS_ALL,
> +		(MINIMUM_FPS << 16), INT_MAX,
> +		1, (DEFAULT_FPS << 16)},
> +
> +	{TIMESTAMP_RATE, ENC | DEC, CODECS_ALL,
> +		(MINIMUM_FPS << 16), INT_MAX,
> +		1, (DEFAULT_FPS << 16)},
> +
> +	{SCALE_FACTOR, ENC, H264 | HEVC, 1, 8, 1, 8},
> +
> +	{MB_CYCLES_VSP, ENC, CODECS_ALL, 25, 25, 1, 25},
> +
> +	{MB_CYCLES_VSP, DEC, CODECS_ALL, 25, 25, 1, 25},
> +
> +	{MB_CYCLES_VSP, DEC, VP9, 60, 60, 1, 60},
> +
> +	{MB_CYCLES_VPP, ENC, CODECS_ALL, 675, 675, 1, 675},
> +
> +	{MB_CYCLES_VPP, DEC, CODECS_ALL, 200, 200, 1, 200},
> +
> +	{MB_CYCLES_LP, ENC, CODECS_ALL, 320, 320, 1, 320},
> +
> +	{MB_CYCLES_LP, DEC, CODECS_ALL, 200, 200, 1, 200},
> +
> +	{MB_CYCLES_FW, ENC | DEC, CODECS_ALL, 489583, 489583, 1, 489583},
> +
> +	{MB_CYCLES_FW_VPP, ENC, CODECS_ALL, 48405, 48405, 1, 48405},
> +
> +	{MB_CYCLES_FW_VPP, DEC, CODECS_ALL, 66234, 66234, 1, 66234},
> +
> +	{HFLIP, ENC, CODECS_ALL,
> +		0, 1, 1, 0,
> +		V4L2_CID_HFLIP,
> +		HFI_PROP_FLIP,
> +		CAP_FLAG_OUTPUT_PORT |
> +		CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED},
> +
> +	{VFLIP, ENC, CODECS_ALL,
> +		0, 1, 1, 0,
> +		V4L2_CID_VFLIP,
> +		HFI_PROP_FLIP,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> +		CAP_FLAG_DYNAMIC_ALLOWED},
> +
> +	{ROTATION, ENC, CODECS_ALL,
> +		0, 270, 90, 0,
> +		V4L2_CID_ROTATE,
> +		HFI_PROP_ROTATION,
> +		CAP_FLAG_OUTPUT_PORT},
> +
> +	{HEADER_MODE, ENC, CODECS_ALL,
> +		V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE,
> +		V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
> +		BIT(V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) |
> +		BIT(V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME),
> +		V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE,
> +		V4L2_CID_MPEG_VIDEO_HEADER_MODE,
> +		HFI_PROP_SEQ_HEADER_MODE,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> +
> +	{PREPEND_SPSPPS_TO_IDR, ENC, CODECS_ALL,
> +		0, 1, 1, 0,
> +		V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR},
> +
> +	{WITHOUT_STARTCODE, ENC, CODECS_ALL,
> +		0, 1, 1, 0,
> +		V4L2_CID_MPEG_VIDEO_HEVC_WITHOUT_STARTCODE,
> +		HFI_PROP_NAL_LENGTH_FIELD,
> +		CAP_FLAG_OUTPUT_PORT},
> +
> +	{NAL_LENGTH_FIELD, ENC, CODECS_ALL,
> +		V4L2_MPEG_VIDEO_HEVC_SIZE_0,
> +		V4L2_MPEG_VIDEO_HEVC_SIZE_4,
> +		BIT(V4L2_MPEG_VIDEO_HEVC_SIZE_0) |
> +		BIT(V4L2_MPEG_VIDEO_HEVC_SIZE_4),
> +		V4L2_MPEG_VIDEO_HEVC_SIZE_0,
> +		V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD,
> +		HFI_PROP_NAL_LENGTH_FIELD,
> +		CAP_FLAG_MENU | CAP_FLAG_OUTPUT_PORT},
> +
> +	/* TODO: Firmware introduced enumeration type for this
> +	 * with and without seq header.
> +	 */
> +	{REQUEST_I_FRAME, ENC, H264 | HEVC,
> +		0, 0, 0, 0,
> +		V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME,
> +		HFI_PROP_REQUEST_SYNC_FRAME,
> +		CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED},
> +
> +	/* Enc: Keeping CABAC and CAVLC as same bitrate.
> +	 * Dec: there's no use of Bitrate cap
> +	 */
> +	{BIT_RATE, ENC, H264 | HEVC,
> +		1, MAX_BITRATE, 1, DEFAULT_BITRATE,
> +		V4L2_CID_MPEG_VIDEO_BITRATE,
> +		HFI_PROP_TOTAL_BITRATE,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> +		CAP_FLAG_DYNAMIC_ALLOWED},
> +
> +	{BITRATE_MODE, ENC, H264,
> +		V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
> +		V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
> +		BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) |
> +		BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_CBR),
> +		V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
> +		V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
> +		HFI_PROP_RATE_CONTROL,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> +
> +	{BITRATE_MODE, ENC, HEVC,
> +		V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
> +		V4L2_MPEG_VIDEO_BITRATE_MODE_CQ,
> +		BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) |
> +		BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) |
> +		BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_CQ),
> +		V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
> +		V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
> +		HFI_PROP_RATE_CONTROL,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> +
> +	{CABAC_MAX_BITRATE, ENC, H264 | HEVC, 0,
> +		160000000, 1, 160000000},
> +
> +	{CAVLC_MAX_BITRATE, ENC, H264, 0,
> +		220000000, 1, 220000000},
> +
> +	{ALLINTRA_MAX_BITRATE, ENC, H264 | HEVC, 0,
> +		245000000, 1, 245000000},
> +
> +	{NUM_COMV, DEC, CODECS_ALL,
> +		0, INT_MAX, 1, 0},
> +
> +	{LOSSLESS, ENC, HEVC,
> +		0, 1, 1, 0,
> +		V4L2_CID_MPEG_VIDEO_HEVC_LOSSLESS_CU},
> +
> +	{FRAME_SKIP_MODE, ENC, H264 | HEVC,
> +		V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED,
> +		V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT,
> +		BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED) |
> +		BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT) |
> +		BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT),
> +		V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED,
> +		V4L2_CID_MPEG_VIDEO_FRAME_SKIP_MODE,
> +		0,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> +
> +	{FRAME_RC_ENABLE, ENC, H264 | HEVC,
> +		0, 1, 1, 1,
> +		V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE},
> +
> +	{CONSTANT_QUALITY, ENC, HEVC,
> +		1, MAX_CONSTANT_QUALITY, 1, 90,
> +		V4L2_CID_MPEG_VIDEO_CONSTANT_QUALITY,
> +		HFI_PROP_CONSTANT_QUALITY,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> +		CAP_FLAG_DYNAMIC_ALLOWED},
> +
> +	{GOP_SIZE, ENC, CODECS_ALL,
> +		0, INT_MAX, 1, 2 * DEFAULT_FPS - 1,
> +		V4L2_CID_MPEG_VIDEO_GOP_SIZE,
> +		HFI_PROP_MAX_GOP_FRAMES,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> +		CAP_FLAG_DYNAMIC_ALLOWED},
> +
> +	{GOP_CLOSURE, ENC, H264 | HEVC,
> +		0, 1, 1, 1,
> +		V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
> +		0},
> +
> +	{B_FRAME, ENC, H264 | HEVC,
> +		0, 7, 1, 0,
> +		V4L2_CID_MPEG_VIDEO_B_FRAMES,
> +		HFI_PROP_MAX_B_FRAMES,
> +		CAP_FLAG_OUTPUT_PORT},
> +
> +	{LTR_COUNT, ENC, H264 | HEVC,
> +		0, MAX_LTR_FRAME_COUNT_2, 1, 0,
> +		V4L2_CID_MPEG_VIDEO_LTR_COUNT,
> +		HFI_PROP_LTR_COUNT,
> +		CAP_FLAG_OUTPUT_PORT},
> +
> +	{USE_LTR, ENC, H264 | HEVC,
> +		0,
> +		((1 << MAX_LTR_FRAME_COUNT_2) - 1),
> +		0, 0,
> +		V4L2_CID_MPEG_VIDEO_USE_LTR_FRAMES,
> +		HFI_PROP_LTR_USE,
> +		CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED},
> +
> +	{MARK_LTR, ENC, H264 | HEVC,
> +		INVALID_DEFAULT_MARK_OR_USE_LTR,
> +		(MAX_LTR_FRAME_COUNT_2 - 1),
> +		1, INVALID_DEFAULT_MARK_OR_USE_LTR,
> +		V4L2_CID_MPEG_VIDEO_FRAME_LTR_INDEX,
> +		HFI_PROP_LTR_MARK,
> +		CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED},
> +
> +	{BASELAYER_PRIORITY, ENC, H264,
> +		0, MAX_BASE_LAYER_PRIORITY_ID, 1, 0,
> +		V4L2_CID_MPEG_VIDEO_BASELAYER_PRIORITY_ID,
> +		HFI_PROP_BASELAYER_PRIORITYID,
> +		CAP_FLAG_OUTPUT_PORT},
> +
> +	{IR_TYPE, ENC, H264 | HEVC,
> +		V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_RANDOM,
> +		V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_CYCLIC,
> +		BIT(V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_RANDOM) |
> +		BIT(V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_CYCLIC),
> +		V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_RANDOM,
> +		V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE,
> +		0,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> +
> +	{IR_PERIOD, ENC, H264 | HEVC,
> +		0, INT_MAX, 1, 0,
> +		V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD,
> +		0,
> +		CAP_FLAG_INPUT_PORT | CAP_FLAG_OUTPUT_PORT |
> +		CAP_FLAG_DYNAMIC_ALLOWED},
> +
> +	{AU_DELIMITER, ENC, H264 | HEVC,
> +		0, 1, 1, 0,
> +		V4L2_CID_MPEG_VIDEO_AU_DELIMITER,
> +		HFI_PROP_AUD,
> +		CAP_FLAG_OUTPUT_PORT},
> +
> +	{MIN_QUALITY, ENC, H264 | HEVC,
> +		0, MAX_SUPPORTED_MIN_QUALITY, 70, MAX_SUPPORTED_MIN_QUALITY,
> +		0,
> +		HFI_PROP_MAINTAIN_MIN_QUALITY,
> +		CAP_FLAG_OUTPUT_PORT},
> +
> +	{VBV_DELAY, ENC, H264 | HEVC,
> +		200, 300, 100, 300,
> +		V4L2_CID_MPEG_VIDEO_VBV_DELAY,
> +		HFI_PROP_VBV_DELAY,
> +		CAP_FLAG_OUTPUT_PORT},
> +
> +	{PEAK_BITRATE, ENC, H264 | HEVC,
> +		/* default peak bitrate is 10% larger than avg bitrate */
> +		1, MAX_BITRATE, 1, DEFAULT_BITRATE,
> +		V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
> +		HFI_PROP_TOTAL_PEAK_BITRATE,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> +			CAP_FLAG_DYNAMIC_ALLOWED},
> +
> +	{MIN_FRAME_QP, ENC, H264,
> +		MIN_QP_8BIT, MAX_QP, 1, MIN_QP_8BIT,
> +		V4L2_CID_MPEG_VIDEO_H264_MIN_QP,
> +		HFI_PROP_MIN_QP_PACKED,
> +		CAP_FLAG_OUTPUT_PORT},
> +
> +	{MIN_FRAME_QP, ENC, HEVC,
> +		MIN_QP_10BIT, MAX_QP, 1, MIN_QP_10BIT,
> +		V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP,
> +		HFI_PROP_MIN_QP_PACKED,
> +		CAP_FLAG_OUTPUT_PORT},
> +
> +	{I_FRAME_MIN_QP, ENC, H264,
> +		MIN_QP_8BIT, MAX_QP, 1, MIN_QP_8BIT,
> +		V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MIN_QP},
> +
> +	{I_FRAME_MIN_QP, ENC, HEVC,
> +		MIN_QP_10BIT, MAX_QP, 1, MIN_QP_10BIT,
> +		V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_MIN_QP},
> +
> +	{P_FRAME_MIN_QP, ENC, H264,
> +		MIN_QP_8BIT, MAX_QP, 1, MIN_QP_8BIT,
> +		V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MIN_QP},
> +
> +	{P_FRAME_MIN_QP, ENC, HEVC,
> +		MIN_QP_10BIT, MAX_QP, 1, MIN_QP_10BIT,
> +		V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_MIN_QP},
> +
> +	{B_FRAME_MIN_QP, ENC, H264,
> +		MIN_QP_8BIT, MAX_QP, 1, MIN_QP_8BIT,
> +		V4L2_CID_MPEG_VIDEO_H264_B_FRAME_MIN_QP},
> +
> +	{B_FRAME_MIN_QP, ENC, HEVC,
> +		MIN_QP_10BIT, MAX_QP, 1, MIN_QP_10BIT,
> +		V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_MIN_QP},
> +
> +	{MAX_FRAME_QP, ENC, H264,
> +		MIN_QP_8BIT, MAX_QP, 1, MAX_QP,
> +		V4L2_CID_MPEG_VIDEO_H264_MAX_QP,
> +		HFI_PROP_MAX_QP_PACKED,
> +		CAP_FLAG_OUTPUT_PORT},
> +
> +	{MAX_FRAME_QP, ENC, HEVC,
> +		MIN_QP_10BIT, MAX_QP, 1, MAX_QP,
> +		V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP,
> +		HFI_PROP_MAX_QP_PACKED,
> +		CAP_FLAG_OUTPUT_PORT},
> +
> +	{I_FRAME_MAX_QP, ENC, H264,
> +		MIN_QP_8BIT, MAX_QP, 1, MAX_QP,
> +		V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MAX_QP},
> +
> +	{I_FRAME_MAX_QP, ENC, HEVC,
> +		MIN_QP_10BIT, MAX_QP, 1, MAX_QP,
> +		V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_MAX_QP},
> +
> +	{P_FRAME_MAX_QP, ENC, H264,
> +		MIN_QP_8BIT, MAX_QP, 1, MAX_QP,
> +		V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MAX_QP},
> +
> +	{P_FRAME_MAX_QP, ENC, HEVC,
> +		MIN_QP_10BIT, MAX_QP, 1, MAX_QP,
> +		V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_MAX_QP},
> +
> +	{B_FRAME_MAX_QP, ENC, H264,
> +		MIN_QP_8BIT, MAX_QP, 1, MAX_QP,
> +		V4L2_CID_MPEG_VIDEO_H264_B_FRAME_MAX_QP},
> +
> +	{B_FRAME_MAX_QP, ENC, HEVC,
> +		MIN_QP_10BIT, MAX_QP, 1, MAX_QP,
> +		V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_MAX_QP},
> +
> +	{I_FRAME_QP, ENC, HEVC,
> +		MIN_QP_10BIT, MAX_QP, 1, DEFAULT_QP,
> +		V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP,
> +		HFI_PROP_QP_PACKED,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> +			CAP_FLAG_DYNAMIC_ALLOWED},
> +
> +	{I_FRAME_QP, ENC, H264,
> +		MIN_QP_8BIT, MAX_QP, 1, DEFAULT_QP,
> +		V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP,
> +		HFI_PROP_QP_PACKED,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> +			CAP_FLAG_DYNAMIC_ALLOWED},
> +
> +	{P_FRAME_QP, ENC, HEVC,
> +		MIN_QP_10BIT, MAX_QP, 1, DEFAULT_QP,
> +		V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP,
> +		HFI_PROP_QP_PACKED,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> +			CAP_FLAG_DYNAMIC_ALLOWED},
> +
> +	{P_FRAME_QP, ENC, H264,
> +		MIN_QP_8BIT, MAX_QP, 1, DEFAULT_QP,
> +		V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP,
> +		HFI_PROP_QP_PACKED,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> +			CAP_FLAG_DYNAMIC_ALLOWED},
> +
> +	{B_FRAME_QP, ENC, HEVC,
> +		MIN_QP_10BIT, MAX_QP, 1, DEFAULT_QP,
> +		V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP,
> +		HFI_PROP_QP_PACKED,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> +			CAP_FLAG_DYNAMIC_ALLOWED},
> +
> +	{B_FRAME_QP, ENC, H264,
> +		MIN_QP_8BIT, MAX_QP, 1, DEFAULT_QP,
> +		V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP,
> +		HFI_PROP_QP_PACKED,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> +			CAP_FLAG_DYNAMIC_ALLOWED},
> +
> +	{LAYER_TYPE, ENC, HEVC,
> +		V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B,
> +		V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P,
> +		BIT(V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B) |
> +		BIT(V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P),
> +		V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P,
> +		V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE,
> +		HFI_PROP_LAYER_ENCODING_TYPE,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> +
> +	{LAYER_TYPE, ENC, H264,
> +		V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B,
> +		V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P,
> +		BIT(V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B) |
> +		BIT(V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P),
> +		V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P,
> +		V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE,
> +		HFI_PROP_LAYER_ENCODING_TYPE,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> +
> +	{LAYER_ENABLE, ENC, H264,
> +		0, 1, 1, 0,
> +		V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING,
> +		HFI_PROP_LAYER_ENCODING_TYPE,
> +		CAP_FLAG_OUTPUT_PORT},
> +
> +	{LAYER_ENABLE, ENC, HEVC,
> +		0, 1, 1, 0,
> +		0,
> +		0,
> +		CAP_FLAG_OUTPUT_PORT},
> +
> +	{ENH_LAYER_COUNT, ENC, HEVC,
> +		0, 5, 1, 0,
> +		V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER,
> +		HFI_PROP_LAYER_COUNT,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> +			CAP_FLAG_DYNAMIC_ALLOWED},
> +
> +	{ENH_LAYER_COUNT, ENC, H264,
> +		0, 5, 1, 0,
> +		V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER,
> +		HFI_PROP_LAYER_COUNT,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> +			CAP_FLAG_DYNAMIC_ALLOWED},
> +
> +	{L0_BR, ENC, H264,
> +		1, MAX_BITRATE, 1, DEFAULT_BITRATE,
> +		V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L0_BR,
> +		HFI_PROP_BITRATE_LAYER1,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> +			CAP_FLAG_DYNAMIC_ALLOWED},
> +
> +	{L0_BR, ENC, HEVC,
> +		1, MAX_BITRATE, 1, DEFAULT_BITRATE,
> +		V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L0_BR,
> +		HFI_PROP_BITRATE_LAYER1,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> +			CAP_FLAG_DYNAMIC_ALLOWED},
> +
> +	{L1_BR, ENC, H264,
> +		1, MAX_BITRATE, 1, DEFAULT_BITRATE,
> +		V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L1_BR,
> +		HFI_PROP_BITRATE_LAYER2,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> +			CAP_FLAG_DYNAMIC_ALLOWED},
> +
> +	{L1_BR, ENC, HEVC,
> +		1, MAX_BITRATE, 1, DEFAULT_BITRATE,
> +		V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L1_BR,
> +		HFI_PROP_BITRATE_LAYER2,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> +			CAP_FLAG_DYNAMIC_ALLOWED},
> +
> +	{L2_BR, ENC, H264,
> +		1, MAX_BITRATE, 1, DEFAULT_BITRATE,
> +		V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L2_BR,
> +		HFI_PROP_BITRATE_LAYER3,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> +			CAP_FLAG_DYNAMIC_ALLOWED},
> +
> +	{L2_BR, ENC, HEVC,
> +		1, MAX_BITRATE, 1, DEFAULT_BITRATE,
> +		V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L2_BR,
> +		HFI_PROP_BITRATE_LAYER3,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> +			CAP_FLAG_DYNAMIC_ALLOWED},
> +
> +	{L3_BR, ENC, H264,
> +		1, MAX_BITRATE, 1, DEFAULT_BITRATE,
> +		V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L3_BR,
> +		HFI_PROP_BITRATE_LAYER4,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> +			CAP_FLAG_DYNAMIC_ALLOWED},
> +	{L3_BR, ENC, HEVC,
> +		1, MAX_BITRATE, 1, DEFAULT_BITRATE,
> +		V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L3_BR,
> +		HFI_PROP_BITRATE_LAYER4,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> +			CAP_FLAG_DYNAMIC_ALLOWED},
> +
> +	{L4_BR, ENC, H264,
> +		1, MAX_BITRATE, 1, DEFAULT_BITRATE,
> +		V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L4_BR,
> +		HFI_PROP_BITRATE_LAYER5,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> +			CAP_FLAG_DYNAMIC_ALLOWED},
> +
> +	{L4_BR, ENC, HEVC,
> +		1, MAX_BITRATE, 1, DEFAULT_BITRATE,
> +		V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L4_BR,
> +		HFI_PROP_BITRATE_LAYER5,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> +			CAP_FLAG_DYNAMIC_ALLOWED},
> +
> +	{L5_BR, ENC, H264,
> +		1, MAX_BITRATE, 1, DEFAULT_BITRATE,
> +		V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L5_BR,
> +		HFI_PROP_BITRATE_LAYER6,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> +			CAP_FLAG_DYNAMIC_ALLOWED},
> +
> +	{L5_BR, ENC, HEVC,
> +		1, MAX_BITRATE, 1, DEFAULT_BITRATE,
> +		V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L5_BR,
> +		HFI_PROP_BITRATE_LAYER6,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> +			CAP_FLAG_DYNAMIC_ALLOWED},
> +
> +	{ENTROPY_MODE, ENC, H264,
> +		V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
> +		V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
> +		BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC) |
> +		BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC),
> +		V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
> +		V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE,
> +		HFI_PROP_CABAC_SESSION,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> +
> +	{ENTROPY_MODE, DEC, H264 | HEVC | VP9,
> +		V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
> +		V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
> +		BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC) |
> +		BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC),
> +		V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
> +		0,
> +		HFI_PROP_CABAC_SESSION},
> +
> +	{PROFILE, ENC | DEC, H264,
> +		V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
> +		V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH,
> +		BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
> +		BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH) |
> +		BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
> +		BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
> +		BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH),
> +		V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
> +		V4L2_CID_MPEG_VIDEO_H264_PROFILE,
> +		HFI_PROP_PROFILE,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> +
> +	{PROFILE, ENC | DEC, HEVC,
> +		V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
> +		V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10,
> +		BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) |
> +		BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE) |
> +		BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10),
> +		V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
> +		V4L2_CID_MPEG_VIDEO_HEVC_PROFILE,
> +		HFI_PROP_PROFILE,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> +
> +	{PROFILE, DEC, VP9,
> +		V4L2_MPEG_VIDEO_VP9_PROFILE_0,
> +		V4L2_MPEG_VIDEO_VP9_PROFILE_2,
> +		BIT(V4L2_MPEG_VIDEO_VP9_PROFILE_0) |
> +		BIT(V4L2_MPEG_VIDEO_VP9_PROFILE_2),
> +		V4L2_MPEG_VIDEO_VP9_PROFILE_0,
> +		V4L2_CID_MPEG_VIDEO_VP9_PROFILE,
> +		HFI_PROP_PROFILE,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> +
> +	{LEVEL, ENC, H264,
> +		V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
> +		V4L2_MPEG_VIDEO_H264_LEVEL_6_0,
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_0) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_1) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_2) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_0),
> +		V4L2_MPEG_VIDEO_H264_LEVEL_5_0,
> +		V4L2_CID_MPEG_VIDEO_H264_LEVEL,
> +		HFI_PROP_LEVEL,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> +
> +	{LEVEL, ENC, HEVC,
> +		V4L2_MPEG_VIDEO_HEVC_LEVEL_1,
> +		V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2,
> +		BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_1) |
> +		BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2) |
> +		BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) |
> +		BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3) |
> +		BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) |
> +		BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4) |
> +		BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1) |
> +		BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5) |
> +		BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1) |
> +		BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2) |
> +		BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6) |
> +		BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1) |
> +		BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2),
> +		V4L2_MPEG_VIDEO_HEVC_LEVEL_5,
> +		V4L2_CID_MPEG_VIDEO_HEVC_LEVEL,
> +		HFI_PROP_LEVEL,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> +
> +	{LEVEL, DEC, H264,
> +		V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
> +		V4L2_MPEG_VIDEO_H264_LEVEL_6_2,
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_0) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_1) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_2) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_0) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_1) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_2),
> +		V4L2_MPEG_VIDEO_H264_LEVEL_6_1,
> +		V4L2_CID_MPEG_VIDEO_H264_LEVEL,
> +		HFI_PROP_LEVEL,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> +
> +	{LEVEL, DEC, HEVC,
> +		V4L2_MPEG_VIDEO_HEVC_LEVEL_1,
> +		V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2,
> +		BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_1) |
> +		BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2) |
> +		BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) |
> +		BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3) |
> +		BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) |
> +		BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4) |
> +		BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1) |
> +		BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5) |
> +		BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1) |
> +		BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2) |
> +		BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6) |
> +		BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1) |
> +		BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2),
> +		V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1,
> +		V4L2_CID_MPEG_VIDEO_HEVC_LEVEL,
> +		HFI_PROP_LEVEL,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> +
> +	{LEVEL, DEC, VP9,
> +		V4L2_MPEG_VIDEO_VP9_LEVEL_1_0,
> +		V4L2_MPEG_VIDEO_VP9_LEVEL_6_0,
> +		BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_1_0) |
> +		BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_1_1) |
> +		BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_2_0) |
> +		BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_2_1) |
> +		BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_3_0) |
> +		BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_3_1) |
> +		BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_4_0) |
> +		BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_4_1) |
> +		BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_5_0) |
> +		BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_5_1) |
> +		BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_5_2) |
> +		BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_6_0),
> +		V4L2_MPEG_VIDEO_VP9_LEVEL_6_0,
> +		V4L2_CID_MPEG_VIDEO_VP9_LEVEL,
> +		HFI_PROP_LEVEL,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> +
> +	{HEVC_TIER, ENC | DEC, HEVC,
> +		V4L2_MPEG_VIDEO_HEVC_TIER_MAIN,
> +		V4L2_MPEG_VIDEO_HEVC_TIER_HIGH,
> +		BIT(V4L2_MPEG_VIDEO_HEVC_TIER_MAIN) |
> +		BIT(V4L2_MPEG_VIDEO_HEVC_TIER_HIGH),
> +		V4L2_MPEG_VIDEO_HEVC_TIER_HIGH,
> +		V4L2_CID_MPEG_VIDEO_HEVC_TIER,
> +		HFI_PROP_TIER,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> +
> +	{LF_MODE, ENC, H264,
> +		V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED,
> +		DB_H264_DISABLE_SLICE_BOUNDARY,
> +		BIT(V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED) |
> +		BIT(V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED) |
> +		BIT(DB_H264_DISABLE_SLICE_BOUNDARY),
> +		V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED,
> +		V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE,
> +		HFI_PROP_DEBLOCKING_MODE,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> +
> +	{LF_MODE, ENC, HEVC,
> +		V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_DISABLED,
> +		DB_HEVC_DISABLE_SLICE_BOUNDARY,
> +		BIT(V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_DISABLED) |
> +		BIT(V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_ENABLED) |
> +		BIT(DB_HEVC_DISABLE_SLICE_BOUNDARY),
> +		V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_ENABLED,
> +		V4L2_CID_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE,
> +		HFI_PROP_DEBLOCKING_MODE,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> +
> +	{LF_ALPHA, ENC, H264,
> +		-6, 6, 1, 0,
> +		V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA},
> +
> +	{LF_ALPHA, ENC, HEVC,
> +		-6, 6, 1, 0,
> +		V4L2_CID_MPEG_VIDEO_HEVC_LF_TC_OFFSET_DIV2},
> +
> +	{LF_BETA, ENC, H264,
> +		-6, 6, 1, 0,
> +		V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA},
> +
> +	{LF_BETA, ENC, HEVC,
> +		-6, 6, 1, 0,
> +		V4L2_CID_MPEG_VIDEO_HEVC_LF_BETA_OFFSET_DIV2},
> +
> +	{SLICE_MODE, ENC, H264 | HEVC,
> +		V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE,
> +		V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES,
> +		BIT(V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE) |
> +		BIT(V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) |
> +		BIT(V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES),
> +		V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE,
> +		V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE,
> +		0,
> +		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> +
> +	{SLICE_MAX_BYTES, ENC, H264 | HEVC,
> +		MIN_SLICE_BYTE_SIZE, MAX_SLICE_BYTE_SIZE,
> +		1, MIN_SLICE_BYTE_SIZE,
> +		V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES,
> +		HFI_PROP_MULTI_SLICE_BYTES_COUNT,
> +		CAP_FLAG_OUTPUT_PORT},
> +
> +	{SLICE_MAX_MB, ENC, H264 | HEVC,
> +		1, MAX_SLICE_MB_SIZE, 1, 1,
> +		V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB,
> +		HFI_PROP_MULTI_SLICE_MB_COUNT,
> +		CAP_FLAG_OUTPUT_PORT},
> +
> +	{MB_RC, ENC, H264 | HEVC,
> +		0, 1, 1, 1,
> +		V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE,
> +		0,
> +		CAP_FLAG_OUTPUT_PORT},
> +
> +	{TRANSFORM_8X8, ENC, H264,
> +		0, 1, 1, 1,
> +		V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM,
> +		HFI_PROP_8X8_TRANSFORM,
> +		CAP_FLAG_OUTPUT_PORT},
> +
> +	{CHROMA_QP_INDEX_OFFSET, ENC, HEVC,
> +		MIN_CHROMA_QP_OFFSET, MAX_CHROMA_QP_OFFSET,
> +		1, MAX_CHROMA_QP_OFFSET,
> +		V4L2_CID_MPEG_VIDEO_H264_CHROMA_QP_INDEX_OFFSET,
> +		HFI_PROP_CHROMA_QP_OFFSET,
> +		CAP_FLAG_OUTPUT_PORT},
> +
> +	{DISPLAY_DELAY_ENABLE, DEC, H264 | HEVC | VP9,
> +		0, 1, 1, 0,
> +		V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE,
> +		HFI_PROP_DECODE_ORDER_OUTPUT,
> +		CAP_FLAG_INPUT_PORT},
> +
> +	{DISPLAY_DELAY, DEC, H264 | HEVC | VP9,
> +		0, 1, 1, 0,
> +		V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY,
> +		HFI_PROP_DECODE_ORDER_OUTPUT,
> +		CAP_FLAG_INPUT_PORT},
> +
> +	{OUTPUT_ORDER, DEC, H264 | HEVC | VP9,
> +		0, 1, 1, 0,
> +		0,
> +		HFI_PROP_DECODE_ORDER_OUTPUT,
> +		CAP_FLAG_INPUT_PORT},
> +
> +	{INPUT_BUF_HOST_MAX_COUNT, ENC | DEC, CODECS_ALL,
> +		DEFAULT_MAX_HOST_BUF_COUNT, DEFAULT_MAX_HOST_BURST_BUF_COUNT,
> +		1, DEFAULT_MAX_HOST_BUF_COUNT,
> +		0,
> +		HFI_PROP_BUFFER_HOST_MAX_COUNT,
> +		CAP_FLAG_INPUT_PORT},
> +
> +	{OUTPUT_BUF_HOST_MAX_COUNT, ENC | DEC, CODECS_ALL,
> +		DEFAULT_MAX_HOST_BUF_COUNT, DEFAULT_MAX_HOST_BURST_BUF_COUNT,
> +		1, DEFAULT_MAX_HOST_BUF_COUNT,
> +		0,
> +		HFI_PROP_BUFFER_HOST_MAX_COUNT,
> +		CAP_FLAG_OUTPUT_PORT},
> +
> +	{CONCEAL_COLOR_8BIT, DEC, CODECS_ALL, 0x0, 0xff3fcff, 1,
> +		DEFAULT_VIDEO_CONCEAL_COLOR_BLACK,
> +		V4L2_CID_MPEG_VIDEO_MUTE_YUV,
> +		HFI_PROP_CONCEAL_COLOR_8BIT,
> +		CAP_FLAG_INPUT_PORT},
> +
> +	{CONCEAL_COLOR_10BIT, DEC, CODECS_ALL, 0x0, 0x3fffffff, 1,
> +		DEFAULT_VIDEO_CONCEAL_COLOR_BLACK,
> +		V4L2_CID_MPEG_VIDEO_MUTE_YUV,
> +		HFI_PROP_CONCEAL_COLOR_10BIT,
> +		CAP_FLAG_INPUT_PORT},
> +
> +	{STAGE, DEC | ENC, CODECS_ALL,
> +		MSM_VIDC_STAGE_1,
> +		MSM_VIDC_STAGE_2, 1,
> +		MSM_VIDC_STAGE_2,
> +		0,
> +		HFI_PROP_STAGE},
> +
> +	{PIPE, DEC | ENC, CODECS_ALL,
> +		MSM_VIDC_PIPE_1,
> +		MSM_VIDC_PIPE_4, 1,
> +		MSM_VIDC_PIPE_4,
> +		0,
> +		HFI_PROP_PIPE},
> +
> +	{POC, DEC, H264, 0, 2, 1, 1,
> +		0,
> +		HFI_PROP_PIC_ORDER_CNT_TYPE},
> +
> +	{QUALITY_MODE, ENC, CODECS_ALL,
> +		MSM_VIDC_MAX_QUALITY_MODE,
> +		MSM_VIDC_POWER_SAVE_MODE, 1,
> +		MSM_VIDC_POWER_SAVE_MODE},
> +
> +	{CODED_FRAMES, DEC, H264 | HEVC,
> +		CODED_FRAMES_PROGRESSIVE, CODED_FRAMES_INTERLACE,
> +		1, CODED_FRAMES_PROGRESSIVE,
> +		0,
> +		HFI_PROP_CODED_FRAMES},
> +
> +	{BIT_DEPTH, DEC, CODECS_ALL, BIT_DEPTH_8, BIT_DEPTH_10, 1, BIT_DEPTH_8,
> +		0,
> +		HFI_PROP_LUMA_CHROMA_BIT_DEPTH},
> +
> +	{BITSTREAM_SIZE_OVERWRITE, DEC, CODECS_ALL, 0, INT_MAX, 1, 0,
> +		0},
> +
> +	{DEFAULT_HEADER, DEC, CODECS_ALL,
> +		0, 1, 1, 0,
> +		0,
> +		HFI_PROP_DEC_DEFAULT_HEADER},
> +
> +	{RAP_FRAME, DEC, CODECS_ALL,
> +		0, 1, 1, 1,
> +		0,
> +		HFI_PROP_DEC_START_FROM_RAP_FRAME,
> +		CAP_FLAG_INPUT_PORT},
> +
> +	{SEQ_CHANGE_AT_SYNC_FRAME, DEC, CODECS_ALL,
> +		0, 1, 1, 1,
> +		0,
> +		HFI_PROP_SEQ_CHANGE_AT_SYNC_FRAME,
> +		CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED},
> +
> +	{ALL_INTRA, ENC, H264 | HEVC,
> +		0, 1, 1, 0,
> +		0,
> +		0,
> +		CAP_FLAG_OUTPUT_PORT},
> +};
> +
> +static struct msm_platform_inst_cap_dependency instance_cap_dependency_data_sm8550[] = {
> +	/* {cap, domain, codec,
> +	 *      children,
> +	 *      adjust, set}
> +	 */
> +
> +	{PIX_FMTS, ENC, H264,
> +		{IR_PERIOD}},
> +
> +	{PIX_FMTS, ENC, HEVC,
> +		{PROFILE, MIN_FRAME_QP, MAX_FRAME_QP, I_FRAME_QP, P_FRAME_QP,
> +			B_FRAME_QP, MIN_QUALITY, IR_PERIOD, LTR_COUNT}},
> +
> +	{PIX_FMTS, DEC, HEVC,
> +		{PROFILE}},
> +
> +	{FRAME_RATE, ENC, CODECS_ALL,
> +		{0},
> +		NULL,
> +		msm_vidc_set_q16},
> +
> +	{HFLIP, ENC, CODECS_ALL,
> +		{0},
> +		NULL,
> +		msm_vidc_set_flip},
> +
> +	{VFLIP, ENC, CODECS_ALL,
> +		{0},
> +		NULL,
> +		msm_vidc_set_flip},
> +
> +	{ROTATION, ENC, CODECS_ALL,
> +		{0},
> +		NULL,
> +		msm_vidc_set_rotation},
> +
> +	{HEADER_MODE, ENC, CODECS_ALL,
> +		{0},
> +		NULL,
> +		msm_vidc_set_header_mode},
> +
> +	{WITHOUT_STARTCODE, ENC, CODECS_ALL,
> +		{0},
> +		NULL,
> +		msm_vidc_set_nal_length},
> +
> +	{REQUEST_I_FRAME, ENC, H264 | HEVC,
> +		{0},
> +		NULL,
> +		msm_vidc_set_req_sync_frame},
> +
> +	{BIT_RATE, ENC, H264,
> +		{PEAK_BITRATE, L0_BR},
> +		msm_vidc_adjust_bitrate,
> +		msm_vidc_set_bitrate},
> +
> +	{BIT_RATE, ENC, HEVC,
> +		{PEAK_BITRATE, L0_BR},
> +		msm_vidc_adjust_bitrate,
> +		msm_vidc_set_bitrate},
> +
> +	{BITRATE_MODE, ENC, H264,
> +		{LTR_COUNT, IR_PERIOD, I_FRAME_QP, P_FRAME_QP,
> +			B_FRAME_QP, ENH_LAYER_COUNT, BIT_RATE,
> +			MIN_QUALITY, VBV_DELAY,
> +			PEAK_BITRATE, SLICE_MODE},
> +		msm_vidc_adjust_bitrate_mode,
> +		msm_vidc_set_u32_enum},
> +
> +	{BITRATE_MODE, ENC, HEVC,
> +		{LTR_COUNT, IR_PERIOD, I_FRAME_QP, P_FRAME_QP,
> +			B_FRAME_QP, CONSTANT_QUALITY, ENH_LAYER_COUNT,
> +			BIT_RATE, MIN_QUALITY, VBV_DELAY,
> +			PEAK_BITRATE, SLICE_MODE},
> +		msm_vidc_adjust_bitrate_mode,
> +		msm_vidc_set_u32_enum},
> +
> +	{CONSTANT_QUALITY, ENC, HEVC,
> +		{0},
> +		NULL,
> +		msm_vidc_set_constant_quality},
> +
> +	{GOP_SIZE, ENC, CODECS_ALL,
> +		{ALL_INTRA},
> +		msm_vidc_adjust_gop_size,
> +		msm_vidc_set_gop_size},
> +
> +	{B_FRAME, ENC, H264 | HEVC,
> +		{ALL_INTRA},
> +		msm_vidc_adjust_b_frame,
> +		msm_vidc_set_u32},
> +
> +	{LTR_COUNT, ENC, H264 | HEVC,
> +		{0},
> +		msm_vidc_adjust_ltr_count,
> +		msm_vidc_set_u32},
> +
> +	{USE_LTR, ENC, H264 | HEVC,
> +		{0},
> +		msm_vidc_adjust_use_ltr,
> +		msm_vidc_set_use_and_mark_ltr},
> +
> +	{MARK_LTR, ENC, H264 | HEVC,
> +		{0},
> +		msm_vidc_adjust_mark_ltr,
> +		msm_vidc_set_use_and_mark_ltr},
> +
> +	{IR_PERIOD, ENC, H264 | HEVC,
> +		{0},
> +		msm_vidc_adjust_ir_period,
> +		msm_vidc_set_ir_period},
> +
> +	{AU_DELIMITER, ENC, H264 | HEVC,
> +		{0},
> +		NULL,
> +		msm_vidc_set_u32},
> +
> +	{MIN_QUALITY, ENC, H264,
> +		{0},
> +		msm_vidc_adjust_min_quality,
> +		msm_vidc_set_u32},
> +
> +	{MIN_QUALITY, ENC, HEVC,
> +		{0},
> +		msm_vidc_adjust_min_quality,
> +		msm_vidc_set_u32},
> +
> +	{VBV_DELAY, ENC, H264 | HEVC,
> +		{0},
> +		NULL,
> +		msm_vidc_set_cbr_related_properties},
> +
> +	{PEAK_BITRATE, ENC, H264 | HEVC,
> +		{0},
> +		msm_vidc_adjust_peak_bitrate,
> +		msm_vidc_set_cbr_related_properties},
> +
> +	{MIN_FRAME_QP, ENC, H264,
> +		{0},
> +		NULL,
> +		msm_vidc_set_min_qp},
> +
> +	{MIN_FRAME_QP, ENC, HEVC,
> +		{0},
> +		msm_vidc_adjust_hevc_min_qp,
> +		msm_vidc_set_min_qp},
> +
> +	{MAX_FRAME_QP, ENC, H264,
> +		{0},
> +		NULL,
> +		msm_vidc_set_max_qp},
> +
> +	{MAX_FRAME_QP, ENC, HEVC,
> +		{0},
> +		msm_vidc_adjust_hevc_max_qp,
> +		msm_vidc_set_max_qp},
> +
> +	{I_FRAME_QP, ENC, HEVC,
> +		{0},
> +		msm_vidc_adjust_hevc_i_frame_qp,
> +		msm_vidc_set_frame_qp},
> +
> +	{I_FRAME_QP, ENC, H264,
> +		{0},
> +		NULL,
> +		msm_vidc_set_frame_qp},
> +
> +	{P_FRAME_QP, ENC, HEVC,
> +		{0},
> +		msm_vidc_adjust_hevc_p_frame_qp,
> +		msm_vidc_set_frame_qp},
> +
> +	{P_FRAME_QP, ENC, H264,
> +		{0},
> +		NULL,
> +		msm_vidc_set_frame_qp},
> +
> +	{B_FRAME_QP, ENC, HEVC,
> +		{0},
> +		msm_vidc_adjust_hevc_b_frame_qp,
> +		msm_vidc_set_frame_qp},
> +
> +	{B_FRAME_QP, ENC, H264,
> +		{0},
> +		NULL,
> +		msm_vidc_set_frame_qp},
> +
> +	{LAYER_TYPE, ENC, H264 | HEVC,
> +		{LTR_COUNT}},
> +
> +	{LAYER_ENABLE, ENC, H264 | HEVC,
> +		{0}},
> +
> +	{ENH_LAYER_COUNT, ENC, H264 | HEVC,
> +		{GOP_SIZE, B_FRAME, BIT_RATE, MIN_QUALITY, SLICE_MODE,
> +			LTR_COUNT},
> +		msm_vidc_adjust_layer_count,
> +		msm_vidc_set_layer_count_and_type},
> +
> +	{L0_BR, ENC, H264 | HEVC,
> +		{L1_BR},
> +		msm_vidc_adjust_layer_bitrate,
> +		msm_vidc_set_layer_bitrate},
> +
> +	{L1_BR, ENC, H264 | HEVC,
> +		{L2_BR},
> +		msm_vidc_adjust_layer_bitrate,
> +		msm_vidc_set_layer_bitrate},
> +
> +	{L2_BR, ENC, H264 | HEVC,
> +		{L3_BR},
> +		msm_vidc_adjust_layer_bitrate,
> +		msm_vidc_set_layer_bitrate},
> +
> +	{L3_BR, ENC, H264 | HEVC,
> +		{L4_BR},
> +		msm_vidc_adjust_layer_bitrate,
> +		msm_vidc_set_layer_bitrate},
> +
> +	{L4_BR, ENC, H264 | HEVC,
> +		{L5_BR},
> +		msm_vidc_adjust_layer_bitrate,
> +		msm_vidc_set_layer_bitrate},
> +
> +	{L5_BR, ENC, H264 | HEVC,
> +		{0},
> +		msm_vidc_adjust_layer_bitrate,
> +		msm_vidc_set_layer_bitrate},
> +
> +	{ENTROPY_MODE, ENC, H264,
> +		{BIT_RATE},
> +		msm_vidc_adjust_entropy_mode,
> +		msm_vidc_set_u32},
> +
> +	{PROFILE, ENC, H264,
> +		{ENTROPY_MODE, TRANSFORM_8X8},
> +		NULL,
> +		msm_vidc_set_u32_enum},
> +
> +	{PROFILE, DEC, H264,
> +		{ENTROPY_MODE},
> +		NULL,
> +		msm_vidc_set_u32_enum},
> +
> +	{PROFILE, ENC | DEC, HEVC,
> +		{0},
> +		msm_vidc_adjust_profile,
> +		msm_vidc_set_u32_enum},
> +
> +	{PROFILE, DEC, VP9,
> +		{0},
> +		NULL,
> +		msm_vidc_set_u32_enum},
> +
> +	{LEVEL, DEC, CODECS_ALL,
> +		{0},
> +		NULL,
> +		msm_vidc_set_u32_enum},
> +
> +	{LEVEL, ENC, CODECS_ALL,
> +		{0},
> +		NULL,
> +		msm_vidc_set_level},
> +
> +	{HEVC_TIER, ENC | DEC, HEVC,
> +		{0},
> +		NULL,
> +		msm_vidc_set_u32_enum},
> +
> +	{LF_MODE, ENC, CODECS_ALL,
> +		{0},
> +		NULL,
> +		msm_vidc_set_deblock_mode},
> +
> +	{SLICE_MODE, ENC, H264 | HEVC,
> +		{STAGE},
> +		msm_vidc_adjust_slice_count,
> +		msm_vidc_set_slice_count},
> +
> +	{TRANSFORM_8X8, ENC, H264,
> +		{0},
> +		msm_vidc_adjust_transform_8x8,
> +		msm_vidc_set_u32},
> +
> +	{CHROMA_QP_INDEX_OFFSET, ENC, HEVC,
> +		{0},
> +		msm_vidc_adjust_chroma_qp_index_offset,
> +		msm_vidc_set_chroma_qp_index_offset},
> +
> +	{DISPLAY_DELAY_ENABLE, DEC, H264 | HEVC | VP9,
> +		{OUTPUT_ORDER},
> +		NULL,
> +		NULL},
> +
> +	{DISPLAY_DELAY, DEC, H264 | HEVC | VP9,
> +		{OUTPUT_ORDER},
> +		NULL,
> +		NULL},
> +
> +	{OUTPUT_ORDER, DEC, H264 | HEVC | VP9,
> +		{0},
> +		msm_vidc_adjust_output_order,
> +		msm_vidc_set_u32},
> +
> +	{INPUT_BUF_HOST_MAX_COUNT, ENC | DEC, CODECS_ALL,
> +		{0},
> +		msm_vidc_adjust_input_buf_host_max_count,
> +		msm_vidc_set_u32},
> +
> +	{INPUT_BUF_HOST_MAX_COUNT, ENC, H264 | HEVC,
> +		{0},
> +		msm_vidc_adjust_input_buf_host_max_count,
> +		msm_vidc_set_u32},
> +
> +	{OUTPUT_BUF_HOST_MAX_COUNT, ENC | DEC, CODECS_ALL,
> +		{0},
> +		msm_vidc_adjust_output_buf_host_max_count,
> +		msm_vidc_set_u32},
> +
> +	{OUTPUT_BUF_HOST_MAX_COUNT, ENC, H264 | HEVC,
> +		{0},
> +		msm_vidc_adjust_output_buf_host_max_count,
> +		msm_vidc_set_u32},
> +
> +	{CONCEAL_COLOR_8BIT, DEC, CODECS_ALL,
> +		{0},
> +		NULL,
> +		msm_vidc_set_u32_packed},
> +
> +	{CONCEAL_COLOR_10BIT, DEC, CODECS_ALL,
> +		{0},
> +		NULL,
> +		msm_vidc_set_u32_packed},
> +
> +	{STAGE, ENC | DEC, CODECS_ALL,
> +		{0},
> +		NULL,
> +		msm_vidc_set_stage},
> +
> +	{STAGE, ENC, H264 | HEVC,
> +		{0},
> +		NULL,
> +		msm_vidc_set_stage},
> +
> +	{STAGE, DEC, H264 | HEVC | VP9,
> +		{0},
> +		NULL,
> +		msm_vidc_set_stage},
> +
> +	{PIPE, DEC | ENC, CODECS_ALL,
> +		{0},
> +		NULL,
> +		msm_vidc_set_pipe},
> +
> +	{RAP_FRAME, DEC, CODECS_ALL,
> +		{0},
> +		NULL,
> +		msm_vidc_set_u32},
> +
> +	{ALL_INTRA, ENC, H264 | HEVC,
> +		{LTR_COUNT, IR_PERIOD, SLICE_MODE, BIT_RATE},
> +		msm_vidc_adjust_all_intra,
> +		NULL},
> +};
> +
> +/* Default UBWC config for LPDDR5 */
> +static struct msm_vidc_ubwc_config_data ubwc_config_sm8550[] = {
> +	UBWC_CONFIG(8, 32, 16, 0, 1, 1, 1),
> +};
> +
> +static struct msm_vidc_format_capability format_data_sm8550 = {
> +	.codec_info = codec_data_sm8550,
> +	.codec_info_size = ARRAY_SIZE(codec_data_sm8550),
> +	.color_format_info = color_format_data_sm8550,
> +	.color_format_info_size = ARRAY_SIZE(color_format_data_sm8550),
> +	.color_prim_info = color_primaries_data_sm8550,
> +	.color_prim_info_size = ARRAY_SIZE(color_primaries_data_sm8550),
> +	.transfer_char_info = transfer_char_data_sm8550,
> +	.transfer_char_info_size = ARRAY_SIZE(transfer_char_data_sm8550),
> +	.matrix_coeff_info = matrix_coeff_data_sm8550,
> +	.matrix_coeff_info_size = ARRAY_SIZE(matrix_coeff_data_sm8550),
> +};
> +
> +/* name, min_kbps, max_kbps */
> +static const struct bw_table sm8550_bw_table[] = {
> +	{ "venus-cnoc",  1000, 1000     },
> +	{ "venus-ddr",   1000, 15000000 },

We have OPP tables for that. There is no need to limit the min/max, just 
put it to OPP.

> +};
> +
> +/* name */
> +static const struct pd_table sm8550_pd_table[] = {
> +	{ "iris-ctl" },
> +	{ "vcodec"   },
> +};
> +
> +/* name */
> +static const char * const sm8550_opp_table[] = { "mx", "mmcx", NULL };
> +
> +/* name, clock id, scaling */
> +static const struct clk_table sm8550_clk_table[] = {
> +	{ "gcc_video_axi0",         GCC_VIDEO_AXI0_CLK,     0 },
> +	{ "core_clk",               VIDEO_CC_MVS0C_CLK,     0 },
> +	{ "vcodec_clk",             VIDEO_CC_MVS0_CLK,      1 },
> +};

This strucuture looks like a perfect candidate to be replaced by 
devm_clk_bulk_get_all().

> +
> +/* name, exclusive_release */
> +static const struct clk_rst_table sm8550_clk_reset_table[] = {
> +	{ "video_axi_reset",        0  },

Can we assume that resets are generic at least?

> +};
> +
> +/* name, start, size, secure, dma_coherant, region, dma_mask */
> +const struct context_bank_table sm8550_context_bank_table[] = {
> +	{"qcom,vidc,cb-ns", 0x25800000, 0xba800000, 0, 1, MSM_VIDC_NON_SECURE, 0xe0000000 - 1},
> +	{"qcom,vidc,cb-sec-non-pxl",   0x01000000, 0x24800000, 1, 0, MSM_VIDC_SECURE_NONPIXEL,  0 },

Aren't these a properties of subdevices? If so, why are you putting them 
here?

> +};
> +
> +/* freq */
> +static struct freq_table sm8550_freq_table[] = {
> +	{533333333}, {444000000}, {366000000}, {338000000}, {240000000}

OPP table contents.

> +};
> +
> +/* register, value, mask */
> +static const struct reg_preset_table sm8550_reg_preset_table[] = {
> +	{ 0xB0088, 0x0, 0x11 },
> +};
> +
> +/* decoder properties */
> +static const u32 sm8550_vdec_psc_avc[] = {
> +	HFI_PROP_BITSTREAM_RESOLUTION,
> +	HFI_PROP_CROP_OFFSETS,
> +	HFI_PROP_CODED_FRAMES,
> +	HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT,
> +	HFI_PROP_PIC_ORDER_CNT_TYPE,
> +	HFI_PROP_PROFILE,
> +	HFI_PROP_LEVEL,
> +	HFI_PROP_SIGNAL_COLOR_INFO,
> +};
> +
> +static const u32 sm8550_vdec_psc_hevc[] = {
> +	HFI_PROP_BITSTREAM_RESOLUTION,
> +	HFI_PROP_CROP_OFFSETS,
> +	HFI_PROP_LUMA_CHROMA_BIT_DEPTH,
> +	HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT,
> +	HFI_PROP_PROFILE,
> +	HFI_PROP_LEVEL,
> +	HFI_PROP_TIER,
> +	HFI_PROP_SIGNAL_COLOR_INFO,
> +};
> +
> +static const u32 sm8550_vdec_psc_vp9[] = {
> +	HFI_PROP_BITSTREAM_RESOLUTION,
> +	HFI_PROP_CROP_OFFSETS,
> +	HFI_PROP_LUMA_CHROMA_BIT_DEPTH,
> +	HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT,
> +	HFI_PROP_PROFILE,
> +	HFI_PROP_LEVEL,
> +};
> +
> +static const u32 sm8550_vdec_input_properties_avc[] = {
> +	HFI_PROP_NO_OUTPUT,
> +	HFI_PROP_SUBFRAME_INPUT,
> +};
> +
> +static const u32 sm8550_vdec_input_properties_hevc[] = {
> +	HFI_PROP_NO_OUTPUT,
> +	HFI_PROP_SUBFRAME_INPUT,
> +};
> +
> +static const u32 sm8550_vdec_input_properties_vp9[] = {
> +	HFI_PROP_NO_OUTPUT,
> +	HFI_PROP_SUBFRAME_INPUT,
> +};
> +
> +static const u32 sm8550_vdec_output_properties_avc[] = {
> +	HFI_PROP_WORST_COMPRESSION_RATIO,
> +	HFI_PROP_WORST_COMPLEXITY_FACTOR,
> +	HFI_PROP_PICTURE_TYPE,
> +	HFI_PROP_DPB_LIST,
> +	HFI_PROP_CABAC_SESSION,
> +};
> +
> +static const u32 sm8550_vdec_output_properties_hevc[] = {
> +	HFI_PROP_WORST_COMPRESSION_RATIO,
> +	HFI_PROP_WORST_COMPLEXITY_FACTOR,
> +	HFI_PROP_PICTURE_TYPE,
> +	HFI_PROP_DPB_LIST,
> +};
> +
> +static const u32 sm8550_vdec_output_properties_vp9[] = {
> +	HFI_PROP_WORST_COMPRESSION_RATIO,
> +	HFI_PROP_WORST_COMPLEXITY_FACTOR,
> +	HFI_PROP_PICTURE_TYPE,
> +	HFI_PROP_DPB_LIST,
> +};
> +
> +static const struct msm_vidc_platform_data sm8550_data = {
> +	/* resources dependent on other module */
> +	.bw_tbl = sm8550_bw_table,
> +	.bw_tbl_size = ARRAY_SIZE(sm8550_bw_table),
> +	.clk_tbl = sm8550_clk_table,
> +	.clk_tbl_size = ARRAY_SIZE(sm8550_clk_table),
> +	.clk_rst_tbl = sm8550_clk_reset_table,
> +	.clk_rst_tbl_size = ARRAY_SIZE(sm8550_clk_reset_table),
> +	.subcache_tbl = NULL,
> +	.subcache_tbl_size = 0,
> +
> +	/* populate context bank */
> +	.context_bank_tbl = sm8550_context_bank_table,
> +	.context_bank_tbl_size = ARRAY_SIZE(sm8550_context_bank_table),
> +
> +	/* populate power domain and opp table */
> +	.pd_tbl = sm8550_pd_table,
> +	.pd_tbl_size = ARRAY_SIZE(sm8550_pd_table),
> +	.opp_tbl = sm8550_opp_table,
> +	.opp_tbl_size = ARRAY_SIZE(sm8550_opp_table),
> +
> +	/* platform specific resources */
> +	.freq_tbl = sm8550_freq_table,
> +	.freq_tbl_size = ARRAY_SIZE(sm8550_freq_table),
> +	.reg_prst_tbl = sm8550_reg_preset_table,
> +	.reg_prst_tbl_size = ARRAY_SIZE(sm8550_reg_preset_table),
> +	.fwname = "vpu30_4v",
> +	.pas_id = 9,
> +
> +	/* caps related resorces */
> +	.core_data = core_data_sm8550,
> +	.core_data_size = ARRAY_SIZE(core_data_sm8550),
> +	.inst_cap_data = instance_cap_data_sm8550,
> +	.inst_cap_data_size = ARRAY_SIZE(instance_cap_data_sm8550),
> +	.inst_cap_dependency_data = instance_cap_dependency_data_sm8550,
> +	.inst_cap_dependency_data_size = ARRAY_SIZE(instance_cap_dependency_data_sm8550),
> +	.ubwc_config = ubwc_config_sm8550,
> +	.format_data = &format_data_sm8550,
> +
> +	/* decoder properties related*/
> +	.psc_avc_tbl = sm8550_vdec_psc_avc,
> +	.psc_avc_tbl_size = ARRAY_SIZE(sm8550_vdec_psc_avc),
> +	.psc_hevc_tbl = sm8550_vdec_psc_hevc,
> +	.psc_hevc_tbl_size = ARRAY_SIZE(sm8550_vdec_psc_hevc),
> +	.psc_vp9_tbl = sm8550_vdec_psc_vp9,
> +	.psc_vp9_tbl_size = ARRAY_SIZE(sm8550_vdec_psc_vp9),
> +	.dec_input_prop_avc = sm8550_vdec_input_properties_avc,
> +	.dec_input_prop_hevc = sm8550_vdec_input_properties_hevc,
> +	.dec_input_prop_vp9 = sm8550_vdec_input_properties_vp9,
> +	.dec_input_prop_size_avc = ARRAY_SIZE(sm8550_vdec_input_properties_avc),
> +	.dec_input_prop_size_hevc = ARRAY_SIZE(sm8550_vdec_input_properties_hevc),
> +	.dec_input_prop_size_vp9 = ARRAY_SIZE(sm8550_vdec_input_properties_vp9),
> +	.dec_output_prop_avc = sm8550_vdec_output_properties_avc,
> +	.dec_output_prop_hevc = sm8550_vdec_output_properties_hevc,
> +	.dec_output_prop_vp9 = sm8550_vdec_output_properties_vp9,
> +	.dec_output_prop_size_avc = ARRAY_SIZE(sm8550_vdec_output_properties_avc),
> +	.dec_output_prop_size_hevc = ARRAY_SIZE(sm8550_vdec_output_properties_hevc),
> +	.dec_output_prop_size_vp9 = ARRAY_SIZE(sm8550_vdec_output_properties_vp9),

Size should come next to the array reference.

> +};
> +
> +static int msm_vidc_init_data(struct msm_vidc_core *core)
> +{
> +	d_vpr_h("%s: initialize sm8550 data\n", __func__);
> +
> +	core->platform->data = sm8550_data;
> +

Please use of_device_match_data() instead.

> +	return 0;
> +}
> +
> +int msm_vidc_init_platform_sm8550(struct msm_vidc_core *core)
> +{
> +	return msm_vidc_init_data(core);
> +}
Dmitry Baryshkov July 28, 2023, 2:40 p.m. UTC | #5
On Fri, 28 Jul 2023 at 17:28, Vikash Garodia <quic_vgarodia@quicinc.com> wrote:
>
> From: Dikshita Agarwal <quic_dikshita@quicinc.com>
>
> This adds iris driver Makefile and Kconfig, also changes
> v4l2 platform/qcom Makefile/Kconfig in order to
> enable compilation of the driver.
>
> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
> Signed-off-by: Vikash Garodia <quic_vgarodia@quicinc.com>
> ---
>  drivers/media/platform/qcom/Kconfig       |  1 +
>  drivers/media/platform/qcom/Makefile      |  1 +
>  drivers/media/platform/qcom/iris/Kconfig  | 15 ++++++++++
>  drivers/media/platform/qcom/iris/Makefile | 46 +++++++++++++++++++++++++++++++
>  4 files changed, 63 insertions(+)
>  create mode 100644 drivers/media/platform/qcom/iris/Kconfig
>  create mode 100644 drivers/media/platform/qcom/iris/Makefile
>
> diff --git a/drivers/media/platform/qcom/Kconfig b/drivers/media/platform/qcom/Kconfig
> index cc5799b..b86bebd 100644
> --- a/drivers/media/platform/qcom/Kconfig
> +++ b/drivers/media/platform/qcom/Kconfig
> @@ -4,3 +4,4 @@ comment "Qualcomm media platform drivers"
>
>  source "drivers/media/platform/qcom/camss/Kconfig"
>  source "drivers/media/platform/qcom/venus/Kconfig"
> +source "drivers/media/platform/qcom/iris/Kconfig"
> diff --git a/drivers/media/platform/qcom/Makefile b/drivers/media/platform/qcom/Makefile
> index 4f055c3..83eea29 100644
> --- a/drivers/media/platform/qcom/Makefile
> +++ b/drivers/media/platform/qcom/Makefile
> @@ -1,3 +1,4 @@
>  # SPDX-License-Identifier: GPL-2.0-only
>  obj-y += camss/
>  obj-y += venus/
> +obj-y += iris/
> diff --git a/drivers/media/platform/qcom/iris/Kconfig b/drivers/media/platform/qcom/iris/Kconfig
> new file mode 100644
> index 0000000..d434c31
> --- /dev/null
> +++ b/drivers/media/platform/qcom/iris/Kconfig
> @@ -0,0 +1,15 @@
> +config VIDEO_QCOM_IRIS
> +       tristate "Qualcomm Iris V4L2 encoder/decoder driver"
> +       depends on V4L_MEM2MEM_DRIVERS
> +       depends on VIDEO_DEV && QCOM_SMEM
> +       depends on (ARCH_QCOM && IOMMU_DMA) || COMPILE_TEST
> +       select QCOM_MDT_LOADER if ARCH_QCOM
> +       select QCOM_SCM
> +       select VIDEOBUF2_DMA_CONTIG
> +       select V4L2_MEM2MEM_DEV
> +       select DMABUF_HEAPS
> +       help
> +         This is a V4L2 driver for Qualcomm Iris video accelerator
> +         hardware. It accelerates encoding and decoding operations
> +         on various Qualcomm SoCs.
> +         To compile this driver as a module choose m here.
> diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile
> new file mode 100644
> index 0000000..e681c4f
> --- /dev/null
> +++ b/drivers/media/platform/qcom/iris/Makefile
> @@ -0,0 +1,46 @@
> +KBUILD_OPTIONS+= VIDEO_ROOT=$(KERNEL_SRC)/$(M)
> +
> +VIDEO_COMPILE_TIME = $(shell date)
> +VIDEO_COMPILE_BY = $(shell whoami | sed 's/\\/\\\\/')
> +VIDEO_COMPILE_HOST = $(shell uname -n)
> +VIDEO_GEN_PATH = $(srctree)/$(src)/vidc/inc/video_generated_h
> +
> +$(shell echo '#define VIDEO_COMPILE_TIME "$(VIDEO_COMPILE_TIME)"' > $(VIDEO_GEN_PATH))
> +$(shell echo '#define VIDEO_COMPILE_BY "$(VIDEO_COMPILE_BY)"' >> $(VIDEO_GEN_PATH))
> +$(shell echo '#define VIDEO_COMPILE_HOST "$(VIDEO_COMPILE_HOST)"' >> $(VIDEO_GEN_PATH))

Why do you need this at all?

> +
> +iris-objs += vidc/src/msm_vidc_v4l2.o \
> +                  vidc/src/msm_vidc_vb2.o \
> +                  vidc/src/msm_vidc.o \
> +                  vidc/src/msm_vdec.o \
> +                  vidc/src/msm_venc.o \
> +                  vidc/src/msm_vidc_driver.o \
> +                  vidc/src/msm_vidc_control.o \
> +                  vidc/src/msm_vidc_buffer.o \
> +                  vidc/src/msm_vidc_power.o \
> +                  vidc/src/msm_vidc_probe.o \
> +                  vidc/src/resources.o \
> +                  vidc/src/firmware.o \
> +                  vidc/src/msm_vidc_debug.o \
> +                  vidc/src/msm_vidc_memory.o \
> +                  vidc/src/venus_hfi.o \
> +                  vidc/src/venus_hfi_queue.o \
> +                  vidc/src/hfi_packet.o \
> +                  vidc/src/venus_hfi_response.o \
> +                  vidc/src/msm_vidc_state.o \
> +                  platform/common/src/msm_vidc_platform.o \
> +                  platform/sm8550/src/msm_vidc_sm8550.o \
> +                  variant/common/src/msm_vidc_variant.o \
> +                  variant/iris3/src/msm_vidc_buffer_iris3.o \
> +                  variant/iris3/src/msm_vidc_iris3.o \
> +                  variant/iris3/src/msm_vidc_power_iris3.o \
> +                  variant/iris3/src/msm_vidc_bus_iris3.o \
> +                  variant/iris3/src/msm_vidc_clock_iris3.o
> +
> +obj-$(CONFIG_VIDEO_QCOM_IRIS) += iris.o
> +
> +ccflags-y += -I$(srctree)/$(src)/vidc/inc
> +ccflags-y += -I$(srctree)/$(src)/platform/common/inc
> +ccflags-y += -I$(srctree)/$(src)/platform/sm8550/inc
> +ccflags-y += -I$(srctree)/$(src)/variant/common/inc
> +ccflags-y += -I$(srctree)/$(src)/variant/iris3/inc

For me this is a sign of the bad structure of the include files.
Please define proper interfaces between submodules. The parts of the
driver usually should include files from the top-level dir only (and
from the local subdirectory of course).

> --
> 2.7.4
>
Bryan O'Donoghue July 28, 2023, 3:25 p.m. UTC | #6
On 28/07/2023 14:23, Vikash Garodia wrote:
> From: Dikshita Agarwal <quic_dikshita@quicinc.com>
> 
> This adds iris driver Makefile and Kconfig, also changes
> v4l2 platform/qcom Makefile/Kconfig in order to
> enable compilation of the driver.

This is not a meaningfully bisectable patch.

It should go with the addition of the driver. Its good practice to break 
up incremental changes to a driver in a series but, I don't see why you 
really need to do that when adding a whole new driver.

Just

- Documentation
- Bindings
- Driver code

On the other hand if you were switching on IRIS in the default defconfig 
then that should be a separate patch.

If we were say adding inter-frame power-collapse to the existing venus 
as part of a series, then that makes sense as a standalone patch but IMO 
when adding a whole new driver, add it as one.

Its easier to read that way

---
bod
Dmitry Baryshkov July 28, 2023, 3:51 p.m. UTC | #7
On 28/07/2023 18:25, Bryan O'Donoghue wrote:
> On 28/07/2023 14:23, Vikash Garodia wrote:
>> From: Dikshita Agarwal <quic_dikshita@quicinc.com>
>>
>> This adds iris driver Makefile and Kconfig, also changes
>> v4l2 platform/qcom Makefile/Kconfig in order to
>> enable compilation of the driver.
> 
> This is not a meaningfully bisectable patch.
> 
> It should go with the addition of the driver. Its good practice to break 
> up incremental changes to a driver in a series but, I don't see why you 
> really need to do that when adding a whole new driver.
> 
> Just
> 
> - Documentation
> - Bindings
> - Driver code
> 
> On the other hand if you were switching on IRIS in the default defconfig 
> then that should be a separate patch.
> 
> If we were say adding inter-frame power-collapse to the existing venus 
> as part of a series, then that makes sense as a standalone patch but IMO 
> when adding a whole new driver, add it as one.
> 
> Its easier to read that way

It wouldn't pass through mailing list filters.
Bryan O'Donoghue July 28, 2023, 3:58 p.m. UTC | #8
On 28/07/2023 14:23, Vikash Garodia wrote:
> +	rc = hfi_packet_sys_intraframe_powercollapse(core, core->packet,
> +						     core->packet_size, enable);
> +	if (rc)
> +		return rc;

I'm 99.9999999999 % sure this is misnamed.

"Inter" means in-between two things.
"Intra" means inside of one thing.

So "intraframe" means inside of one frame "interframe" would mean power 
collapsing in-between two frames, which is what I think this does.

And I'd still rather be adding inter-frame power-collapse to as many 
different versions of the existing silicon and new silicon as opposed to 
segregating it off in a new driver.

I'm assuming that more than sm8550 supports it since @ the end of the 
day this is a firmware feature to power-collapse during an active 
session when we aren't busy.

---
bod
Konrad Dybcio July 28, 2023, 5:21 p.m. UTC | #9
On 28.07.2023 15:23, Vikash Garodia wrote:
> This implements decoder functionalities of the driver.
> 
> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
> Signed-off-by: Vikash Garodia <quic_vgarodia@quicinc.com>
> ---
I see a whole bunch of shifts, ANDs, etc.

Please convert that to GENMASK + FIELD_PREP/FIELD_GET

Konrad
Nicolas Dufresne July 28, 2023, 5:38 p.m. UTC | #10
Hi Dmitry,

Le vendredi 28 juillet 2023 à 16:32 +0300, Dmitry Baryshkov a écrit :
> On 28/07/2023 16:23, Vikash Garodia wrote:
> > This patch series introduces support for Qualcomm new video acceleration
> > hardware architecture, used for video stream decoding/encoding. This driver
> > is based on new communication protocol between video hardware and application
> > processor.
> > 
> > This driver comes with below capabilities:
> > - V4L2 complaint video driver with M2M and STREAMING capability.
> > - Supports H264, H265, VP9 decoders.
> > - Supports H264, H265 encoders.
> > 
> > This driver comes with below features:
> > - Centralized resource and memory management.
> > - Centralized management of core and instance states.
> > - Defines platform specific capabilities and features. As a results, it provides
> >    a single point of control to enable/disable a given feature depending on
> >    specific platform capabilities.
> > - Handles hardware interdependent configurations. For a given configuration from
> >    client, the driver checks for hardware dependent configuration/s and updates
> >    the same.
> > - Handles multiple complex video scenarios involving state transitions - DRC,
> >    Drain, Seek, back to back DRC, DRC during Drain sequence, DRC during Seek
> >    sequence.
> > - Introduces a flexible way for driver to subscribe for any property with
> >    hardware. Hardware would inform driver with those subscribed property with any
> >    change in value.
> > - Introduces performance (clock and bus) model based on new hardware
> >    architecture.
> > - Introduces multi thread safe design to handle communication between client and
> >    hardware.
> > - Adapts encoder quality improvements available in new hardware architecture.
> > - Implements asynchronous communication with hardware to achieve better
> >    experience in low latency usecases.
> > - Supports multi stage hardware architecture for encode/decode.
> > - Output and capture planes are controlled independently. Thereby providing a
> >    way to reconfigure individual plane.
> > - Hardware packetization layer supports synchronization between configuration
> >    packet and data packet.
> > - Introduces a flexibility to receive a hardware response for a given command
> >    packet.
> > - Native hardware support of LAST flag which is mandatory to align with port
> >    reconfiguration and DRAIN sequence as per V4L guidelines.
> > - Native hardware support for drain sequence.
> > 
> > I think that the driver is in good shape for mainline kernel, and I hope the
> > review comments will help to improve it, so please do review, and make comments.
> 
> No bindings, no driver. Please post start the series from the bindings.

In your next iteration, make sure to include full v4l2-compliance report in your
cover letter since we cannot assume maintainers.

In addition to this, we now ask for fluster scores for each of your supported
decoders. We expect the results to have no timeout, and ideally the
error/failure explained (aka unsupported resolution, profile, subsampling, bit
depth, etc.). Note that inter-resolution change is not possible with V4L2 today,
so no need to explain why these VP9 tests fails. Fluster supports V4L2 decoding
through GStreamer (gst-launch + video4linux plugin) and FFMPEG at the moment. It
will run through ITU conformance vectors for HEVC and H.264, and run through
libvpx and and chromium test vectors for VP9.

https://github.com/fluendo/fluster

regards,
Nicolas

> 
> > 
> > Dikshita Agarwal (17):
> >    iris: vidc: add core functions
> >    iris: add vidc wrapper file
> >    iris: vidc: add vb2 ops
> >    iris: vidc: add helpers for memory management
> >    iris: vidc: add helper functions for resource management
> >    iris: vidc: add helper functions for power management
> >    iris: add helpers for media format
> >    iris: vidc: add PIL functionality for video firmware
> >    iris: platform: add platform files
> >    iris: platform: sm8550: add capability file for sm8550
> >    iris: variant: add helper functions for register handling
> >    iris: variant: iris3: add iris3 specific ops
> >    iris: variant: iris3: add helpers for buffer size calculations
> >    iris: variant: iris3: add helper for bus and clock calculation
> >    iris: variant: iris: implement the logic to compute bus bandwidth
> >    iris: variant: iris3: implement logic to compute clock frequency
> >    iris: enable building of iris video driver
> > 
> > Vikash Garodia (16):
> >    MAINTAINERS: Add Qualcomm Iris video accelerator driver
> >    iris: vidc: add v4l2 wrapper file
> >    iris: vidc: define video core and instance context
> >    iris: iris: add video encoder files
> >    iris: vidc: add video decoder files
> >    iris: vidc: add control files
> >    iris: vidc: add helper functions
> >    iris: vidc: add helpers for state management
> >    iris: add vidc buffer files
> >    iris: vidc: define various structures and enum
> >    iris: vidc: hfi: add Host Firmware Interface (HFI)
> >    iris: vidc: hfi: add Host Firmware Interface (HFI) response handling
> >    iris: vidc: hfi: add helpers for handling shared queues
> >    iris: vidc: hfi: Add packetization layer
> >    iris: vidc: hfi: defines HFI properties and enums
> >    iris: vidc: add debug files
> > 
> >   MAINTAINERS                                        |   10 +
> >   drivers/media/platform/qcom/Kconfig                |    1 +
> >   drivers/media/platform/qcom/Makefile               |    1 +
> >   drivers/media/platform/qcom/iris/Kconfig           |   15 +
> >   drivers/media/platform/qcom/iris/Makefile          |   46 +
> >   .../iris/platform/common/inc/msm_vidc_platform.h   |  305 ++
> >   .../iris/platform/common/src/msm_vidc_platform.c   | 2499 ++++++++++++
> >   .../iris/platform/sm8550/inc/msm_vidc_sm8550.h     |   14 +
> >   .../iris/platform/sm8550/src/msm_vidc_sm8550.c     | 1727 ++++++++
> >   .../iris/variant/common/inc/msm_vidc_variant.h     |   22 +
> >   .../iris/variant/common/src/msm_vidc_variant.c     |  163 +
> >   .../qcom/iris/variant/iris3/inc/hfi_buffer_iris3.h | 1481 +++++++
> >   .../iris/variant/iris3/inc/msm_vidc_buffer_iris3.h |   19 +
> >   .../qcom/iris/variant/iris3/inc/msm_vidc_iris3.h   |   15 +
> >   .../iris/variant/iris3/inc/msm_vidc_power_iris3.h  |   17 +
> >   .../iris/variant/iris3/inc/perf_static_model.h     |  229 ++
> >   .../iris/variant/iris3/src/msm_vidc_buffer_iris3.c |  595 +++
> >   .../iris/variant/iris3/src/msm_vidc_bus_iris3.c    |  884 ++++
> >   .../iris/variant/iris3/src/msm_vidc_clock_iris3.c  |  627 +++
> >   .../qcom/iris/variant/iris3/src/msm_vidc_iris3.c   |  954 +++++
> >   .../iris/variant/iris3/src/msm_vidc_power_iris3.c  |  345 ++
> >   .../media/platform/qcom/iris/vidc/inc/firmware.h   |   18 +
> >   .../platform/qcom/iris/vidc/inc/hfi_command.h      |  190 +
> >   .../media/platform/qcom/iris/vidc/inc/hfi_packet.h |   52 +
> >   .../platform/qcom/iris/vidc/inc/hfi_property.h     |  666 +++
> >   .../platform/qcom/iris/vidc/inc/msm_media_info.h   |  599 +++
> >   .../media/platform/qcom/iris/vidc/inc/msm_vdec.h   |   40 +
> >   .../media/platform/qcom/iris/vidc/inc/msm_venc.h   |   34 +
> >   .../media/platform/qcom/iris/vidc/inc/msm_vidc.h   |   60 +
> >   .../platform/qcom/iris/vidc/inc/msm_vidc_buffer.h  |   32 +
> >   .../platform/qcom/iris/vidc/inc/msm_vidc_control.h |   26 +
> >   .../platform/qcom/iris/vidc/inc/msm_vidc_core.h    |  165 +
> >   .../platform/qcom/iris/vidc/inc/msm_vidc_debug.h   |  186 +
> >   .../platform/qcom/iris/vidc/inc/msm_vidc_driver.h  |  352 ++
> >   .../platform/qcom/iris/vidc/inc/msm_vidc_inst.h    |  207 +
> >   .../qcom/iris/vidc/inc/msm_vidc_internal.h         |  787 ++++
> >   .../platform/qcom/iris/vidc/inc/msm_vidc_memory.h  |   83 +
> >   .../platform/qcom/iris/vidc/inc/msm_vidc_power.h   |   94 +
> >   .../platform/qcom/iris/vidc/inc/msm_vidc_state.h   |  102 +
> >   .../platform/qcom/iris/vidc/inc/msm_vidc_v4l2.h    |   77 +
> >   .../platform/qcom/iris/vidc/inc/msm_vidc_vb2.h     |   39 +
> >   .../media/platform/qcom/iris/vidc/inc/resources.h  |  259 ++
> >   .../media/platform/qcom/iris/vidc/inc/venus_hfi.h  |   66 +
> >   .../platform/qcom/iris/vidc/inc/venus_hfi_queue.h  |   89 +
> >   .../qcom/iris/vidc/inc/venus_hfi_response.h        |   26 +
> >   .../media/platform/qcom/iris/vidc/src/firmware.c   |  294 ++
> >   .../media/platform/qcom/iris/vidc/src/hfi_packet.c |  657 +++
> >   .../media/platform/qcom/iris/vidc/src/msm_vdec.c   | 2091 ++++++++++
> >   .../media/platform/qcom/iris/vidc/src/msm_venc.c   | 1484 +++++++
> >   .../media/platform/qcom/iris/vidc/src/msm_vidc.c   |  841 ++++
> >   .../platform/qcom/iris/vidc/src/msm_vidc_buffer.c  |  290 ++
> >   .../platform/qcom/iris/vidc/src/msm_vidc_control.c |  824 ++++
> >   .../platform/qcom/iris/vidc/src/msm_vidc_debug.c   |  581 +++
> >   .../platform/qcom/iris/vidc/src/msm_vidc_driver.c  | 4276 ++++++++++++++++++++
> >   .../platform/qcom/iris/vidc/src/msm_vidc_memory.c  |  448 ++
> >   .../platform/qcom/iris/vidc/src/msm_vidc_power.c   |  560 +++
> >   .../platform/qcom/iris/vidc/src/msm_vidc_probe.c   |  660 +++
> >   .../platform/qcom/iris/vidc/src/msm_vidc_state.c   | 1607 ++++++++
> >   .../platform/qcom/iris/vidc/src/msm_vidc_v4l2.c    |  953 +++++
> >   .../platform/qcom/iris/vidc/src/msm_vidc_vb2.c     |  605 +++
> >   .../media/platform/qcom/iris/vidc/src/resources.c  | 1321 ++++++
> >   .../media/platform/qcom/iris/vidc/src/venus_hfi.c  | 1503 +++++++
> >   .../platform/qcom/iris/vidc/src/venus_hfi_queue.c  |  537 +++
> >   .../qcom/iris/vidc/src/venus_hfi_response.c        | 1607 ++++++++
> >   64 files changed, 35357 insertions(+)
> >   create mode 100644 drivers/media/platform/qcom/iris/Kconfig
> >   create mode 100644 drivers/media/platform/qcom/iris/Makefile
> >   create mode 100644 drivers/media/platform/qcom/iris/platform/common/inc/msm_vidc_platform.h
> >   create mode 100644 drivers/media/platform/qcom/iris/platform/common/src/msm_vidc_platform.c
> >   create mode 100644 drivers/media/platform/qcom/iris/platform/sm8550/inc/msm_vidc_sm8550.h
> >   create mode 100644 drivers/media/platform/qcom/iris/platform/sm8550/src/msm_vidc_sm8550.c
> >   create mode 100644 drivers/media/platform/qcom/iris/variant/common/inc/msm_vidc_variant.h
> >   create mode 100644 drivers/media/platform/qcom/iris/variant/common/src/msm_vidc_variant.c
> >   create mode 100644 drivers/media/platform/qcom/iris/variant/iris3/inc/hfi_buffer_iris3.h
> >   create mode 100644 drivers/media/platform/qcom/iris/variant/iris3/inc/msm_vidc_buffer_iris3.h
> >   create mode 100644 drivers/media/platform/qcom/iris/variant/iris3/inc/msm_vidc_iris3.h
> >   create mode 100644 drivers/media/platform/qcom/iris/variant/iris3/inc/msm_vidc_power_iris3.h
> >   create mode 100644 drivers/media/platform/qcom/iris/variant/iris3/inc/perf_static_model.h
> >   create mode 100644 drivers/media/platform/qcom/iris/variant/iris3/src/msm_vidc_buffer_iris3.c
> >   create mode 100644 drivers/media/platform/qcom/iris/variant/iris3/src/msm_vidc_bus_iris3.c
> >   create mode 100644 drivers/media/platform/qcom/iris/variant/iris3/src/msm_vidc_clock_iris3.c
> >   create mode 100644 drivers/media/platform/qcom/iris/variant/iris3/src/msm_vidc_iris3.c
> >   create mode 100644 drivers/media/platform/qcom/iris/variant/iris3/src/msm_vidc_power_iris3.c
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/firmware.h
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/hfi_command.h
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/hfi_packet.h
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/hfi_property.h
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_media_info.h
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vdec.h
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_venc.h
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc.h
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_buffer.h
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_control.h
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_core.h
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_debug.h
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_driver.h
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_inst.h
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_internal.h
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_memory.h
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_power.h
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_state.h
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_v4l2.h
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_vb2.h
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/resources.h
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/venus_hfi.h
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/venus_hfi_queue.h
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/venus_hfi_response.h
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/firmware.c
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/hfi_packet.c
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vdec.c
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_venc.c
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc.c
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_buffer.c
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_control.c
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_debug.c
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_driver.c
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_memory.c
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_power.c
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_probe.c
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_state.c
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_v4l2.c
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_vb2.c
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/resources.c
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/venus_hfi.c
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/venus_hfi_queue.c
> >   create mode 100644 drivers/media/platform/qcom/iris/vidc/src/venus_hfi_response.c
> > 
>
Krzysztof Kozlowski July 31, 2023, 9:23 p.m. UTC | #11
On 28/07/2023 15:23, Vikash Garodia wrote:
> Here is the implementation of v4l2 wrapper functions for all
> v4l2 IOCTLs.
> 
> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
> Signed-off-by: Vikash Garodia <quic_vgarodia@quicinc.com>
> ---
>  .../platform/qcom/iris/vidc/inc/msm_vidc_v4l2.h    |  77 ++
>  .../platform/qcom/iris/vidc/src/msm_vidc_v4l2.c    | 953 +++++++++++++++++++++
>  2 files changed, 1030 insertions(+)
>  create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_v4l2.h
>  create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_v4l2.c
> 
> diff --git a/drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_v4l2.h b/drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_v4l2.h
> new file mode 100644
> index 0000000..3766c9d
> --- /dev/null
> +++ b/drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_v4l2.h
> @@ -0,0 +1,77 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
> + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
> + */
> +
> +#ifndef _MSM_VIDC_V4L2_H_
> +#define _MSM_VIDC_V4L2_H_
> +
> +#include <linux/fs.h>
> +#include <linux/poll.h>
> +#include <media/v4l2-ctrls.h>
> +#include <media/v4l2-dev.h>
> +#include <media/v4l2-ioctl.h>
> +
> +int msm_v4l2_open(struct file *filp);
> +int msm_v4l2_close(struct file *filp);
> +int msm_v4l2_querycap(struct file *filp, void *fh,
> +		      struct v4l2_capability *cap);
> +int msm_v4l2_enum_fmt(struct file *file, void *fh,
> +		      struct v4l2_fmtdesc *f);
> +int msm_v4l2_try_fmt(struct file *file, void *fh,
> +		     struct v4l2_format *f);
> +int msm_v4l2_s_fmt(struct file *file, void *fh,
> +		   struct v4l2_format *f);
> +int msm_v4l2_g_fmt(struct file *file, void *fh,
> +		   struct v4l2_format *f);
> +int msm_v4l2_s_selection(struct file *file, void *fh,
> +			 struct v4l2_selection *s);
> +int msm_v4l2_g_selection(struct file *file, void *fh,
> +			 struct v4l2_selection *s);
> +int msm_v4l2_s_parm(struct file *file, void *fh,
> +		    struct v4l2_streamparm *a);
> +int msm_v4l2_g_parm(struct file *file, void *fh,
> +		    struct v4l2_streamparm *a);
> +int msm_v4l2_reqbufs(struct file *file, void *fh,
> +		     struct v4l2_requestbuffers *b);
> +int msm_v4l2_querybuf(struct file *file, void *fh,
> +		      struct v4l2_buffer *b);
> +int msm_v4l2_create_bufs(struct file *filp, void *fh,
> +			 struct v4l2_create_buffers *b);
> +int msm_v4l2_prepare_buf(struct file *filp, void *fh,
> +			 struct v4l2_buffer *b);
> +int msm_v4l2_qbuf(struct file *file, void *fh,
> +		  struct v4l2_buffer *b);
> +int msm_v4l2_dqbuf(struct file *file, void *fh,
> +		   struct v4l2_buffer *b);
> +int msm_v4l2_streamon(struct file *file, void *fh,
> +		      enum v4l2_buf_type i);
> +int msm_v4l2_streamoff(struct file *file, void *fh,
> +		       enum v4l2_buf_type i);
> +int msm_v4l2_subscribe_event(struct v4l2_fh *fh,
> +			     const struct v4l2_event_subscription *sub);
> +int msm_v4l2_unsubscribe_event(struct v4l2_fh *fh,
> +			       const struct v4l2_event_subscription *sub);
> +int msm_v4l2_try_decoder_cmd(struct file *file, void *fh,
> +			     struct v4l2_decoder_cmd *enc);
> +int msm_v4l2_decoder_cmd(struct file *file, void *fh,
> +			 struct v4l2_decoder_cmd *dec);
> +int msm_v4l2_try_encoder_cmd(struct file *file, void *fh,
> +			     struct v4l2_encoder_cmd *enc);
> +int msm_v4l2_encoder_cmd(struct file *file, void *fh,
> +			 struct v4l2_encoder_cmd *enc);
> +int msm_v4l2_enum_framesizes(struct file *file, void *fh,
> +			     struct v4l2_frmsizeenum *fsize);
> +int msm_v4l2_enum_frameintervals(struct file *file, void *fh,
> +				 struct v4l2_frmivalenum *fival);
> +int msm_v4l2_queryctrl(struct file *file, void *fh,
> +		       struct v4l2_queryctrl *ctrl);
> +int msm_v4l2_querymenu(struct file *file, void *fh,
> +		       struct v4l2_querymenu *qmenu);
> +unsigned int msm_v4l2_poll(struct file *filp,
> +			   struct poll_table_struct *pt);
> +void msm_v4l2_m2m_device_run(void *priv);
> +void msm_v4l2_m2m_job_abort(void *priv);
> +
> +#endif // _MSM_VIDC_V4L2_H_
> diff --git a/drivers/media/platform/qcom/iris/vidc/src/msm_vidc_v4l2.c b/drivers/media/platform/qcom/iris/vidc/src/msm_vidc_v4l2.c
> new file mode 100644
> index 0000000..6dfb18b
> --- /dev/null
> +++ b/drivers/media/platform/qcom/iris/vidc/src/msm_vidc_v4l2.c
> @@ -0,0 +1,953 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
> + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
> + */
> +
> +#include "msm_vidc.h"
> +#include "msm_vidc_core.h"
> +#include "msm_vidc_debug.h"
> +#include "msm_vidc_driver.h"
> +#include "msm_vidc_inst.h"
> +#include "msm_vidc_internal.h"
> +#include "msm_vidc_v4l2.h"
> +
> +static struct msm_vidc_inst *get_vidc_inst(struct file *filp, void *fh)
> +{
> +	if (!filp || !filp->private_data)
> +		return NULL;
> +	return container_of(filp->private_data,
> +					struct msm_vidc_inst, fh);
> +}
> +
> +unsigned int msm_v4l2_poll(struct file *filp, struct poll_table_struct *pt)
> +{
> +	int poll = 0;
> +	struct msm_vidc_inst *inst = get_vidc_inst(filp, NULL);
> +
> +	inst = get_inst_ref(g_core, inst);
> +	if (!inst) {
> +		d_vpr_e("%s: invalid instance\n", __func__);

This does not look like Linux coding style. Don't create your own
abstraction layer over Linux internal API. Use standard Linux functions
which will behave better and scale along with kernel development.

> +		return POLLERR;
> +	}
> +	if (is_session_error(inst)) {
> +		i_vpr_e(inst, "%s: inst in error state\n", __func__);

i_vpr_e is so obvious for every kernel developer... Please, no.

> +		poll = POLLERR;
> +		goto exit;
> +	}
> +
> +	poll = msm_vidc_poll((void *)inst, filp, pt);
> +	if (poll)
> +		goto exit;
> +
> +exit:
> +	put_inst(inst);
> +	return poll;
> +}
> +
> +int msm_v4l2_open(struct file *filp)
> +{
> +	struct video_device *vdev = video_devdata(filp);
> +	struct msm_video_device *vid_dev =
> +		container_of(vdev, struct msm_video_device, vdev);
> +	struct msm_vidc_core *core = video_drvdata(filp);
> +	struct msm_vidc_inst *inst;
> +
> +	inst = msm_vidc_open(core, vid_dev->type);
> +	if (!inst) {
> +		d_vpr_e("Failed to create instance, type = %d\n",
> +			vid_dev->type);
> +		return -ENOMEM;
> +	}
> +	filp->private_data = &inst->fh;
> +	return 0;
> +}
> +
> +int msm_v4l2_close(struct file *filp)
> +{
> +	int rc = 0;
> +	struct msm_vidc_inst *inst;
> +
> +	inst = get_vidc_inst(filp, NULL);
> +	if (!inst) {
> +		d_vpr_e("%s: invalid instance\n", __func__);
> +		return -EINVAL;
> +	}
> +
> +	rc = msm_vidc_close(inst);
> +	filp->private_data = NULL;
> +	return rc;
> +}
> +
> +int msm_v4l2_querycap(struct file *filp, void *fh,
> +		      struct v4l2_capability *cap)
> +{
> +	struct msm_vidc_inst *inst = get_vidc_inst(filp, fh);
> +	int rc = 0;
> +
> +	inst = get_inst_ref(g_core, inst);
> +	if (!inst || !cap) {
> +		d_vpr_e("%s: invalid instance\n", __func__);
> +		return -EINVAL;
> +	}
> +
> +	client_lock(inst, __func__);

? So we don't know what's this? Mutex? Spinlock? Own reinvented lock?

> +	inst_lock(inst, __func__);

Neither this?

No, don't create your own abstractions over standard API.

Best regards,
Krzysztof
Stanimir Varbanov Aug. 14, 2023, 12:58 p.m. UTC | #12
Hi Dmitry,

On 28.07.23 г. 17:01 ч., Dmitry Baryshkov wrote:
> On 28/07/2023 16:23, Vikash Garodia wrote:
>> This patch series introduces support for Qualcomm new video acceleration
>> hardware architecture, used for video stream decoding/encoding. This 
>> driver
>> is based on new communication protocol between video hardware and 
>> application
>> processor.
>>
>> This driver comes with below capabilities:
>> - V4L2 complaint video driver with M2M and STREAMING capability.
>> - Supports H264, H265, VP9 decoders.
>> - Supports H264, H265 encoders.
> 
> Please describe, why is it impossible to support this hardware in the 
> venus driver. We do not usually add new drivers for the new generations 
> of the hardware, unless it is fully incompatible with the previous 
> generations. Let me point you to camss or drm/msm drivers. They have 
> successfully solved the issue of supporting multiple generations of the 
> hardware in the same driver.
> 
> Unless the "iris3" is completely different from all the previous 
> generations, I strongly suggest spending time on restructuring existing 
> venus driver and then adding support for the new hardware there instead 
> of dumping out something completely new.

AFAIK the major differences are HW IP and firmware interface (by 
firmware interface I mean a protocol, API and API behavior). The 
firmware and its interface has been re-written to align closely with the 
current v4l2 specs for encoders/decoders state machines [1][2]. On the 
other side current mainline Venus driver firmware is following interface 
similar to OpenMAX.

There are incompatibilities between both firmware interfaces which 
cannot easily combined in a common driver. Even if there is a 
possibility to do that it will lead us to a unreadable driver source 
code and maintenance burden.

Vikash, could elaborate more on firmware interface differences.

[1] 
https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/dev-decoder.html

[2] 
https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/dev-encoder.html
Dmitry Baryshkov Aug. 14, 2023, 3 p.m. UTC | #13
Hi Stan,

On Mon, 14 Aug 2023 at 15:58, Stanimir Varbanov
<stanimir.k.varbanov@gmail.com> wrote:
>
> Hi Dmitry,
>
> On 28.07.23 г. 17:01 ч., Dmitry Baryshkov wrote:
> > On 28/07/2023 16:23, Vikash Garodia wrote:
> >> This patch series introduces support for Qualcomm new video acceleration
> >> hardware architecture, used for video stream decoding/encoding. This
> >> driver
> >> is based on new communication protocol between video hardware and
> >> application
> >> processor.
> >>
> >> This driver comes with below capabilities:
> >> - V4L2 complaint video driver with M2M and STREAMING capability.
> >> - Supports H264, H265, VP9 decoders.
> >> - Supports H264, H265 encoders.
> >
> > Please describe, why is it impossible to support this hardware in the
> > venus driver. We do not usually add new drivers for the new generations
> > of the hardware, unless it is fully incompatible with the previous
> > generations. Let me point you to camss or drm/msm drivers. They have
> > successfully solved the issue of supporting multiple generations of the
> > hardware in the same driver.
> >
> > Unless the "iris3" is completely different from all the previous
> > generations, I strongly suggest spending time on restructuring existing
> > venus driver and then adding support for the new hardware there instead
> > of dumping out something completely new.
>
> AFAIK the major differences are HW IP and firmware interface (by
> firmware interface I mean a protocol, API and API behavior). The
> firmware and its interface has been re-written to align closely with the
> current v4l2 specs for encoders/decoders state machines [1][2]. On the
> other side current mainline Venus driver firmware is following interface
> similar to OpenMAX.
>
> There are incompatibilities between both firmware interfaces which
> cannot easily combined in a common driver. Even if there is a
> possibility to do that it will lead us to a unreadable driver source
> code and maintenance burden.

Thank you for your explanation!

If the hardware is more or less the same, then the existing venus
driver should be refactored and split into hardware driver and the
firmware interface. Then iris3 can come up as a second driver
implementing support for new firmware interface but utilising common
hardware-related code.

> Vikash, could elaborate more on firmware interface differences.

Do we have any details on firmware versions that implement older
(OpenMAX-like) interface vs versions implementing new (v4l2-like)
interface?

> [1]
> https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/dev-decoder.html
>
> [2]
> https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/dev-encoder.html
Dikshita Agarwal Aug. 14, 2023, 6:49 p.m. UTC | #14
On 7/28/2023 7:15 PM, Konrad Dybcio wrote:
> On 28.07.2023 15:23, Vikash Garodia wrote:
>> From: Dikshita Agarwal <quic_dikshita@quicinc.com>
>>
>> This implements the platform driver methods, file
>> operations and v4l2 registration.
>>
>> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
>> Signed-off-by: Vikash Garodia <quic_vgarodia@quicinc.com>
>> ---
> [...]
> 
>> +struct msm_vidc_core *g_core;
>> +
>> +static inline bool is_video_device(struct device *dev)
>> +{
>> +	return !!(of_device_is_compatible(dev->of_node, "qcom,sm8550-vidc"));
>> +}
> Are you expecting this to be expanded each time support for new SoC is added?
> 
I understand the concern here.
Will remove this API in next version.
>> +
>> +static inline bool is_video_context_bank_device(struct device *dev)
>> +{
>> +	return !!(of_device_is_compatible(dev->of_node, "qcom,vidc,cb-ns"));
>> +}
>> +
>> +static int msm_vidc_init_resources(struct msm_vidc_core *core)
>> +{
>> +	struct msm_vidc_resource *res = NULL;
> No need to initialize, you use it right after defining.
Agree, will remove.
> 
>> +	int rc = 0;
> I think 'ret' is more common for a return-value-holding variable.
> 
Agree, will replace 'rc' with 'ret' in all APIs in next version
>> +
>> +	res = devm_kzalloc(&core->pdev->dev, sizeof(*res), GFP_KERNEL);
>> +	if (!res) {
>> +		d_vpr_e("%s: failed to alloc memory for resource\n", __func__);
>> +		return -ENOMEM;
>> +	}
>> +	core->resource = res;
> I don't think the 'res' variable makes sense.
> 
Sure, Will update, res->resource
>> +
>> +	rc = call_res_op(core, init, core);
>> +	if (rc) {
>> +		d_vpr_e("%s: Failed to init resources: %d\n", __func__, rc);
>> +		return rc;
> you can omit this line and return rc/ret at the last line of this func.
> 
The abstraction layer for resource is not required so this API will be
changed in next version, will take care of return values as well.
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct of_device_id msm_vidc_dt_match[] = {
>> +	{.compatible = "qcom,sm8550-vidc"},
> { .compatible = .... " },
> 
>> +	{.compatible = "qcom,vidc,cb-ns"},
>> +	MSM_VIDC_EMPTY_BRACE
> why?
> 
Right, it's not needed, Will replace with {}
>> +};
>> +MODULE_DEVICE_TABLE(of, msm_vidc_dt_match);
>> +
>> +static void msm_vidc_release_video_device(struct video_device *vdev)
>> +{
>> +	d_vpr_e("%s: video device released\n", __func__);
>> +}
> Doesn't sound too useful? And definitely not with an error print?
> 
The device structure is embedded in the core structure, so driver needs to
set the release() callback. hence this API is required.
This API doesn't free anything here because the core struture will be freed
when device is removed.
Will remove error print in next version.
>> +
>> +static void msm_vidc_unregister_video_device(struct msm_vidc_core *core,
>> +					     enum msm_vidc_domain_type type)
>> +{
>> +	int index;
>> +
>> +	if (type == MSM_VIDC_DECODER)
> I'm not sure this is defined.
> 
>> +		index = 0;
>> +	else if (type == MSM_VIDC_ENCODER)
> Or this.
> 
These macros are defined in [1]

[1]:
https://patchwork.linuxtv.org/project/linux-media/patch/1690550624-14642-18-git-send-email-quic_vgarodia@quicinc.com/

> Can't we just assign index = MSM_VIDC_EN/DECODER?
> these are bitmasks hence can not be used as array index and the bitmask
values are being used in driver at multiple places.
>> +		index = 1;
>> +	else
>> +		return;
>> +
>> +	v4l2_m2m_release(core->vdev[index].m2m_dev);
>> +
>> +	video_set_drvdata(&core->vdev[index].vdev, NULL);
>> +	video_unregister_device(&core->vdev[index].vdev);
>> +}
>> +
>> +static int msm_vidc_register_video_device(struct msm_vidc_core *core,
>> +					  enum msm_vidc_domain_type type, int nr)
>> +{
>> +	int rc = 0;
>> +	int index;
>> +
>> +	d_vpr_h("%s: domain %d\n", __func__, type);
>> +
>> +	if (type == MSM_VIDC_DECODER)
>> +		index = 0;
>> +	else if (type == MSM_VIDC_ENCODER)
>> +		index = 1;
>> +	else
>> +		return -EINVAL;
>> +
>> +	core->vdev[index].vdev.release =
>> +		msm_vidc_release_video_device;
>> +	core->vdev[index].vdev.fops = core->v4l2_file_ops;
>> +	if (type == MSM_VIDC_DECODER)
>> +		core->vdev[index].vdev.ioctl_ops = core->v4l2_ioctl_ops_dec;
>> +	else
>> +		core->vdev[index].vdev.ioctl_ops = core->v4l2_ioctl_ops_enc;
>> +	core->vdev[index].vdev.vfl_dir = VFL_DIR_M2M;
>> +	core->vdev[index].type = type;
>> +	core->vdev[index].vdev.v4l2_dev = &core->v4l2_dev;
>> +	core->vdev[index].vdev.device_caps = core->capabilities[DEVICE_CAPS].value;
>> +	rc = video_register_device(&core->vdev[index].vdev,
>> +				   VFL_TYPE_VIDEO, nr);
>> +	if (rc) {
>> +		d_vpr_e("Failed to register the video device\n");
>> +		return rc;
>> +	}
>> +	video_set_drvdata(&core->vdev[index].vdev, core);
>> +
>> +	core->vdev[index].m2m_dev = v4l2_m2m_init(core->v4l2_m2m_ops);
>> +	if (IS_ERR(core->vdev[index].m2m_dev)) {
>> +		d_vpr_e("Failed to initialize V4L2 M2M device\n");
>> +		rc = PTR_ERR(core->vdev[index].m2m_dev);
>> +		goto m2m_init_failed;
>> +	}
>> +
>> +	return 0;
>> +
>> +m2m_init_failed:
>> +	video_unregister_device(&core->vdev[index].vdev);
>> +	return rc;
>> +}
>> +
>> +static int msm_vidc_deinitialize_core(struct msm_vidc_core *core)
>> +{
>> +	int rc = 0;
>> +
>> +	if (!core) {
> Are we expecting to ever hit this?
> 
True, it's highly unlikely that we hit this, will remove the check.
>> +		d_vpr_e("%s: invalid params\n", __func__);
>> +		return -EINVAL;
>> +	}
>> +
>> +	mutex_destroy(&core->lock);
>> +	msm_vidc_update_core_state(core, MSM_VIDC_CORE_DEINIT, __func__);
> Not defined.
> 
it is defined in [2]

>> +
>> +	if (core->batch_workq)
>> +		destroy_workqueue(core->batch_workq);
>> +
>> +	if (core->pm_workq)
>> +		destroy_workqueue(core->pm_workq);
>> +
>> +	core->batch_workq = NULL;
>> +	core->pm_workq = NULL;
>> +
>> +	return rc;
>> +}
>> +
>> +static int msm_vidc_initialize_core(struct msm_vidc_core *core)
>> +{
>> +	int rc = 0;
>> +
>> +	msm_vidc_update_core_state(core, MSM_VIDC_CORE_DEINIT, __func__);
> Not defined.
> 
it is defined in [2]

[2]:
https://patchwork.linuxtv.org/project/linux-media/patch/1690550624-14642-15-git-send-email-quic_vgarodia@quicinc.com/
>> +
>> +	core->pm_workq = create_singlethread_workqueue("pm_workq");
>> +	if (!core->pm_workq) {
>> +		d_vpr_e("%s: create pm workq failed\n", __func__);
>> +		rc = -EINVAL;
>> +		goto exit;
>> +	}
>> +
>> +	core->batch_workq = create_singlethread_workqueue("batch_workq");
>> +	if (!core->batch_workq) {
>> +		d_vpr_e("%s: create batch workq failed\n", __func__);
>> +		rc = -EINVAL;
>> +		goto exit;
>> +	}
>> +
>> +	core->packet_size = VIDC_IFACEQ_VAR_HUGE_PKT_SIZE;
>> +	core->packet = devm_kzalloc(&core->pdev->dev, core->packet_size, GFP_KERNEL);
>> +	if (!core->packet) {
>> +		d_vpr_e("%s: failed to alloc core packet\n", __func__);
>> +		rc = -ENOMEM;
>> +		goto exit;
>> +	}
>> +
>> +	core->response_packet = devm_kzalloc(&core->pdev->dev, core->packet_size, GFP_KERNEL);
>> +	if (!core->packet) {
>> +		d_vpr_e("%s: failed to alloc core response packet\n", __func__);
>> +		rc = -ENOMEM;
>> +		goto exit;
>> +	}
>> +
>> +	mutex_init(&core->lock);
>> +	INIT_LIST_HEAD(&core->instances);
>> +	INIT_LIST_HEAD(&core->dangling_instances);
>> +
>> +	INIT_DELAYED_WORK(&core->pm_work, venus_hfi_pm_work_handler);
>> +	INIT_DELAYED_WORK(&core->fw_unload_work, msm_vidc_fw_unload_handler);
>> +
>> +	return 0;
> Either return rc/ret here or don't initialize it at definition.
> 
Sure, Will fix it.
>> +exit:
>> +	if (core->batch_workq)
>> +		destroy_workqueue(core->batch_workq);
>> +	if (core->pm_workq)
>> +		destroy_workqueue(core->pm_workq);
>> +	core->batch_workq = NULL;
>> +	core->pm_workq = NULL;
>> +
>> +	return rc;
>> +}
> [...]
> 
>> +
>> +static int msm_vidc_pm_suspend(struct device *dev)
>> +{
>> +	int rc = 0;
>> +	struct msm_vidc_core *core;
>> +	enum msm_vidc_allow allow = MSM_VIDC_DISALLOW;
>> +
>> +	/*
>> +	 * Bail out if
>> +	 * - driver possibly not probed yet
> Would the pm callbacks be registered by then?
> 
>> +	 * - not the main device. We don't support power management on
>> +	 *   subdevices (e.g. context banks)
> I'm not sure registering context banks as different kinds of devices
> within the same driver is a good idea, this seems rather convoluted.
> 
Sure, will remove the separate probe for context bank in next version.
>> +	 */
>> +	if (!dev || !dev->driver || !is_video_device(dev))
>> +		return 0;
>> +
>> +	core = dev_get_drvdata(dev);
>> +	if (!core) {
>> +		d_vpr_e("%s: invalid core\n", __func__);
>> +		return -EINVAL;
>> +	}
>> +
>> +	core_lock(core, __func__);
>> +	allow = msm_vidc_allow_pm_suspend(core);
>> +
>> +	if (allow == MSM_VIDC_IGNORE) {
>> +		d_vpr_h("%s: pm already suspended\n", __func__);
>> +		msm_vidc_change_core_sub_state(core, 0, CORE_SUBSTATE_PM_SUSPEND, __func__);
>> +		rc = 0;
>> +		goto unlock;
>> +	} else if (allow != MSM_VIDC_ALLOW) {
>> +		d_vpr_h("%s: pm suspend not allowed\n", __func__);
>> +		rc = 0;
>> +		goto unlock;
>> +	}
>> +
>> +	rc = msm_vidc_suspend(core);
>> +	if (rc == -EOPNOTSUPP)
>> +		rc = 0;
>> +	else if (rc)
>> +		d_vpr_e("Failed to suspend: %d\n", rc);
>> +	else
>> +		msm_vidc_change_core_sub_state(core, 0, CORE_SUBSTATE_PM_SUSPEND, __func__);
>> +
>> +unlock:
>> +	core_unlock(core, __func__);
>> +	return rc;
>> +}
>> +
>> +static int msm_vidc_pm_resume(struct device *dev)
> Same comments as in _suspend
> 
> Konrad
Dikshita Agarwal Aug. 14, 2023, 6:58 p.m. UTC | #15
On 7/28/2023 7:19 PM, Dmitry Baryshkov wrote:
> On 28/07/2023 16:23, Vikash Garodia wrote:
>> From: Dikshita Agarwal <quic_dikshita@quicinc.com>
>>
>> This implements the platform driver methods, file
>> operations and v4l2 registration.
>>
>> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
>> Signed-off-by: Vikash Garodia <quic_vgarodia@quicinc.com>
>> ---
>>   .../platform/qcom/iris/vidc/src/msm_vidc_probe.c   | 660
>> +++++++++++++++++++++
>>   1 file changed, 660 insertions(+)
>>   create mode 100644
>> drivers/media/platform/qcom/iris/vidc/src/msm_vidc_probe.c
>>
>> diff --git a/drivers/media/platform/qcom/iris/vidc/src/msm_vidc_probe.c
>> b/drivers/media/platform/qcom/iris/vidc/src/msm_vidc_probe.c
>> new file mode 100644
>> index 0000000..43439cb
>> --- /dev/null
>> +++ b/drivers/media/platform/qcom/iris/vidc/src/msm_vidc_probe.c
>> @@ -0,0 +1,660 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Copyright (c) 2020-2022, The Linux Foundation. All rights reserved.
>> + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
>> + */
>> +
>> +#include <linux/interrupt.h>
>> +#include <linux/io.h>
>> +#include <linux/iommu.h>
>> +#include <linux/module.h>
>> +#include <linux/of.h>
>> +#include <linux/of_platform.h>
>> +#include <linux/stringify.h>
>> +#include <linux/version.h>
>> +#include <linux/workqueue.h>
>> +
>> +#include "msm_vidc_core.h"
>> +#include "msm_vidc_debug.h"
>> +#include "msm_vidc_driver.h"
>> +#include "msm_vidc_internal.h"
>> +#include "msm_vidc_memory.h"
>> +#include "msm_vidc_platform.h"
>> +#include "msm_vidc_state.h"
>> +#include "venus_hfi.h"
> 
> This files are not present yet, so this commit doesn't have a change of
> being compiled in any way.
> 
>> +
>> +#define BASE_DEVICE_NUMBER 32
>> +
>> +struct msm_vidc_core *g_core;
>> +
>> +static inline bool is_video_device(struct device *dev)
>> +{
>> +    return !!(of_device_is_compatible(dev->of_node, "qcom,sm8550-vidc"));
> 
> Are you going to add future platforms to this list? Please don't duplicate
> of_match_data here.
> Sure, Will remove this API in next version.
>> +}
>> +
>> +static inline bool is_video_context_bank_device(struct device *dev)
>> +{
>> +    return !!(of_device_is_compatible(dev->of_node, "qcom,vidc,cb-ns"));
>> +}
>> +
>> +static int msm_vidc_init_resources(struct msm_vidc_core *core)
>> +{
>> +    struct msm_vidc_resource *res = NULL;
>> +    int rc = 0;
>> +
>> +    res = devm_kzalloc(&core->pdev->dev, sizeof(*res), GFP_KERNEL);
>> +    if (!res) {
>> +        d_vpr_e("%s: failed to alloc memory for resource\n", __func__);
> 
> Where is this macro defined? Please structure your comments in a logical
> way, so that one can read them from the beginning and understand what is
> going one.
> 
> This is not to mention that adding such debugging wrappers doesn't have a
> lot of value.
> 
I understand the concern here, will remove the custom debug wrappers in
next version.
>> +        return -ENOMEM;
>> +    }
>> +    core->resource = res;
>> +
>> +    rc = call_res_op(core, init, core);
> 
> What is call_res_op?
> 
This implements the resource ops, but as we don't need the abstraction for
resource ops, this will be removed in next version.
>> +    if (rc) {
>> +        d_vpr_e("%s: Failed to init resources: %d\n", __func__, rc);
>> +        return rc;
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>> +static const struct of_device_id msm_vidc_dt_match[] = {
>> +    {.compatible = "qcom,sm8550-vidc"},
>> +    {.compatible = "qcom,vidc,cb-ns"},
>> +    MSM_VIDC_EMPTY_BRACE
> 
> NO!!! Please use {} directly.
> 
I Understand, will replace with {}.
>> +};
>> +MODULE_DEVICE_TABLE(of, msm_vidc_dt_match);
>> +
>> +static void msm_vidc_release_video_device(struct video_device *vdev)
>> +{
>> +    d_vpr_e("%s: video device released\n", __func__);
>> +}
>> +
>> +static void msm_vidc_unregister_video_device(struct msm_vidc_core *core,
>> +                         enum msm_vidc_domain_type type)
>> +{
>> +    int index;
>> +
>> +    if (type == MSM_VIDC_DECODER)
>> +        index = 0;
>> +    else if (type == MSM_VIDC_ENCODER)
>> +        index = 1;
>> +    else
>> +        return;
> 
> You can index by the type instead of converting to index.
> 
MSM_VIDC_DECODER/MSM_VIDC_ENCODER are bit masks hence can not be used as
array index and these bit mask values are being used in driver at multiple
places.
>> +
>> +    v4l2_m2m_release(core->vdev[index].m2m_dev);
>> +
>> +    video_set_drvdata(&core->vdev[index].vdev, NULL);
>> +    video_unregister_device(&core->vdev[index].vdev);
>> +}
>> +
>> +static int msm_vidc_register_video_device(struct msm_vidc_core *core,
>> +                      enum msm_vidc_domain_type type, int nr)
>> +{
>> +    int rc = 0;
>> +    int index;
>> +
>> +    d_vpr_h("%s: domain %d\n", __func__, type);
>> +
>> +    if (type == MSM_VIDC_DECODER)
>> +        index = 0;
>> +    else if (type == MSM_VIDC_ENCODER)
>> +        index = 1;
>> +    else
>> +        return -EINVAL;
>> +
>> +    core->vdev[index].vdev.release =
>> +        msm_vidc_release_video_device;
>> +    core->vdev[index].vdev.fops = core->v4l2_file_ops;
>> +    if (type == MSM_VIDC_DECODER)
>> +        core->vdev[index].vdev.ioctl_ops = core->v4l2_ioctl_ops_dec;
>> +    else
>> +        core->vdev[index].vdev.ioctl_ops = core->v4l2_ioctl_ops_enc;
>> +    core->vdev[index].vdev.vfl_dir = VFL_DIR_M2M;
>> +    core->vdev[index].type = type;
>> +    core->vdev[index].vdev.v4l2_dev = &core->v4l2_dev;
>> +    core->vdev[index].vdev.device_caps =
>> core->capabilities[DEVICE_CAPS].value;
>> +    rc = video_register_device(&core->vdev[index].vdev,
>> +                   VFL_TYPE_VIDEO, nr);
>> +    if (rc) {
>> +        d_vpr_e("Failed to register the video device\n");
>> +        return rc;
>> +    }
>> +    video_set_drvdata(&core->vdev[index].vdev, core);
>> +
>> +    core->vdev[index].m2m_dev = v4l2_m2m_init(core->v4l2_m2m_ops);
>> +    if (IS_ERR(core->vdev[index].m2m_dev)) {
>> +        d_vpr_e("Failed to initialize V4L2 M2M device\n");
>> +        rc = PTR_ERR(core->vdev[index].m2m_dev);
>> +        goto m2m_init_failed;
>> +    }
>> +
>> +    return 0;
>> +
>> +m2m_init_failed:
>> +    video_unregister_device(&core->vdev[index].vdev);
>> +    return rc;
>> +}
>> +
>> +static int msm_vidc_deinitialize_core(struct msm_vidc_core *core)
>> +{
>> +    int rc = 0;
>> +
>> +    if (!core) {
>> +        d_vpr_e("%s: invalid params\n", __func__);
>> +        return -EINVAL;
>> +    }
>> +
>> +    mutex_destroy(&core->lock);
>> +    msm_vidc_update_core_state(core, MSM_VIDC_CORE_DEINIT, __func__);
>> +
>> +    if (core->batch_workq)
>> +        destroy_workqueue(core->batch_workq);
>> +
>> +    if (core->pm_workq)
>> +        destroy_workqueue(core->pm_workq);
>> +
>> +    core->batch_workq = NULL;
>> +    core->pm_workq = NULL;
>> +
>> +    return rc;
>> +}
>> +
>> +static int msm_vidc_initialize_core(struct msm_vidc_core *core)
>> +{
>> +    int rc = 0;
>> +
>> +    msm_vidc_update_core_state(core, MSM_VIDC_CORE_DEINIT, __func__);
>> +
>> +    core->pm_workq = create_singlethread_workqueue("pm_workq");
>> +    if (!core->pm_workq) {
>> +        d_vpr_e("%s: create pm workq failed\n", __func__);
>> +        rc = -EINVAL;
>> +        goto exit;
>> +    }
>> +
>> +    core->batch_workq = create_singlethread_workqueue("batch_workq");
>> +    if (!core->batch_workq) {
>> +        d_vpr_e("%s: create batch workq failed\n", __func__);
>> +        rc = -EINVAL;
>> +        goto exit;
>> +    }
>> +
>> +    core->packet_size = VIDC_IFACEQ_VAR_HUGE_PKT_SIZE;
>> +    core->packet = devm_kzalloc(&core->pdev->dev, core->packet_size,
>> GFP_KERNEL);
>> +    if (!core->packet) {
>> +        d_vpr_e("%s: failed to alloc core packet\n", __func__);
>> +        rc = -ENOMEM;
>> +        goto exit;
>> +    }
>> +
>> +    core->response_packet = devm_kzalloc(&core->pdev->dev,
>> core->packet_size, GFP_KERNEL);
>> +    if (!core->packet) {
>> +        d_vpr_e("%s: failed to alloc core response packet\n", __func__);
>> +        rc = -ENOMEM;
>> +        goto exit;
>> +    }
>> +
>> +    mutex_init(&core->lock);
>> +    INIT_LIST_HEAD(&core->instances);
>> +    INIT_LIST_HEAD(&core->dangling_instances);
>> +
>> +    INIT_DELAYED_WORK(&core->pm_work, venus_hfi_pm_work_handler);
>> +    INIT_DELAYED_WORK(&core->fw_unload_work, msm_vidc_fw_unload_handler);
>> +
>> +    return 0;
>> +exit:
>> +    if (core->batch_workq)
>> +        destroy_workqueue(core->batch_workq);
>> +    if (core->pm_workq)
>> +        destroy_workqueue(core->pm_workq);
>> +    core->batch_workq = NULL;
>> +    core->pm_workq = NULL;
>> +
>> +    return rc;
>> +}
>> +
>> +static void msm_vidc_devm_deinit_core(void *res)
>> +{
>> +    struct msm_vidc_core *core = res;
>> +
>> +    msm_vidc_deinitialize_core(core);
>> +}
>> +
>> +static int msm_vidc_devm_init_core(struct device *dev, struct
>> msm_vidc_core *core)
>> +{
>> +    int rc = 0;
>> +
>> +    if (!dev || !core) {
>> +        d_vpr_e("%s: invalid params\n", __func__);
>> +        return -EINVAL;
>> +    }
>> +
>> +    rc = msm_vidc_initialize_core(core);
>> +    if (rc) {
>> +        d_vpr_e("%s: init failed with %d\n", __func__, rc);
>> +        return rc;
>> +    }
>> +
>> +    rc = devm_add_action_or_reset(dev, msm_vidc_devm_deinit_core, (void
>> *)core);
>> +    if (rc)
>> +        return -EINVAL;
>> +
>> +    return rc;
>> +}
>> +
>> +static void msm_vidc_devm_debugfs_put(void *res)
>> +{
>> +    struct dentry *parent = res;
>> +
>> +    debugfs_remove_recursive(parent);
>> +}
>> +
>> +static struct dentry *msm_vidc_devm_debugfs_get(struct device *dev)
> 
> Why is it called get?
> 
this will be removed in next version as part of debug wrappers removal
> 
>> +{
>> +    struct dentry *parent = NULL;
>> +    int rc = 0;
>> +
>> +    if (!dev) {
>> +        d_vpr_e("%s: invalid params\n", __func__);
>> +        return NULL;
>> +    }
>> +
>> +    parent = msm_vidc_debugfs_init_drv();
>> +    if (!parent)
>> +        return NULL;
>> +
>> +    rc = devm_add_action_or_reset(dev, msm_vidc_devm_debugfs_put, (void
>> *)parent);
>> +    if (rc)
>> +        return NULL;
>> +
>> +    return parent;
>> +}
>> +
>> +static int msm_vidc_setup_context_bank(struct msm_vidc_core *core,
>> +                       struct device *dev)
>> +{
>> +    struct context_bank_info *cb = NULL;
>> +    int rc = 0;
>> +
>> +    cb = msm_vidc_get_context_bank_for_device(core, dev);
>> +    if (!cb) {
>> +        d_vpr_e("%s: Failed to get context bank device for %s\n",
>> +            __func__, dev_name(dev));
>> +        return -EIO;
>> +    }
>> +
>> +    /* populate dev & domain field */
>> +    cb->dev = dev;
>> +    cb->domain = iommu_get_domain_for_dev(cb->dev);
>> +    if (!cb->domain) {
>> +        d_vpr_e("%s: Failed to get iommu domain for %s\n", __func__,
>> dev_name(dev));
>> +        return -EIO;
>> +    }
>> +
>> +    if (cb->dma_mask) {
>> +        rc = dma_set_mask_and_coherent(cb->dev, cb->dma_mask);
>> +        if (rc) {
>> +            d_vpr_e("%s: dma_set_mask_and_coherent failed\n", __func__);
>> +            return rc;
>> +        }
>> +    }
>> +
>> +    /*
>> +     * configure device segment size and segment boundary to ensure
>> +     * iommu mapping returns one mapping (which is required for partial
>> +     * cache operations)
>> +     */
>> +    if (!dev->dma_parms)
>> +        dev->dma_parms =
>> +            devm_kzalloc(dev, sizeof(*dev->dma_parms), GFP_KERNEL);
>> +    dma_set_max_seg_size(dev, (unsigned int)DMA_BIT_MASK(32));
>> +    dma_set_seg_boundary(dev, (unsigned long)DMA_BIT_MASK(64));
>> +
>> +    iommu_set_fault_handler(cb->domain, msm_vidc_smmu_fault_handler,
>> (void *)core);
>> +
>> +    d_vpr_h("%s: name %s addr start %x size %x secure %d\n",
>> +        __func__, cb->name, cb->addr_range.start,
>> +        cb->addr_range.size, cb->secure);
>> +    d_vpr_h("%s: dma_coherant %d region %d dev_name %s domain %pK
>> dma_mask %llu\n",
>> +        __func__, cb->dma_coherant, cb->region, dev_name(cb->dev),
>> +        cb->domain, cb->dma_mask);
>> +
>> +    return rc;
>> +}
>> +
>> +static int msm_vidc_remove_video_device(struct platform_device *pdev)
>> +{
>> +    struct msm_vidc_core *core;
>> +
>> +    if (!pdev) {
>> +        d_vpr_e("%s: invalid input %pK", __func__, pdev);
>> +        return -EINVAL;
>> +    }
>> +
>> +    core = dev_get_drvdata(&pdev->dev);
>> +    if (!core) {
>> +        d_vpr_e("%s: invalid core\n", __func__);
>> +        return -EINVAL;
>> +    }
>> +
>> +    msm_vidc_core_deinit(core, true);
>> +    venus_hfi_queue_deinit(core);
>> +
>> +    msm_vidc_unregister_video_device(core, MSM_VIDC_ENCODER);
>> +    msm_vidc_unregister_video_device(core, MSM_VIDC_DECODER);
>> +
>> +    v4l2_device_unregister(&core->v4l2_dev);
>> +
>> +    d_vpr_h("depopulating sub devices\n");
>> +    /*
>> +     * Trigger remove for each sub-device i.e. qcom,context-bank,xxxx
>> +     * When msm_vidc_remove is called for each sub-device, destroy
>> +     * context-bank mappings.
>> +     */
>> +    of_platform_depopulate(&pdev->dev);
>> +
>> +    dev_set_drvdata(&pdev->dev, NULL);
>> +    g_core = NULL;
>> +    d_vpr_h("%s(): succssful\n", __func__);
>> +
>> +    return 0;
>> +}
>> +
>> +static int msm_vidc_remove_context_bank(struct platform_device *pdev)
>> +{
>> +    d_vpr_h("%s(): %s\n", __func__, dev_name(&pdev->dev));
>> +
>> +    return 0;
>> +}
>> +
>> +static int msm_vidc_remove(struct platform_device *pdev)
>> +{
>> +    /*
>> +     * Sub devices remove will be triggered by of_platform_depopulate()
>> +     * after core_deinit(). It return immediately after completing
>> +     * sub-device remove.
>> +     */
>> +    if (is_video_device(&pdev->dev))
>> +        return msm_vidc_remove_video_device(pdev);
>> +    else if (is_video_context_bank_device(&pdev->dev))
>> +        return msm_vidc_remove_context_bank(pdev);
>> +
>> +    /* How did we end up here? */
>> +    WARN_ON(1);
>> +    return -EINVAL;
>> +}
>> +
>> +static int msm_vidc_probe_video_device(struct platform_device *pdev)
>> +{
>> +    int rc = 0;
>> +    struct msm_vidc_core *core = NULL;
>> +    int nr = BASE_DEVICE_NUMBER;
>> +
>> +    d_vpr_h("%s: %s\n", __func__, dev_name(&pdev->dev));
>> +
>> +    core = devm_kzalloc(&pdev->dev, sizeof(struct msm_vidc_core),
>> GFP_KERNEL);
>> +    if (!core) {
>> +        d_vpr_e("%s: failed to alloc memory for core\n", __func__);
>> +        return -ENOMEM;
>> +    }
>> +    g_core = core;
>> +
>> +    core->pdev = pdev;
>> +    dev_set_drvdata(&pdev->dev, core);
>> +
>> +    core->debugfs_parent = msm_vidc_devm_debugfs_get(&pdev->dev);
>> +    if (!core->debugfs_parent)
>> +        d_vpr_h("Failed to create debugfs for msm_vidc\n");
>> +
>> +    rc = msm_vidc_devm_init_core(&pdev->dev, core);
>> +    if (rc) {
>> +        d_vpr_e("%s: init core failed with %d\n", __func__, rc);
>> +        goto init_core_failed;
>> +    }
>> +
>> +    rc = msm_vidc_init_platform(core);
>> +    if (rc) {
>> +        d_vpr_e("%s: init platform failed with %d\n", __func__, rc);
>> +        rc = -EINVAL;
>> +        goto init_plat_failed;
>> +    }
>> +
>> +    rc = msm_vidc_init_resources(core);
>> +    if (rc) {
>> +        d_vpr_e("%s: init resource failed with %d\n", __func__, rc);
>> +        goto init_res_failed;
>> +    }
>> +
>> +    rc = msm_vidc_init_core_caps(core);
>> +    if (rc) {
>> +        d_vpr_e("%s: init core caps failed with %d\n", __func__, rc);
>> +        goto init_res_failed;
>> +    }
>> +
>> +    rc = msm_vidc_init_instance_caps(core);
>> +    if (rc) {
>> +        d_vpr_e("%s: init inst cap failed with %d\n", __func__, rc);
>> +        goto init_inst_caps_fail;
>> +    }
>> +
>> +    core->debugfs_root = msm_vidc_debugfs_init_core(core);
>> +    if (!core->debugfs_root)
>> +        d_vpr_h("Failed to init debugfs core\n");
>> +
>> +    d_vpr_h("populating sub devices\n");
>> +    /*
>> +     * Trigger probe for each sub-device i.e. qcom,msm-vidc,context-bank.
>> +     * When msm_vidc_probe is called for each sub-device, parse the
>> +     * context-bank details.
>> +     */
>> +    rc = of_platform_populate(pdev->dev.of_node, msm_vidc_dt_match, NULL,
>> +                  &pdev->dev);
>> +    if (rc) {
>> +        d_vpr_e("Failed to trigger probe for sub-devices\n");
>> +        goto sub_dev_failed;
>> +    }
>> +
>> +    rc = v4l2_device_register(&pdev->dev, &core->v4l2_dev);
>> +    if (rc) {
>> +        d_vpr_e("Failed to register v4l2 device\n");
>> +        goto v4l2_reg_failed;
>> +    }
>> +
>> +    /* setup the decoder device */
>> +    rc = msm_vidc_register_video_device(core, MSM_VIDC_DECODER, nr);
>> +    if (rc) {
>> +        d_vpr_e("Failed to register video decoder\n");
>> +        goto dec_reg_failed;
>> +    }
>> +
>> +    /* setup the encoder device */
>> +    rc = msm_vidc_register_video_device(core, MSM_VIDC_ENCODER, nr + 1);
>> +    if (rc) {
>> +        d_vpr_e("Failed to register video encoder\n");
>> +        goto enc_reg_failed;
>> +    }
>> +
>> +    rc = venus_hfi_queue_init(core);
>> +    if (rc) {
>> +        d_vpr_e("%s: interface queues init failed\n", __func__);
>> +        goto queues_init_failed;
>> +    }
>> +
>> +    rc = msm_vidc_core_init(core);
>> +    if (rc) {
>> +        d_vpr_e("%s: sys init failed\n", __func__);
>> +        goto core_init_failed;
>> +    }
>> +
>> +    d_vpr_h("%s(): succssful\n", __func__);
>> +
>> +    return rc;
>> +
>> +core_init_failed:
>> +    venus_hfi_queue_deinit(core);
>> +queues_init_failed:
>> +    of_platform_depopulate(&pdev->dev);
>> +sub_dev_failed:
>> +    msm_vidc_unregister_video_device(core, MSM_VIDC_ENCODER);
>> +enc_reg_failed:
>> +    msm_vidc_unregister_video_device(core, MSM_VIDC_DECODER);
>> +dec_reg_failed:
>> +    v4l2_device_unregister(&core->v4l2_dev);
>> +v4l2_reg_failed:
>> +init_inst_caps_fail:
>> +init_res_failed:
>> +init_plat_failed:
>> +init_core_failed:
>> +    dev_set_drvdata(&pdev->dev, NULL);
>> +    g_core = NULL;
>> +
>> +    return rc;
>> +}
>> +
>> +static int msm_vidc_probe_context_bank(struct platform_device *pdev)
>> +{
>> +    struct msm_vidc_core *core = NULL;
>> +    int rc = 0;
>> +
>> +    if (!pdev) {
>> +        d_vpr_e("%s: Invalid platform device %pK", __func__, pdev);
>> +        return -EINVAL;
>> +    } else if (!pdev->dev.parent) {
>> +        d_vpr_e("%s: Failed to find a parent for %s\n",
>> +            __func__, dev_name(&pdev->dev));
>> +        return -ENODEV;
>> +    }
>> +
>> +    d_vpr_h("%s(): %s\n", __func__, dev_name(&pdev->dev));
>> +
>> +    core = dev_get_drvdata(pdev->dev.parent);
>> +    if (!core) {
>> +        d_vpr_e("%s: core not found in device %s",
>> +            __func__, dev_name(pdev->dev.parent));
>> +        return -EINVAL;
>> +    }
>> +
>> +    rc = msm_vidc_setup_context_bank(core, &pdev->dev);
>> +    if (rc) {
>> +        d_vpr_e("%s: Failed to probe context bank %s\n",
>> +            __func__, dev_name(&pdev->dev));
>> +        return rc;
>> +    }
>> +
>> +    return rc;
>> +}
>> +
>> +static int msm_vidc_probe(struct platform_device *pdev)
>> +{
>> +    if (!pdev) {
>> +        d_vpr_e("%s: invalid params\n", __func__);
>> +        return -EINVAL;
>> +    }
>> +
>> +    /*
>> +     * Sub devices probe will be triggered by of_platform_populate()
>> towards
>> +     * the end of the probe function after msm-vidc device probe is
>> +     * completed. Return immediately after completing sub-device probe.
>> +     */
>> +    if (is_video_device(&pdev->dev))
>> +        return msm_vidc_probe_video_device(pdev);
>> +    else if (is_video_context_bank_device(&pdev->dev))
>> +        return msm_vidc_probe_context_bank(pdev);
>> +
>> +    /* How did we end up here? */
>> +    WARN_ON(1);
>> +    return -EINVAL;
> 
> No. Please don't hack around the driver infrastructure and register two
> separate drivers. They can even come in two separate commits, simplifying
> the review.
> 
Sure, will remove the separate probe for context bank in next version.
>> +}
>> +
>> +static int msm_vidc_pm_suspend(struct device *dev)
>> +{
>> +    int rc = 0;
>> +    struct msm_vidc_core *core;
>> +    enum msm_vidc_allow allow = MSM_VIDC_DISALLOW;
>> +
>> +    /*
>> +     * Bail out if
>> +     * - driver possibly not probed yet
>> +     * - not the main device. We don't support power management on
>> +     *   subdevices (e.g. context banks)
>> +     */
>> +    if (!dev || !dev->driver || !is_video_device(dev))
>> +        return 0;
>> +
>> +    core = dev_get_drvdata(dev);
>> +    if (!core) {
>> +        d_vpr_e("%s: invalid core\n", __func__);
>> +        return -EINVAL;
>> +    }
>> +
>> +    core_lock(core, __func__);
>> +    allow = msm_vidc_allow_pm_suspend(core);
>> +
>> +    if (allow == MSM_VIDC_IGNORE) {
>> +        d_vpr_h("%s: pm already suspended\n", __func__);
>> +        msm_vidc_change_core_sub_state(core, 0,
>> CORE_SUBSTATE_PM_SUSPEND, __func__);
>> +        rc = 0;
>> +        goto unlock;
>> +    } else if (allow != MSM_VIDC_ALLOW) {
>> +        d_vpr_h("%s: pm suspend not allowed\n", __func__);
>> +        rc = 0;
>> +        goto unlock;
>> +    }
>> +
>> +    rc = msm_vidc_suspend(core);
>> +    if (rc == -EOPNOTSUPP)
>> +        rc = 0;
>> +    else if (rc)
>> +        d_vpr_e("Failed to suspend: %d\n", rc);
>> +    else
>> +        msm_vidc_change_core_sub_state(core, 0,
>> CORE_SUBSTATE_PM_SUSPEND, __func__);
>> +
>> +unlock:
>> +    core_unlock(core, __func__);
>> +    return rc;
>> +}
>> +
>> +static int msm_vidc_pm_resume(struct device *dev)
>> +{
>> +    struct msm_vidc_core *core;
>> +
>> +    /*
>> +     * Bail out if
>> +     * - driver possibly not probed yet
>> +     * - not the main device. We don't support power management on
>> +     *   subdevices (e.g. context banks)
>> +     */
>> +    if (!dev || !dev->driver || !is_video_device(dev))
>> +        return 0;
>> +
>> +    core = dev_get_drvdata(dev);
>> +    if (!core) {
>> +        d_vpr_e("%s: invalid core\n", __func__);
>> +        return -EINVAL;
>> +    }
>> +
>> +    /* remove PM suspend from core sub_state */
>> +    core_lock(core, __func__);
>> +    msm_vidc_change_core_sub_state(core, CORE_SUBSTATE_PM_SUSPEND, 0,
>> __func__);
>> +    core_unlock(core, __func__);
>> +
>> +    return 0;
>> +}
>> +
>> +static const struct dev_pm_ops msm_vidc_pm_ops = {
>> +    SET_SYSTEM_SLEEP_PM_OPS(msm_vidc_pm_suspend, msm_vidc_pm_resume)
> 
> No runtime PM?
runtime PM is not added in this series, but we plan to add it at later
point of time.
> 
>> +};
>> +
>> +struct platform_driver msm_vidc_driver = {
>> +    .probe = msm_vidc_probe,
>> +    .remove = msm_vidc_remove,
>> +    .driver = {
>> +        .name = "msm_vidc_v4l2",
>> +        .of_match_table = msm_vidc_dt_match,
>> +        .pm = &msm_vidc_pm_ops,
>> +    },
>> +};
>> +
>> +module_platform_driver(msm_vidc_driver);
>> +MODULE_LICENSE("GPL");
> 
> Unfortunately, after taking a glance at first two patches, I have to stop.
> It is nearly impossible to review it.
> 
> Please start from the beginning, split the driver according to the logical
> functions, not per-file. Ideally something should be compillable starting
> from one of the first patches, if not the very first one. This would
> guarantee that your patchset is structured logically.
> 
> Please add DT bindings. New driver series should start from the bindings
> anyway.
> 
> Please drop your custom debugging wrappers. Use dev_info, dev_warn, dev_err
> and dev_dbg instead.
> 
> Please drop the custom multi-device-single-driver scheme. If there are
> different kinds of devices, there should be different drivers.
> 
> Please take a look around. If you are pushing your driver for kernel
> inclusion, it should not stand out by the style and by the typical code
> seuqences.

Thanks a lot for all your comments, will take care of these in next version.
> 
>
Dikshita Agarwal Aug. 14, 2023, 7 p.m. UTC | #16
On 8/1/2023 2:53 AM, Krzysztof Kozlowski wrote:
> On 28/07/2023 15:23, Vikash Garodia wrote:
>> Here is the implementation of v4l2 wrapper functions for all
>> v4l2 IOCTLs.
>>
>> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
>> Signed-off-by: Vikash Garodia <quic_vgarodia@quicinc.com>
>> ---
>>  .../platform/qcom/iris/vidc/inc/msm_vidc_v4l2.h    |  77 ++
>>  .../platform/qcom/iris/vidc/src/msm_vidc_v4l2.c    | 953 +++++++++++++++++++++
>>  2 files changed, 1030 insertions(+)
>>  create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_v4l2.h
>>  create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_v4l2.c
>>
>> diff --git a/drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_v4l2.h b/drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_v4l2.h
>> new file mode 100644
>> index 0000000..3766c9d
>> --- /dev/null
>> +++ b/drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_v4l2.h
>> @@ -0,0 +1,77 @@
>> +/* SPDX-License-Identifier: GPL-2.0-only */
>> +/*
>> + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
>> + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
>> + */
>> +
>> +#ifndef _MSM_VIDC_V4L2_H_
>> +#define _MSM_VIDC_V4L2_H_
>> +
>> +#include <linux/fs.h>
>> +#include <linux/poll.h>
>> +#include <media/v4l2-ctrls.h>
>> +#include <media/v4l2-dev.h>
>> +#include <media/v4l2-ioctl.h>
>> +
>> +int msm_v4l2_open(struct file *filp);
>> +int msm_v4l2_close(struct file *filp);
>> +int msm_v4l2_querycap(struct file *filp, void *fh,
>> +		      struct v4l2_capability *cap);
>> +int msm_v4l2_enum_fmt(struct file *file, void *fh,
>> +		      struct v4l2_fmtdesc *f);
>> +int msm_v4l2_try_fmt(struct file *file, void *fh,
>> +		     struct v4l2_format *f);
>> +int msm_v4l2_s_fmt(struct file *file, void *fh,
>> +		   struct v4l2_format *f);
>> +int msm_v4l2_g_fmt(struct file *file, void *fh,
>> +		   struct v4l2_format *f);
>> +int msm_v4l2_s_selection(struct file *file, void *fh,
>> +			 struct v4l2_selection *s);
>> +int msm_v4l2_g_selection(struct file *file, void *fh,
>> +			 struct v4l2_selection *s);
>> +int msm_v4l2_s_parm(struct file *file, void *fh,
>> +		    struct v4l2_streamparm *a);
>> +int msm_v4l2_g_parm(struct file *file, void *fh,
>> +		    struct v4l2_streamparm *a);
>> +int msm_v4l2_reqbufs(struct file *file, void *fh,
>> +		     struct v4l2_requestbuffers *b);
>> +int msm_v4l2_querybuf(struct file *file, void *fh,
>> +		      struct v4l2_buffer *b);
>> +int msm_v4l2_create_bufs(struct file *filp, void *fh,
>> +			 struct v4l2_create_buffers *b);
>> +int msm_v4l2_prepare_buf(struct file *filp, void *fh,
>> +			 struct v4l2_buffer *b);
>> +int msm_v4l2_qbuf(struct file *file, void *fh,
>> +		  struct v4l2_buffer *b);
>> +int msm_v4l2_dqbuf(struct file *file, void *fh,
>> +		   struct v4l2_buffer *b);
>> +int msm_v4l2_streamon(struct file *file, void *fh,
>> +		      enum v4l2_buf_type i);
>> +int msm_v4l2_streamoff(struct file *file, void *fh,
>> +		       enum v4l2_buf_type i);
>> +int msm_v4l2_subscribe_event(struct v4l2_fh *fh,
>> +			     const struct v4l2_event_subscription *sub);
>> +int msm_v4l2_unsubscribe_event(struct v4l2_fh *fh,
>> +			       const struct v4l2_event_subscription *sub);
>> +int msm_v4l2_try_decoder_cmd(struct file *file, void *fh,
>> +			     struct v4l2_decoder_cmd *enc);
>> +int msm_v4l2_decoder_cmd(struct file *file, void *fh,
>> +			 struct v4l2_decoder_cmd *dec);
>> +int msm_v4l2_try_encoder_cmd(struct file *file, void *fh,
>> +			     struct v4l2_encoder_cmd *enc);
>> +int msm_v4l2_encoder_cmd(struct file *file, void *fh,
>> +			 struct v4l2_encoder_cmd *enc);
>> +int msm_v4l2_enum_framesizes(struct file *file, void *fh,
>> +			     struct v4l2_frmsizeenum *fsize);
>> +int msm_v4l2_enum_frameintervals(struct file *file, void *fh,
>> +				 struct v4l2_frmivalenum *fival);
>> +int msm_v4l2_queryctrl(struct file *file, void *fh,
>> +		       struct v4l2_queryctrl *ctrl);
>> +int msm_v4l2_querymenu(struct file *file, void *fh,
>> +		       struct v4l2_querymenu *qmenu);
>> +unsigned int msm_v4l2_poll(struct file *filp,
>> +			   struct poll_table_struct *pt);
>> +void msm_v4l2_m2m_device_run(void *priv);
>> +void msm_v4l2_m2m_job_abort(void *priv);
>> +
>> +#endif // _MSM_VIDC_V4L2_H_
>> diff --git a/drivers/media/platform/qcom/iris/vidc/src/msm_vidc_v4l2.c b/drivers/media/platform/qcom/iris/vidc/src/msm_vidc_v4l2.c
>> new file mode 100644
>> index 0000000..6dfb18b
>> --- /dev/null
>> +++ b/drivers/media/platform/qcom/iris/vidc/src/msm_vidc_v4l2.c
>> @@ -0,0 +1,953 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
>> + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
>> + */
>> +
>> +#include "msm_vidc.h"
>> +#include "msm_vidc_core.h"
>> +#include "msm_vidc_debug.h"
>> +#include "msm_vidc_driver.h"
>> +#include "msm_vidc_inst.h"
>> +#include "msm_vidc_internal.h"
>> +#include "msm_vidc_v4l2.h"
>> +
>> +static struct msm_vidc_inst *get_vidc_inst(struct file *filp, void *fh)
>> +{
>> +	if (!filp || !filp->private_data)
>> +		return NULL;
>> +	return container_of(filp->private_data,
>> +					struct msm_vidc_inst, fh);
>> +}
>> +
>> +unsigned int msm_v4l2_poll(struct file *filp, struct poll_table_struct *pt)
>> +{
>> +	int poll = 0;
>> +	struct msm_vidc_inst *inst = get_vidc_inst(filp, NULL);
>> +
>> +	inst = get_inst_ref(g_core, inst);
>> +	if (!inst) {
>> +		d_vpr_e("%s: invalid instance\n", __func__);
> 
> This does not look like Linux coding style. Don't create your own
> abstraction layer over Linux internal API. Use standard Linux functions
> which will behave better and scale along with kernel development.
> 
I understand. these custom debug wrappers will be removed in next version.
>> +		return POLLERR;
>> +	}
>> +	if (is_session_error(inst)) {
>> +		i_vpr_e(inst, "%s: inst in error state\n", __func__);
> 
> i_vpr_e is so obvious for every kernel developer... Please, no.
> 
>> +		poll = POLLERR;
>> +		goto exit;
>> +	}
>> +
>> +	poll = msm_vidc_poll((void *)inst, filp, pt);
>> +	if (poll)
>> +		goto exit;
>> +
>> +exit:
>> +	put_inst(inst);
>> +	return poll;
>> +}
>> +
>> +int msm_v4l2_open(struct file *filp)
>> +{
>> +	struct video_device *vdev = video_devdata(filp);
>> +	struct msm_video_device *vid_dev =
>> +		container_of(vdev, struct msm_video_device, vdev);
>> +	struct msm_vidc_core *core = video_drvdata(filp);
>> +	struct msm_vidc_inst *inst;
>> +
>> +	inst = msm_vidc_open(core, vid_dev->type);
>> +	if (!inst) {
>> +		d_vpr_e("Failed to create instance, type = %d\n",
>> +			vid_dev->type);
>> +		return -ENOMEM;
>> +	}
>> +	filp->private_data = &inst->fh;
>> +	return 0;
>> +}
>> +
>> +int msm_v4l2_close(struct file *filp)
>> +{
>> +	int rc = 0;
>> +	struct msm_vidc_inst *inst;
>> +
>> +	inst = get_vidc_inst(filp, NULL);
>> +	if (!inst) {
>> +		d_vpr_e("%s: invalid instance\n", __func__);
>> +		return -EINVAL;
>> +	}
>> +
>> +	rc = msm_vidc_close(inst);
>> +	filp->private_data = NULL;
>> +	return rc;
>> +}
>> +
>> +int msm_v4l2_querycap(struct file *filp, void *fh,
>> +		      struct v4l2_capability *cap)
>> +{
>> +	struct msm_vidc_inst *inst = get_vidc_inst(filp, fh);
>> +	int rc = 0;
>> +
>> +	inst = get_inst_ref(g_core, inst);
>> +	if (!inst || !cap) {
>> +		d_vpr_e("%s: invalid instance\n", __func__);
>> +		return -EINVAL;
>> +	}
>> +
>> +	client_lock(inst, __func__);
> 
> ? So we don't know what's this? Mutex? Spinlock? Own reinvented lock?
> 
>> +	inst_lock(inst, __func__);
> 
> Neither this?
> 
> No, don't create your own abstractions over standard API.
Sure, will remove these custom wrappers and use standard API directly in
next version.
> 
> Best regards,
> Krzysztof
>
Dikshita Agarwal Aug. 14, 2023, 7:11 p.m. UTC | #17
On 7/28/2023 9:28 PM, Bryan O'Donoghue wrote:
> On 28/07/2023 14:23, Vikash Garodia wrote:
>> +    rc = hfi_packet_sys_intraframe_powercollapse(core, core->packet,
>> +                             core->packet_size, enable);
>> +    if (rc)
>> +        return rc;
> 
> I'm 99.9999999999 % sure this is misnamed.
> 
> "Inter" means in-between two things.
> "Intra" means inside of one thing.
> 
> So "intraframe" means inside of one frame "interframe" would mean power
> collapsing in-between two frames, which is what I think this does.
> 
> And I'd still rather be adding inter-frame power-collapse to as many
> different versions of the existing silicon and new silicon as opposed to
> segregating it off in a new driver.
> 
> I'm assuming that more than sm8550 supports it since @ the end of the day
> this is a firmware feature to power-collapse during an active session when
> we aren't busy.
> 
You are actually 100% correct here, it is indeed inter frame power collapse,
Will rename this api with hfi_packet_sys_interframe_powercollapse

Thanks,
Dikshita
> ---
> bod
Dikshita Agarwal Aug. 14, 2023, 7:13 p.m. UTC | #18
On 7/28/2023 10:51 PM, Konrad Dybcio wrote:
> On 28.07.2023 15:23, Vikash Garodia wrote:
>> This implements decoder functionalities of the driver.
>>
>> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
>> Signed-off-by: Vikash Garodia <quic_vgarodia@quicinc.com>
>> ---
> I see a whole bunch of shifts, ANDs, etc.
> 
> Please convert that to GENMASK + FIELD_PREP/FIELD_GET
> 
Sure, will explore more on this.

> Konrad
Dikshita Agarwal Aug. 14, 2023, 7:15 p.m. UTC | #19
On 7/28/2023 11:11 PM, Konrad Dybcio wrote:
> On 28.07.2023 15:23, Vikash Garodia wrote:
>> This implements common helper functions for v4l2 to vidc and
>> vice versa conversion for different enums.
>> Add helpers for state checks, buffer management, locks etc.
>>
>> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
>> Signed-off-by: Vikash Garodia <quic_vgarodia@quicinc.com>
>> ---
> [...]
> 
>> +
>> +#define is_odd(val) ((val) % 2 == 1)
>> +#define in_range(val, min, max) (((min) <= (val)) && ((val) <= (max)))
>> +#define COUNT_BITS(a, out) {       \
> hweight.* functions?
> 
> [...]
> 
sure, will replace with hweight.
>> +
>> +const char *cap_name(enum msm_vidc_inst_capability_type cap_id)
>> +{
>> +	const char *name = "UNKNOWN CAP";
> Perhaps it'd be worth to include the unknown cap id here
> 
could you please elaborate more on this.
>> +
>> +	if (cap_id >= ARRAY_SIZE(cap_name_arr))
>> +		goto exit;
>> +
>> +	name = cap_name_arr[cap_id];
>> +
>> +exit:
>> +	return name;
>> +}
> [...]
> 
>> +
>> +const char *buf_name(enum msm_vidc_buffer_type type)
>> +{
>> +	const char *name = "UNKNOWN BUF";
> Similarly here
> 
could you please elaborate more on this.
>> +
>> +	if (type >= ARRAY_SIZE(buf_type_name_arr))
>> +		goto exit;
>> +
>> +	name = buf_type_name_arr[type];
>> +
>> +exit:
>> +	return name;
>> +}
> [...]
> 
>> +const char *v4l2_type_name(u32 port)
>> +{
>> +	switch (port) {
> switch-case seems a bit excessive here.
> 
>> +	case INPUT_MPLANE:      return "INPUT";
>> +	case OUTPUT_MPLANE:     return "OUTPUT";
>> +	}
>> +
>> +	return "UNKNOWN";
>> +}
that's right, will fix in next version
> [...]
> 
> There's some more stuff I'd comment on, but 4500 lines in a single patch
> is way too much to logically follow.
> 
> Couple more style suggestions:
> - use Reverse-Christmas-tree sorting for variable declarations
> - some oneliner functions could possibly become preprocessor macros
> - when printing giant debug messages, you may want to use loops
> - make sure your indentation is in order, 100 chars per line is
>   totally fine
> - generally inline magic hex values are discouraged, but if they're
>   necessary, the hex should be lowercase
Nice suggestions! will take care of these comments in next version.

Thanks,
Dikshita
> 
> Konrad
Dikshita Agarwal Aug. 14, 2023, 7:35 p.m. UTC | #20
On 7/28/2023 7:43 PM, Dmitry Baryshkov wrote:
> On 28/07/2023 16:23, Vikash Garodia wrote:
>> From: Dikshita Agarwal <quic_dikshita@quicinc.com>
>>
>> This implements all the capabilities supported by sm8550.
>>
>> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
>> Signed-off-by: Vikash Garodia <quic_vgarodia@quicinc.com>
>> ---
>>   .../iris/platform/sm8550/inc/msm_vidc_sm8550.h     |   14 +
>>   .../iris/platform/sm8550/src/msm_vidc_sm8550.c     | 1727
>> ++++++++++++++++++++
>>   2 files changed, 1741 insertions(+)
>>   create mode 100644
>> drivers/media/platform/qcom/iris/platform/sm8550/inc/msm_vidc_sm8550.h
>>   create mode 100644
>> drivers/media/platform/qcom/iris/platform/sm8550/src/msm_vidc_sm8550.c
>>
>> diff --git
>> a/drivers/media/platform/qcom/iris/platform/sm8550/inc/msm_vidc_sm8550.h
>> b/drivers/media/platform/qcom/iris/platform/sm8550/inc/msm_vidc_sm8550.h
>> new file mode 100644
>> index 0000000..0a2f172
>> --- /dev/null
>> +++ b/drivers/media/platform/qcom/iris/platform/sm8550/inc/msm_vidc_sm8550.h
>> @@ -0,0 +1,14 @@
>> +/* SPDX-License-Identifier: GPL-2.0-only */
>> +/*
>> + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
>> + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights
>> reserved.
>> + */
>> +
>> +#ifndef _MSM_VIDC_SM8550_H_
>> +#define _MSM_VIDC_SM8550_H_
>> +
>> +#include "msm_vidc_core.h"
>> +
>> +int msm_vidc_init_platform_sm8550(struct msm_vidc_core *core);
>> +
>> +#endif // _MSM_VIDC_SM8550_H_
>> diff --git
>> a/drivers/media/platform/qcom/iris/platform/sm8550/src/msm_vidc_sm8550.c
>> b/drivers/media/platform/qcom/iris/platform/sm8550/src/msm_vidc_sm8550.c
>> new file mode 100644
>> index 0000000..2408556
>> --- /dev/null
>> +++ b/drivers/media/platform/qcom/iris/platform/sm8550/src/msm_vidc_sm8550.c
>> @@ -0,0 +1,1727 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
>> + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights
>> reserved.
>> + */
>> +
>> +#include <dt-bindings/clock/qcom,sm8550-gcc.h>
>> +#include <dt-bindings/clock/qcom,sm8450-videocc.h>
>> +
>> +#include "hfi_command.h"
>> +#include "hfi_property.h"
>> +#include "msm_vidc_control.h"
>> +#include "msm_vidc_debug.h"
>> +#include "msm_vidc_iris3.h"
>> +#include "msm_vidc_sm8550.h"
>> +#include "msm_vidc_platform.h"
>> +
>> +/* version: major[24:31], minor[16:23], revision[0:15] */
>> +#define DRIVER_VERSION          0x04000000
>> +#define DEFAULT_VIDEO_CONCEAL_COLOR_BLACK 0x8020010
>> +#define MAX_BASE_LAYER_PRIORITY_ID 63
>> +#define MAX_OP_POINT            31
>> +#define MAX_BITRATE             245000000
>> +#define DEFAULT_BITRATE         20000000
>> +#define MINIMUM_FPS             1
>> +#define MAXIMUM_FPS             480
>> +#define MAXIMUM_DEC_FPS         960
>> +#define MAX_QP                  51
>> +#define DEFAULT_QP              20
>> +#define MAX_CONSTANT_QUALITY    100
>> +#define MIN_SLICE_BYTE_SIZE     512
>> +#define MAX_SLICE_BYTE_SIZE       \
>> +    ((MAX_BITRATE) >> 3)
>> +#define MAX_SLICE_MB_SIZE         \
>> +    (((4096 + 15) >> 4) * ((2304 + 15) >> 4))
>> +
>> +#define ENC     MSM_VIDC_ENCODER
>> +#define DEC     MSM_VIDC_DECODER
>> +#define H264    MSM_VIDC_H264
>> +#define HEVC    MSM_VIDC_HEVC
>> +#define VP9     MSM_VIDC_VP9
> 
> Another redefinition. Inline it.
> >> +#define CODECS_ALL     (H264 | HEVC | VP9)
>> +#define MAXIMUM_OVERRIDE_VP9_FPS 200
>> +
>> +static struct codec_info codec_data_sm8550[] = {
>> +    {
>> +        .v4l2_codec  = V4L2_PIX_FMT_H264,
>> +        .vidc_codec  = MSM_VIDC_H264,
>> +        .pixfmt_name = "AVC",
> 
> Have you considered using existing code which enumerates formats? For
> example, it is much better to refactor v4l_fill_fmtdesc() to allow getting
> the description instead of adding your own names here.
> Not to mention that printk supports %p4cc for printing fourcc values. I
> hope you knew that.
> 
Sure, will explore more on this.
>> +    },
>> +    {
>> +        .v4l2_codec  = V4L2_PIX_FMT_HEVC,
>> +        .vidc_codec  = MSM_VIDC_HEVC,
>> +        .pixfmt_name = "HEVC",
>> +    },
>> +    {
>> +        .v4l2_codec  = V4L2_PIX_FMT_VP9,
>> +        .vidc_codec  = MSM_VIDC_VP9,
>> +        .pixfmt_name = "VP9",
>> +    },
>> +};
>> +
>> +static struct color_format_info color_format_data_sm8550[] = {
>> +    {
>> +        .v4l2_color_format = V4L2_PIX_FMT_NV12,
>> +        .vidc_color_format = MSM_VIDC_FMT_NV12,
>> +        .pixfmt_name       = "NV12",
>> +    },
>> +    {
>> +        .v4l2_color_format = V4L2_PIX_FMT_NV21,
>> +        .vidc_color_format = MSM_VIDC_FMT_NV21,
>> +        .pixfmt_name       = "NV21",
>> +    },
>> +    {
>> +        .v4l2_color_format = V4L2_PIX_FMT_QC08C,
>> +        .vidc_color_format = MSM_VIDC_FMT_NV12C,
>> +        .pixfmt_name       = "NV12C",
>> +    },
>> +    {
>> +        .v4l2_color_format = V4L2_PIX_FMT_QC10C,
>> +        .vidc_color_format = MSM_VIDC_FMT_TP10C,
>> +        .pixfmt_name       = "TP10C",
>> +    },
>> +    {
>> +        .v4l2_color_format = V4L2_PIX_FMT_RGBA32,
>> +        .vidc_color_format = MSM_VIDC_FMT_RGBA8888,
>> +        .pixfmt_name       = "RGBA",
>> +    },
>> +};
>> +
>> +static struct color_primaries_info color_primaries_data_sm8550[] = {
>> +    {
>> +        .v4l2_color_primaries  = V4L2_COLORSPACE_DEFAULT,
>> +        .vidc_color_primaries  = MSM_VIDC_PRIMARIES_RESERVED,
>> +    },
>> +    {
>> +        .v4l2_color_primaries  = V4L2_COLORSPACE_REC709,
>> +        .vidc_color_primaries  = MSM_VIDC_PRIMARIES_BT709,
>> +    },
>> +    {
>> +        .v4l2_color_primaries  = V4L2_COLORSPACE_470_SYSTEM_M,
>> +        .vidc_color_primaries  = MSM_VIDC_PRIMARIES_BT470_SYSTEM_M,
>> +    },
>> +    {
>> +        .v4l2_color_primaries  = V4L2_COLORSPACE_470_SYSTEM_BG,
>> +        .vidc_color_primaries  = MSM_VIDC_PRIMARIES_BT470_SYSTEM_BG,
>> +    },
>> +    {
>> +        .v4l2_color_primaries  = V4L2_COLORSPACE_SMPTE170M,
>> +        .vidc_color_primaries  = MSM_VIDC_PRIMARIES_BT601_525,
>> +    },
>> +    {
>> +        .v4l2_color_primaries  = V4L2_COLORSPACE_SMPTE240M,
>> +        .vidc_color_primaries  = MSM_VIDC_PRIMARIES_SMPTE_ST240M,
>> +    },
>> +    {
>> +        .v4l2_color_primaries  = V4L2_COLORSPACE_BT2020,
>> +        .vidc_color_primaries  = MSM_VIDC_PRIMARIES_BT2020,
>> +    },
>> +    {
>> +        .v4l2_color_primaries  = V4L2_COLORSPACE_DCI_P3,
>> +        .vidc_color_primaries  = MSM_VIDC_PRIMARIES_SMPTE_RP431_2,
>> +    },
>> +};
>> +
>> +static struct transfer_char_info transfer_char_data_sm8550[] = {
>> +    {
>> +        .v4l2_transfer_char  = V4L2_XFER_FUNC_DEFAULT,
>> +        .vidc_transfer_char  = MSM_VIDC_TRANSFER_RESERVED,
>> +    },
>> +    {
>> +        .v4l2_transfer_char  = V4L2_XFER_FUNC_709,
>> +        .vidc_transfer_char  = MSM_VIDC_TRANSFER_BT709,
>> +    },
>> +    {
>> +        .v4l2_transfer_char  = V4L2_XFER_FUNC_SMPTE240M,
>> +        .vidc_transfer_char  = MSM_VIDC_TRANSFER_SMPTE_ST240M,
>> +    },
>> +    {
>> +        .v4l2_transfer_char  = V4L2_XFER_FUNC_SRGB,
>> +        .vidc_transfer_char  = MSM_VIDC_TRANSFER_SRGB_SYCC,
>> +    },
>> +    {
>> +        .v4l2_transfer_char  = V4L2_XFER_FUNC_SMPTE2084,
>> +        .vidc_transfer_char  = MSM_VIDC_TRANSFER_SMPTE_ST2084_PQ,
>> +    },
>> +};
>> +
>> +static struct matrix_coeff_info matrix_coeff_data_sm8550[] = {
>> +    {
>> +        .v4l2_matrix_coeff  = V4L2_YCBCR_ENC_DEFAULT,
>> +        .vidc_matrix_coeff  = MSM_VIDC_MATRIX_COEFF_RESERVED,
>> +    },
>> +    {
>> +        .v4l2_matrix_coeff  = V4L2_YCBCR_ENC_709,
>> +        .vidc_matrix_coeff  = MSM_VIDC_MATRIX_COEFF_BT709,
>> +    },
>> +    {
>> +        .v4l2_matrix_coeff  = V4L2_YCBCR_ENC_XV709,
>> +        .vidc_matrix_coeff  = MSM_VIDC_MATRIX_COEFF_BT709,
>> +    },
>> +    {
>> +        .v4l2_matrix_coeff  = V4L2_YCBCR_ENC_XV601,
>> +        .vidc_matrix_coeff  =
>> MSM_VIDC_MATRIX_COEFF_BT470_SYS_BG_OR_BT601_625,
>> +    },
>> +    {
>> +        .v4l2_matrix_coeff  = V4L2_YCBCR_ENC_601,
>> +        .vidc_matrix_coeff  =
>> MSM_VIDC_MATRIX_COEFF_BT601_525_BT1358_525_OR_625,
>> +    },
>> +    {
>> +        .v4l2_matrix_coeff  = V4L2_YCBCR_ENC_SMPTE240M,
>> +        .vidc_matrix_coeff  = MSM_VIDC_MATRIX_COEFF_SMPTE_ST240,
>> +    },
>> +    {
>> +        .v4l2_matrix_coeff  = V4L2_YCBCR_ENC_BT2020,
>> +        .vidc_matrix_coeff  = MSM_VIDC_MATRIX_COEFF_BT2020_NON_CONSTANT,
>> +    },
>> +    {
>> +        .v4l2_matrix_coeff  = V4L2_YCBCR_ENC_BT2020_CONST_LUM,
>> +        .vidc_matrix_coeff  = MSM_VIDC_MATRIX_COEFF_BT2020_CONSTANT,
>> +    },
>> +};
> 
> Are you going to say that these tables are platform-specific instead of
> being generic to the driver?
> 
future platform can support new codec and that will require new color
primaries. So, yes these can differ for different platforms.
>> +
>> +static struct msm_platform_core_capability core_data_sm8550[] = {
>> +    /* {type, value} */
>> +    {ENC_CODECS, H264 | HEVC},
>> +    {DEC_CODECS, H264 | HEVC | VP9},
>> +    {MAX_SESSION_COUNT, 16},
>> +    {MAX_NUM_720P_SESSIONS, 16},
>> +    {MAX_NUM_1080P_SESSIONS, 16},
>> +    {MAX_NUM_4K_SESSIONS, 8},
>> +    {MAX_NUM_8K_SESSIONS, 2},
>> +    {MAX_RT_MBPF, 174080},    /* (8192x4352)/256 + (4096x2176)/256*/
>> +    {MAX_MBPF, 278528}, /* ((8192x4352)/256) * 2 */
>> +    {MAX_MBPS, 7833600},    /* max_load
>> +                 * 7680x4320@60fps or 3840x2176@240fps
>> +                 * which is greater than 4096x2176@120fps,
>> +                 * 8192x4320@48fps
>> +                 */
>> +    {MAX_MBPF_HQ, 8160}, /* ((1920x1088)/256) */
>> +    {MAX_MBPS_HQ, 489600}, /* ((1920x1088)/256)@60fps */
>> +    {MAX_MBPF_B_FRAME, 32640}, /* 3840x2176/256 */
>> +    {MAX_MBPS_B_FRAME, 1958400}, /* 3840x2176/256 MBs@60fps */
>> +    {MAX_MBPS_ALL_INTRA, 1044480}, /* 4096x2176/256 MBs@30fps */
>> +    {MAX_ENH_LAYER_COUNT, 5},
>> +    {NUM_VPP_PIPE, 4},
>> +    {SW_PC, 1},
>> +    {FW_UNLOAD, 0},
>> +    {HW_RESPONSE_TIMEOUT, HW_RESPONSE_TIMEOUT_VALUE}, /* 1000 ms */
>> +    {SW_PC_DELAY,         SW_PC_DELAY_VALUE        }, /* 1500 ms
>> (>HW_RESPONSE_TIMEOUT)*/
>> +    {FW_UNLOAD_DELAY,     FW_UNLOAD_DELAY_VALUE    }, /* 3000 ms
>> (>SW_PC_DELAY)*/
>> +    {DCVS, 1},
>> +    {DECODE_BATCH, 1},
>> +    {DECODE_BATCH_TIMEOUT, 200},
>> +    {STATS_TIMEOUT_MS, 2000},
>> +    {NON_FATAL_FAULTS, 1},
>> +    {DEVICE_CAPS, V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING},
> 
> Unless there is a good reason, please change this to be a proper data
> structure instead of being a type-value array. With the T-V it is
> impossible to notice if the value is missing or duplicated. This comment
> also applies to the next 'capability' array.
> 
Core has set of caps. All caps might not be supported for all the hardware.
So it's quite valid to miss a cap entry if its not applicable for that
hardware.
subsequently with caps as enum, it will become easy to copy these caps from
platform to core.

please check msm_vidc_init_core_caps API in [1]

[1]
https://patchwork.linuxtv.org/project/linux-media/patch/1690550624-14642-11-git-send-email-quic_vgarodia@quicinc.com/

>> +};
>> +
>> +static struct msm_platform_inst_capability instance_cap_data_sm8550[] = {
>> +    /* {cap, domain, codec,
>> +     *      min, max, step_or_mask, value,
>> +     *      v4l2_id,
>> +     *      hfi_id,
>> +     *      flags}
>> +     */
>> +    {FRAME_WIDTH, DEC, CODECS_ALL, 96, 8192, 1, 1920},
>> +
>> +    {FRAME_WIDTH, DEC, VP9, 96, 4096, 1, 1920},
>> +
>> +    {FRAME_WIDTH, ENC, CODECS_ALL, 128, 8192, 1, 1920},
>> +
>> +    {FRAME_WIDTH, ENC, HEVC, 96, 8192, 1, 1920},
>> +
>> +    {LOSSLESS_FRAME_WIDTH, ENC, CODECS_ALL, 128, 4096, 1, 1920},
>> +
>> +    {LOSSLESS_FRAME_WIDTH, ENC, HEVC, 96, 4096, 1, 1920},
>> +
>> +    {FRAME_HEIGHT, DEC, CODECS_ALL, 96, 8192, 1, 1080},
>> +
>> +    {FRAME_HEIGHT, DEC, VP9, 96, 4096, 1, 1080},
>> +
>> +    {FRAME_HEIGHT, ENC, CODECS_ALL, 128, 8192, 1, 1080},
>> +
>> +    {FRAME_HEIGHT, ENC, HEVC, 96, 8192, 1, 1080},
>> +
>> +    {LOSSLESS_FRAME_HEIGHT, ENC, CODECS_ALL, 128, 4096, 1, 1080},
>> +
>> +    {LOSSLESS_FRAME_HEIGHT, ENC, HEVC, 96, 4096, 1, 1080},
>> +
>> +    {PIX_FMTS, ENC | DEC, H264,
>> +        MSM_VIDC_FMT_NV12,
>> +        MSM_VIDC_FMT_NV12C,
>> +        MSM_VIDC_FMT_NV12 | MSM_VIDC_FMT_NV21 | MSM_VIDC_FMT_NV12C,
>> +        MSM_VIDC_FMT_NV12C},
>> +
>> +    {PIX_FMTS, ENC | DEC, HEVC | VP9,
>> +        MSM_VIDC_FMT_NV12,
>> +        MSM_VIDC_FMT_TP10C,
>> +        MSM_VIDC_FMT_NV12 | MSM_VIDC_FMT_NV21 | MSM_VIDC_FMT_NV12C |
>> +        MSM_VIDC_FMT_TP10C,
>> +        MSM_VIDC_FMT_NV12C},
>> +
>> +    {MIN_BUFFERS_INPUT, ENC | DEC, CODECS_ALL, 0, 64, 1, 4,
>> +        V4L2_CID_MIN_BUFFERS_FOR_OUTPUT,
>> +        0,
>> +        CAP_FLAG_VOLATILE},
>> +
>> +    {MIN_BUFFERS_OUTPUT, ENC | DEC, CODECS_ALL,
>> +        0, 64, 1, 4,
>> +        V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,
>> +        HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_VOLATILE},
>> +
>> +    /* (8192 * 4320) / 256 */
>> +    {MBPF, ENC, CODECS_ALL, 64, 138240, 1, 138240},
>> +
>> +    {MBPF, ENC, HEVC, 36, 138240, 1, 138240},
>> +
>> +    {MBPF, DEC, CODECS_ALL, 36, 138240, 1, 138240},
>> +
>> +    /* (4096 * 2304) / 256 */
>> +    {MBPF, DEC, VP9, 36, 36864, 1, 36864},
>> +
>> +    /* (4096 * 2304) / 256 */
>> +    {LOSSLESS_MBPF, ENC, H264 | HEVC, 64, 36864, 1, 36864},
>> +
>> +    /* Batch Mode Decode */
>> +    /* TODO: update with new values based on updated voltage corner */
>> +    {BATCH_MBPF, DEC, H264 | HEVC | VP9, 64, 34816, 1, 34816},
>> +
>> +    /* (4096 * 2304) / 256 */
>> +    {BATCH_FPS, DEC, H264 | HEVC | VP9, 1, 120, 1, 120},
>> +
>> +    {FRAME_RATE, ENC | DEC, CODECS_ALL,
>> +        (MINIMUM_FPS << 16), (MAXIMUM_FPS << 16),
>> +        1, (DEFAULT_FPS << 16),
>> +        0,
>> +        HFI_PROP_FRAME_RATE,
>> +        CAP_FLAG_OUTPUT_PORT},
>> +
>> +    {OPERATING_RATE, ENC | DEC, CODECS_ALL,
>> +        (MINIMUM_FPS << 16), (MAXIMUM_FPS << 16),
>> +        1, (DEFAULT_FPS << 16)},
>> +
>> +    {INPUT_RATE, ENC | DEC, CODECS_ALL,
>> +        (MINIMUM_FPS << 16), INT_MAX,
>> +        1, (DEFAULT_FPS << 16)},
>> +
>> +    {TIMESTAMP_RATE, ENC | DEC, CODECS_ALL,
>> +        (MINIMUM_FPS << 16), INT_MAX,
>> +        1, (DEFAULT_FPS << 16)},
>> +
>> +    {SCALE_FACTOR, ENC, H264 | HEVC, 1, 8, 1, 8},
>> +
>> +    {MB_CYCLES_VSP, ENC, CODECS_ALL, 25, 25, 1, 25},
>> +
>> +    {MB_CYCLES_VSP, DEC, CODECS_ALL, 25, 25, 1, 25},
>> +
>> +    {MB_CYCLES_VSP, DEC, VP9, 60, 60, 1, 60},
>> +
>> +    {MB_CYCLES_VPP, ENC, CODECS_ALL, 675, 675, 1, 675},
>> +
>> +    {MB_CYCLES_VPP, DEC, CODECS_ALL, 200, 200, 1, 200},
>> +
>> +    {MB_CYCLES_LP, ENC, CODECS_ALL, 320, 320, 1, 320},
>> +
>> +    {MB_CYCLES_LP, DEC, CODECS_ALL, 200, 200, 1, 200},
>> +
>> +    {MB_CYCLES_FW, ENC | DEC, CODECS_ALL, 489583, 489583, 1, 489583},
>> +
>> +    {MB_CYCLES_FW_VPP, ENC, CODECS_ALL, 48405, 48405, 1, 48405},
>> +
>> +    {MB_CYCLES_FW_VPP, DEC, CODECS_ALL, 66234, 66234, 1, 66234},
>> +
>> +    {HFLIP, ENC, CODECS_ALL,
>> +        0, 1, 1, 0,
>> +        V4L2_CID_HFLIP,
>> +        HFI_PROP_FLIP,
>> +        CAP_FLAG_OUTPUT_PORT |
>> +        CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED},
>> +
>> +    {VFLIP, ENC, CODECS_ALL,
>> +        0, 1, 1, 0,
>> +        V4L2_CID_VFLIP,
>> +        HFI_PROP_FLIP,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> +        CAP_FLAG_DYNAMIC_ALLOWED},
>> +
>> +    {ROTATION, ENC, CODECS_ALL,
>> +        0, 270, 90, 0,
>> +        V4L2_CID_ROTATE,
>> +        HFI_PROP_ROTATION,
>> +        CAP_FLAG_OUTPUT_PORT},
>> +
>> +    {HEADER_MODE, ENC, CODECS_ALL,
>> +        V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE,
>> +        V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
>> +        BIT(V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) |
>> +        BIT(V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME),
>> +        V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE,
>> +        V4L2_CID_MPEG_VIDEO_HEADER_MODE,
>> +        HFI_PROP_SEQ_HEADER_MODE,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
>> +
>> +    {PREPEND_SPSPPS_TO_IDR, ENC, CODECS_ALL,
>> +        0, 1, 1, 0,
>> +        V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR},
>> +
>> +    {WITHOUT_STARTCODE, ENC, CODECS_ALL,
>> +        0, 1, 1, 0,
>> +        V4L2_CID_MPEG_VIDEO_HEVC_WITHOUT_STARTCODE,
>> +        HFI_PROP_NAL_LENGTH_FIELD,
>> +        CAP_FLAG_OUTPUT_PORT},
>> +
>> +    {NAL_LENGTH_FIELD, ENC, CODECS_ALL,
>> +        V4L2_MPEG_VIDEO_HEVC_SIZE_0,
>> +        V4L2_MPEG_VIDEO_HEVC_SIZE_4,
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_SIZE_0) |
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_SIZE_4),
>> +        V4L2_MPEG_VIDEO_HEVC_SIZE_0,
>> +        V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD,
>> +        HFI_PROP_NAL_LENGTH_FIELD,
>> +        CAP_FLAG_MENU | CAP_FLAG_OUTPUT_PORT},
>> +
>> +    /* TODO: Firmware introduced enumeration type for this
>> +     * with and without seq header.
>> +     */
>> +    {REQUEST_I_FRAME, ENC, H264 | HEVC,
>> +        0, 0, 0, 0,
>> +        V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME,
>> +        HFI_PROP_REQUEST_SYNC_FRAME,
>> +        CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED},
>> +
>> +    /* Enc: Keeping CABAC and CAVLC as same bitrate.
>> +     * Dec: there's no use of Bitrate cap
>> +     */
>> +    {BIT_RATE, ENC, H264 | HEVC,
>> +        1, MAX_BITRATE, 1, DEFAULT_BITRATE,
>> +        V4L2_CID_MPEG_VIDEO_BITRATE,
>> +        HFI_PROP_TOTAL_BITRATE,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> +        CAP_FLAG_DYNAMIC_ALLOWED},
>> +
>> +    {BITRATE_MODE, ENC, H264,
>> +        V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
>> +        V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
>> +        BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) |
>> +        BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_CBR),
>> +        V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
>> +        V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
>> +        HFI_PROP_RATE_CONTROL,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
>> +
>> +    {BITRATE_MODE, ENC, HEVC,
>> +        V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
>> +        V4L2_MPEG_VIDEO_BITRATE_MODE_CQ,
>> +        BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) |
>> +        BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) |
>> +        BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_CQ),
>> +        V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
>> +        V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
>> +        HFI_PROP_RATE_CONTROL,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
>> +
>> +    {CABAC_MAX_BITRATE, ENC, H264 | HEVC, 0,
>> +        160000000, 1, 160000000},
>> +
>> +    {CAVLC_MAX_BITRATE, ENC, H264, 0,
>> +        220000000, 1, 220000000},
>> +
>> +    {ALLINTRA_MAX_BITRATE, ENC, H264 | HEVC, 0,
>> +        245000000, 1, 245000000},
>> +
>> +    {NUM_COMV, DEC, CODECS_ALL,
>> +        0, INT_MAX, 1, 0},
>> +
>> +    {LOSSLESS, ENC, HEVC,
>> +        0, 1, 1, 0,
>> +        V4L2_CID_MPEG_VIDEO_HEVC_LOSSLESS_CU},
>> +
>> +    {FRAME_SKIP_MODE, ENC, H264 | HEVC,
>> +        V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED,
>> +        V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT,
>> +        BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED) |
>> +        BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT) |
>> +        BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT),
>> +        V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED,
>> +        V4L2_CID_MPEG_VIDEO_FRAME_SKIP_MODE,
>> +        0,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
>> +
>> +    {FRAME_RC_ENABLE, ENC, H264 | HEVC,
>> +        0, 1, 1, 1,
>> +        V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE},
>> +
>> +    {CONSTANT_QUALITY, ENC, HEVC,
>> +        1, MAX_CONSTANT_QUALITY, 1, 90,
>> +        V4L2_CID_MPEG_VIDEO_CONSTANT_QUALITY,
>> +        HFI_PROP_CONSTANT_QUALITY,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> +        CAP_FLAG_DYNAMIC_ALLOWED},
>> +
>> +    {GOP_SIZE, ENC, CODECS_ALL,
>> +        0, INT_MAX, 1, 2 * DEFAULT_FPS - 1,
>> +        V4L2_CID_MPEG_VIDEO_GOP_SIZE,
>> +        HFI_PROP_MAX_GOP_FRAMES,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> +        CAP_FLAG_DYNAMIC_ALLOWED},
>> +
>> +    {GOP_CLOSURE, ENC, H264 | HEVC,
>> +        0, 1, 1, 1,
>> +        V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
>> +        0},
>> +
>> +    {B_FRAME, ENC, H264 | HEVC,
>> +        0, 7, 1, 0,
>> +        V4L2_CID_MPEG_VIDEO_B_FRAMES,
>> +        HFI_PROP_MAX_B_FRAMES,
>> +        CAP_FLAG_OUTPUT_PORT},
>> +
>> +    {LTR_COUNT, ENC, H264 | HEVC,
>> +        0, MAX_LTR_FRAME_COUNT_2, 1, 0,
>> +        V4L2_CID_MPEG_VIDEO_LTR_COUNT,
>> +        HFI_PROP_LTR_COUNT,
>> +        CAP_FLAG_OUTPUT_PORT},
>> +
>> +    {USE_LTR, ENC, H264 | HEVC,
>> +        0,
>> +        ((1 << MAX_LTR_FRAME_COUNT_2) - 1),
>> +        0, 0,
>> +        V4L2_CID_MPEG_VIDEO_USE_LTR_FRAMES,
>> +        HFI_PROP_LTR_USE,
>> +        CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED},
>> +
>> +    {MARK_LTR, ENC, H264 | HEVC,
>> +        INVALID_DEFAULT_MARK_OR_USE_LTR,
>> +        (MAX_LTR_FRAME_COUNT_2 - 1),
>> +        1, INVALID_DEFAULT_MARK_OR_USE_LTR,
>> +        V4L2_CID_MPEG_VIDEO_FRAME_LTR_INDEX,
>> +        HFI_PROP_LTR_MARK,
>> +        CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED},
>> +
>> +    {BASELAYER_PRIORITY, ENC, H264,
>> +        0, MAX_BASE_LAYER_PRIORITY_ID, 1, 0,
>> +        V4L2_CID_MPEG_VIDEO_BASELAYER_PRIORITY_ID,
>> +        HFI_PROP_BASELAYER_PRIORITYID,
>> +        CAP_FLAG_OUTPUT_PORT},
>> +
>> +    {IR_TYPE, ENC, H264 | HEVC,
>> +        V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_RANDOM,
>> +        V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_CYCLIC,
>> +        BIT(V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_RANDOM) |
>> +        BIT(V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_CYCLIC),
>> +        V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_RANDOM,
>> +        V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE,
>> +        0,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
>> +
>> +    {IR_PERIOD, ENC, H264 | HEVC,
>> +        0, INT_MAX, 1, 0,
>> +        V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD,
>> +        0,
>> +        CAP_FLAG_INPUT_PORT | CAP_FLAG_OUTPUT_PORT |
>> +        CAP_FLAG_DYNAMIC_ALLOWED},
>> +
>> +    {AU_DELIMITER, ENC, H264 | HEVC,
>> +        0, 1, 1, 0,
>> +        V4L2_CID_MPEG_VIDEO_AU_DELIMITER,
>> +        HFI_PROP_AUD,
>> +        CAP_FLAG_OUTPUT_PORT},
>> +
>> +    {MIN_QUALITY, ENC, H264 | HEVC,
>> +        0, MAX_SUPPORTED_MIN_QUALITY, 70, MAX_SUPPORTED_MIN_QUALITY,
>> +        0,
>> +        HFI_PROP_MAINTAIN_MIN_QUALITY,
>> +        CAP_FLAG_OUTPUT_PORT},
>> +
>> +    {VBV_DELAY, ENC, H264 | HEVC,
>> +        200, 300, 100, 300,
>> +        V4L2_CID_MPEG_VIDEO_VBV_DELAY,
>> +        HFI_PROP_VBV_DELAY,
>> +        CAP_FLAG_OUTPUT_PORT},
>> +
>> +    {PEAK_BITRATE, ENC, H264 | HEVC,
>> +        /* default peak bitrate is 10% larger than avg bitrate */
>> +        1, MAX_BITRATE, 1, DEFAULT_BITRATE,
>> +        V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
>> +        HFI_PROP_TOTAL_PEAK_BITRATE,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> +            CAP_FLAG_DYNAMIC_ALLOWED},
>> +
>> +    {MIN_FRAME_QP, ENC, H264,
>> +        MIN_QP_8BIT, MAX_QP, 1, MIN_QP_8BIT,
>> +        V4L2_CID_MPEG_VIDEO_H264_MIN_QP,
>> +        HFI_PROP_MIN_QP_PACKED,
>> +        CAP_FLAG_OUTPUT_PORT},
>> +
>> +    {MIN_FRAME_QP, ENC, HEVC,
>> +        MIN_QP_10BIT, MAX_QP, 1, MIN_QP_10BIT,
>> +        V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP,
>> +        HFI_PROP_MIN_QP_PACKED,
>> +        CAP_FLAG_OUTPUT_PORT},
>> +
>> +    {I_FRAME_MIN_QP, ENC, H264,
>> +        MIN_QP_8BIT, MAX_QP, 1, MIN_QP_8BIT,
>> +        V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MIN_QP},
>> +
>> +    {I_FRAME_MIN_QP, ENC, HEVC,
>> +        MIN_QP_10BIT, MAX_QP, 1, MIN_QP_10BIT,
>> +        V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_MIN_QP},
>> +
>> +    {P_FRAME_MIN_QP, ENC, H264,
>> +        MIN_QP_8BIT, MAX_QP, 1, MIN_QP_8BIT,
>> +        V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MIN_QP},
>> +
>> +    {P_FRAME_MIN_QP, ENC, HEVC,
>> +        MIN_QP_10BIT, MAX_QP, 1, MIN_QP_10BIT,
>> +        V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_MIN_QP},
>> +
>> +    {B_FRAME_MIN_QP, ENC, H264,
>> +        MIN_QP_8BIT, MAX_QP, 1, MIN_QP_8BIT,
>> +        V4L2_CID_MPEG_VIDEO_H264_B_FRAME_MIN_QP},
>> +
>> +    {B_FRAME_MIN_QP, ENC, HEVC,
>> +        MIN_QP_10BIT, MAX_QP, 1, MIN_QP_10BIT,
>> +        V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_MIN_QP},
>> +
>> +    {MAX_FRAME_QP, ENC, H264,
>> +        MIN_QP_8BIT, MAX_QP, 1, MAX_QP,
>> +        V4L2_CID_MPEG_VIDEO_H264_MAX_QP,
>> +        HFI_PROP_MAX_QP_PACKED,
>> +        CAP_FLAG_OUTPUT_PORT},
>> +
>> +    {MAX_FRAME_QP, ENC, HEVC,
>> +        MIN_QP_10BIT, MAX_QP, 1, MAX_QP,
>> +        V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP,
>> +        HFI_PROP_MAX_QP_PACKED,
>> +        CAP_FLAG_OUTPUT_PORT},
>> +
>> +    {I_FRAME_MAX_QP, ENC, H264,
>> +        MIN_QP_8BIT, MAX_QP, 1, MAX_QP,
>> +        V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MAX_QP},
>> +
>> +    {I_FRAME_MAX_QP, ENC, HEVC,
>> +        MIN_QP_10BIT, MAX_QP, 1, MAX_QP,
>> +        V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_MAX_QP},
>> +
>> +    {P_FRAME_MAX_QP, ENC, H264,
>> +        MIN_QP_8BIT, MAX_QP, 1, MAX_QP,
>> +        V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MAX_QP},
>> +
>> +    {P_FRAME_MAX_QP, ENC, HEVC,
>> +        MIN_QP_10BIT, MAX_QP, 1, MAX_QP,
>> +        V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_MAX_QP},
>> +
>> +    {B_FRAME_MAX_QP, ENC, H264,
>> +        MIN_QP_8BIT, MAX_QP, 1, MAX_QP,
>> +        V4L2_CID_MPEG_VIDEO_H264_B_FRAME_MAX_QP},
>> +
>> +    {B_FRAME_MAX_QP, ENC, HEVC,
>> +        MIN_QP_10BIT, MAX_QP, 1, MAX_QP,
>> +        V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_MAX_QP},
>> +
>> +    {I_FRAME_QP, ENC, HEVC,
>> +        MIN_QP_10BIT, MAX_QP, 1, DEFAULT_QP,
>> +        V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP,
>> +        HFI_PROP_QP_PACKED,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> +            CAP_FLAG_DYNAMIC_ALLOWED},
>> +
>> +    {I_FRAME_QP, ENC, H264,
>> +        MIN_QP_8BIT, MAX_QP, 1, DEFAULT_QP,
>> +        V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP,
>> +        HFI_PROP_QP_PACKED,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> +            CAP_FLAG_DYNAMIC_ALLOWED},
>> +
>> +    {P_FRAME_QP, ENC, HEVC,
>> +        MIN_QP_10BIT, MAX_QP, 1, DEFAULT_QP,
>> +        V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP,
>> +        HFI_PROP_QP_PACKED,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> +            CAP_FLAG_DYNAMIC_ALLOWED},
>> +
>> +    {P_FRAME_QP, ENC, H264,
>> +        MIN_QP_8BIT, MAX_QP, 1, DEFAULT_QP,
>> +        V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP,
>> +        HFI_PROP_QP_PACKED,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> +            CAP_FLAG_DYNAMIC_ALLOWED},
>> +
>> +    {B_FRAME_QP, ENC, HEVC,
>> +        MIN_QP_10BIT, MAX_QP, 1, DEFAULT_QP,
>> +        V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP,
>> +        HFI_PROP_QP_PACKED,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> +            CAP_FLAG_DYNAMIC_ALLOWED},
>> +
>> +    {B_FRAME_QP, ENC, H264,
>> +        MIN_QP_8BIT, MAX_QP, 1, DEFAULT_QP,
>> +        V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP,
>> +        HFI_PROP_QP_PACKED,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> +            CAP_FLAG_DYNAMIC_ALLOWED},
>> +
>> +    {LAYER_TYPE, ENC, HEVC,
>> +        V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B,
>> +        V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P,
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B) |
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P),
>> +        V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P,
>> +        V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE,
>> +        HFI_PROP_LAYER_ENCODING_TYPE,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
>> +
>> +    {LAYER_TYPE, ENC, H264,
>> +        V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B,
>> +        V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P,
>> +        BIT(V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P),
>> +        V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P,
>> +        V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE,
>> +        HFI_PROP_LAYER_ENCODING_TYPE,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
>> +
>> +    {LAYER_ENABLE, ENC, H264,
>> +        0, 1, 1, 0,
>> +        V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING,
>> +        HFI_PROP_LAYER_ENCODING_TYPE,
>> +        CAP_FLAG_OUTPUT_PORT},
>> +
>> +    {LAYER_ENABLE, ENC, HEVC,
>> +        0, 1, 1, 0,
>> +        0,
>> +        0,
>> +        CAP_FLAG_OUTPUT_PORT},
>> +
>> +    {ENH_LAYER_COUNT, ENC, HEVC,
>> +        0, 5, 1, 0,
>> +        V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER,
>> +        HFI_PROP_LAYER_COUNT,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> +            CAP_FLAG_DYNAMIC_ALLOWED},
>> +
>> +    {ENH_LAYER_COUNT, ENC, H264,
>> +        0, 5, 1, 0,
>> +        V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER,
>> +        HFI_PROP_LAYER_COUNT,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> +            CAP_FLAG_DYNAMIC_ALLOWED},
>> +
>> +    {L0_BR, ENC, H264,
>> +        1, MAX_BITRATE, 1, DEFAULT_BITRATE,
>> +        V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L0_BR,
>> +        HFI_PROP_BITRATE_LAYER1,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> +            CAP_FLAG_DYNAMIC_ALLOWED},
>> +
>> +    {L0_BR, ENC, HEVC,
>> +        1, MAX_BITRATE, 1, DEFAULT_BITRATE,
>> +        V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L0_BR,
>> +        HFI_PROP_BITRATE_LAYER1,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> +            CAP_FLAG_DYNAMIC_ALLOWED},
>> +
>> +    {L1_BR, ENC, H264,
>> +        1, MAX_BITRATE, 1, DEFAULT_BITRATE,
>> +        V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L1_BR,
>> +        HFI_PROP_BITRATE_LAYER2,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> +            CAP_FLAG_DYNAMIC_ALLOWED},
>> +
>> +    {L1_BR, ENC, HEVC,
>> +        1, MAX_BITRATE, 1, DEFAULT_BITRATE,
>> +        V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L1_BR,
>> +        HFI_PROP_BITRATE_LAYER2,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> +            CAP_FLAG_DYNAMIC_ALLOWED},
>> +
>> +    {L2_BR, ENC, H264,
>> +        1, MAX_BITRATE, 1, DEFAULT_BITRATE,
>> +        V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L2_BR,
>> +        HFI_PROP_BITRATE_LAYER3,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> +            CAP_FLAG_DYNAMIC_ALLOWED},
>> +
>> +    {L2_BR, ENC, HEVC,
>> +        1, MAX_BITRATE, 1, DEFAULT_BITRATE,
>> +        V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L2_BR,
>> +        HFI_PROP_BITRATE_LAYER3,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> +            CAP_FLAG_DYNAMIC_ALLOWED},
>> +
>> +    {L3_BR, ENC, H264,
>> +        1, MAX_BITRATE, 1, DEFAULT_BITRATE,
>> +        V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L3_BR,
>> +        HFI_PROP_BITRATE_LAYER4,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> +            CAP_FLAG_DYNAMIC_ALLOWED},
>> +    {L3_BR, ENC, HEVC,
>> +        1, MAX_BITRATE, 1, DEFAULT_BITRATE,
>> +        V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L3_BR,
>> +        HFI_PROP_BITRATE_LAYER4,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> +            CAP_FLAG_DYNAMIC_ALLOWED},
>> +
>> +    {L4_BR, ENC, H264,
>> +        1, MAX_BITRATE, 1, DEFAULT_BITRATE,
>> +        V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L4_BR,
>> +        HFI_PROP_BITRATE_LAYER5,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> +            CAP_FLAG_DYNAMIC_ALLOWED},
>> +
>> +    {L4_BR, ENC, HEVC,
>> +        1, MAX_BITRATE, 1, DEFAULT_BITRATE,
>> +        V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L4_BR,
>> +        HFI_PROP_BITRATE_LAYER5,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> +            CAP_FLAG_DYNAMIC_ALLOWED},
>> +
>> +    {L5_BR, ENC, H264,
>> +        1, MAX_BITRATE, 1, DEFAULT_BITRATE,
>> +        V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L5_BR,
>> +        HFI_PROP_BITRATE_LAYER6,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> +            CAP_FLAG_DYNAMIC_ALLOWED},
>> +
>> +    {L5_BR, ENC, HEVC,
>> +        1, MAX_BITRATE, 1, DEFAULT_BITRATE,
>> +        V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L5_BR,
>> +        HFI_PROP_BITRATE_LAYER6,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> +            CAP_FLAG_DYNAMIC_ALLOWED},
>> +
>> +    {ENTROPY_MODE, ENC, H264,
>> +        V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
>> +        V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
>> +        BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC),
>> +        V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
>> +        V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE,
>> +        HFI_PROP_CABAC_SESSION,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
>> +
>> +    {ENTROPY_MODE, DEC, H264 | HEVC | VP9,
>> +        V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
>> +        V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
>> +        BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC),
>> +        V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
>> +        0,
>> +        HFI_PROP_CABAC_SESSION},
>> +
>> +    {PROFILE, ENC | DEC, H264,
>> +        V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
>> +        V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH,
>> +        BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH),
>> +        V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
>> +        V4L2_CID_MPEG_VIDEO_H264_PROFILE,
>> +        HFI_PROP_PROFILE,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
>> +
>> +    {PROFILE, ENC | DEC, HEVC,
>> +        V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
>> +        V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10,
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) |
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE) |
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10),
>> +        V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
>> +        V4L2_CID_MPEG_VIDEO_HEVC_PROFILE,
>> +        HFI_PROP_PROFILE,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
>> +
>> +    {PROFILE, DEC, VP9,
>> +        V4L2_MPEG_VIDEO_VP9_PROFILE_0,
>> +        V4L2_MPEG_VIDEO_VP9_PROFILE_2,
>> +        BIT(V4L2_MPEG_VIDEO_VP9_PROFILE_0) |
>> +        BIT(V4L2_MPEG_VIDEO_VP9_PROFILE_2),
>> +        V4L2_MPEG_VIDEO_VP9_PROFILE_0,
>> +        V4L2_CID_MPEG_VIDEO_VP9_PROFILE,
>> +        HFI_PROP_PROFILE,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
>> +
>> +    {LEVEL, ENC, H264,
>> +        V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
>> +        V4L2_MPEG_VIDEO_H264_LEVEL_6_0,
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_0) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_1) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_2) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_0),
>> +        V4L2_MPEG_VIDEO_H264_LEVEL_5_0,
>> +        V4L2_CID_MPEG_VIDEO_H264_LEVEL,
>> +        HFI_PROP_LEVEL,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
>> +
>> +    {LEVEL, ENC, HEVC,
>> +        V4L2_MPEG_VIDEO_HEVC_LEVEL_1,
>> +        V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2,
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_1) |
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2) |
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) |
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3) |
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) |
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4) |
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1) |
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5) |
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1) |
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2) |
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6) |
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1) |
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2),
>> +        V4L2_MPEG_VIDEO_HEVC_LEVEL_5,
>> +        V4L2_CID_MPEG_VIDEO_HEVC_LEVEL,
>> +        HFI_PROP_LEVEL,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
>> +
>> +    {LEVEL, DEC, H264,
>> +        V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
>> +        V4L2_MPEG_VIDEO_H264_LEVEL_6_2,
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_0) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_1) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_2) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_0) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_1) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_2),
>> +        V4L2_MPEG_VIDEO_H264_LEVEL_6_1,
>> +        V4L2_CID_MPEG_VIDEO_H264_LEVEL,
>> +        HFI_PROP_LEVEL,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
>> +
>> +    {LEVEL, DEC, HEVC,
>> +        V4L2_MPEG_VIDEO_HEVC_LEVEL_1,
>> +        V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2,
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_1) |
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2) |
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) |
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3) |
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) |
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4) |
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1) |
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5) |
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1) |
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2) |
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6) |
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1) |
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2),
>> +        V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1,
>> +        V4L2_CID_MPEG_VIDEO_HEVC_LEVEL,
>> +        HFI_PROP_LEVEL,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
>> +
>> +    {LEVEL, DEC, VP9,
>> +        V4L2_MPEG_VIDEO_VP9_LEVEL_1_0,
>> +        V4L2_MPEG_VIDEO_VP9_LEVEL_6_0,
>> +        BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_1_0) |
>> +        BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_1_1) |
>> +        BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_2_0) |
>> +        BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_2_1) |
>> +        BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_3_0) |
>> +        BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_3_1) |
>> +        BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_4_0) |
>> +        BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_4_1) |
>> +        BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_5_0) |
>> +        BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_5_1) |
>> +        BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_5_2) |
>> +        BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_6_0),
>> +        V4L2_MPEG_VIDEO_VP9_LEVEL_6_0,
>> +        V4L2_CID_MPEG_VIDEO_VP9_LEVEL,
>> +        HFI_PROP_LEVEL,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
>> +
>> +    {HEVC_TIER, ENC | DEC, HEVC,
>> +        V4L2_MPEG_VIDEO_HEVC_TIER_MAIN,
>> +        V4L2_MPEG_VIDEO_HEVC_TIER_HIGH,
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_TIER_MAIN) |
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_TIER_HIGH),
>> +        V4L2_MPEG_VIDEO_HEVC_TIER_HIGH,
>> +        V4L2_CID_MPEG_VIDEO_HEVC_TIER,
>> +        HFI_PROP_TIER,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
>> +
>> +    {LF_MODE, ENC, H264,
>> +        V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED,
>> +        DB_H264_DISABLE_SLICE_BOUNDARY,
>> +        BIT(V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED) |
>> +        BIT(V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED) |
>> +        BIT(DB_H264_DISABLE_SLICE_BOUNDARY),
>> +        V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED,
>> +        V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE,
>> +        HFI_PROP_DEBLOCKING_MODE,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
>> +
>> +    {LF_MODE, ENC, HEVC,
>> +        V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_DISABLED,
>> +        DB_HEVC_DISABLE_SLICE_BOUNDARY,
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_DISABLED) |
>> +        BIT(V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_ENABLED) |
>> +        BIT(DB_HEVC_DISABLE_SLICE_BOUNDARY),
>> +        V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_ENABLED,
>> +        V4L2_CID_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE,
>> +        HFI_PROP_DEBLOCKING_MODE,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
>> +
>> +    {LF_ALPHA, ENC, H264,
>> +        -6, 6, 1, 0,
>> +        V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA},
>> +
>> +    {LF_ALPHA, ENC, HEVC,
>> +        -6, 6, 1, 0,
>> +        V4L2_CID_MPEG_VIDEO_HEVC_LF_TC_OFFSET_DIV2},
>> +
>> +    {LF_BETA, ENC, H264,
>> +        -6, 6, 1, 0,
>> +        V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA},
>> +
>> +    {LF_BETA, ENC, HEVC,
>> +        -6, 6, 1, 0,
>> +        V4L2_CID_MPEG_VIDEO_HEVC_LF_BETA_OFFSET_DIV2},
>> +
>> +    {SLICE_MODE, ENC, H264 | HEVC,
>> +        V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE,
>> +        V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES,
>> +        BIT(V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE) |
>> +        BIT(V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) |
>> +        BIT(V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES),
>> +        V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE,
>> +        V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE,
>> +        0,
>> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
>> +
>> +    {SLICE_MAX_BYTES, ENC, H264 | HEVC,
>> +        MIN_SLICE_BYTE_SIZE, MAX_SLICE_BYTE_SIZE,
>> +        1, MIN_SLICE_BYTE_SIZE,
>> +        V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES,
>> +        HFI_PROP_MULTI_SLICE_BYTES_COUNT,
>> +        CAP_FLAG_OUTPUT_PORT},
>> +
>> +    {SLICE_MAX_MB, ENC, H264 | HEVC,
>> +        1, MAX_SLICE_MB_SIZE, 1, 1,
>> +        V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB,
>> +        HFI_PROP_MULTI_SLICE_MB_COUNT,
>> +        CAP_FLAG_OUTPUT_PORT},
>> +
>> +    {MB_RC, ENC, H264 | HEVC,
>> +        0, 1, 1, 1,
>> +        V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE,
>> +        0,
>> +        CAP_FLAG_OUTPUT_PORT},
>> +
>> +    {TRANSFORM_8X8, ENC, H264,
>> +        0, 1, 1, 1,
>> +        V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM,
>> +        HFI_PROP_8X8_TRANSFORM,
>> +        CAP_FLAG_OUTPUT_PORT},
>> +
>> +    {CHROMA_QP_INDEX_OFFSET, ENC, HEVC,
>> +        MIN_CHROMA_QP_OFFSET, MAX_CHROMA_QP_OFFSET,
>> +        1, MAX_CHROMA_QP_OFFSET,
>> +        V4L2_CID_MPEG_VIDEO_H264_CHROMA_QP_INDEX_OFFSET,
>> +        HFI_PROP_CHROMA_QP_OFFSET,
>> +        CAP_FLAG_OUTPUT_PORT},
>> +
>> +    {DISPLAY_DELAY_ENABLE, DEC, H264 | HEVC | VP9,
>> +        0, 1, 1, 0,
>> +        V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE,
>> +        HFI_PROP_DECODE_ORDER_OUTPUT,
>> +        CAP_FLAG_INPUT_PORT},
>> +
>> +    {DISPLAY_DELAY, DEC, H264 | HEVC | VP9,
>> +        0, 1, 1, 0,
>> +        V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY,
>> +        HFI_PROP_DECODE_ORDER_OUTPUT,
>> +        CAP_FLAG_INPUT_PORT},
>> +
>> +    {OUTPUT_ORDER, DEC, H264 | HEVC | VP9,
>> +        0, 1, 1, 0,
>> +        0,
>> +        HFI_PROP_DECODE_ORDER_OUTPUT,
>> +        CAP_FLAG_INPUT_PORT},
>> +
>> +    {INPUT_BUF_HOST_MAX_COUNT, ENC | DEC, CODECS_ALL,
>> +        DEFAULT_MAX_HOST_BUF_COUNT, DEFAULT_MAX_HOST_BURST_BUF_COUNT,
>> +        1, DEFAULT_MAX_HOST_BUF_COUNT,
>> +        0,
>> +        HFI_PROP_BUFFER_HOST_MAX_COUNT,
>> +        CAP_FLAG_INPUT_PORT},
>> +
>> +    {OUTPUT_BUF_HOST_MAX_COUNT, ENC | DEC, CODECS_ALL,
>> +        DEFAULT_MAX_HOST_BUF_COUNT, DEFAULT_MAX_HOST_BURST_BUF_COUNT,
>> +        1, DEFAULT_MAX_HOST_BUF_COUNT,
>> +        0,
>> +        HFI_PROP_BUFFER_HOST_MAX_COUNT,
>> +        CAP_FLAG_OUTPUT_PORT},
>> +
>> +    {CONCEAL_COLOR_8BIT, DEC, CODECS_ALL, 0x0, 0xff3fcff, 1,
>> +        DEFAULT_VIDEO_CONCEAL_COLOR_BLACK,
>> +        V4L2_CID_MPEG_VIDEO_MUTE_YUV,
>> +        HFI_PROP_CONCEAL_COLOR_8BIT,
>> +        CAP_FLAG_INPUT_PORT},
>> +
>> +    {CONCEAL_COLOR_10BIT, DEC, CODECS_ALL, 0x0, 0x3fffffff, 1,
>> +        DEFAULT_VIDEO_CONCEAL_COLOR_BLACK,
>> +        V4L2_CID_MPEG_VIDEO_MUTE_YUV,
>> +        HFI_PROP_CONCEAL_COLOR_10BIT,
>> +        CAP_FLAG_INPUT_PORT},
>> +
>> +    {STAGE, DEC | ENC, CODECS_ALL,
>> +        MSM_VIDC_STAGE_1,
>> +        MSM_VIDC_STAGE_2, 1,
>> +        MSM_VIDC_STAGE_2,
>> +        0,
>> +        HFI_PROP_STAGE},
>> +
>> +    {PIPE, DEC | ENC, CODECS_ALL,
>> +        MSM_VIDC_PIPE_1,
>> +        MSM_VIDC_PIPE_4, 1,
>> +        MSM_VIDC_PIPE_4,
>> +        0,
>> +        HFI_PROP_PIPE},
>> +
>> +    {POC, DEC, H264, 0, 2, 1, 1,
>> +        0,
>> +        HFI_PROP_PIC_ORDER_CNT_TYPE},
>> +
>> +    {QUALITY_MODE, ENC, CODECS_ALL,
>> +        MSM_VIDC_MAX_QUALITY_MODE,
>> +        MSM_VIDC_POWER_SAVE_MODE, 1,
>> +        MSM_VIDC_POWER_SAVE_MODE},
>> +
>> +    {CODED_FRAMES, DEC, H264 | HEVC,
>> +        CODED_FRAMES_PROGRESSIVE, CODED_FRAMES_INTERLACE,
>> +        1, CODED_FRAMES_PROGRESSIVE,
>> +        0,
>> +        HFI_PROP_CODED_FRAMES},
>> +
>> +    {BIT_DEPTH, DEC, CODECS_ALL, BIT_DEPTH_8, BIT_DEPTH_10, 1, BIT_DEPTH_8,
>> +        0,
>> +        HFI_PROP_LUMA_CHROMA_BIT_DEPTH},
>> +
>> +    {BITSTREAM_SIZE_OVERWRITE, DEC, CODECS_ALL, 0, INT_MAX, 1, 0,
>> +        0},
>> +
>> +    {DEFAULT_HEADER, DEC, CODECS_ALL,
>> +        0, 1, 1, 0,
>> +        0,
>> +        HFI_PROP_DEC_DEFAULT_HEADER},
>> +
>> +    {RAP_FRAME, DEC, CODECS_ALL,
>> +        0, 1, 1, 1,
>> +        0,
>> +        HFI_PROP_DEC_START_FROM_RAP_FRAME,
>> +        CAP_FLAG_INPUT_PORT},
>> +
>> +    {SEQ_CHANGE_AT_SYNC_FRAME, DEC, CODECS_ALL,
>> +        0, 1, 1, 1,
>> +        0,
>> +        HFI_PROP_SEQ_CHANGE_AT_SYNC_FRAME,
>> +        CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED},
>> +
>> +    {ALL_INTRA, ENC, H264 | HEVC,
>> +        0, 1, 1, 0,
>> +        0,
>> +        0,
>> +        CAP_FLAG_OUTPUT_PORT},
>> +};
>> +
>> +static struct msm_platform_inst_cap_dependency
>> instance_cap_dependency_data_sm8550[] = {
>> +    /* {cap, domain, codec,
>> +     *      children,
>> +     *      adjust, set}
>> +     */
>> +
>> +    {PIX_FMTS, ENC, H264,
>> +        {IR_PERIOD}},
>> +
>> +    {PIX_FMTS, ENC, HEVC,
>> +        {PROFILE, MIN_FRAME_QP, MAX_FRAME_QP, I_FRAME_QP, P_FRAME_QP,
>> +            B_FRAME_QP, MIN_QUALITY, IR_PERIOD, LTR_COUNT}},
>> +
>> +    {PIX_FMTS, DEC, HEVC,
>> +        {PROFILE}},
>> +
>> +    {FRAME_RATE, ENC, CODECS_ALL,
>> +        {0},
>> +        NULL,
>> +        msm_vidc_set_q16},
>> +
>> +    {HFLIP, ENC, CODECS_ALL,
>> +        {0},
>> +        NULL,
>> +        msm_vidc_set_flip},
>> +
>> +    {VFLIP, ENC, CODECS_ALL,
>> +        {0},
>> +        NULL,
>> +        msm_vidc_set_flip},
>> +
>> +    {ROTATION, ENC, CODECS_ALL,
>> +        {0},
>> +        NULL,
>> +        msm_vidc_set_rotation},
>> +
>> +    {HEADER_MODE, ENC, CODECS_ALL,
>> +        {0},
>> +        NULL,
>> +        msm_vidc_set_header_mode},
>> +
>> +    {WITHOUT_STARTCODE, ENC, CODECS_ALL,
>> +        {0},
>> +        NULL,
>> +        msm_vidc_set_nal_length},
>> +
>> +    {REQUEST_I_FRAME, ENC, H264 | HEVC,
>> +        {0},
>> +        NULL,
>> +        msm_vidc_set_req_sync_frame},
>> +
>> +    {BIT_RATE, ENC, H264,
>> +        {PEAK_BITRATE, L0_BR},
>> +        msm_vidc_adjust_bitrate,
>> +        msm_vidc_set_bitrate},
>> +
>> +    {BIT_RATE, ENC, HEVC,
>> +        {PEAK_BITRATE, L0_BR},
>> +        msm_vidc_adjust_bitrate,
>> +        msm_vidc_set_bitrate},
>> +
>> +    {BITRATE_MODE, ENC, H264,
>> +        {LTR_COUNT, IR_PERIOD, I_FRAME_QP, P_FRAME_QP,
>> +            B_FRAME_QP, ENH_LAYER_COUNT, BIT_RATE,
>> +            MIN_QUALITY, VBV_DELAY,
>> +            PEAK_BITRATE, SLICE_MODE},
>> +        msm_vidc_adjust_bitrate_mode,
>> +        msm_vidc_set_u32_enum},
>> +
>> +    {BITRATE_MODE, ENC, HEVC,
>> +        {LTR_COUNT, IR_PERIOD, I_FRAME_QP, P_FRAME_QP,
>> +            B_FRAME_QP, CONSTANT_QUALITY, ENH_LAYER_COUNT,
>> +            BIT_RATE, MIN_QUALITY, VBV_DELAY,
>> +            PEAK_BITRATE, SLICE_MODE},
>> +        msm_vidc_adjust_bitrate_mode,
>> +        msm_vidc_set_u32_enum},
>> +
>> +    {CONSTANT_QUALITY, ENC, HEVC,
>> +        {0},
>> +        NULL,
>> +        msm_vidc_set_constant_quality},
>> +
>> +    {GOP_SIZE, ENC, CODECS_ALL,
>> +        {ALL_INTRA},
>> +        msm_vidc_adjust_gop_size,
>> +        msm_vidc_set_gop_size},
>> +
>> +    {B_FRAME, ENC, H264 | HEVC,
>> +        {ALL_INTRA},
>> +        msm_vidc_adjust_b_frame,
>> +        msm_vidc_set_u32},
>> +
>> +    {LTR_COUNT, ENC, H264 | HEVC,
>> +        {0},
>> +        msm_vidc_adjust_ltr_count,
>> +        msm_vidc_set_u32},
>> +
>> +    {USE_LTR, ENC, H264 | HEVC,
>> +        {0},
>> +        msm_vidc_adjust_use_ltr,
>> +        msm_vidc_set_use_and_mark_ltr},
>> +
>> +    {MARK_LTR, ENC, H264 | HEVC,
>> +        {0},
>> +        msm_vidc_adjust_mark_ltr,
>> +        msm_vidc_set_use_and_mark_ltr},
>> +
>> +    {IR_PERIOD, ENC, H264 | HEVC,
>> +        {0},
>> +        msm_vidc_adjust_ir_period,
>> +        msm_vidc_set_ir_period},
>> +
>> +    {AU_DELIMITER, ENC, H264 | HEVC,
>> +        {0},
>> +        NULL,
>> +        msm_vidc_set_u32},
>> +
>> +    {MIN_QUALITY, ENC, H264,
>> +        {0},
>> +        msm_vidc_adjust_min_quality,
>> +        msm_vidc_set_u32},
>> +
>> +    {MIN_QUALITY, ENC, HEVC,
>> +        {0},
>> +        msm_vidc_adjust_min_quality,
>> +        msm_vidc_set_u32},
>> +
>> +    {VBV_DELAY, ENC, H264 | HEVC,
>> +        {0},
>> +        NULL,
>> +        msm_vidc_set_cbr_related_properties},
>> +
>> +    {PEAK_BITRATE, ENC, H264 | HEVC,
>> +        {0},
>> +        msm_vidc_adjust_peak_bitrate,
>> +        msm_vidc_set_cbr_related_properties},
>> +
>> +    {MIN_FRAME_QP, ENC, H264,
>> +        {0},
>> +        NULL,
>> +        msm_vidc_set_min_qp},
>> +
>> +    {MIN_FRAME_QP, ENC, HEVC,
>> +        {0},
>> +        msm_vidc_adjust_hevc_min_qp,
>> +        msm_vidc_set_min_qp},
>> +
>> +    {MAX_FRAME_QP, ENC, H264,
>> +        {0},
>> +        NULL,
>> +        msm_vidc_set_max_qp},
>> +
>> +    {MAX_FRAME_QP, ENC, HEVC,
>> +        {0},
>> +        msm_vidc_adjust_hevc_max_qp,
>> +        msm_vidc_set_max_qp},
>> +
>> +    {I_FRAME_QP, ENC, HEVC,
>> +        {0},
>> +        msm_vidc_adjust_hevc_i_frame_qp,
>> +        msm_vidc_set_frame_qp},
>> +
>> +    {I_FRAME_QP, ENC, H264,
>> +        {0},
>> +        NULL,
>> +        msm_vidc_set_frame_qp},
>> +
>> +    {P_FRAME_QP, ENC, HEVC,
>> +        {0},
>> +        msm_vidc_adjust_hevc_p_frame_qp,
>> +        msm_vidc_set_frame_qp},
>> +
>> +    {P_FRAME_QP, ENC, H264,
>> +        {0},
>> +        NULL,
>> +        msm_vidc_set_frame_qp},
>> +
>> +    {B_FRAME_QP, ENC, HEVC,
>> +        {0},
>> +        msm_vidc_adjust_hevc_b_frame_qp,
>> +        msm_vidc_set_frame_qp},
>> +
>> +    {B_FRAME_QP, ENC, H264,
>> +        {0},
>> +        NULL,
>> +        msm_vidc_set_frame_qp},
>> +
>> +    {LAYER_TYPE, ENC, H264 | HEVC,
>> +        {LTR_COUNT}},
>> +
>> +    {LAYER_ENABLE, ENC, H264 | HEVC,
>> +        {0}},
>> +
>> +    {ENH_LAYER_COUNT, ENC, H264 | HEVC,
>> +        {GOP_SIZE, B_FRAME, BIT_RATE, MIN_QUALITY, SLICE_MODE,
>> +            LTR_COUNT},
>> +        msm_vidc_adjust_layer_count,
>> +        msm_vidc_set_layer_count_and_type},
>> +
>> +    {L0_BR, ENC, H264 | HEVC,
>> +        {L1_BR},
>> +        msm_vidc_adjust_layer_bitrate,
>> +        msm_vidc_set_layer_bitrate},
>> +
>> +    {L1_BR, ENC, H264 | HEVC,
>> +        {L2_BR},
>> +        msm_vidc_adjust_layer_bitrate,
>> +        msm_vidc_set_layer_bitrate},
>> +
>> +    {L2_BR, ENC, H264 | HEVC,
>> +        {L3_BR},
>> +        msm_vidc_adjust_layer_bitrate,
>> +        msm_vidc_set_layer_bitrate},
>> +
>> +    {L3_BR, ENC, H264 | HEVC,
>> +        {L4_BR},
>> +        msm_vidc_adjust_layer_bitrate,
>> +        msm_vidc_set_layer_bitrate},
>> +
>> +    {L4_BR, ENC, H264 | HEVC,
>> +        {L5_BR},
>> +        msm_vidc_adjust_layer_bitrate,
>> +        msm_vidc_set_layer_bitrate},
>> +
>> +    {L5_BR, ENC, H264 | HEVC,
>> +        {0},
>> +        msm_vidc_adjust_layer_bitrate,
>> +        msm_vidc_set_layer_bitrate},
>> +
>> +    {ENTROPY_MODE, ENC, H264,
>> +        {BIT_RATE},
>> +        msm_vidc_adjust_entropy_mode,
>> +        msm_vidc_set_u32},
>> +
>> +    {PROFILE, ENC, H264,
>> +        {ENTROPY_MODE, TRANSFORM_8X8},
>> +        NULL,
>> +        msm_vidc_set_u32_enum},
>> +
>> +    {PROFILE, DEC, H264,
>> +        {ENTROPY_MODE},
>> +        NULL,
>> +        msm_vidc_set_u32_enum},
>> +
>> +    {PROFILE, ENC | DEC, HEVC,
>> +        {0},
>> +        msm_vidc_adjust_profile,
>> +        msm_vidc_set_u32_enum},
>> +
>> +    {PROFILE, DEC, VP9,
>> +        {0},
>> +        NULL,
>> +        msm_vidc_set_u32_enum},
>> +
>> +    {LEVEL, DEC, CODECS_ALL,
>> +        {0},
>> +        NULL,
>> +        msm_vidc_set_u32_enum},
>> +
>> +    {LEVEL, ENC, CODECS_ALL,
>> +        {0},
>> +        NULL,
>> +        msm_vidc_set_level},
>> +
>> +    {HEVC_TIER, ENC | DEC, HEVC,
>> +        {0},
>> +        NULL,
>> +        msm_vidc_set_u32_enum},
>> +
>> +    {LF_MODE, ENC, CODECS_ALL,
>> +        {0},
>> +        NULL,
>> +        msm_vidc_set_deblock_mode},
>> +
>> +    {SLICE_MODE, ENC, H264 | HEVC,
>> +        {STAGE},
>> +        msm_vidc_adjust_slice_count,
>> +        msm_vidc_set_slice_count},
>> +
>> +    {TRANSFORM_8X8, ENC, H264,
>> +        {0},
>> +        msm_vidc_adjust_transform_8x8,
>> +        msm_vidc_set_u32},
>> +
>> +    {CHROMA_QP_INDEX_OFFSET, ENC, HEVC,
>> +        {0},
>> +        msm_vidc_adjust_chroma_qp_index_offset,
>> +        msm_vidc_set_chroma_qp_index_offset},
>> +
>> +    {DISPLAY_DELAY_ENABLE, DEC, H264 | HEVC | VP9,
>> +        {OUTPUT_ORDER},
>> +        NULL,
>> +        NULL},
>> +
>> +    {DISPLAY_DELAY, DEC, H264 | HEVC | VP9,
>> +        {OUTPUT_ORDER},
>> +        NULL,
>> +        NULL},
>> +
>> +    {OUTPUT_ORDER, DEC, H264 | HEVC | VP9,
>> +        {0},
>> +        msm_vidc_adjust_output_order,
>> +        msm_vidc_set_u32},
>> +
>> +    {INPUT_BUF_HOST_MAX_COUNT, ENC | DEC, CODECS_ALL,
>> +        {0},
>> +        msm_vidc_adjust_input_buf_host_max_count,
>> +        msm_vidc_set_u32},
>> +
>> +    {INPUT_BUF_HOST_MAX_COUNT, ENC, H264 | HEVC,
>> +        {0},
>> +        msm_vidc_adjust_input_buf_host_max_count,
>> +        msm_vidc_set_u32},
>> +
>> +    {OUTPUT_BUF_HOST_MAX_COUNT, ENC | DEC, CODECS_ALL,
>> +        {0},
>> +        msm_vidc_adjust_output_buf_host_max_count,
>> +        msm_vidc_set_u32},
>> +
>> +    {OUTPUT_BUF_HOST_MAX_COUNT, ENC, H264 | HEVC,
>> +        {0},
>> +        msm_vidc_adjust_output_buf_host_max_count,
>> +        msm_vidc_set_u32},
>> +
>> +    {CONCEAL_COLOR_8BIT, DEC, CODECS_ALL,
>> +        {0},
>> +        NULL,
>> +        msm_vidc_set_u32_packed},
>> +
>> +    {CONCEAL_COLOR_10BIT, DEC, CODECS_ALL,
>> +        {0},
>> +        NULL,
>> +        msm_vidc_set_u32_packed},
>> +
>> +    {STAGE, ENC | DEC, CODECS_ALL,
>> +        {0},
>> +        NULL,
>> +        msm_vidc_set_stage},
>> +
>> +    {STAGE, ENC, H264 | HEVC,
>> +        {0},
>> +        NULL,
>> +        msm_vidc_set_stage},
>> +
>> +    {STAGE, DEC, H264 | HEVC | VP9,
>> +        {0},
>> +        NULL,
>> +        msm_vidc_set_stage},
>> +
>> +    {PIPE, DEC | ENC, CODECS_ALL,
>> +        {0},
>> +        NULL,
>> +        msm_vidc_set_pipe},
>> +
>> +    {RAP_FRAME, DEC, CODECS_ALL,
>> +        {0},
>> +        NULL,
>> +        msm_vidc_set_u32},
>> +
>> +    {ALL_INTRA, ENC, H264 | HEVC,
>> +        {LTR_COUNT, IR_PERIOD, SLICE_MODE, BIT_RATE},
>> +        msm_vidc_adjust_all_intra,
>> +        NULL},
>> +};
>> +
>> +/* Default UBWC config for LPDDR5 */
>> +static struct msm_vidc_ubwc_config_data ubwc_config_sm8550[] = {
>> +    UBWC_CONFIG(8, 32, 16, 0, 1, 1, 1),
>> +};
>> +
>> +static struct msm_vidc_format_capability format_data_sm8550 = {
>> +    .codec_info = codec_data_sm8550,
>> +    .codec_info_size = ARRAY_SIZE(codec_data_sm8550),
>> +    .color_format_info = color_format_data_sm8550,
>> +    .color_format_info_size = ARRAY_SIZE(color_format_data_sm8550),
>> +    .color_prim_info = color_primaries_data_sm8550,
>> +    .color_prim_info_size = ARRAY_SIZE(color_primaries_data_sm8550),
>> +    .transfer_char_info = transfer_char_data_sm8550,
>> +    .transfer_char_info_size = ARRAY_SIZE(transfer_char_data_sm8550),
>> +    .matrix_coeff_info = matrix_coeff_data_sm8550,
>> +    .matrix_coeff_info_size = ARRAY_SIZE(matrix_coeff_data_sm8550),
>> +};
>> +
>> +/* name, min_kbps, max_kbps */
>> +static const struct bw_table sm8550_bw_table[] = {
>> +    { "venus-cnoc",  1000, 1000     },
>> +    { "venus-ddr",   1000, 15000000 },
> 
> We have OPP tables for that. There is no need to limit the min/max, just
> put it to OPP.
> 
This table is used to vote for min and max bus bandwidth.
for some test vector with bad picture order count, ref count can be huge,
so DPB needs to be filled with high number of reference frames to process
current frames, this needs faster frame processing so to address such
cases, driver vote for max bus bandwidth.
for some cases, when system is in suspend state, there might be some
residual transitions happening for which driver needs to vote for min
frequency during suspend state.
>> +};
>> +
>> +/* name */
>> +static const struct pd_table sm8550_pd_table[] = {
>> +    { "iris-ctl" },
>> +    { "vcodec"   },
>> +};
>> +
>> +/* name */
>> +static const char * const sm8550_opp_table[] = { "mx", "mmcx", NULL };
>> +
>> +/* name, clock id, scaling */
>> +static const struct clk_table sm8550_clk_table[] = {
>> +    { "gcc_video_axi0",         GCC_VIDEO_AXI0_CLK,     0 },
>> +    { "core_clk",               VIDEO_CC_MVS0C_CLK,     0 },
>> +    { "vcodec_clk",             VIDEO_CC_MVS0_CLK,      1 },
>> +};
> 
> This strucuture looks like a perfect candidate to be replaced by
> devm_clk_bulk_get_all().
> 
Nice suggestion, will explore this.
>> +
>> +/* name, exclusive_release */
>> +static const struct clk_rst_table sm8550_clk_reset_table[] = {
>> +    { "video_axi_reset",        0  },
> 
> Can we assume that resets are generic at least?
> 
reset clocks can change for different hardware.
>> +};
>> +
>> +/* name, start, size, secure, dma_coherant, region, dma_mask */
>> +const struct context_bank_table sm8550_context_bank_table[] = {
>> +    {"qcom,vidc,cb-ns", 0x25800000, 0xba800000, 0, 1,
>> MSM_VIDC_NON_SECURE, 0xe0000000 - 1},
>> +    {"qcom,vidc,cb-sec-non-pxl",   0x01000000, 0x24800000, 1, 0,
>> MSM_VIDC_SECURE_NONPIXEL,  0 },
> 
> Aren't these a properties of subdevices? If so, why are you putting them here?
> 
Will remove these in next version.
>> +};
>> +
>> +/* freq */
>> +static struct freq_table sm8550_freq_table[] = {
>> +    {533333333}, {444000000}, {366000000}, {338000000}, {240000000}
> 
> OPP table contents.
> 
we are using this freq table at multiple places apart from voting like
- setting freq to turbo for few use cases
- limiting the freq to NOM
- changing the frequency levels based on DCVS
hence this table is need.
>> +};
>> +
>> +/* register, value, mask */
>> +static const struct reg_preset_table sm8550_reg_preset_table[] = {
>> +    { 0xB0088, 0x0, 0x11 },
>> +};
>> +
>> +/* decoder properties */
>> +static const u32 sm8550_vdec_psc_avc[] = {
>> +    HFI_PROP_BITSTREAM_RESOLUTION,
>> +    HFI_PROP_CROP_OFFSETS,
>> +    HFI_PROP_CODED_FRAMES,
>> +    HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT,
>> +    HFI_PROP_PIC_ORDER_CNT_TYPE,
>> +    HFI_PROP_PROFILE,
>> +    HFI_PROP_LEVEL,
>> +    HFI_PROP_SIGNAL_COLOR_INFO,
>> +};
>> +
>> +static const u32 sm8550_vdec_psc_hevc[] = {
>> +    HFI_PROP_BITSTREAM_RESOLUTION,
>> +    HFI_PROP_CROP_OFFSETS,
>> +    HFI_PROP_LUMA_CHROMA_BIT_DEPTH,
>> +    HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT,
>> +    HFI_PROP_PROFILE,
>> +    HFI_PROP_LEVEL,
>> +    HFI_PROP_TIER,
>> +    HFI_PROP_SIGNAL_COLOR_INFO,
>> +};
>> +
>> +static const u32 sm8550_vdec_psc_vp9[] = {
>> +    HFI_PROP_BITSTREAM_RESOLUTION,
>> +    HFI_PROP_CROP_OFFSETS,
>> +    HFI_PROP_LUMA_CHROMA_BIT_DEPTH,
>> +    HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT,
>> +    HFI_PROP_PROFILE,
>> +    HFI_PROP_LEVEL,
>> +};
>> +
>> +static const u32 sm8550_vdec_input_properties_avc[] = {
>> +    HFI_PROP_NO_OUTPUT,
>> +    HFI_PROP_SUBFRAME_INPUT,
>> +};
>> +
>> +static const u32 sm8550_vdec_input_properties_hevc[] = {
>> +    HFI_PROP_NO_OUTPUT,
>> +    HFI_PROP_SUBFRAME_INPUT,
>> +};
>> +
>> +static const u32 sm8550_vdec_input_properties_vp9[] = {
>> +    HFI_PROP_NO_OUTPUT,
>> +    HFI_PROP_SUBFRAME_INPUT,
>> +};
>> +
>> +static const u32 sm8550_vdec_output_properties_avc[] = {
>> +    HFI_PROP_WORST_COMPRESSION_RATIO,
>> +    HFI_PROP_WORST_COMPLEXITY_FACTOR,
>> +    HFI_PROP_PICTURE_TYPE,
>> +    HFI_PROP_DPB_LIST,
>> +    HFI_PROP_CABAC_SESSION,
>> +};
>> +
>> +static const u32 sm8550_vdec_output_properties_hevc[] = {
>> +    HFI_PROP_WORST_COMPRESSION_RATIO,
>> +    HFI_PROP_WORST_COMPLEXITY_FACTOR,
>> +    HFI_PROP_PICTURE_TYPE,
>> +    HFI_PROP_DPB_LIST,
>> +};
>> +
>> +static const u32 sm8550_vdec_output_properties_vp9[] = {
>> +    HFI_PROP_WORST_COMPRESSION_RATIO,
>> +    HFI_PROP_WORST_COMPLEXITY_FACTOR,
>> +    HFI_PROP_PICTURE_TYPE,
>> +    HFI_PROP_DPB_LIST,
>> +};
>> +
>> +static const struct msm_vidc_platform_data sm8550_data = {
>> +    /* resources dependent on other module */
>> +    .bw_tbl = sm8550_bw_table,
>> +    .bw_tbl_size = ARRAY_SIZE(sm8550_bw_table),
>> +    .clk_tbl = sm8550_clk_table,
>> +    .clk_tbl_size = ARRAY_SIZE(sm8550_clk_table),
>> +    .clk_rst_tbl = sm8550_clk_reset_table,
>> +    .clk_rst_tbl_size = ARRAY_SIZE(sm8550_clk_reset_table),
>> +    .subcache_tbl = NULL,
>> +    .subcache_tbl_size = 0,
>> +
>> +    /* populate context bank */
>> +    .context_bank_tbl = sm8550_context_bank_table,
>> +    .context_bank_tbl_size = ARRAY_SIZE(sm8550_context_bank_table),
>> +
>> +    /* populate power domain and opp table */
>> +    .pd_tbl = sm8550_pd_table,
>> +    .pd_tbl_size = ARRAY_SIZE(sm8550_pd_table),
>> +    .opp_tbl = sm8550_opp_table,
>> +    .opp_tbl_size = ARRAY_SIZE(sm8550_opp_table),
>> +
>> +    /* platform specific resources */
>> +    .freq_tbl = sm8550_freq_table,
>> +    .freq_tbl_size = ARRAY_SIZE(sm8550_freq_table),
>> +    .reg_prst_tbl = sm8550_reg_preset_table,
>> +    .reg_prst_tbl_size = ARRAY_SIZE(sm8550_reg_preset_table),
>> +    .fwname = "vpu30_4v",
>> +    .pas_id = 9,
>> +
>> +    /* caps related resorces */
>> +    .core_data = core_data_sm8550,
>> +    .core_data_size = ARRAY_SIZE(core_data_sm8550),
>> +    .inst_cap_data = instance_cap_data_sm8550,
>> +    .inst_cap_data_size = ARRAY_SIZE(instance_cap_data_sm8550),
>> +    .inst_cap_dependency_data = instance_cap_dependency_data_sm8550,
>> +    .inst_cap_dependency_data_size =
>> ARRAY_SIZE(instance_cap_dependency_data_sm8550),
>> +    .ubwc_config = ubwc_config_sm8550,
>> +    .format_data = &format_data_sm8550,
>> +
>> +    /* decoder properties related*/
>> +    .psc_avc_tbl = sm8550_vdec_psc_avc,
>> +    .psc_avc_tbl_size = ARRAY_SIZE(sm8550_vdec_psc_avc),
>> +    .psc_hevc_tbl = sm8550_vdec_psc_hevc,
>> +    .psc_hevc_tbl_size = ARRAY_SIZE(sm8550_vdec_psc_hevc),
>> +    .psc_vp9_tbl = sm8550_vdec_psc_vp9,
>> +    .psc_vp9_tbl_size = ARRAY_SIZE(sm8550_vdec_psc_vp9),
>> +    .dec_input_prop_avc = sm8550_vdec_input_properties_avc,
>> +    .dec_input_prop_hevc = sm8550_vdec_input_properties_hevc,
>> +    .dec_input_prop_vp9 = sm8550_vdec_input_properties_vp9,
>> +    .dec_input_prop_size_avc =
>> ARRAY_SIZE(sm8550_vdec_input_properties_avc),
>> +    .dec_input_prop_size_hevc =
>> ARRAY_SIZE(sm8550_vdec_input_properties_hevc),
>> +    .dec_input_prop_size_vp9 =
>> ARRAY_SIZE(sm8550_vdec_input_properties_vp9),
>> +    .dec_output_prop_avc = sm8550_vdec_output_properties_avc,
>> +    .dec_output_prop_hevc = sm8550_vdec_output_properties_hevc,
>> +    .dec_output_prop_vp9 = sm8550_vdec_output_properties_vp9,
>> +    .dec_output_prop_size_avc =
>> ARRAY_SIZE(sm8550_vdec_output_properties_avc),
>> +    .dec_output_prop_size_hevc =
>> ARRAY_SIZE(sm8550_vdec_output_properties_hevc),
>> +    .dec_output_prop_size_vp9 =
>> ARRAY_SIZE(sm8550_vdec_output_properties_vp9),
> 
> Size should come next to the array reference.
correct, will fix in next version
> 
>> +};
>> +
>> +static int msm_vidc_init_data(struct msm_vidc_core *core)
>> +{
>> +    d_vpr_h("%s: initialize sm8550 data\n", __func__);
>> +
>> +    core->platform->data = sm8550_data;
>> +
> 
> Please use of_device_match_data() instead.
> 
Thanks for the suggestion, will implement in next version.

Thanks,
Dikshita
>> +    return 0;
>> +}
>> +
>> +int msm_vidc_init_platform_sm8550(struct msm_vidc_core *core)
>> +{
>> +    return msm_vidc_init_data(core);
>> +}
>
Dmitry Baryshkov Aug. 14, 2023, 9:03 p.m. UTC | #21
On Mon, 14 Aug 2023 at 21:58, Dikshita Agarwal
<quic_dikshita@quicinc.com> wrote:
>
>
>
> On 7/28/2023 7:19 PM, Dmitry Baryshkov wrote:
> > On 28/07/2023 16:23, Vikash Garodia wrote:
> >> From: Dikshita Agarwal <quic_dikshita@quicinc.com>
> >>
> >> This implements the platform driver methods, file
> >> operations and v4l2 registration.
> >>
> >> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
> >> Signed-off-by: Vikash Garodia <quic_vgarodia@quicinc.com>
> >> ---
> >>   .../platform/qcom/iris/vidc/src/msm_vidc_probe.c   | 660
> >> +++++++++++++++++++++
> >>   1 file changed, 660 insertions(+)
> >>   create mode 100644
> >> drivers/media/platform/qcom/iris/vidc/src/msm_vidc_probe.c
> >>
> >> diff --git a/drivers/media/platform/qcom/iris/vidc/src/msm_vidc_probe.c
> >> b/drivers/media/platform/qcom/iris/vidc/src/msm_vidc_probe.c
> >> new file mode 100644
> >> index 0000000..43439cb
> >> --- /dev/null
> >> +++ b/drivers/media/platform/qcom/iris/vidc/src/msm_vidc_probe.c
> >> @@ -0,0 +1,660 @@
> >> +// SPDX-License-Identifier: GPL-2.0-only
> >> +/*
> >> + * Copyright (c) 2020-2022, The Linux Foundation. All rights reserved.
> >> + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
> >> + */
> >> +
> >> +#include <linux/interrupt.h>
> >> +#include <linux/io.h>
> >> +#include <linux/iommu.h>
> >> +#include <linux/module.h>
> >> +#include <linux/of.h>
> >> +#include <linux/of_platform.h>
> >> +#include <linux/stringify.h>
> >> +#include <linux/version.h>
> >> +#include <linux/workqueue.h>
> >> +
> >> +#include "msm_vidc_core.h"
> >> +#include "msm_vidc_debug.h"
> >> +#include "msm_vidc_driver.h"
> >> +#include "msm_vidc_internal.h"
> >> +#include "msm_vidc_memory.h"
> >> +#include "msm_vidc_platform.h"
> >> +#include "msm_vidc_state.h"
> >> +#include "venus_hfi.h"
> >
> > This files are not present yet, so this commit doesn't have a change of
> > being compiled in any way.
> >
> >> +
> >> +#define BASE_DEVICE_NUMBER 32
> >> +
> >> +struct msm_vidc_core *g_core;
> >> +
> >> +static inline bool is_video_device(struct device *dev)
> >> +{
> >> +    return !!(of_device_is_compatible(dev->of_node, "qcom,sm8550-vidc"));
> >
> > Are you going to add future platforms to this list? Please don't duplicate
> > of_match_data here.
> > Sure, Will remove this API in next version.
> >> +}
> >> +
> >> +static inline bool is_video_context_bank_device(struct device *dev)
> >> +{
> >> +    return !!(of_device_is_compatible(dev->of_node, "qcom,vidc,cb-ns"));
> >> +}
> >> +
> >> +static int msm_vidc_init_resources(struct msm_vidc_core *core)
> >> +{
> >> +    struct msm_vidc_resource *res = NULL;
> >> +    int rc = 0;
> >> +
> >> +    res = devm_kzalloc(&core->pdev->dev, sizeof(*res), GFP_KERNEL);
> >> +    if (!res) {
> >> +        d_vpr_e("%s: failed to alloc memory for resource\n", __func__);
> >
> > Where is this macro defined? Please structure your comments in a logical
> > way, so that one can read them from the beginning and understand what is
> > going one.
> >
> > This is not to mention that adding such debugging wrappers doesn't have a
> > lot of value.
> >
> I understand the concern here, will remove the custom debug wrappers in
> next version.
> >> +        return -ENOMEM;
> >> +    }
> >> +    core->resource = res;
> >> +
> >> +    rc = call_res_op(core, init, core);
> >
> > What is call_res_op?
> >
> This implements the resource ops, but as we don't need the abstraction for
> resource ops, this will be removed in next version.
> >> +    if (rc) {
> >> +        d_vpr_e("%s: Failed to init resources: %d\n", __func__, rc);
> >> +        return rc;
> >> +    }
> >> +
> >> +    return 0;
> >> +}
> >> +
> >> +static const struct of_device_id msm_vidc_dt_match[] = {
> >> +    {.compatible = "qcom,sm8550-vidc"},
> >> +    {.compatible = "qcom,vidc,cb-ns"},
> >> +    MSM_VIDC_EMPTY_BRACE
> >
> > NO!!! Please use {} directly.
> >
> I Understand, will replace with {}.
> >> +};
> >> +MODULE_DEVICE_TABLE(of, msm_vidc_dt_match);
> >> +
> >> +static void msm_vidc_release_video_device(struct video_device *vdev)
> >> +{
> >> +    d_vpr_e("%s: video device released\n", __func__);
> >> +}
> >> +
> >> +static void msm_vidc_unregister_video_device(struct msm_vidc_core *core,
> >> +                         enum msm_vidc_domain_type type)
> >> +{
> >> +    int index;
> >> +
> >> +    if (type == MSM_VIDC_DECODER)
> >> +        index = 0;
> >> +    else if (type == MSM_VIDC_ENCODER)
> >> +        index = 1;
> >> +    else
> >> +        return;
> >
> > You can index by the type instead of converting to index.
> >
> MSM_VIDC_DECODER/MSM_VIDC_ENCODER are bit masks hence can not be used as
> array index and these bit mask values are being used in driver at multiple
> places.

A subdevice can not be a decoder and an encoder at the same time, can
it? So, please replace masks with indices.

> >> +
> >> +    v4l2_m2m_release(core->vdev[index].m2m_dev);
> >> +
> >> +    video_set_drvdata(&core->vdev[index].vdev, NULL);
> >> +    video_unregister_device(&core->vdev[index].vdev);
> >> +}
> >> +
> >> +static int msm_vidc_register_video_device(struct msm_vidc_core *core,
> >> +                      enum msm_vidc_domain_type type, int nr)
> >> +{
> >> +    int rc = 0;
> >> +    int index;
> >> +
> >> +    d_vpr_h("%s: domain %d\n", __func__, type);
> >> +
> >> +    if (type == MSM_VIDC_DECODER)
> >> +        index = 0;
> >> +    else if (type == MSM_VIDC_ENCODER)
> >> +        index = 1;
> >> +    else
> >> +        return -EINVAL;
> >> +
> >> +    core->vdev[index].vdev.release =
> >> +        msm_vidc_release_video_device;
> >> +    core->vdev[index].vdev.fops = core->v4l2_file_ops;
> >> +    if (type == MSM_VIDC_DECODER)
> >> +        core->vdev[index].vdev.ioctl_ops = core->v4l2_ioctl_ops_dec;
> >> +    else
> >> +        core->vdev[index].vdev.ioctl_ops = core->v4l2_ioctl_ops_enc;
> >> +    core->vdev[index].vdev.vfl_dir = VFL_DIR_M2M;
> >> +    core->vdev[index].type = type;
> >> +    core->vdev[index].vdev.v4l2_dev = &core->v4l2_dev;
> >> +    core->vdev[index].vdev.device_caps =
> >> core->capabilities[DEVICE_CAPS].value;
> >> +    rc = video_register_device(&core->vdev[index].vdev,
> >> +                   VFL_TYPE_VIDEO, nr);
> >> +    if (rc) {
> >> +        d_vpr_e("Failed to register the video device\n");
> >> +        return rc;
> >> +    }
> >> +    video_set_drvdata(&core->vdev[index].vdev, core);
> >> +
> >> +    core->vdev[index].m2m_dev = v4l2_m2m_init(core->v4l2_m2m_ops);
> >> +    if (IS_ERR(core->vdev[index].m2m_dev)) {
> >> +        d_vpr_e("Failed to initialize V4L2 M2M device\n");
> >> +        rc = PTR_ERR(core->vdev[index].m2m_dev);
> >> +        goto m2m_init_failed;
> >> +    }
> >> +
> >> +    return 0;
> >> +
> >> +m2m_init_failed:
> >> +    video_unregister_device(&core->vdev[index].vdev);
> >> +    return rc;
> >> +}
> >> +
> >> +static int msm_vidc_deinitialize_core(struct msm_vidc_core *core)
> >> +{
> >> +    int rc = 0;
> >> +
> >> +    if (!core) {
> >> +        d_vpr_e("%s: invalid params\n", __func__);
> >> +        return -EINVAL;
> >> +    }
> >> +
> >> +    mutex_destroy(&core->lock);
> >> +    msm_vidc_update_core_state(core, MSM_VIDC_CORE_DEINIT, __func__);
> >> +
> >> +    if (core->batch_workq)
> >> +        destroy_workqueue(core->batch_workq);
> >> +
> >> +    if (core->pm_workq)
> >> +        destroy_workqueue(core->pm_workq);
> >> +
> >> +    core->batch_workq = NULL;
> >> +    core->pm_workq = NULL;
> >> +
> >> +    return rc;
> >> +}
> >> +
> >> +static int msm_vidc_initialize_core(struct msm_vidc_core *core)
> >> +{
> >> +    int rc = 0;
> >> +
> >> +    msm_vidc_update_core_state(core, MSM_VIDC_CORE_DEINIT, __func__);
> >> +
> >> +    core->pm_workq = create_singlethread_workqueue("pm_workq");
> >> +    if (!core->pm_workq) {
> >> +        d_vpr_e("%s: create pm workq failed\n", __func__);
> >> +        rc = -EINVAL;
> >> +        goto exit;
> >> +    }
> >> +
> >> +    core->batch_workq = create_singlethread_workqueue("batch_workq");
> >> +    if (!core->batch_workq) {
> >> +        d_vpr_e("%s: create batch workq failed\n", __func__);
> >> +        rc = -EINVAL;
> >> +        goto exit;
> >> +    }
> >> +
> >> +    core->packet_size = VIDC_IFACEQ_VAR_HUGE_PKT_SIZE;
> >> +    core->packet = devm_kzalloc(&core->pdev->dev, core->packet_size,
> >> GFP_KERNEL);
> >> +    if (!core->packet) {
> >> +        d_vpr_e("%s: failed to alloc core packet\n", __func__);
> >> +        rc = -ENOMEM;
> >> +        goto exit;
> >> +    }
> >> +
> >> +    core->response_packet = devm_kzalloc(&core->pdev->dev,
> >> core->packet_size, GFP_KERNEL);
> >> +    if (!core->packet) {
> >> +        d_vpr_e("%s: failed to alloc core response packet\n", __func__);
> >> +        rc = -ENOMEM;
> >> +        goto exit;
> >> +    }
> >> +
> >> +    mutex_init(&core->lock);
> >> +    INIT_LIST_HEAD(&core->instances);
> >> +    INIT_LIST_HEAD(&core->dangling_instances);
> >> +
> >> +    INIT_DELAYED_WORK(&core->pm_work, venus_hfi_pm_work_handler);
> >> +    INIT_DELAYED_WORK(&core->fw_unload_work, msm_vidc_fw_unload_handler);
> >> +
> >> +    return 0;
> >> +exit:
> >> +    if (core->batch_workq)
> >> +        destroy_workqueue(core->batch_workq);
> >> +    if (core->pm_workq)
> >> +        destroy_workqueue(core->pm_workq);
> >> +    core->batch_workq = NULL;
> >> +    core->pm_workq = NULL;
> >> +
> >> +    return rc;
> >> +}
> >> +
> >> +static void msm_vidc_devm_deinit_core(void *res)
> >> +{
> >> +    struct msm_vidc_core *core = res;
> >> +
> >> +    msm_vidc_deinitialize_core(core);
> >> +}
> >> +
> >> +static int msm_vidc_devm_init_core(struct device *dev, struct
> >> msm_vidc_core *core)
> >> +{
> >> +    int rc = 0;
> >> +
> >> +    if (!dev || !core) {
> >> +        d_vpr_e("%s: invalid params\n", __func__);
> >> +        return -EINVAL;
> >> +    }
> >> +
> >> +    rc = msm_vidc_initialize_core(core);
> >> +    if (rc) {
> >> +        d_vpr_e("%s: init failed with %d\n", __func__, rc);
> >> +        return rc;
> >> +    }
> >> +
> >> +    rc = devm_add_action_or_reset(dev, msm_vidc_devm_deinit_core, (void
> >> *)core);
> >> +    if (rc)
> >> +        return -EINVAL;
> >> +
> >> +    return rc;
> >> +}
> >> +
> >> +static void msm_vidc_devm_debugfs_put(void *res)
> >> +{
> >> +    struct dentry *parent = res;
> >> +
> >> +    debugfs_remove_recursive(parent);
> >> +}
> >> +
> >> +static struct dentry *msm_vidc_devm_debugfs_get(struct device *dev)
> >
> > Why is it called get?
> >
> this will be removed in next version as part of debug wrappers removal
> >
> >> +{
> >> +    struct dentry *parent = NULL;
> >> +    int rc = 0;
> >> +
> >> +    if (!dev) {
> >> +        d_vpr_e("%s: invalid params\n", __func__);
> >> +        return NULL;
> >> +    }
> >> +
> >> +    parent = msm_vidc_debugfs_init_drv();
> >> +    if (!parent)
> >> +        return NULL;
> >> +
> >> +    rc = devm_add_action_or_reset(dev, msm_vidc_devm_debugfs_put, (void
> >> *)parent);
> >> +    if (rc)
> >> +        return NULL;
> >> +
> >> +    return parent;
> >> +}
> >> +
> >> +static int msm_vidc_setup_context_bank(struct msm_vidc_core *core,
> >> +                       struct device *dev)
> >> +{
> >> +    struct context_bank_info *cb = NULL;
> >> +    int rc = 0;
> >> +
> >> +    cb = msm_vidc_get_context_bank_for_device(core, dev);
> >> +    if (!cb) {
> >> +        d_vpr_e("%s: Failed to get context bank device for %s\n",
> >> +            __func__, dev_name(dev));
> >> +        return -EIO;
> >> +    }
> >> +
> >> +    /* populate dev & domain field */
> >> +    cb->dev = dev;
> >> +    cb->domain = iommu_get_domain_for_dev(cb->dev);
> >> +    if (!cb->domain) {
> >> +        d_vpr_e("%s: Failed to get iommu domain for %s\n", __func__,
> >> dev_name(dev));
> >> +        return -EIO;
> >> +    }
> >> +
> >> +    if (cb->dma_mask) {
> >> +        rc = dma_set_mask_and_coherent(cb->dev, cb->dma_mask);
> >> +        if (rc) {
> >> +            d_vpr_e("%s: dma_set_mask_and_coherent failed\n", __func__);
> >> +            return rc;
> >> +        }
> >> +    }
> >> +
> >> +    /*
> >> +     * configure device segment size and segment boundary to ensure
> >> +     * iommu mapping returns one mapping (which is required for partial
> >> +     * cache operations)
> >> +     */
> >> +    if (!dev->dma_parms)
> >> +        dev->dma_parms =
> >> +            devm_kzalloc(dev, sizeof(*dev->dma_parms), GFP_KERNEL);
> >> +    dma_set_max_seg_size(dev, (unsigned int)DMA_BIT_MASK(32));
> >> +    dma_set_seg_boundary(dev, (unsigned long)DMA_BIT_MASK(64));
> >> +
> >> +    iommu_set_fault_handler(cb->domain, msm_vidc_smmu_fault_handler,
> >> (void *)core);
> >> +
> >> +    d_vpr_h("%s: name %s addr start %x size %x secure %d\n",
> >> +        __func__, cb->name, cb->addr_range.start,
> >> +        cb->addr_range.size, cb->secure);
> >> +    d_vpr_h("%s: dma_coherant %d region %d dev_name %s domain %pK
> >> dma_mask %llu\n",
> >> +        __func__, cb->dma_coherant, cb->region, dev_name(cb->dev),
> >> +        cb->domain, cb->dma_mask);
> >> +
> >> +    return rc;
> >> +}
> >> +
> >> +static int msm_vidc_remove_video_device(struct platform_device *pdev)
> >> +{
> >> +    struct msm_vidc_core *core;
> >> +
> >> +    if (!pdev) {
> >> +        d_vpr_e("%s: invalid input %pK", __func__, pdev);
> >> +        return -EINVAL;
> >> +    }
> >> +
> >> +    core = dev_get_drvdata(&pdev->dev);
> >> +    if (!core) {
> >> +        d_vpr_e("%s: invalid core\n", __func__);
> >> +        return -EINVAL;
> >> +    }
> >> +
> >> +    msm_vidc_core_deinit(core, true);
> >> +    venus_hfi_queue_deinit(core);
> >> +
> >> +    msm_vidc_unregister_video_device(core, MSM_VIDC_ENCODER);
> >> +    msm_vidc_unregister_video_device(core, MSM_VIDC_DECODER);
> >> +
> >> +    v4l2_device_unregister(&core->v4l2_dev);
> >> +
> >> +    d_vpr_h("depopulating sub devices\n");
> >> +    /*
> >> +     * Trigger remove for each sub-device i.e. qcom,context-bank,xxxx
> >> +     * When msm_vidc_remove is called for each sub-device, destroy
> >> +     * context-bank mappings.
> >> +     */
> >> +    of_platform_depopulate(&pdev->dev);
> >> +
> >> +    dev_set_drvdata(&pdev->dev, NULL);
> >> +    g_core = NULL;
> >> +    d_vpr_h("%s(): succssful\n", __func__);
> >> +
> >> +    return 0;
> >> +}
> >> +
> >> +static int msm_vidc_remove_context_bank(struct platform_device *pdev)
> >> +{
> >> +    d_vpr_h("%s(): %s\n", __func__, dev_name(&pdev->dev));
> >> +
> >> +    return 0;
> >> +}
> >> +
> >> +static int msm_vidc_remove(struct platform_device *pdev)
> >> +{
> >> +    /*
> >> +     * Sub devices remove will be triggered by of_platform_depopulate()
> >> +     * after core_deinit(). It return immediately after completing
> >> +     * sub-device remove.
> >> +     */
> >> +    if (is_video_device(&pdev->dev))
> >> +        return msm_vidc_remove_video_device(pdev);
> >> +    else if (is_video_context_bank_device(&pdev->dev))
> >> +        return msm_vidc_remove_context_bank(pdev);
> >> +
> >> +    /* How did we end up here? */
> >> +    WARN_ON(1);
> >> +    return -EINVAL;
> >> +}
> >> +
> >> +static int msm_vidc_probe_video_device(struct platform_device *pdev)
> >> +{
> >> +    int rc = 0;
> >> +    struct msm_vidc_core *core = NULL;
> >> +    int nr = BASE_DEVICE_NUMBER;
> >> +
> >> +    d_vpr_h("%s: %s\n", __func__, dev_name(&pdev->dev));
> >> +
> >> +    core = devm_kzalloc(&pdev->dev, sizeof(struct msm_vidc_core),
> >> GFP_KERNEL);
> >> +    if (!core) {
> >> +        d_vpr_e("%s: failed to alloc memory for core\n", __func__);
> >> +        return -ENOMEM;
> >> +    }
> >> +    g_core = core;
> >> +
> >> +    core->pdev = pdev;
> >> +    dev_set_drvdata(&pdev->dev, core);
> >> +
> >> +    core->debugfs_parent = msm_vidc_devm_debugfs_get(&pdev->dev);
> >> +    if (!core->debugfs_parent)
> >> +        d_vpr_h("Failed to create debugfs for msm_vidc\n");
> >> +
> >> +    rc = msm_vidc_devm_init_core(&pdev->dev, core);
> >> +    if (rc) {
> >> +        d_vpr_e("%s: init core failed with %d\n", __func__, rc);
> >> +        goto init_core_failed;
> >> +    }
> >> +
> >> +    rc = msm_vidc_init_platform(core);
> >> +    if (rc) {
> >> +        d_vpr_e("%s: init platform failed with %d\n", __func__, rc);
> >> +        rc = -EINVAL;
> >> +        goto init_plat_failed;
> >> +    }
> >> +
> >> +    rc = msm_vidc_init_resources(core);
> >> +    if (rc) {
> >> +        d_vpr_e("%s: init resource failed with %d\n", __func__, rc);
> >> +        goto init_res_failed;
> >> +    }
> >> +
> >> +    rc = msm_vidc_init_core_caps(core);
> >> +    if (rc) {
> >> +        d_vpr_e("%s: init core caps failed with %d\n", __func__, rc);
> >> +        goto init_res_failed;
> >> +    }
> >> +
> >> +    rc = msm_vidc_init_instance_caps(core);
> >> +    if (rc) {
> >> +        d_vpr_e("%s: init inst cap failed with %d\n", __func__, rc);
> >> +        goto init_inst_caps_fail;
> >> +    }
> >> +
> >> +    core->debugfs_root = msm_vidc_debugfs_init_core(core);
> >> +    if (!core->debugfs_root)
> >> +        d_vpr_h("Failed to init debugfs core\n");
> >> +
> >> +    d_vpr_h("populating sub devices\n");
> >> +    /*
> >> +     * Trigger probe for each sub-device i.e. qcom,msm-vidc,context-bank.
> >> +     * When msm_vidc_probe is called for each sub-device, parse the
> >> +     * context-bank details.
> >> +     */
> >> +    rc = of_platform_populate(pdev->dev.of_node, msm_vidc_dt_match, NULL,
> >> +                  &pdev->dev);
> >> +    if (rc) {
> >> +        d_vpr_e("Failed to trigger probe for sub-devices\n");
> >> +        goto sub_dev_failed;
> >> +    }
> >> +
> >> +    rc = v4l2_device_register(&pdev->dev, &core->v4l2_dev);
> >> +    if (rc) {
> >> +        d_vpr_e("Failed to register v4l2 device\n");
> >> +        goto v4l2_reg_failed;
> >> +    }
> >> +
> >> +    /* setup the decoder device */
> >> +    rc = msm_vidc_register_video_device(core, MSM_VIDC_DECODER, nr);
> >> +    if (rc) {
> >> +        d_vpr_e("Failed to register video decoder\n");
> >> +        goto dec_reg_failed;
> >> +    }
> >> +
> >> +    /* setup the encoder device */
> >> +    rc = msm_vidc_register_video_device(core, MSM_VIDC_ENCODER, nr + 1);
> >> +    if (rc) {
> >> +        d_vpr_e("Failed to register video encoder\n");
> >> +        goto enc_reg_failed;
> >> +    }
> >> +
> >> +    rc = venus_hfi_queue_init(core);
> >> +    if (rc) {
> >> +        d_vpr_e("%s: interface queues init failed\n", __func__);
> >> +        goto queues_init_failed;
> >> +    }
> >> +
> >> +    rc = msm_vidc_core_init(core);
> >> +    if (rc) {
> >> +        d_vpr_e("%s: sys init failed\n", __func__);
> >> +        goto core_init_failed;
> >> +    }
> >> +
> >> +    d_vpr_h("%s(): succssful\n", __func__);
> >> +
> >> +    return rc;
> >> +
> >> +core_init_failed:
> >> +    venus_hfi_queue_deinit(core);
> >> +queues_init_failed:
> >> +    of_platform_depopulate(&pdev->dev);
> >> +sub_dev_failed:
> >> +    msm_vidc_unregister_video_device(core, MSM_VIDC_ENCODER);
> >> +enc_reg_failed:
> >> +    msm_vidc_unregister_video_device(core, MSM_VIDC_DECODER);
> >> +dec_reg_failed:
> >> +    v4l2_device_unregister(&core->v4l2_dev);
> >> +v4l2_reg_failed:
> >> +init_inst_caps_fail:
> >> +init_res_failed:
> >> +init_plat_failed:
> >> +init_core_failed:
> >> +    dev_set_drvdata(&pdev->dev, NULL);
> >> +    g_core = NULL;
> >> +
> >> +    return rc;
> >> +}
> >> +
> >> +static int msm_vidc_probe_context_bank(struct platform_device *pdev)
> >> +{
> >> +    struct msm_vidc_core *core = NULL;
> >> +    int rc = 0;
> >> +
> >> +    if (!pdev) {
> >> +        d_vpr_e("%s: Invalid platform device %pK", __func__, pdev);
> >> +        return -EINVAL;
> >> +    } else if (!pdev->dev.parent) {
> >> +        d_vpr_e("%s: Failed to find a parent for %s\n",
> >> +            __func__, dev_name(&pdev->dev));
> >> +        return -ENODEV;
> >> +    }
> >> +
> >> +    d_vpr_h("%s(): %s\n", __func__, dev_name(&pdev->dev));
> >> +
> >> +    core = dev_get_drvdata(pdev->dev.parent);
> >> +    if (!core) {
> >> +        d_vpr_e("%s: core not found in device %s",
> >> +            __func__, dev_name(pdev->dev.parent));
> >> +        return -EINVAL;
> >> +    }
> >> +
> >> +    rc = msm_vidc_setup_context_bank(core, &pdev->dev);
> >> +    if (rc) {
> >> +        d_vpr_e("%s: Failed to probe context bank %s\n",
> >> +            __func__, dev_name(&pdev->dev));
> >> +        return rc;
> >> +    }
> >> +
> >> +    return rc;
> >> +}
> >> +
> >> +static int msm_vidc_probe(struct platform_device *pdev)
> >> +{
> >> +    if (!pdev) {
> >> +        d_vpr_e("%s: invalid params\n", __func__);
> >> +        return -EINVAL;
> >> +    }
> >> +
> >> +    /*
> >> +     * Sub devices probe will be triggered by of_platform_populate()
> >> towards
> >> +     * the end of the probe function after msm-vidc device probe is
> >> +     * completed. Return immediately after completing sub-device probe.
> >> +     */
> >> +    if (is_video_device(&pdev->dev))
> >> +        return msm_vidc_probe_video_device(pdev);
> >> +    else if (is_video_context_bank_device(&pdev->dev))
> >> +        return msm_vidc_probe_context_bank(pdev);
> >> +
> >> +    /* How did we end up here? */
> >> +    WARN_ON(1);
> >> +    return -EINVAL;
> >
> > No. Please don't hack around the driver infrastructure and register two
> > separate drivers. They can even come in two separate commits, simplifying
> > the review.
> >
> Sure, will remove the separate probe for context bank in next version.
> >> +}
> >> +
> >> +static int msm_vidc_pm_suspend(struct device *dev)
> >> +{
> >> +    int rc = 0;
> >> +    struct msm_vidc_core *core;
> >> +    enum msm_vidc_allow allow = MSM_VIDC_DISALLOW;
> >> +
> >> +    /*
> >> +     * Bail out if
> >> +     * - driver possibly not probed yet
> >> +     * - not the main device. We don't support power management on
> >> +     *   subdevices (e.g. context banks)
> >> +     */
> >> +    if (!dev || !dev->driver || !is_video_device(dev))
> >> +        return 0;
> >> +
> >> +    core = dev_get_drvdata(dev);
> >> +    if (!core) {
> >> +        d_vpr_e("%s: invalid core\n", __func__);
> >> +        return -EINVAL;
> >> +    }
> >> +
> >> +    core_lock(core, __func__);
> >> +    allow = msm_vidc_allow_pm_suspend(core);
> >> +
> >> +    if (allow == MSM_VIDC_IGNORE) {
> >> +        d_vpr_h("%s: pm already suspended\n", __func__);
> >> +        msm_vidc_change_core_sub_state(core, 0,
> >> CORE_SUBSTATE_PM_SUSPEND, __func__);
> >> +        rc = 0;
> >> +        goto unlock;
> >> +    } else if (allow != MSM_VIDC_ALLOW) {
> >> +        d_vpr_h("%s: pm suspend not allowed\n", __func__);
> >> +        rc = 0;
> >> +        goto unlock;
> >> +    }
> >> +
> >> +    rc = msm_vidc_suspend(core);
> >> +    if (rc == -EOPNOTSUPP)
> >> +        rc = 0;
> >> +    else if (rc)
> >> +        d_vpr_e("Failed to suspend: %d\n", rc);
> >> +    else
> >> +        msm_vidc_change_core_sub_state(core, 0,
> >> CORE_SUBSTATE_PM_SUSPEND, __func__);
> >> +
> >> +unlock:
> >> +    core_unlock(core, __func__);
> >> +    return rc;
> >> +}
> >> +
> >> +static int msm_vidc_pm_resume(struct device *dev)
> >> +{
> >> +    struct msm_vidc_core *core;
> >> +
> >> +    /*
> >> +     * Bail out if
> >> +     * - driver possibly not probed yet
> >> +     * - not the main device. We don't support power management on
> >> +     *   subdevices (e.g. context banks)
> >> +     */
> >> +    if (!dev || !dev->driver || !is_video_device(dev))
> >> +        return 0;
> >> +
> >> +    core = dev_get_drvdata(dev);
> >> +    if (!core) {
> >> +        d_vpr_e("%s: invalid core\n", __func__);
> >> +        return -EINVAL;
> >> +    }
> >> +
> >> +    /* remove PM suspend from core sub_state */
> >> +    core_lock(core, __func__);
> >> +    msm_vidc_change_core_sub_state(core, CORE_SUBSTATE_PM_SUSPEND, 0,
> >> __func__);
> >> +    core_unlock(core, __func__);
> >> +
> >> +    return 0;
> >> +}
> >> +
> >> +static const struct dev_pm_ops msm_vidc_pm_ops = {
> >> +    SET_SYSTEM_SLEEP_PM_OPS(msm_vidc_pm_suspend, msm_vidc_pm_resume)
> >
> > No runtime PM?
> runtime PM is not added in this series, but we plan to add it at later
> point of time.
> >
> >> +};
> >> +
> >> +struct platform_driver msm_vidc_driver = {
> >> +    .probe = msm_vidc_probe,
> >> +    .remove = msm_vidc_remove,
> >> +    .driver = {
> >> +        .name = "msm_vidc_v4l2",
> >> +        .of_match_table = msm_vidc_dt_match,
> >> +        .pm = &msm_vidc_pm_ops,
> >> +    },
> >> +};
> >> +
> >> +module_platform_driver(msm_vidc_driver);
> >> +MODULE_LICENSE("GPL");
> >
> > Unfortunately, after taking a glance at first two patches, I have to stop.
> > It is nearly impossible to review it.
> >
> > Please start from the beginning, split the driver according to the logical
> > functions, not per-file. Ideally something should be compillable starting
> > from one of the first patches, if not the very first one. This would
> > guarantee that your patchset is structured logically.
> >
> > Please add DT bindings. New driver series should start from the bindings
> > anyway.
> >
> > Please drop your custom debugging wrappers. Use dev_info, dev_warn, dev_err
> > and dev_dbg instead.
> >
> > Please drop the custom multi-device-single-driver scheme. If there are
> > different kinds of devices, there should be different drivers.
> >
> > Please take a look around. If you are pushing your driver for kernel
> > inclusion, it should not stand out by the style and by the typical code
> > seuqences.
>
> Thanks a lot for all your comments, will take care of these in next version.
Dmitry Baryshkov Aug. 14, 2023, 9:17 p.m. UTC | #22
On Mon, 14 Aug 2023 at 22:36, Dikshita Agarwal
<quic_dikshita@quicinc.com> wrote:
>
>
>
> On 7/28/2023 7:43 PM, Dmitry Baryshkov wrote:
> > On 28/07/2023 16:23, Vikash Garodia wrote:
> >> From: Dikshita Agarwal <quic_dikshita@quicinc.com>
> >>
> >> This implements all the capabilities supported by sm8550.
> >>
> >> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
> >> Signed-off-by: Vikash Garodia <quic_vgarodia@quicinc.com>
> >> ---
> >>   .../iris/platform/sm8550/inc/msm_vidc_sm8550.h     |   14 +
> >>   .../iris/platform/sm8550/src/msm_vidc_sm8550.c     | 1727
> >> ++++++++++++++++++++
> >>   2 files changed, 1741 insertions(+)
> >>   create mode 100644
> >> drivers/media/platform/qcom/iris/platform/sm8550/inc/msm_vidc_sm8550.h
> >>   create mode 100644
> >> drivers/media/platform/qcom/iris/platform/sm8550/src/msm_vidc_sm8550.c
> >>
> >> diff --git
> >> a/drivers/media/platform/qcom/iris/platform/sm8550/inc/msm_vidc_sm8550.h
> >> b/drivers/media/platform/qcom/iris/platform/sm8550/inc/msm_vidc_sm8550.h
> >> new file mode 100644
> >> index 0000000..0a2f172
> >> --- /dev/null
> >> +++ b/drivers/media/platform/qcom/iris/platform/sm8550/inc/msm_vidc_sm8550.h
> >> @@ -0,0 +1,14 @@
> >> +/* SPDX-License-Identifier: GPL-2.0-only */
> >> +/*
> >> + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
> >> + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights
> >> reserved.
> >> + */
> >> +
> >> +#ifndef _MSM_VIDC_SM8550_H_
> >> +#define _MSM_VIDC_SM8550_H_
> >> +
> >> +#include "msm_vidc_core.h"
> >> +
> >> +int msm_vidc_init_platform_sm8550(struct msm_vidc_core *core);
> >> +
> >> +#endif // _MSM_VIDC_SM8550_H_
> >> diff --git
> >> a/drivers/media/platform/qcom/iris/platform/sm8550/src/msm_vidc_sm8550.c
> >> b/drivers/media/platform/qcom/iris/platform/sm8550/src/msm_vidc_sm8550.c
> >> new file mode 100644
> >> index 0000000..2408556
> >> --- /dev/null
> >> +++ b/drivers/media/platform/qcom/iris/platform/sm8550/src/msm_vidc_sm8550.c
> >> @@ -0,0 +1,1727 @@
> >> +// SPDX-License-Identifier: GPL-2.0-only
> >> +/*
> >> + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
> >> + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights
> >> reserved.
> >> + */
> >> +
> >> +#include <dt-bindings/clock/qcom,sm8550-gcc.h>
> >> +#include <dt-bindings/clock/qcom,sm8450-videocc.h>
> >> +
> >> +#include "hfi_command.h"
> >> +#include "hfi_property.h"
> >> +#include "msm_vidc_control.h"
> >> +#include "msm_vidc_debug.h"
> >> +#include "msm_vidc_iris3.h"
> >> +#include "msm_vidc_sm8550.h"
> >> +#include "msm_vidc_platform.h"
> >> +
> >> +/* version: major[24:31], minor[16:23], revision[0:15] */
> >> +#define DRIVER_VERSION          0x04000000
> >> +#define DEFAULT_VIDEO_CONCEAL_COLOR_BLACK 0x8020010
> >> +#define MAX_BASE_LAYER_PRIORITY_ID 63
> >> +#define MAX_OP_POINT            31
> >> +#define MAX_BITRATE             245000000
> >> +#define DEFAULT_BITRATE         20000000
> >> +#define MINIMUM_FPS             1
> >> +#define MAXIMUM_FPS             480
> >> +#define MAXIMUM_DEC_FPS         960
> >> +#define MAX_QP                  51
> >> +#define DEFAULT_QP              20
> >> +#define MAX_CONSTANT_QUALITY    100
> >> +#define MIN_SLICE_BYTE_SIZE     512
> >> +#define MAX_SLICE_BYTE_SIZE       \
> >> +    ((MAX_BITRATE) >> 3)
> >> +#define MAX_SLICE_MB_SIZE         \
> >> +    (((4096 + 15) >> 4) * ((2304 + 15) >> 4))
> >> +
> >> +#define ENC     MSM_VIDC_ENCODER
> >> +#define DEC     MSM_VIDC_DECODER
> >> +#define H264    MSM_VIDC_H264
> >> +#define HEVC    MSM_VIDC_HEVC
> >> +#define VP9     MSM_VIDC_VP9
> >
> > Another redefinition. Inline it.
> > >> +#define CODECS_ALL     (H264 | HEVC | VP9)
> >> +#define MAXIMUM_OVERRIDE_VP9_FPS 200
> >> +
> >> +static struct codec_info codec_data_sm8550[] = {
> >> +    {
> >> +        .v4l2_codec  = V4L2_PIX_FMT_H264,
> >> +        .vidc_codec  = MSM_VIDC_H264,
> >> +        .pixfmt_name = "AVC",
> >
> > Have you considered using existing code which enumerates formats? For
> > example, it is much better to refactor v4l_fill_fmtdesc() to allow getting
> > the description instead of adding your own names here.
> > Not to mention that printk supports %p4cc for printing fourcc values. I
> > hope you knew that.
> >
> Sure, will explore more on this.
> >> +    },
> >> +    {
> >> +        .v4l2_codec  = V4L2_PIX_FMT_HEVC,
> >> +        .vidc_codec  = MSM_VIDC_HEVC,
> >> +        .pixfmt_name = "HEVC",
> >> +    },
> >> +    {
> >> +        .v4l2_codec  = V4L2_PIX_FMT_VP9,
> >> +        .vidc_codec  = MSM_VIDC_VP9,
> >> +        .pixfmt_name = "VP9",
> >> +    },
> >> +};
> >> +
> >> +static struct color_format_info color_format_data_sm8550[] = {
> >> +    {
> >> +        .v4l2_color_format = V4L2_PIX_FMT_NV12,
> >> +        .vidc_color_format = MSM_VIDC_FMT_NV12,
> >> +        .pixfmt_name       = "NV12",
> >> +    },
> >> +    {
> >> +        .v4l2_color_format = V4L2_PIX_FMT_NV21,
> >> +        .vidc_color_format = MSM_VIDC_FMT_NV21,
> >> +        .pixfmt_name       = "NV21",
> >> +    },
> >> +    {
> >> +        .v4l2_color_format = V4L2_PIX_FMT_QC08C,
> >> +        .vidc_color_format = MSM_VIDC_FMT_NV12C,
> >> +        .pixfmt_name       = "NV12C",
> >> +    },
> >> +    {
> >> +        .v4l2_color_format = V4L2_PIX_FMT_QC10C,
> >> +        .vidc_color_format = MSM_VIDC_FMT_TP10C,
> >> +        .pixfmt_name       = "TP10C",
> >> +    },
> >> +    {
> >> +        .v4l2_color_format = V4L2_PIX_FMT_RGBA32,
> >> +        .vidc_color_format = MSM_VIDC_FMT_RGBA8888,
> >> +        .pixfmt_name       = "RGBA",
> >> +    },
> >> +};
> >> +
> >> +static struct color_primaries_info color_primaries_data_sm8550[] = {
> >> +    {
> >> +        .v4l2_color_primaries  = V4L2_COLORSPACE_DEFAULT,
> >> +        .vidc_color_primaries  = MSM_VIDC_PRIMARIES_RESERVED,
> >> +    },
> >> +    {
> >> +        .v4l2_color_primaries  = V4L2_COLORSPACE_REC709,
> >> +        .vidc_color_primaries  = MSM_VIDC_PRIMARIES_BT709,
> >> +    },
> >> +    {
> >> +        .v4l2_color_primaries  = V4L2_COLORSPACE_470_SYSTEM_M,
> >> +        .vidc_color_primaries  = MSM_VIDC_PRIMARIES_BT470_SYSTEM_M,
> >> +    },
> >> +    {
> >> +        .v4l2_color_primaries  = V4L2_COLORSPACE_470_SYSTEM_BG,
> >> +        .vidc_color_primaries  = MSM_VIDC_PRIMARIES_BT470_SYSTEM_BG,
> >> +    },
> >> +    {
> >> +        .v4l2_color_primaries  = V4L2_COLORSPACE_SMPTE170M,
> >> +        .vidc_color_primaries  = MSM_VIDC_PRIMARIES_BT601_525,
> >> +    },
> >> +    {
> >> +        .v4l2_color_primaries  = V4L2_COLORSPACE_SMPTE240M,
> >> +        .vidc_color_primaries  = MSM_VIDC_PRIMARIES_SMPTE_ST240M,
> >> +    },
> >> +    {
> >> +        .v4l2_color_primaries  = V4L2_COLORSPACE_BT2020,
> >> +        .vidc_color_primaries  = MSM_VIDC_PRIMARIES_BT2020,
> >> +    },
> >> +    {
> >> +        .v4l2_color_primaries  = V4L2_COLORSPACE_DCI_P3,
> >> +        .vidc_color_primaries  = MSM_VIDC_PRIMARIES_SMPTE_RP431_2,
> >> +    },
> >> +};
> >> +
> >> +static struct transfer_char_info transfer_char_data_sm8550[] = {
> >> +    {
> >> +        .v4l2_transfer_char  = V4L2_XFER_FUNC_DEFAULT,
> >> +        .vidc_transfer_char  = MSM_VIDC_TRANSFER_RESERVED,
> >> +    },
> >> +    {
> >> +        .v4l2_transfer_char  = V4L2_XFER_FUNC_709,
> >> +        .vidc_transfer_char  = MSM_VIDC_TRANSFER_BT709,
> >> +    },
> >> +    {
> >> +        .v4l2_transfer_char  = V4L2_XFER_FUNC_SMPTE240M,
> >> +        .vidc_transfer_char  = MSM_VIDC_TRANSFER_SMPTE_ST240M,
> >> +    },
> >> +    {
> >> +        .v4l2_transfer_char  = V4L2_XFER_FUNC_SRGB,
> >> +        .vidc_transfer_char  = MSM_VIDC_TRANSFER_SRGB_SYCC,
> >> +    },
> >> +    {
> >> +        .v4l2_transfer_char  = V4L2_XFER_FUNC_SMPTE2084,
> >> +        .vidc_transfer_char  = MSM_VIDC_TRANSFER_SMPTE_ST2084_PQ,
> >> +    },
> >> +};
> >> +
> >> +static struct matrix_coeff_info matrix_coeff_data_sm8550[] = {
> >> +    {
> >> +        .v4l2_matrix_coeff  = V4L2_YCBCR_ENC_DEFAULT,
> >> +        .vidc_matrix_coeff  = MSM_VIDC_MATRIX_COEFF_RESERVED,
> >> +    },
> >> +    {
> >> +        .v4l2_matrix_coeff  = V4L2_YCBCR_ENC_709,
> >> +        .vidc_matrix_coeff  = MSM_VIDC_MATRIX_COEFF_BT709,
> >> +    },
> >> +    {
> >> +        .v4l2_matrix_coeff  = V4L2_YCBCR_ENC_XV709,
> >> +        .vidc_matrix_coeff  = MSM_VIDC_MATRIX_COEFF_BT709,
> >> +    },
> >> +    {
> >> +        .v4l2_matrix_coeff  = V4L2_YCBCR_ENC_XV601,
> >> +        .vidc_matrix_coeff  =
> >> MSM_VIDC_MATRIX_COEFF_BT470_SYS_BG_OR_BT601_625,
> >> +    },
> >> +    {
> >> +        .v4l2_matrix_coeff  = V4L2_YCBCR_ENC_601,
> >> +        .vidc_matrix_coeff  =
> >> MSM_VIDC_MATRIX_COEFF_BT601_525_BT1358_525_OR_625,
> >> +    },
> >> +    {
> >> +        .v4l2_matrix_coeff  = V4L2_YCBCR_ENC_SMPTE240M,
> >> +        .vidc_matrix_coeff  = MSM_VIDC_MATRIX_COEFF_SMPTE_ST240,
> >> +    },
> >> +    {
> >> +        .v4l2_matrix_coeff  = V4L2_YCBCR_ENC_BT2020,
> >> +        .vidc_matrix_coeff  = MSM_VIDC_MATRIX_COEFF_BT2020_NON_CONSTANT,
> >> +    },
> >> +    {
> >> +        .v4l2_matrix_coeff  = V4L2_YCBCR_ENC_BT2020_CONST_LUM,
> >> +        .vidc_matrix_coeff  = MSM_VIDC_MATRIX_COEFF_BT2020_CONSTANT,
> >> +    },
> >> +};
> >
> > Are you going to say that these tables are platform-specific instead of
> > being generic to the driver?
> >
> future platform can support new codec and that will require new color
> primaries. So, yes these can differ for different platforms.

Please do not try to implement support for not-yet-existing hardware.
Move this table into the generic code until you have a real cause of
disagreement about matrix coefficients. Otherwise the table can simply
be expanded to add new color primaries support.

> >> +
> >> +static struct msm_platform_core_capability core_data_sm8550[] = {
> >> +    /* {type, value} */
> >> +    {ENC_CODECS, H264 | HEVC},
> >> +    {DEC_CODECS, H264 | HEVC | VP9},
> >> +    {MAX_SESSION_COUNT, 16},
> >> +    {MAX_NUM_720P_SESSIONS, 16},
> >> +    {MAX_NUM_1080P_SESSIONS, 16},
> >> +    {MAX_NUM_4K_SESSIONS, 8},
> >> +    {MAX_NUM_8K_SESSIONS, 2},
> >> +    {MAX_RT_MBPF, 174080},    /* (8192x4352)/256 + (4096x2176)/256*/
> >> +    {MAX_MBPF, 278528}, /* ((8192x4352)/256) * 2 */
> >> +    {MAX_MBPS, 7833600},    /* max_load
> >> +                 * 7680x4320@60fps or 3840x2176@240fps
> >> +                 * which is greater than 4096x2176@120fps,
> >> +                 * 8192x4320@48fps
> >> +                 */
> >> +    {MAX_MBPF_HQ, 8160}, /* ((1920x1088)/256) */
> >> +    {MAX_MBPS_HQ, 489600}, /* ((1920x1088)/256)@60fps */
> >> +    {MAX_MBPF_B_FRAME, 32640}, /* 3840x2176/256 */
> >> +    {MAX_MBPS_B_FRAME, 1958400}, /* 3840x2176/256 MBs@60fps */
> >> +    {MAX_MBPS_ALL_INTRA, 1044480}, /* 4096x2176/256 MBs@30fps */
> >> +    {MAX_ENH_LAYER_COUNT, 5},
> >> +    {NUM_VPP_PIPE, 4},
> >> +    {SW_PC, 1},
> >> +    {FW_UNLOAD, 0},
> >> +    {HW_RESPONSE_TIMEOUT, HW_RESPONSE_TIMEOUT_VALUE}, /* 1000 ms */
> >> +    {SW_PC_DELAY,         SW_PC_DELAY_VALUE        }, /* 1500 ms
> >> (>HW_RESPONSE_TIMEOUT)*/
> >> +    {FW_UNLOAD_DELAY,     FW_UNLOAD_DELAY_VALUE    }, /* 3000 ms
> >> (>SW_PC_DELAY)*/
> >> +    {DCVS, 1},
> >> +    {DECODE_BATCH, 1},
> >> +    {DECODE_BATCH_TIMEOUT, 200},
> >> +    {STATS_TIMEOUT_MS, 2000},
> >> +    {NON_FATAL_FAULTS, 1},
> >> +    {DEVICE_CAPS, V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING},
> >
> > Unless there is a good reason, please change this to be a proper data
> > structure instead of being a type-value array. With the T-V it is
> > impossible to notice if the value is missing or duplicated. This comment
> > also applies to the next 'capability' array.
> >
> Core has set of caps. All caps might not be supported for all the hardware.
> So it's quite valid to miss a cap entry if its not applicable for that
> hardware.
> subsequently with caps as enum, it will become easy to copy these caps from
> platform to core.

... and it becomes harder to check them (e.g. for duplicates). Please
use nested structures and omit values for undefined capabilities.

>
> please check msm_vidc_init_core_caps API in [1]
>
> [1]
> https://patchwork.linuxtv.org/project/linux-media/patch/1690550624-14642-11-git-send-email-quic_vgarodia@quicinc.com/

In that patch I see that capabilities are enumerated as an array.
Which is already much better than plain tag-value data structure. But
please drop both implementations and use existing C language
constructions.

>
> >> +};
> >> +
> >> +static struct msm_platform_inst_capability instance_cap_data_sm8550[] = {
> >> +    /* {cap, domain, codec,
> >> +     *      min, max, step_or_mask, value,
> >> +     *      v4l2_id,
> >> +     *      hfi_id,
> >> +     *      flags}
> >> +     */
> >> +    {FRAME_WIDTH, DEC, CODECS_ALL, 96, 8192, 1, 1920},
> >> +
> >> +    {FRAME_WIDTH, DEC, VP9, 96, 4096, 1, 1920},
> >> +
> >> +    {FRAME_WIDTH, ENC, CODECS_ALL, 128, 8192, 1, 1920},
> >> +
> >> +    {FRAME_WIDTH, ENC, HEVC, 96, 8192, 1, 1920},
> >> +
> >> +    {LOSSLESS_FRAME_WIDTH, ENC, CODECS_ALL, 128, 4096, 1, 1920},
> >> +
> >> +    {LOSSLESS_FRAME_WIDTH, ENC, HEVC, 96, 4096, 1, 1920},
> >> +
> >> +    {FRAME_HEIGHT, DEC, CODECS_ALL, 96, 8192, 1, 1080},
> >> +
> >> +    {FRAME_HEIGHT, DEC, VP9, 96, 4096, 1, 1080},
> >> +
> >> +    {FRAME_HEIGHT, ENC, CODECS_ALL, 128, 8192, 1, 1080},
> >> +
> >> +    {FRAME_HEIGHT, ENC, HEVC, 96, 8192, 1, 1080},
> >> +
> >> +    {LOSSLESS_FRAME_HEIGHT, ENC, CODECS_ALL, 128, 4096, 1, 1080},
> >> +
> >> +    {LOSSLESS_FRAME_HEIGHT, ENC, HEVC, 96, 4096, 1, 1080},
> >> +
> >> +    {PIX_FMTS, ENC | DEC, H264,
> >> +        MSM_VIDC_FMT_NV12,
> >> +        MSM_VIDC_FMT_NV12C,
> >> +        MSM_VIDC_FMT_NV12 | MSM_VIDC_FMT_NV21 | MSM_VIDC_FMT_NV12C,
> >> +        MSM_VIDC_FMT_NV12C},
> >> +
> >> +    {PIX_FMTS, ENC | DEC, HEVC | VP9,
> >> +        MSM_VIDC_FMT_NV12,
> >> +        MSM_VIDC_FMT_TP10C,
> >> +        MSM_VIDC_FMT_NV12 | MSM_VIDC_FMT_NV21 | MSM_VIDC_FMT_NV12C |
> >> +        MSM_VIDC_FMT_TP10C,
> >> +        MSM_VIDC_FMT_NV12C},
> >> +
> >> +    {MIN_BUFFERS_INPUT, ENC | DEC, CODECS_ALL, 0, 64, 1, 4,
> >> +        V4L2_CID_MIN_BUFFERS_FOR_OUTPUT,
> >> +        0,
> >> +        CAP_FLAG_VOLATILE},
> >> +
> >> +    {MIN_BUFFERS_OUTPUT, ENC | DEC, CODECS_ALL,
> >> +        0, 64, 1, 4,
> >> +        V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,
> >> +        HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_VOLATILE},
> >> +
> >> +    /* (8192 * 4320) / 256 */
> >> +    {MBPF, ENC, CODECS_ALL, 64, 138240, 1, 138240},
> >> +
> >> +    {MBPF, ENC, HEVC, 36, 138240, 1, 138240},
> >> +
> >> +    {MBPF, DEC, CODECS_ALL, 36, 138240, 1, 138240},
> >> +
> >> +    /* (4096 * 2304) / 256 */
> >> +    {MBPF, DEC, VP9, 36, 36864, 1, 36864},
> >> +
> >> +    /* (4096 * 2304) / 256 */
> >> +    {LOSSLESS_MBPF, ENC, H264 | HEVC, 64, 36864, 1, 36864},
> >> +
> >> +    /* Batch Mode Decode */
> >> +    /* TODO: update with new values based on updated voltage corner */
> >> +    {BATCH_MBPF, DEC, H264 | HEVC | VP9, 64, 34816, 1, 34816},
> >> +
> >> +    /* (4096 * 2304) / 256 */
> >> +    {BATCH_FPS, DEC, H264 | HEVC | VP9, 1, 120, 1, 120},
> >> +
> >> +    {FRAME_RATE, ENC | DEC, CODECS_ALL,
> >> +        (MINIMUM_FPS << 16), (MAXIMUM_FPS << 16),
> >> +        1, (DEFAULT_FPS << 16),
> >> +        0,
> >> +        HFI_PROP_FRAME_RATE,
> >> +        CAP_FLAG_OUTPUT_PORT},
> >> +
> >> +    {OPERATING_RATE, ENC | DEC, CODECS_ALL,
> >> +        (MINIMUM_FPS << 16), (MAXIMUM_FPS << 16),
> >> +        1, (DEFAULT_FPS << 16)},
> >> +
> >> +    {INPUT_RATE, ENC | DEC, CODECS_ALL,
> >> +        (MINIMUM_FPS << 16), INT_MAX,
> >> +        1, (DEFAULT_FPS << 16)},
> >> +
> >> +    {TIMESTAMP_RATE, ENC | DEC, CODECS_ALL,
> >> +        (MINIMUM_FPS << 16), INT_MAX,
> >> +        1, (DEFAULT_FPS << 16)},
> >> +
> >> +    {SCALE_FACTOR, ENC, H264 | HEVC, 1, 8, 1, 8},
> >> +
> >> +    {MB_CYCLES_VSP, ENC, CODECS_ALL, 25, 25, 1, 25},
> >> +
> >> +    {MB_CYCLES_VSP, DEC, CODECS_ALL, 25, 25, 1, 25},
> >> +
> >> +    {MB_CYCLES_VSP, DEC, VP9, 60, 60, 1, 60},
> >> +
> >> +    {MB_CYCLES_VPP, ENC, CODECS_ALL, 675, 675, 1, 675},
> >> +
> >> +    {MB_CYCLES_VPP, DEC, CODECS_ALL, 200, 200, 1, 200},
> >> +
> >> +    {MB_CYCLES_LP, ENC, CODECS_ALL, 320, 320, 1, 320},
> >> +
> >> +    {MB_CYCLES_LP, DEC, CODECS_ALL, 200, 200, 1, 200},
> >> +
> >> +    {MB_CYCLES_FW, ENC | DEC, CODECS_ALL, 489583, 489583, 1, 489583},
> >> +
> >> +    {MB_CYCLES_FW_VPP, ENC, CODECS_ALL, 48405, 48405, 1, 48405},
> >> +
> >> +    {MB_CYCLES_FW_VPP, DEC, CODECS_ALL, 66234, 66234, 1, 66234},
> >> +
> >> +    {HFLIP, ENC, CODECS_ALL,
> >> +        0, 1, 1, 0,
> >> +        V4L2_CID_HFLIP,
> >> +        HFI_PROP_FLIP,
> >> +        CAP_FLAG_OUTPUT_PORT |
> >> +        CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED},
> >> +
> >> +    {VFLIP, ENC, CODECS_ALL,
> >> +        0, 1, 1, 0,
> >> +        V4L2_CID_VFLIP,
> >> +        HFI_PROP_FLIP,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> >> +        CAP_FLAG_DYNAMIC_ALLOWED},
> >> +
> >> +    {ROTATION, ENC, CODECS_ALL,
> >> +        0, 270, 90, 0,
> >> +        V4L2_CID_ROTATE,
> >> +        HFI_PROP_ROTATION,
> >> +        CAP_FLAG_OUTPUT_PORT},
> >> +
> >> +    {HEADER_MODE, ENC, CODECS_ALL,
> >> +        V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE,
> >> +        V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
> >> +        BIT(V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) |
> >> +        BIT(V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME),
> >> +        V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE,
> >> +        V4L2_CID_MPEG_VIDEO_HEADER_MODE,
> >> +        HFI_PROP_SEQ_HEADER_MODE,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> >> +
> >> +    {PREPEND_SPSPPS_TO_IDR, ENC, CODECS_ALL,
> >> +        0, 1, 1, 0,
> >> +        V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR},
> >> +
> >> +    {WITHOUT_STARTCODE, ENC, CODECS_ALL,
> >> +        0, 1, 1, 0,
> >> +        V4L2_CID_MPEG_VIDEO_HEVC_WITHOUT_STARTCODE,
> >> +        HFI_PROP_NAL_LENGTH_FIELD,
> >> +        CAP_FLAG_OUTPUT_PORT},
> >> +
> >> +    {NAL_LENGTH_FIELD, ENC, CODECS_ALL,
> >> +        V4L2_MPEG_VIDEO_HEVC_SIZE_0,
> >> +        V4L2_MPEG_VIDEO_HEVC_SIZE_4,
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_SIZE_0) |
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_SIZE_4),
> >> +        V4L2_MPEG_VIDEO_HEVC_SIZE_0,
> >> +        V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD,
> >> +        HFI_PROP_NAL_LENGTH_FIELD,
> >> +        CAP_FLAG_MENU | CAP_FLAG_OUTPUT_PORT},
> >> +
> >> +    /* TODO: Firmware introduced enumeration type for this
> >> +     * with and without seq header.
> >> +     */
> >> +    {REQUEST_I_FRAME, ENC, H264 | HEVC,
> >> +        0, 0, 0, 0,
> >> +        V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME,
> >> +        HFI_PROP_REQUEST_SYNC_FRAME,
> >> +        CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED},
> >> +
> >> +    /* Enc: Keeping CABAC and CAVLC as same bitrate.
> >> +     * Dec: there's no use of Bitrate cap
> >> +     */
> >> +    {BIT_RATE, ENC, H264 | HEVC,
> >> +        1, MAX_BITRATE, 1, DEFAULT_BITRATE,
> >> +        V4L2_CID_MPEG_VIDEO_BITRATE,
> >> +        HFI_PROP_TOTAL_BITRATE,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> >> +        CAP_FLAG_DYNAMIC_ALLOWED},
> >> +
> >> +    {BITRATE_MODE, ENC, H264,
> >> +        V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
> >> +        V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
> >> +        BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) |
> >> +        BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_CBR),
> >> +        V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
> >> +        V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
> >> +        HFI_PROP_RATE_CONTROL,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> >> +
> >> +    {BITRATE_MODE, ENC, HEVC,
> >> +        V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
> >> +        V4L2_MPEG_VIDEO_BITRATE_MODE_CQ,
> >> +        BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) |
> >> +        BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) |
> >> +        BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_CQ),
> >> +        V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
> >> +        V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
> >> +        HFI_PROP_RATE_CONTROL,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> >> +
> >> +    {CABAC_MAX_BITRATE, ENC, H264 | HEVC, 0,
> >> +        160000000, 1, 160000000},
> >> +
> >> +    {CAVLC_MAX_BITRATE, ENC, H264, 0,
> >> +        220000000, 1, 220000000},
> >> +
> >> +    {ALLINTRA_MAX_BITRATE, ENC, H264 | HEVC, 0,
> >> +        245000000, 1, 245000000},
> >> +
> >> +    {NUM_COMV, DEC, CODECS_ALL,
> >> +        0, INT_MAX, 1, 0},
> >> +
> >> +    {LOSSLESS, ENC, HEVC,
> >> +        0, 1, 1, 0,
> >> +        V4L2_CID_MPEG_VIDEO_HEVC_LOSSLESS_CU},
> >> +
> >> +    {FRAME_SKIP_MODE, ENC, H264 | HEVC,
> >> +        V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED,
> >> +        V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT,
> >> +        BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED) |
> >> +        BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT) |
> >> +        BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT),
> >> +        V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED,
> >> +        V4L2_CID_MPEG_VIDEO_FRAME_SKIP_MODE,
> >> +        0,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> >> +
> >> +    {FRAME_RC_ENABLE, ENC, H264 | HEVC,
> >> +        0, 1, 1, 1,
> >> +        V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE},
> >> +
> >> +    {CONSTANT_QUALITY, ENC, HEVC,
> >> +        1, MAX_CONSTANT_QUALITY, 1, 90,
> >> +        V4L2_CID_MPEG_VIDEO_CONSTANT_QUALITY,
> >> +        HFI_PROP_CONSTANT_QUALITY,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> >> +        CAP_FLAG_DYNAMIC_ALLOWED},
> >> +
> >> +    {GOP_SIZE, ENC, CODECS_ALL,
> >> +        0, INT_MAX, 1, 2 * DEFAULT_FPS - 1,
> >> +        V4L2_CID_MPEG_VIDEO_GOP_SIZE,
> >> +        HFI_PROP_MAX_GOP_FRAMES,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> >> +        CAP_FLAG_DYNAMIC_ALLOWED},
> >> +
> >> +    {GOP_CLOSURE, ENC, H264 | HEVC,
> >> +        0, 1, 1, 1,
> >> +        V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
> >> +        0},
> >> +
> >> +    {B_FRAME, ENC, H264 | HEVC,
> >> +        0, 7, 1, 0,
> >> +        V4L2_CID_MPEG_VIDEO_B_FRAMES,
> >> +        HFI_PROP_MAX_B_FRAMES,
> >> +        CAP_FLAG_OUTPUT_PORT},
> >> +
> >> +    {LTR_COUNT, ENC, H264 | HEVC,
> >> +        0, MAX_LTR_FRAME_COUNT_2, 1, 0,
> >> +        V4L2_CID_MPEG_VIDEO_LTR_COUNT,
> >> +        HFI_PROP_LTR_COUNT,
> >> +        CAP_FLAG_OUTPUT_PORT},
> >> +
> >> +    {USE_LTR, ENC, H264 | HEVC,
> >> +        0,
> >> +        ((1 << MAX_LTR_FRAME_COUNT_2) - 1),
> >> +        0, 0,
> >> +        V4L2_CID_MPEG_VIDEO_USE_LTR_FRAMES,
> >> +        HFI_PROP_LTR_USE,
> >> +        CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED},
> >> +
> >> +    {MARK_LTR, ENC, H264 | HEVC,
> >> +        INVALID_DEFAULT_MARK_OR_USE_LTR,
> >> +        (MAX_LTR_FRAME_COUNT_2 - 1),
> >> +        1, INVALID_DEFAULT_MARK_OR_USE_LTR,
> >> +        V4L2_CID_MPEG_VIDEO_FRAME_LTR_INDEX,
> >> +        HFI_PROP_LTR_MARK,
> >> +        CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED},
> >> +
> >> +    {BASELAYER_PRIORITY, ENC, H264,
> >> +        0, MAX_BASE_LAYER_PRIORITY_ID, 1, 0,
> >> +        V4L2_CID_MPEG_VIDEO_BASELAYER_PRIORITY_ID,
> >> +        HFI_PROP_BASELAYER_PRIORITYID,
> >> +        CAP_FLAG_OUTPUT_PORT},
> >> +
> >> +    {IR_TYPE, ENC, H264 | HEVC,
> >> +        V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_RANDOM,
> >> +        V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_CYCLIC,
> >> +        BIT(V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_RANDOM) |
> >> +        BIT(V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_CYCLIC),
> >> +        V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_RANDOM,
> >> +        V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE,
> >> +        0,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> >> +
> >> +    {IR_PERIOD, ENC, H264 | HEVC,
> >> +        0, INT_MAX, 1, 0,
> >> +        V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD,
> >> +        0,
> >> +        CAP_FLAG_INPUT_PORT | CAP_FLAG_OUTPUT_PORT |
> >> +        CAP_FLAG_DYNAMIC_ALLOWED},
> >> +
> >> +    {AU_DELIMITER, ENC, H264 | HEVC,
> >> +        0, 1, 1, 0,
> >> +        V4L2_CID_MPEG_VIDEO_AU_DELIMITER,
> >> +        HFI_PROP_AUD,
> >> +        CAP_FLAG_OUTPUT_PORT},
> >> +
> >> +    {MIN_QUALITY, ENC, H264 | HEVC,
> >> +        0, MAX_SUPPORTED_MIN_QUALITY, 70, MAX_SUPPORTED_MIN_QUALITY,
> >> +        0,
> >> +        HFI_PROP_MAINTAIN_MIN_QUALITY,
> >> +        CAP_FLAG_OUTPUT_PORT},
> >> +
> >> +    {VBV_DELAY, ENC, H264 | HEVC,
> >> +        200, 300, 100, 300,
> >> +        V4L2_CID_MPEG_VIDEO_VBV_DELAY,
> >> +        HFI_PROP_VBV_DELAY,
> >> +        CAP_FLAG_OUTPUT_PORT},
> >> +
> >> +    {PEAK_BITRATE, ENC, H264 | HEVC,
> >> +        /* default peak bitrate is 10% larger than avg bitrate */
> >> +        1, MAX_BITRATE, 1, DEFAULT_BITRATE,
> >> +        V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
> >> +        HFI_PROP_TOTAL_PEAK_BITRATE,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> >> +            CAP_FLAG_DYNAMIC_ALLOWED},
> >> +
> >> +    {MIN_FRAME_QP, ENC, H264,
> >> +        MIN_QP_8BIT, MAX_QP, 1, MIN_QP_8BIT,
> >> +        V4L2_CID_MPEG_VIDEO_H264_MIN_QP,
> >> +        HFI_PROP_MIN_QP_PACKED,
> >> +        CAP_FLAG_OUTPUT_PORT},
> >> +
> >> +    {MIN_FRAME_QP, ENC, HEVC,
> >> +        MIN_QP_10BIT, MAX_QP, 1, MIN_QP_10BIT,
> >> +        V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP,
> >> +        HFI_PROP_MIN_QP_PACKED,
> >> +        CAP_FLAG_OUTPUT_PORT},
> >> +
> >> +    {I_FRAME_MIN_QP, ENC, H264,
> >> +        MIN_QP_8BIT, MAX_QP, 1, MIN_QP_8BIT,
> >> +        V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MIN_QP},
> >> +
> >> +    {I_FRAME_MIN_QP, ENC, HEVC,
> >> +        MIN_QP_10BIT, MAX_QP, 1, MIN_QP_10BIT,
> >> +        V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_MIN_QP},
> >> +
> >> +    {P_FRAME_MIN_QP, ENC, H264,
> >> +        MIN_QP_8BIT, MAX_QP, 1, MIN_QP_8BIT,
> >> +        V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MIN_QP},
> >> +
> >> +    {P_FRAME_MIN_QP, ENC, HEVC,
> >> +        MIN_QP_10BIT, MAX_QP, 1, MIN_QP_10BIT,
> >> +        V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_MIN_QP},
> >> +
> >> +    {B_FRAME_MIN_QP, ENC, H264,
> >> +        MIN_QP_8BIT, MAX_QP, 1, MIN_QP_8BIT,
> >> +        V4L2_CID_MPEG_VIDEO_H264_B_FRAME_MIN_QP},
> >> +
> >> +    {B_FRAME_MIN_QP, ENC, HEVC,
> >> +        MIN_QP_10BIT, MAX_QP, 1, MIN_QP_10BIT,
> >> +        V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_MIN_QP},
> >> +
> >> +    {MAX_FRAME_QP, ENC, H264,
> >> +        MIN_QP_8BIT, MAX_QP, 1, MAX_QP,
> >> +        V4L2_CID_MPEG_VIDEO_H264_MAX_QP,
> >> +        HFI_PROP_MAX_QP_PACKED,
> >> +        CAP_FLAG_OUTPUT_PORT},
> >> +
> >> +    {MAX_FRAME_QP, ENC, HEVC,
> >> +        MIN_QP_10BIT, MAX_QP, 1, MAX_QP,
> >> +        V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP,
> >> +        HFI_PROP_MAX_QP_PACKED,
> >> +        CAP_FLAG_OUTPUT_PORT},
> >> +
> >> +    {I_FRAME_MAX_QP, ENC, H264,
> >> +        MIN_QP_8BIT, MAX_QP, 1, MAX_QP,
> >> +        V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MAX_QP},
> >> +
> >> +    {I_FRAME_MAX_QP, ENC, HEVC,
> >> +        MIN_QP_10BIT, MAX_QP, 1, MAX_QP,
> >> +        V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_MAX_QP},
> >> +
> >> +    {P_FRAME_MAX_QP, ENC, H264,
> >> +        MIN_QP_8BIT, MAX_QP, 1, MAX_QP,
> >> +        V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MAX_QP},
> >> +
> >> +    {P_FRAME_MAX_QP, ENC, HEVC,
> >> +        MIN_QP_10BIT, MAX_QP, 1, MAX_QP,
> >> +        V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_MAX_QP},
> >> +
> >> +    {B_FRAME_MAX_QP, ENC, H264,
> >> +        MIN_QP_8BIT, MAX_QP, 1, MAX_QP,
> >> +        V4L2_CID_MPEG_VIDEO_H264_B_FRAME_MAX_QP},
> >> +
> >> +    {B_FRAME_MAX_QP, ENC, HEVC,
> >> +        MIN_QP_10BIT, MAX_QP, 1, MAX_QP,
> >> +        V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_MAX_QP},
> >> +
> >> +    {I_FRAME_QP, ENC, HEVC,
> >> +        MIN_QP_10BIT, MAX_QP, 1, DEFAULT_QP,
> >> +        V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP,
> >> +        HFI_PROP_QP_PACKED,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> >> +            CAP_FLAG_DYNAMIC_ALLOWED},
> >> +
> >> +    {I_FRAME_QP, ENC, H264,
> >> +        MIN_QP_8BIT, MAX_QP, 1, DEFAULT_QP,
> >> +        V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP,
> >> +        HFI_PROP_QP_PACKED,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> >> +            CAP_FLAG_DYNAMIC_ALLOWED},
> >> +
> >> +    {P_FRAME_QP, ENC, HEVC,
> >> +        MIN_QP_10BIT, MAX_QP, 1, DEFAULT_QP,
> >> +        V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP,
> >> +        HFI_PROP_QP_PACKED,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> >> +            CAP_FLAG_DYNAMIC_ALLOWED},
> >> +
> >> +    {P_FRAME_QP, ENC, H264,
> >> +        MIN_QP_8BIT, MAX_QP, 1, DEFAULT_QP,
> >> +        V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP,
> >> +        HFI_PROP_QP_PACKED,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> >> +            CAP_FLAG_DYNAMIC_ALLOWED},
> >> +
> >> +    {B_FRAME_QP, ENC, HEVC,
> >> +        MIN_QP_10BIT, MAX_QP, 1, DEFAULT_QP,
> >> +        V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP,
> >> +        HFI_PROP_QP_PACKED,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> >> +            CAP_FLAG_DYNAMIC_ALLOWED},
> >> +
> >> +    {B_FRAME_QP, ENC, H264,
> >> +        MIN_QP_8BIT, MAX_QP, 1, DEFAULT_QP,
> >> +        V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP,
> >> +        HFI_PROP_QP_PACKED,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> >> +            CAP_FLAG_DYNAMIC_ALLOWED},
> >> +
> >> +    {LAYER_TYPE, ENC, HEVC,
> >> +        V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B,
> >> +        V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P,
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B) |
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P),
> >> +        V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P,
> >> +        V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE,
> >> +        HFI_PROP_LAYER_ENCODING_TYPE,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> >> +
> >> +    {LAYER_TYPE, ENC, H264,
> >> +        V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B,
> >> +        V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P,
> >> +        BIT(V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P),
> >> +        V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P,
> >> +        V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE,
> >> +        HFI_PROP_LAYER_ENCODING_TYPE,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> >> +
> >> +    {LAYER_ENABLE, ENC, H264,
> >> +        0, 1, 1, 0,
> >> +        V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING,
> >> +        HFI_PROP_LAYER_ENCODING_TYPE,
> >> +        CAP_FLAG_OUTPUT_PORT},
> >> +
> >> +    {LAYER_ENABLE, ENC, HEVC,
> >> +        0, 1, 1, 0,
> >> +        0,
> >> +        0,
> >> +        CAP_FLAG_OUTPUT_PORT},
> >> +
> >> +    {ENH_LAYER_COUNT, ENC, HEVC,
> >> +        0, 5, 1, 0,
> >> +        V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER,
> >> +        HFI_PROP_LAYER_COUNT,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> >> +            CAP_FLAG_DYNAMIC_ALLOWED},
> >> +
> >> +    {ENH_LAYER_COUNT, ENC, H264,
> >> +        0, 5, 1, 0,
> >> +        V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER,
> >> +        HFI_PROP_LAYER_COUNT,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> >> +            CAP_FLAG_DYNAMIC_ALLOWED},
> >> +
> >> +    {L0_BR, ENC, H264,
> >> +        1, MAX_BITRATE, 1, DEFAULT_BITRATE,
> >> +        V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L0_BR,
> >> +        HFI_PROP_BITRATE_LAYER1,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> >> +            CAP_FLAG_DYNAMIC_ALLOWED},
> >> +
> >> +    {L0_BR, ENC, HEVC,
> >> +        1, MAX_BITRATE, 1, DEFAULT_BITRATE,
> >> +        V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L0_BR,
> >> +        HFI_PROP_BITRATE_LAYER1,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> >> +            CAP_FLAG_DYNAMIC_ALLOWED},
> >> +
> >> +    {L1_BR, ENC, H264,
> >> +        1, MAX_BITRATE, 1, DEFAULT_BITRATE,
> >> +        V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L1_BR,
> >> +        HFI_PROP_BITRATE_LAYER2,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> >> +            CAP_FLAG_DYNAMIC_ALLOWED},
> >> +
> >> +    {L1_BR, ENC, HEVC,
> >> +        1, MAX_BITRATE, 1, DEFAULT_BITRATE,
> >> +        V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L1_BR,
> >> +        HFI_PROP_BITRATE_LAYER2,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> >> +            CAP_FLAG_DYNAMIC_ALLOWED},
> >> +
> >> +    {L2_BR, ENC, H264,
> >> +        1, MAX_BITRATE, 1, DEFAULT_BITRATE,
> >> +        V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L2_BR,
> >> +        HFI_PROP_BITRATE_LAYER3,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> >> +            CAP_FLAG_DYNAMIC_ALLOWED},
> >> +
> >> +    {L2_BR, ENC, HEVC,
> >> +        1, MAX_BITRATE, 1, DEFAULT_BITRATE,
> >> +        V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L2_BR,
> >> +        HFI_PROP_BITRATE_LAYER3,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> >> +            CAP_FLAG_DYNAMIC_ALLOWED},
> >> +
> >> +    {L3_BR, ENC, H264,
> >> +        1, MAX_BITRATE, 1, DEFAULT_BITRATE,
> >> +        V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L3_BR,
> >> +        HFI_PROP_BITRATE_LAYER4,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> >> +            CAP_FLAG_DYNAMIC_ALLOWED},
> >> +    {L3_BR, ENC, HEVC,
> >> +        1, MAX_BITRATE, 1, DEFAULT_BITRATE,
> >> +        V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L3_BR,
> >> +        HFI_PROP_BITRATE_LAYER4,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> >> +            CAP_FLAG_DYNAMIC_ALLOWED},
> >> +
> >> +    {L4_BR, ENC, H264,
> >> +        1, MAX_BITRATE, 1, DEFAULT_BITRATE,
> >> +        V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L4_BR,
> >> +        HFI_PROP_BITRATE_LAYER5,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> >> +            CAP_FLAG_DYNAMIC_ALLOWED},
> >> +
> >> +    {L4_BR, ENC, HEVC,
> >> +        1, MAX_BITRATE, 1, DEFAULT_BITRATE,
> >> +        V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L4_BR,
> >> +        HFI_PROP_BITRATE_LAYER5,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> >> +            CAP_FLAG_DYNAMIC_ALLOWED},
> >> +
> >> +    {L5_BR, ENC, H264,
> >> +        1, MAX_BITRATE, 1, DEFAULT_BITRATE,
> >> +        V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L5_BR,
> >> +        HFI_PROP_BITRATE_LAYER6,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> >> +            CAP_FLAG_DYNAMIC_ALLOWED},
> >> +
> >> +    {L5_BR, ENC, HEVC,
> >> +        1, MAX_BITRATE, 1, DEFAULT_BITRATE,
> >> +        V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L5_BR,
> >> +        HFI_PROP_BITRATE_LAYER6,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> >> +            CAP_FLAG_DYNAMIC_ALLOWED},
> >> +
> >> +    {ENTROPY_MODE, ENC, H264,
> >> +        V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
> >> +        V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
> >> +        BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC),
> >> +        V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
> >> +        V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE,
> >> +        HFI_PROP_CABAC_SESSION,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> >> +
> >> +    {ENTROPY_MODE, DEC, H264 | HEVC | VP9,
> >> +        V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
> >> +        V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
> >> +        BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC),
> >> +        V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
> >> +        0,
> >> +        HFI_PROP_CABAC_SESSION},
> >> +
> >> +    {PROFILE, ENC | DEC, H264,
> >> +        V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
> >> +        V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH,
> >> +        BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH),
> >> +        V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
> >> +        V4L2_CID_MPEG_VIDEO_H264_PROFILE,
> >> +        HFI_PROP_PROFILE,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> >> +
> >> +    {PROFILE, ENC | DEC, HEVC,
> >> +        V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
> >> +        V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10,
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) |
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE) |
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10),
> >> +        V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
> >> +        V4L2_CID_MPEG_VIDEO_HEVC_PROFILE,
> >> +        HFI_PROP_PROFILE,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> >> +
> >> +    {PROFILE, DEC, VP9,
> >> +        V4L2_MPEG_VIDEO_VP9_PROFILE_0,
> >> +        V4L2_MPEG_VIDEO_VP9_PROFILE_2,
> >> +        BIT(V4L2_MPEG_VIDEO_VP9_PROFILE_0) |
> >> +        BIT(V4L2_MPEG_VIDEO_VP9_PROFILE_2),
> >> +        V4L2_MPEG_VIDEO_VP9_PROFILE_0,
> >> +        V4L2_CID_MPEG_VIDEO_VP9_PROFILE,
> >> +        HFI_PROP_PROFILE,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> >> +
> >> +    {LEVEL, ENC, H264,
> >> +        V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
> >> +        V4L2_MPEG_VIDEO_H264_LEVEL_6_0,
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_0) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_1) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_2) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_0),
> >> +        V4L2_MPEG_VIDEO_H264_LEVEL_5_0,
> >> +        V4L2_CID_MPEG_VIDEO_H264_LEVEL,
> >> +        HFI_PROP_LEVEL,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> >> +
> >> +    {LEVEL, ENC, HEVC,
> >> +        V4L2_MPEG_VIDEO_HEVC_LEVEL_1,
> >> +        V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2,
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_1) |
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2) |
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) |
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3) |
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) |
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4) |
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1) |
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5) |
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1) |
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2) |
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6) |
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1) |
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2),
> >> +        V4L2_MPEG_VIDEO_HEVC_LEVEL_5,
> >> +        V4L2_CID_MPEG_VIDEO_HEVC_LEVEL,
> >> +        HFI_PROP_LEVEL,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> >> +
> >> +    {LEVEL, DEC, H264,
> >> +        V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
> >> +        V4L2_MPEG_VIDEO_H264_LEVEL_6_2,
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_0) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_1) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_2) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_0) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_1) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_2),
> >> +        V4L2_MPEG_VIDEO_H264_LEVEL_6_1,
> >> +        V4L2_CID_MPEG_VIDEO_H264_LEVEL,
> >> +        HFI_PROP_LEVEL,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> >> +
> >> +    {LEVEL, DEC, HEVC,
> >> +        V4L2_MPEG_VIDEO_HEVC_LEVEL_1,
> >> +        V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2,
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_1) |
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2) |
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) |
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3) |
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) |
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4) |
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1) |
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5) |
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1) |
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2) |
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6) |
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1) |
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2),
> >> +        V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1,
> >> +        V4L2_CID_MPEG_VIDEO_HEVC_LEVEL,
> >> +        HFI_PROP_LEVEL,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> >> +
> >> +    {LEVEL, DEC, VP9,
> >> +        V4L2_MPEG_VIDEO_VP9_LEVEL_1_0,
> >> +        V4L2_MPEG_VIDEO_VP9_LEVEL_6_0,
> >> +        BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_1_0) |
> >> +        BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_1_1) |
> >> +        BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_2_0) |
> >> +        BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_2_1) |
> >> +        BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_3_0) |
> >> +        BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_3_1) |
> >> +        BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_4_0) |
> >> +        BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_4_1) |
> >> +        BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_5_0) |
> >> +        BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_5_1) |
> >> +        BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_5_2) |
> >> +        BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_6_0),
> >> +        V4L2_MPEG_VIDEO_VP9_LEVEL_6_0,
> >> +        V4L2_CID_MPEG_VIDEO_VP9_LEVEL,
> >> +        HFI_PROP_LEVEL,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> >> +
> >> +    {HEVC_TIER, ENC | DEC, HEVC,
> >> +        V4L2_MPEG_VIDEO_HEVC_TIER_MAIN,
> >> +        V4L2_MPEG_VIDEO_HEVC_TIER_HIGH,
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_TIER_MAIN) |
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_TIER_HIGH),
> >> +        V4L2_MPEG_VIDEO_HEVC_TIER_HIGH,
> >> +        V4L2_CID_MPEG_VIDEO_HEVC_TIER,
> >> +        HFI_PROP_TIER,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> >> +
> >> +    {LF_MODE, ENC, H264,
> >> +        V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED,
> >> +        DB_H264_DISABLE_SLICE_BOUNDARY,
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED) |
> >> +        BIT(V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED) |
> >> +        BIT(DB_H264_DISABLE_SLICE_BOUNDARY),
> >> +        V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED,
> >> +        V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE,
> >> +        HFI_PROP_DEBLOCKING_MODE,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> >> +
> >> +    {LF_MODE, ENC, HEVC,
> >> +        V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_DISABLED,
> >> +        DB_HEVC_DISABLE_SLICE_BOUNDARY,
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_DISABLED) |
> >> +        BIT(V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_ENABLED) |
> >> +        BIT(DB_HEVC_DISABLE_SLICE_BOUNDARY),
> >> +        V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_ENABLED,
> >> +        V4L2_CID_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE,
> >> +        HFI_PROP_DEBLOCKING_MODE,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> >> +
> >> +    {LF_ALPHA, ENC, H264,
> >> +        -6, 6, 1, 0,
> >> +        V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA},
> >> +
> >> +    {LF_ALPHA, ENC, HEVC,
> >> +        -6, 6, 1, 0,
> >> +        V4L2_CID_MPEG_VIDEO_HEVC_LF_TC_OFFSET_DIV2},
> >> +
> >> +    {LF_BETA, ENC, H264,
> >> +        -6, 6, 1, 0,
> >> +        V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA},
> >> +
> >> +    {LF_BETA, ENC, HEVC,
> >> +        -6, 6, 1, 0,
> >> +        V4L2_CID_MPEG_VIDEO_HEVC_LF_BETA_OFFSET_DIV2},
> >> +
> >> +    {SLICE_MODE, ENC, H264 | HEVC,
> >> +        V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE,
> >> +        V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES,
> >> +        BIT(V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE) |
> >> +        BIT(V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) |
> >> +        BIT(V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES),
> >> +        V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE,
> >> +        V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE,
> >> +        0,
> >> +        CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
> >> +
> >> +    {SLICE_MAX_BYTES, ENC, H264 | HEVC,
> >> +        MIN_SLICE_BYTE_SIZE, MAX_SLICE_BYTE_SIZE,
> >> +        1, MIN_SLICE_BYTE_SIZE,
> >> +        V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES,
> >> +        HFI_PROP_MULTI_SLICE_BYTES_COUNT,
> >> +        CAP_FLAG_OUTPUT_PORT},
> >> +
> >> +    {SLICE_MAX_MB, ENC, H264 | HEVC,
> >> +        1, MAX_SLICE_MB_SIZE, 1, 1,
> >> +        V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB,
> >> +        HFI_PROP_MULTI_SLICE_MB_COUNT,
> >> +        CAP_FLAG_OUTPUT_PORT},
> >> +
> >> +    {MB_RC, ENC, H264 | HEVC,
> >> +        0, 1, 1, 1,
> >> +        V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE,
> >> +        0,
> >> +        CAP_FLAG_OUTPUT_PORT},
> >> +
> >> +    {TRANSFORM_8X8, ENC, H264,
> >> +        0, 1, 1, 1,
> >> +        V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM,
> >> +        HFI_PROP_8X8_TRANSFORM,
> >> +        CAP_FLAG_OUTPUT_PORT},
> >> +
> >> +    {CHROMA_QP_INDEX_OFFSET, ENC, HEVC,
> >> +        MIN_CHROMA_QP_OFFSET, MAX_CHROMA_QP_OFFSET,
> >> +        1, MAX_CHROMA_QP_OFFSET,
> >> +        V4L2_CID_MPEG_VIDEO_H264_CHROMA_QP_INDEX_OFFSET,
> >> +        HFI_PROP_CHROMA_QP_OFFSET,
> >> +        CAP_FLAG_OUTPUT_PORT},
> >> +
> >> +    {DISPLAY_DELAY_ENABLE, DEC, H264 | HEVC | VP9,
> >> +        0, 1, 1, 0,
> >> +        V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE,
> >> +        HFI_PROP_DECODE_ORDER_OUTPUT,
> >> +        CAP_FLAG_INPUT_PORT},
> >> +
> >> +    {DISPLAY_DELAY, DEC, H264 | HEVC | VP9,
> >> +        0, 1, 1, 0,
> >> +        V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY,
> >> +        HFI_PROP_DECODE_ORDER_OUTPUT,
> >> +        CAP_FLAG_INPUT_PORT},
> >> +
> >> +    {OUTPUT_ORDER, DEC, H264 | HEVC | VP9,
> >> +        0, 1, 1, 0,
> >> +        0,
> >> +        HFI_PROP_DECODE_ORDER_OUTPUT,
> >> +        CAP_FLAG_INPUT_PORT},
> >> +
> >> +    {INPUT_BUF_HOST_MAX_COUNT, ENC | DEC, CODECS_ALL,
> >> +        DEFAULT_MAX_HOST_BUF_COUNT, DEFAULT_MAX_HOST_BURST_BUF_COUNT,
> >> +        1, DEFAULT_MAX_HOST_BUF_COUNT,
> >> +        0,
> >> +        HFI_PROP_BUFFER_HOST_MAX_COUNT,
> >> +        CAP_FLAG_INPUT_PORT},
> >> +
> >> +    {OUTPUT_BUF_HOST_MAX_COUNT, ENC | DEC, CODECS_ALL,
> >> +        DEFAULT_MAX_HOST_BUF_COUNT, DEFAULT_MAX_HOST_BURST_BUF_COUNT,
> >> +        1, DEFAULT_MAX_HOST_BUF_COUNT,
> >> +        0,
> >> +        HFI_PROP_BUFFER_HOST_MAX_COUNT,
> >> +        CAP_FLAG_OUTPUT_PORT},
> >> +
> >> +    {CONCEAL_COLOR_8BIT, DEC, CODECS_ALL, 0x0, 0xff3fcff, 1,
> >> +        DEFAULT_VIDEO_CONCEAL_COLOR_BLACK,
> >> +        V4L2_CID_MPEG_VIDEO_MUTE_YUV,
> >> +        HFI_PROP_CONCEAL_COLOR_8BIT,
> >> +        CAP_FLAG_INPUT_PORT},
> >> +
> >> +    {CONCEAL_COLOR_10BIT, DEC, CODECS_ALL, 0x0, 0x3fffffff, 1,
> >> +        DEFAULT_VIDEO_CONCEAL_COLOR_BLACK,
> >> +        V4L2_CID_MPEG_VIDEO_MUTE_YUV,
> >> +        HFI_PROP_CONCEAL_COLOR_10BIT,
> >> +        CAP_FLAG_INPUT_PORT},
> >> +
> >> +    {STAGE, DEC | ENC, CODECS_ALL,
> >> +        MSM_VIDC_STAGE_1,
> >> +        MSM_VIDC_STAGE_2, 1,
> >> +        MSM_VIDC_STAGE_2,
> >> +        0,
> >> +        HFI_PROP_STAGE},
> >> +
> >> +    {PIPE, DEC | ENC, CODECS_ALL,
> >> +        MSM_VIDC_PIPE_1,
> >> +        MSM_VIDC_PIPE_4, 1,
> >> +        MSM_VIDC_PIPE_4,
> >> +        0,
> >> +        HFI_PROP_PIPE},
> >> +
> >> +    {POC, DEC, H264, 0, 2, 1, 1,
> >> +        0,
> >> +        HFI_PROP_PIC_ORDER_CNT_TYPE},
> >> +
> >> +    {QUALITY_MODE, ENC, CODECS_ALL,
> >> +        MSM_VIDC_MAX_QUALITY_MODE,
> >> +        MSM_VIDC_POWER_SAVE_MODE, 1,
> >> +        MSM_VIDC_POWER_SAVE_MODE},
> >> +
> >> +    {CODED_FRAMES, DEC, H264 | HEVC,
> >> +        CODED_FRAMES_PROGRESSIVE, CODED_FRAMES_INTERLACE,
> >> +        1, CODED_FRAMES_PROGRESSIVE,
> >> +        0,
> >> +        HFI_PROP_CODED_FRAMES},
> >> +
> >> +    {BIT_DEPTH, DEC, CODECS_ALL, BIT_DEPTH_8, BIT_DEPTH_10, 1, BIT_DEPTH_8,
> >> +        0,
> >> +        HFI_PROP_LUMA_CHROMA_BIT_DEPTH},
> >> +
> >> +    {BITSTREAM_SIZE_OVERWRITE, DEC, CODECS_ALL, 0, INT_MAX, 1, 0,
> >> +        0},
> >> +
> >> +    {DEFAULT_HEADER, DEC, CODECS_ALL,
> >> +        0, 1, 1, 0,
> >> +        0,
> >> +        HFI_PROP_DEC_DEFAULT_HEADER},
> >> +
> >> +    {RAP_FRAME, DEC, CODECS_ALL,
> >> +        0, 1, 1, 1,
> >> +        0,
> >> +        HFI_PROP_DEC_START_FROM_RAP_FRAME,
> >> +        CAP_FLAG_INPUT_PORT},
> >> +
> >> +    {SEQ_CHANGE_AT_SYNC_FRAME, DEC, CODECS_ALL,
> >> +        0, 1, 1, 1,
> >> +        0,
> >> +        HFI_PROP_SEQ_CHANGE_AT_SYNC_FRAME,
> >> +        CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED},
> >> +
> >> +    {ALL_INTRA, ENC, H264 | HEVC,
> >> +        0, 1, 1, 0,
> >> +        0,
> >> +        0,
> >> +        CAP_FLAG_OUTPUT_PORT},
> >> +};
> >> +
> >> +static struct msm_platform_inst_cap_dependency
> >> instance_cap_dependency_data_sm8550[] = {
> >> +    /* {cap, domain, codec,
> >> +     *      children,
> >> +     *      adjust, set}
> >> +     */
> >> +
> >> +    {PIX_FMTS, ENC, H264,
> >> +        {IR_PERIOD}},
> >> +
> >> +    {PIX_FMTS, ENC, HEVC,
> >> +        {PROFILE, MIN_FRAME_QP, MAX_FRAME_QP, I_FRAME_QP, P_FRAME_QP,
> >> +            B_FRAME_QP, MIN_QUALITY, IR_PERIOD, LTR_COUNT}},
> >> +
> >> +    {PIX_FMTS, DEC, HEVC,
> >> +        {PROFILE}},
> >> +
> >> +    {FRAME_RATE, ENC, CODECS_ALL,
> >> +        {0},
> >> +        NULL,
> >> +        msm_vidc_set_q16},
> >> +
> >> +    {HFLIP, ENC, CODECS_ALL,
> >> +        {0},
> >> +        NULL,
> >> +        msm_vidc_set_flip},
> >> +
> >> +    {VFLIP, ENC, CODECS_ALL,
> >> +        {0},
> >> +        NULL,
> >> +        msm_vidc_set_flip},
> >> +
> >> +    {ROTATION, ENC, CODECS_ALL,
> >> +        {0},
> >> +        NULL,
> >> +        msm_vidc_set_rotation},
> >> +
> >> +    {HEADER_MODE, ENC, CODECS_ALL,
> >> +        {0},
> >> +        NULL,
> >> +        msm_vidc_set_header_mode},
> >> +
> >> +    {WITHOUT_STARTCODE, ENC, CODECS_ALL,
> >> +        {0},
> >> +        NULL,
> >> +        msm_vidc_set_nal_length},
> >> +
> >> +    {REQUEST_I_FRAME, ENC, H264 | HEVC,
> >> +        {0},
> >> +        NULL,
> >> +        msm_vidc_set_req_sync_frame},
> >> +
> >> +    {BIT_RATE, ENC, H264,
> >> +        {PEAK_BITRATE, L0_BR},
> >> +        msm_vidc_adjust_bitrate,
> >> +        msm_vidc_set_bitrate},
> >> +
> >> +    {BIT_RATE, ENC, HEVC,
> >> +        {PEAK_BITRATE, L0_BR},
> >> +        msm_vidc_adjust_bitrate,
> >> +        msm_vidc_set_bitrate},
> >> +
> >> +    {BITRATE_MODE, ENC, H264,
> >> +        {LTR_COUNT, IR_PERIOD, I_FRAME_QP, P_FRAME_QP,
> >> +            B_FRAME_QP, ENH_LAYER_COUNT, BIT_RATE,
> >> +            MIN_QUALITY, VBV_DELAY,
> >> +            PEAK_BITRATE, SLICE_MODE},
> >> +        msm_vidc_adjust_bitrate_mode,
> >> +        msm_vidc_set_u32_enum},
> >> +
> >> +    {BITRATE_MODE, ENC, HEVC,
> >> +        {LTR_COUNT, IR_PERIOD, I_FRAME_QP, P_FRAME_QP,
> >> +            B_FRAME_QP, CONSTANT_QUALITY, ENH_LAYER_COUNT,
> >> +            BIT_RATE, MIN_QUALITY, VBV_DELAY,
> >> +            PEAK_BITRATE, SLICE_MODE},
> >> +        msm_vidc_adjust_bitrate_mode,
> >> +        msm_vidc_set_u32_enum},
> >> +
> >> +    {CONSTANT_QUALITY, ENC, HEVC,
> >> +        {0},
> >> +        NULL,
> >> +        msm_vidc_set_constant_quality},
> >> +
> >> +    {GOP_SIZE, ENC, CODECS_ALL,
> >> +        {ALL_INTRA},
> >> +        msm_vidc_adjust_gop_size,
> >> +        msm_vidc_set_gop_size},
> >> +
> >> +    {B_FRAME, ENC, H264 | HEVC,
> >> +        {ALL_INTRA},
> >> +        msm_vidc_adjust_b_frame,
> >> +        msm_vidc_set_u32},
> >> +
> >> +    {LTR_COUNT, ENC, H264 | HEVC,
> >> +        {0},
> >> +        msm_vidc_adjust_ltr_count,
> >> +        msm_vidc_set_u32},
> >> +
> >> +    {USE_LTR, ENC, H264 | HEVC,
> >> +        {0},
> >> +        msm_vidc_adjust_use_ltr,
> >> +        msm_vidc_set_use_and_mark_ltr},
> >> +
> >> +    {MARK_LTR, ENC, H264 | HEVC,
> >> +        {0},
> >> +        msm_vidc_adjust_mark_ltr,
> >> +        msm_vidc_set_use_and_mark_ltr},
> >> +
> >> +    {IR_PERIOD, ENC, H264 | HEVC,
> >> +        {0},
> >> +        msm_vidc_adjust_ir_period,
> >> +        msm_vidc_set_ir_period},
> >> +
> >> +    {AU_DELIMITER, ENC, H264 | HEVC,
> >> +        {0},
> >> +        NULL,
> >> +        msm_vidc_set_u32},
> >> +
> >> +    {MIN_QUALITY, ENC, H264,
> >> +        {0},
> >> +        msm_vidc_adjust_min_quality,
> >> +        msm_vidc_set_u32},
> >> +
> >> +    {MIN_QUALITY, ENC, HEVC,
> >> +        {0},
> >> +        msm_vidc_adjust_min_quality,
> >> +        msm_vidc_set_u32},
> >> +
> >> +    {VBV_DELAY, ENC, H264 | HEVC,
> >> +        {0},
> >> +        NULL,
> >> +        msm_vidc_set_cbr_related_properties},
> >> +
> >> +    {PEAK_BITRATE, ENC, H264 | HEVC,
> >> +        {0},
> >> +        msm_vidc_adjust_peak_bitrate,
> >> +        msm_vidc_set_cbr_related_properties},
> >> +
> >> +    {MIN_FRAME_QP, ENC, H264,
> >> +        {0},
> >> +        NULL,
> >> +        msm_vidc_set_min_qp},
> >> +
> >> +    {MIN_FRAME_QP, ENC, HEVC,
> >> +        {0},
> >> +        msm_vidc_adjust_hevc_min_qp,
> >> +        msm_vidc_set_min_qp},
> >> +
> >> +    {MAX_FRAME_QP, ENC, H264,
> >> +        {0},
> >> +        NULL,
> >> +        msm_vidc_set_max_qp},
> >> +
> >> +    {MAX_FRAME_QP, ENC, HEVC,
> >> +        {0},
> >> +        msm_vidc_adjust_hevc_max_qp,
> >> +        msm_vidc_set_max_qp},
> >> +
> >> +    {I_FRAME_QP, ENC, HEVC,
> >> +        {0},
> >> +        msm_vidc_adjust_hevc_i_frame_qp,
> >> +        msm_vidc_set_frame_qp},
> >> +
> >> +    {I_FRAME_QP, ENC, H264,
> >> +        {0},
> >> +        NULL,
> >> +        msm_vidc_set_frame_qp},
> >> +
> >> +    {P_FRAME_QP, ENC, HEVC,
> >> +        {0},
> >> +        msm_vidc_adjust_hevc_p_frame_qp,
> >> +        msm_vidc_set_frame_qp},
> >> +
> >> +    {P_FRAME_QP, ENC, H264,
> >> +        {0},
> >> +        NULL,
> >> +        msm_vidc_set_frame_qp},
> >> +
> >> +    {B_FRAME_QP, ENC, HEVC,
> >> +        {0},
> >> +        msm_vidc_adjust_hevc_b_frame_qp,
> >> +        msm_vidc_set_frame_qp},
> >> +
> >> +    {B_FRAME_QP, ENC, H264,
> >> +        {0},
> >> +        NULL,
> >> +        msm_vidc_set_frame_qp},
> >> +
> >> +    {LAYER_TYPE, ENC, H264 | HEVC,
> >> +        {LTR_COUNT}},
> >> +
> >> +    {LAYER_ENABLE, ENC, H264 | HEVC,
> >> +        {0}},
> >> +
> >> +    {ENH_LAYER_COUNT, ENC, H264 | HEVC,
> >> +        {GOP_SIZE, B_FRAME, BIT_RATE, MIN_QUALITY, SLICE_MODE,
> >> +            LTR_COUNT},
> >> +        msm_vidc_adjust_layer_count,
> >> +        msm_vidc_set_layer_count_and_type},
> >> +
> >> +    {L0_BR, ENC, H264 | HEVC,
> >> +        {L1_BR},
> >> +        msm_vidc_adjust_layer_bitrate,
> >> +        msm_vidc_set_layer_bitrate},
> >> +
> >> +    {L1_BR, ENC, H264 | HEVC,
> >> +        {L2_BR},
> >> +        msm_vidc_adjust_layer_bitrate,
> >> +        msm_vidc_set_layer_bitrate},
> >> +
> >> +    {L2_BR, ENC, H264 | HEVC,
> >> +        {L3_BR},
> >> +        msm_vidc_adjust_layer_bitrate,
> >> +        msm_vidc_set_layer_bitrate},
> >> +
> >> +    {L3_BR, ENC, H264 | HEVC,
> >> +        {L4_BR},
> >> +        msm_vidc_adjust_layer_bitrate,
> >> +        msm_vidc_set_layer_bitrate},
> >> +
> >> +    {L4_BR, ENC, H264 | HEVC,
> >> +        {L5_BR},
> >> +        msm_vidc_adjust_layer_bitrate,
> >> +        msm_vidc_set_layer_bitrate},
> >> +
> >> +    {L5_BR, ENC, H264 | HEVC,
> >> +        {0},
> >> +        msm_vidc_adjust_layer_bitrate,
> >> +        msm_vidc_set_layer_bitrate},
> >> +
> >> +    {ENTROPY_MODE, ENC, H264,
> >> +        {BIT_RATE},
> >> +        msm_vidc_adjust_entropy_mode,
> >> +        msm_vidc_set_u32},
> >> +
> >> +    {PROFILE, ENC, H264,
> >> +        {ENTROPY_MODE, TRANSFORM_8X8},
> >> +        NULL,
> >> +        msm_vidc_set_u32_enum},
> >> +
> >> +    {PROFILE, DEC, H264,
> >> +        {ENTROPY_MODE},
> >> +        NULL,
> >> +        msm_vidc_set_u32_enum},
> >> +
> >> +    {PROFILE, ENC | DEC, HEVC,
> >> +        {0},
> >> +        msm_vidc_adjust_profile,
> >> +        msm_vidc_set_u32_enum},
> >> +
> >> +    {PROFILE, DEC, VP9,
> >> +        {0},
> >> +        NULL,
> >> +        msm_vidc_set_u32_enum},
> >> +
> >> +    {LEVEL, DEC, CODECS_ALL,
> >> +        {0},
> >> +        NULL,
> >> +        msm_vidc_set_u32_enum},
> >> +
> >> +    {LEVEL, ENC, CODECS_ALL,
> >> +        {0},
> >> +        NULL,
> >> +        msm_vidc_set_level},
> >> +
> >> +    {HEVC_TIER, ENC | DEC, HEVC,
> >> +        {0},
> >> +        NULL,
> >> +        msm_vidc_set_u32_enum},
> >> +
> >> +    {LF_MODE, ENC, CODECS_ALL,
> >> +        {0},
> >> +        NULL,
> >> +        msm_vidc_set_deblock_mode},
> >> +
> >> +    {SLICE_MODE, ENC, H264 | HEVC,
> >> +        {STAGE},
> >> +        msm_vidc_adjust_slice_count,
> >> +        msm_vidc_set_slice_count},
> >> +
> >> +    {TRANSFORM_8X8, ENC, H264,
> >> +        {0},
> >> +        msm_vidc_adjust_transform_8x8,
> >> +        msm_vidc_set_u32},
> >> +
> >> +    {CHROMA_QP_INDEX_OFFSET, ENC, HEVC,
> >> +        {0},
> >> +        msm_vidc_adjust_chroma_qp_index_offset,
> >> +        msm_vidc_set_chroma_qp_index_offset},
> >> +
> >> +    {DISPLAY_DELAY_ENABLE, DEC, H264 | HEVC | VP9,
> >> +        {OUTPUT_ORDER},
> >> +        NULL,
> >> +        NULL},
> >> +
> >> +    {DISPLAY_DELAY, DEC, H264 | HEVC | VP9,
> >> +        {OUTPUT_ORDER},
> >> +        NULL,
> >> +        NULL},
> >> +
> >> +    {OUTPUT_ORDER, DEC, H264 | HEVC | VP9,
> >> +        {0},
> >> +        msm_vidc_adjust_output_order,
> >> +        msm_vidc_set_u32},
> >> +
> >> +    {INPUT_BUF_HOST_MAX_COUNT, ENC | DEC, CODECS_ALL,
> >> +        {0},
> >> +        msm_vidc_adjust_input_buf_host_max_count,
> >> +        msm_vidc_set_u32},
> >> +
> >> +    {INPUT_BUF_HOST_MAX_COUNT, ENC, H264 | HEVC,
> >> +        {0},
> >> +        msm_vidc_adjust_input_buf_host_max_count,
> >> +        msm_vidc_set_u32},
> >> +
> >> +    {OUTPUT_BUF_HOST_MAX_COUNT, ENC | DEC, CODECS_ALL,
> >> +        {0},
> >> +        msm_vidc_adjust_output_buf_host_max_count,
> >> +        msm_vidc_set_u32},
> >> +
> >> +    {OUTPUT_BUF_HOST_MAX_COUNT, ENC, H264 | HEVC,
> >> +        {0},
> >> +        msm_vidc_adjust_output_buf_host_max_count,
> >> +        msm_vidc_set_u32},
> >> +
> >> +    {CONCEAL_COLOR_8BIT, DEC, CODECS_ALL,
> >> +        {0},
> >> +        NULL,
> >> +        msm_vidc_set_u32_packed},
> >> +
> >> +    {CONCEAL_COLOR_10BIT, DEC, CODECS_ALL,
> >> +        {0},
> >> +        NULL,
> >> +        msm_vidc_set_u32_packed},
> >> +
> >> +    {STAGE, ENC | DEC, CODECS_ALL,
> >> +        {0},
> >> +        NULL,
> >> +        msm_vidc_set_stage},
> >> +
> >> +    {STAGE, ENC, H264 | HEVC,
> >> +        {0},
> >> +        NULL,
> >> +        msm_vidc_set_stage},
> >> +
> >> +    {STAGE, DEC, H264 | HEVC | VP9,
> >> +        {0},
> >> +        NULL,
> >> +        msm_vidc_set_stage},
> >> +
> >> +    {PIPE, DEC | ENC, CODECS_ALL,
> >> +        {0},
> >> +        NULL,
> >> +        msm_vidc_set_pipe},
> >> +
> >> +    {RAP_FRAME, DEC, CODECS_ALL,
> >> +        {0},
> >> +        NULL,
> >> +        msm_vidc_set_u32},
> >> +
> >> +    {ALL_INTRA, ENC, H264 | HEVC,
> >> +        {LTR_COUNT, IR_PERIOD, SLICE_MODE, BIT_RATE},
> >> +        msm_vidc_adjust_all_intra,
> >> +        NULL},
> >> +};
> >> +
> >> +/* Default UBWC config for LPDDR5 */
> >> +static struct msm_vidc_ubwc_config_data ubwc_config_sm8550[] = {
> >> +    UBWC_CONFIG(8, 32, 16, 0, 1, 1, 1),
> >> +};
> >> +
> >> +static struct msm_vidc_format_capability format_data_sm8550 = {
> >> +    .codec_info = codec_data_sm8550,
> >> +    .codec_info_size = ARRAY_SIZE(codec_data_sm8550),
> >> +    .color_format_info = color_format_data_sm8550,
> >> +    .color_format_info_size = ARRAY_SIZE(color_format_data_sm8550),
> >> +    .color_prim_info = color_primaries_data_sm8550,
> >> +    .color_prim_info_size = ARRAY_SIZE(color_primaries_data_sm8550),
> >> +    .transfer_char_info = transfer_char_data_sm8550,
> >> +    .transfer_char_info_size = ARRAY_SIZE(transfer_char_data_sm8550),
> >> +    .matrix_coeff_info = matrix_coeff_data_sm8550,
> >> +    .matrix_coeff_info_size = ARRAY_SIZE(matrix_coeff_data_sm8550),
> >> +};
> >> +
> >> +/* name, min_kbps, max_kbps */
> >> +static const struct bw_table sm8550_bw_table[] = {
> >> +    { "venus-cnoc",  1000, 1000     },
> >> +    { "venus-ddr",   1000, 15000000 },
> >
> > We have OPP tables for that. There is no need to limit the min/max, just
> > put it to OPP.
> >
> This table is used to vote for min and max bus bandwidth.
> for some test vector with bad picture order count, ref count can be huge,
> so DPB needs to be filled with high number of reference frames to process
> current frames, this needs faster frame processing so to address such
> cases, driver vote for max bus bandwidth.
> for some cases, when system is in suspend state, there might be some
> residual transitions happening for which driver needs to vote for min
> frequency during suspend state.

So? This can all be handled as a code handling OPP tables. I'm not
judging your voting code. I'm asking you to drop custom table and use
existing kernel mechanism for defining frequency / bandwidth tables.

> >> +};
> >> +
> >> +/* name */
> >> +static const struct pd_table sm8550_pd_table[] = {
> >> +    { "iris-ctl" },
> >> +    { "vcodec"   },
> >> +};
> >> +
> >> +/* name */
> >> +static const char * const sm8550_opp_table[] = { "mx", "mmcx", NULL };
> >> +
> >> +/* name, clock id, scaling */
> >> +static const struct clk_table sm8550_clk_table[] = {
> >> +    { "gcc_video_axi0",         GCC_VIDEO_AXI0_CLK,     0 },
> >> +    { "core_clk",               VIDEO_CC_MVS0C_CLK,     0 },
> >> +    { "vcodec_clk",             VIDEO_CC_MVS0_CLK,      1 },
> >> +};
> >
> > This strucuture looks like a perfect candidate to be replaced by
> > devm_clk_bulk_get_all().
> >
> Nice suggestion, will explore this.
> >> +
> >> +/* name, exclusive_release */
> >> +static const struct clk_rst_table sm8550_clk_reset_table[] = {
> >> +    { "video_axi_reset",        0  },
> >
> > Can we assume that resets are generic at least?
> >
> reset clocks can change for different hardware.

They can. But do they change for existing hardware?

> >> +};
> >> +
> >> +/* name, start, size, secure, dma_coherant, region, dma_mask */
> >> +const struct context_bank_table sm8550_context_bank_table[] = {
> >> +    {"qcom,vidc,cb-ns", 0x25800000, 0xba800000, 0, 1,
> >> MSM_VIDC_NON_SECURE, 0xe0000000 - 1},
> >> +    {"qcom,vidc,cb-sec-non-pxl",   0x01000000, 0x24800000, 1, 0,
> >> MSM_VIDC_SECURE_NONPIXEL,  0 },
> >
> > Aren't these a properties of subdevices? If so, why are you putting them here?
> >
> Will remove these in next version.
> >> +};
> >> +
> >> +/* freq */
> >> +static struct freq_table sm8550_freq_table[] = {
> >> +    {533333333}, {444000000}, {366000000}, {338000000}, {240000000}
> >
> > OPP table contents.
> >
> we are using this freq table at multiple places apart from voting like
> - setting freq to turbo for few use cases
> - limiting the freq to NOM
> - changing the frequency levels based on DCVS
> hence this table is need.

And it doesn't stop it from being encoded as OPP table. We have
devfreq for DCVS, and OPP has a notion of turbo / nominal values.

> >> +};
> >> +
> >> +/* register, value, mask */
> >> +static const struct reg_preset_table sm8550_reg_preset_table[] = {
> >> +    { 0xB0088, 0x0, 0x11 },
> >> +};
> >> +
> >> +/* decoder properties */
> >> +static const u32 sm8550_vdec_psc_avc[] = {
> >> +    HFI_PROP_BITSTREAM_RESOLUTION,
> >> +    HFI_PROP_CROP_OFFSETS,
> >> +    HFI_PROP_CODED_FRAMES,
> >> +    HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT,
> >> +    HFI_PROP_PIC_ORDER_CNT_TYPE,
> >> +    HFI_PROP_PROFILE,
> >> +    HFI_PROP_LEVEL,
> >> +    HFI_PROP_SIGNAL_COLOR_INFO,
> >> +};
> >> +
> >> +static const u32 sm8550_vdec_psc_hevc[] = {
> >> +    HFI_PROP_BITSTREAM_RESOLUTION,
> >> +    HFI_PROP_CROP_OFFSETS,
> >> +    HFI_PROP_LUMA_CHROMA_BIT_DEPTH,
> >> +    HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT,
> >> +    HFI_PROP_PROFILE,
> >> +    HFI_PROP_LEVEL,
> >> +    HFI_PROP_TIER,
> >> +    HFI_PROP_SIGNAL_COLOR_INFO,
> >> +};
> >> +
> >> +static const u32 sm8550_vdec_psc_vp9[] = {
> >> +    HFI_PROP_BITSTREAM_RESOLUTION,
> >> +    HFI_PROP_CROP_OFFSETS,
> >> +    HFI_PROP_LUMA_CHROMA_BIT_DEPTH,
> >> +    HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT,
> >> +    HFI_PROP_PROFILE,
> >> +    HFI_PROP_LEVEL,
> >> +};
> >> +
> >> +static const u32 sm8550_vdec_input_properties_avc[] = {
> >> +    HFI_PROP_NO_OUTPUT,
> >> +    HFI_PROP_SUBFRAME_INPUT,
> >> +};
> >> +
> >> +static const u32 sm8550_vdec_input_properties_hevc[] = {
> >> +    HFI_PROP_NO_OUTPUT,
> >> +    HFI_PROP_SUBFRAME_INPUT,
> >> +};
> >> +
> >> +static const u32 sm8550_vdec_input_properties_vp9[] = {
> >> +    HFI_PROP_NO_OUTPUT,
> >> +    HFI_PROP_SUBFRAME_INPUT,
> >> +};
> >> +
> >> +static const u32 sm8550_vdec_output_properties_avc[] = {
> >> +    HFI_PROP_WORST_COMPRESSION_RATIO,
> >> +    HFI_PROP_WORST_COMPLEXITY_FACTOR,
> >> +    HFI_PROP_PICTURE_TYPE,
> >> +    HFI_PROP_DPB_LIST,
> >> +    HFI_PROP_CABAC_SESSION,
> >> +};
> >> +
> >> +static const u32 sm8550_vdec_output_properties_hevc[] = {
> >> +    HFI_PROP_WORST_COMPRESSION_RATIO,
> >> +    HFI_PROP_WORST_COMPLEXITY_FACTOR,
> >> +    HFI_PROP_PICTURE_TYPE,
> >> +    HFI_PROP_DPB_LIST,
> >> +};
> >> +
> >> +static const u32 sm8550_vdec_output_properties_vp9[] = {
> >> +    HFI_PROP_WORST_COMPRESSION_RATIO,
> >> +    HFI_PROP_WORST_COMPLEXITY_FACTOR,
> >> +    HFI_PROP_PICTURE_TYPE,
> >> +    HFI_PROP_DPB_LIST,
> >> +};
> >> +
> >> +static const struct msm_vidc_platform_data sm8550_data = {
> >> +    /* resources dependent on other module */
> >> +    .bw_tbl = sm8550_bw_table,
> >> +    .bw_tbl_size = ARRAY_SIZE(sm8550_bw_table),
> >> +    .clk_tbl = sm8550_clk_table,
> >> +    .clk_tbl_size = ARRAY_SIZE(sm8550_clk_table),
> >> +    .clk_rst_tbl = sm8550_clk_reset_table,
> >> +    .clk_rst_tbl_size = ARRAY_SIZE(sm8550_clk_reset_table),
> >> +    .subcache_tbl = NULL,
> >> +    .subcache_tbl_size = 0,
> >> +
> >> +    /* populate context bank */
> >> +    .context_bank_tbl = sm8550_context_bank_table,
> >> +    .context_bank_tbl_size = ARRAY_SIZE(sm8550_context_bank_table),
> >> +
> >> +    /* populate power domain and opp table */
> >> +    .pd_tbl = sm8550_pd_table,
> >> +    .pd_tbl_size = ARRAY_SIZE(sm8550_pd_table),
> >> +    .opp_tbl = sm8550_opp_table,
> >> +    .opp_tbl_size = ARRAY_SIZE(sm8550_opp_table),
> >> +
> >> +    /* platform specific resources */
> >> +    .freq_tbl = sm8550_freq_table,
> >> +    .freq_tbl_size = ARRAY_SIZE(sm8550_freq_table),
> >> +    .reg_prst_tbl = sm8550_reg_preset_table,
> >> +    .reg_prst_tbl_size = ARRAY_SIZE(sm8550_reg_preset_table),
> >> +    .fwname = "vpu30_4v",
> >> +    .pas_id = 9,
> >> +
> >> +    /* caps related resorces */
> >> +    .core_data = core_data_sm8550,
> >> +    .core_data_size = ARRAY_SIZE(core_data_sm8550),
> >> +    .inst_cap_data = instance_cap_data_sm8550,
> >> +    .inst_cap_data_size = ARRAY_SIZE(instance_cap_data_sm8550),
> >> +    .inst_cap_dependency_data = instance_cap_dependency_data_sm8550,
> >> +    .inst_cap_dependency_data_size =
> >> ARRAY_SIZE(instance_cap_dependency_data_sm8550),
> >> +    .ubwc_config = ubwc_config_sm8550,
> >> +    .format_data = &format_data_sm8550,
> >> +
> >> +    /* decoder properties related*/
> >> +    .psc_avc_tbl = sm8550_vdec_psc_avc,
> >> +    .psc_avc_tbl_size = ARRAY_SIZE(sm8550_vdec_psc_avc),
> >> +    .psc_hevc_tbl = sm8550_vdec_psc_hevc,
> >> +    .psc_hevc_tbl_size = ARRAY_SIZE(sm8550_vdec_psc_hevc),
> >> +    .psc_vp9_tbl = sm8550_vdec_psc_vp9,
> >> +    .psc_vp9_tbl_size = ARRAY_SIZE(sm8550_vdec_psc_vp9),
> >> +    .dec_input_prop_avc = sm8550_vdec_input_properties_avc,
> >> +    .dec_input_prop_hevc = sm8550_vdec_input_properties_hevc,
> >> +    .dec_input_prop_vp9 = sm8550_vdec_input_properties_vp9,
> >> +    .dec_input_prop_size_avc =
> >> ARRAY_SIZE(sm8550_vdec_input_properties_avc),
> >> +    .dec_input_prop_size_hevc =
> >> ARRAY_SIZE(sm8550_vdec_input_properties_hevc),
> >> +    .dec_input_prop_size_vp9 =
> >> ARRAY_SIZE(sm8550_vdec_input_properties_vp9),
> >> +    .dec_output_prop_avc = sm8550_vdec_output_properties_avc,
> >> +    .dec_output_prop_hevc = sm8550_vdec_output_properties_hevc,
> >> +    .dec_output_prop_vp9 = sm8550_vdec_output_properties_vp9,
> >> +    .dec_output_prop_size_avc =
> >> ARRAY_SIZE(sm8550_vdec_output_properties_avc),
> >> +    .dec_output_prop_size_hevc =
> >> ARRAY_SIZE(sm8550_vdec_output_properties_hevc),
> >> +    .dec_output_prop_size_vp9 =
> >> ARRAY_SIZE(sm8550_vdec_output_properties_vp9),
> >
> > Size should come next to the array reference.
> correct, will fix in next version
> >
> >> +};
> >> +
> >> +static int msm_vidc_init_data(struct msm_vidc_core *core)
> >> +{
> >> +    d_vpr_h("%s: initialize sm8550 data\n", __func__);
> >> +
> >> +    core->platform->data = sm8550_data;
> >> +
> >
> > Please use of_device_match_data() instead.
> >
> Thanks for the suggestion, will implement in next version.

BTW: could you please fix your mailer so that it doesn't insert extra
white space after your quoting level?

>
> Thanks,
> Dikshita
> >> +    return 0;
> >> +}
> >> +
> >> +int msm_vidc_init_platform_sm8550(struct msm_vidc_core *core)
> >> +{
> >> +    return msm_vidc_init_data(core);
> >> +}
> >
Konrad Dybcio Aug. 16, 2023, 11:46 a.m. UTC | #23
On 14.08.2023 21:15, Dikshita Agarwal wrote:
> 
> 
> On 7/28/2023 11:11 PM, Konrad Dybcio wrote:
>> On 28.07.2023 15:23, Vikash Garodia wrote:
>>> This implements common helper functions for v4l2 to vidc and
>>> vice versa conversion for different enums.
>>> Add helpers for state checks, buffer management, locks etc.
>>>
>>> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
>>> Signed-off-by: Vikash Garodia <quic_vgarodia@quicinc.com>
>>> ---
>> [...]
>>
>>> +
>>> +#define is_odd(val) ((val) % 2 == 1)
>>> +#define in_range(val, min, max) (((min) <= (val)) && ((val) <= (max)))
>>> +#define COUNT_BITS(a, out) {       \
>> hweight.* functions?
>>
>> [...]
>>
> sure, will replace with hweight.
>>> +
>>> +const char *cap_name(enum msm_vidc_inst_capability_type cap_id)
>>> +{
>>> +	const char *name = "UNKNOWN CAP";
>> Perhaps it'd be worth to include the unknown cap id here
>>
> could you please elaborate more on this.
>>> +
>>> +	if (cap_id >= ARRAY_SIZE(cap_name_arr))
>>> +		goto exit;
>>> +
>>> +	name = cap_name_arr[cap_id];
>>> +
>>> +exit:
>>> +	return name;
>>> +}
>> [...]
>>
>>> +
>>> +const char *buf_name(enum msm_vidc_buffer_type type)
>>> +{
>>> +	const char *name = "UNKNOWN BUF";
>> Similarly here
>>
> could you please elaborate more on this.
Something like "UNKNOWN BUF (0x15)" instead of just "UNKNOWN BUF"
would help us better understand whether the driver or the hardware
is missing something.


Konrad
Vikash Garodia Aug. 24, 2023, 3:23 p.m. UTC | #24
Hi Dmitry,

On 8/14/2023 8:30 PM, Dmitry Baryshkov wrote:
> Hi Stan,
> 
> On Mon, 14 Aug 2023 at 15:58, Stanimir Varbanov
> <stanimir.k.varbanov@gmail.com> wrote:
>>
>> Hi Dmitry,
>>
>> On 28.07.23 г. 17:01 ч., Dmitry Baryshkov wrote:
>>> On 28/07/2023 16:23, Vikash Garodia wrote:
>>>> This patch series introduces support for Qualcomm new video acceleration
>>>> hardware architecture, used for video stream decoding/encoding. This
>>>> driver
>>>> is based on new communication protocol between video hardware and
>>>> application
>>>> processor.
>>>>
>>>> This driver comes with below capabilities:
>>>> - V4L2 complaint video driver with M2M and STREAMING capability.
>>>> - Supports H264, H265, VP9 decoders.
>>>> - Supports H264, H265 encoders.
>>>
>>> Please describe, why is it impossible to support this hardware in the
>>> venus driver. We do not usually add new drivers for the new generations
>>> of the hardware, unless it is fully incompatible with the previous
>>> generations. Let me point you to camss or drm/msm drivers. They have
>>> successfully solved the issue of supporting multiple generations of the
>>> hardware in the same driver.
>>>
>>> Unless the "iris3" is completely different from all the previous
>>> generations, I strongly suggest spending time on restructuring existing
>>> venus driver and then adding support for the new hardware there instead
>>> of dumping out something completely new.
>>
>> AFAIK the major differences are HW IP and firmware interface (by
>> firmware interface I mean a protocol, API and API behavior). The
>> firmware and its interface has been re-written to align closely with the
>> current v4l2 specs for encoders/decoders state machines [1][2]. On the
>> other side current mainline Venus driver firmware is following interface
>> similar to OpenMAX.
>>
>> There are incompatibilities between both firmware interfaces which
>> cannot easily combined in a common driver. Even if there is a
>> possibility to do that it will lead us to a unreadable driver source
>> code and maintenance burden.
> 
> Thank you for your explanation!
> 
> If the hardware is more or less the same, then the existing venus
> driver should be refactored and split into hardware driver and the
> firmware interface. Then iris3 can come up as a second driver
> implementing support for new firmware interface but utilising common
> hardware-related code.

Its not just about supporting the new firmware interface because if that was the
case, it would have been a simple change. Its also about how the new firmware
interface affects the rest of the video sub-modules and state handling.
We incrementally evaluated whether putting the pieces one by one would make
sense but it doesn’t as every layer got affected and as a whole we decided to go
with this approach.
To elaborate more, let me try to put one of sequence which can provide info on
firmware interface and its handling across different video layers.

>> Vikash, could elaborate more on firmware interface differences.

Many new interfaces are added. Explained below one such video usecase of
handling dynamic resolution change (DRC) during drain. Illustrated a pseudo code
on how this will look if we fit this in venus driver.

- Client issues a STOP command. The command goes through state-wise command
handling, which also checks for cases like back to back drain. Vidc layer, which
handles common encoder and decoder functionality, routes it to decoder stop.
Decoder and driver layer then submits the command "HFI_CMD_DRAIN" to hardware
and moves the sub state to "MSM_VIDC_DRAIN".
- Now before drain is completed, there is a resolution change in one of the
frame queued before drain. Driver receives "HFI_CMD_SETTINGS_CHANGE" in hfi
response layer. The response goes through state check if received in intended
state and if good, changes the state to "MSM_VIDC_DRC | MSM_VIDC_INPUT_PAUSE".
Any further input processing remain paused at this point. The decoder layer then
parses all the bitstream parameters which were subscribed by the driver.
V4L2_EVENT_SOURCE_CHANGE event is raised to client.
- Hardware respond with HFI_INFO_HFI_FLAG_PSC_LAST to indicate LAST frame with
old sequence. Driver substate is added with "MSM_VIDC_DRC_LAST_BUFFER |
MSM_VIDC_OUTPUT_PAUSE". At this point, driver is in state, STREAMING and
substate - MSM_VIDC_DRAIN | MSM_VIDC_DRC | MSM_VIDC_INPUT_PAUSE |
MSM_VIDC_DRC_LAST_BUFFER | MSM_VIDC_OUTPUT_PAUSE. This is when both hardware as
well as driver is paused while waiting for further instructions.
- Client issues START cmd. Vidc layer routes it to decoder layer which checks
for sub states and then allocates/queues internal buffers. At this point, DRC
sequence is completed and substates "MSM_VIDC_DRC | MSM_VIDC_DRC_LAST_BUFFER"
are cleared and both input and output planes are resumed with HFI
"HFI_CMD_RESUME". substate "MSM_VIDC_INPUT_PAUSE" and "MSM_VIDC_OUTPUT_PAUSE" is
cleared as well. So driver is in streaming state with sub state as "MSM_VIDC_DRAIN"
- Hardware issues a response to "HFI_CMD_DRAIN". As part of handling of this,
driver adds to sub state "MSM_VIDC_INPUT_PAUSE". This is done to avoid any
further input processing. Once all the frames are processed, hardware raises HFI
"HFI_INFO_HFI_FLAG_DRAIN_LAST". After doing state check, further sub states
"MSM_VIDC_DRAIN_LAST_BUFFER | MSM_VIDC_OUTPUT_PAUSE" are added. So at this
point, the sub states are MSM_VIDC_DRAIN, MSM_VIDC_DRAIN_LAST_BUFFER,
MSM_VIDC_INPUT_PAUSE and MSM_VIDC_OUTPUT_PAUSE.
- Any pair calls like VIDIOC_STREAMON()/VIDIOC_STREAMOFF() on output or capture
queue, resets the substate to stream again.

If the same needs to be added in venus driver

- Client issues a STOP cmd to initiate drain. Decoder layer for stop handling
needs to be updated something like below //pseudo code  if (old interface)
   send dummy buffer
   change state to VENUS_DEC_STATE_DRAIN
   drain_active = true
 else
   statewise validation of STOP cmd
   state check for back to back drain
   issue HFI_CMD_DRAIN to hardware
   change sub state = MSM_VIDC_DRAIN

- DRC is issued by hardware
  if (old interface) //vdec and hfi response layer
   HFI_EVENT_SESSION_SEQUENCE_CHANGED with type
HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUF_RESOURCES
   changes state to VENUS_DEC_STATE_DRC
   next_buf_last = true
   flush (output)
   reconfig = true
   raise V4L2_EVENT_SOURCE_CHANGE event to client
  else
   HFI_CMD_SETTINGS_CHANGE // in hfi response layer
   state validation for intended state // in state handling layer
   sub state |= MSM_VIDC_DRC | MSM_VIDC_INPUT_PAUSE
   raise V4L2_EVENT_SOURCE_CHANGE event to client

- LAST flag handling
  if (old interface)
    No LAST flag HFI from hardware
    in qbuf_capture
      if (next_buf_last) associated LAST flag
  else
    handle HFI_INFO_HFI_FLAG_PSC_LAST //in response layer
    sub state |= MSM_VIDC_DRC_LAST_BUFFER | MSM_VIDC_OUTPUT_PAUSE

- Client issues START cmd
  if (old interface)
    does not handle VENUS_DEC_STATE_DRC state
  else
    sub state &= ~(MSM_VIDC_DRC | MSM_VIDC_DRC_LAST_BUFFER)
    allocates and queue internal buffer
    call HFI_CMD_RESUME for input and output
    sub state &= ~(MSM_VIDC_INPUT_PAUSE|MSM_VIDC_OUTPUT_PAUSE)

- Hardware response for HFI_CMD_DRAIN
  if (old interface)
    Nothing to do.
  else
    sub state |= MSM_VIDC_INPUT_PAUSE

- Handling for drain LAST flag
  if (old interface)
    receives dummy buffer with EOS
    converts to LAST and send to client
  else
    process HFI_INFO_HFI_FLAG_DRAIN_LAST
    sub state |= MSM_VIDC_DRAIN_LAST_BUFFER | MSM_VIDC_OUTPUT_PAUSE

There are many such complex sequences which would add to complexity if we try to
fit them into existing driver.

> Do we have any details on firmware versions that implement older
> (OpenMAX-like) interface vs versions implementing new (v4l2-like)
> interface?
> 
>> [1]
>> https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/dev-decoder.html
>>
>> [2]
>> https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/dev-encoder.html

Thanks,
Vikash
Vikash Garodia Aug. 24, 2023, 3:32 p.m. UTC | #25
Hi Dmitry,

On 8/15/2023 2:33 AM, Dmitry Baryshkov wrote:
> On Mon, 14 Aug 2023 at 21:58, Dikshita Agarwal
> <quic_dikshita@quicinc.com> wrote:
>>
>>
>>
>> On 7/28/2023 7:19 PM, Dmitry Baryshkov wrote:
>>> On 28/07/2023 16:23, Vikash Garodia wrote:
>>>> From: Dikshita Agarwal <quic_dikshita@quicinc.com>
>>>>
>>>> This implements the platform driver methods, file
>>>> operations and v4l2 registration.
>>>>
>>>> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
>>>> Signed-off-by: Vikash Garodia <quic_vgarodia@quicinc.com>
>>>> ---
>>>>   .../platform/qcom/iris/vidc/src/msm_vidc_probe.c   | 660
>>>> +++++++++++++++++++++
>>>>   1 file changed, 660 insertions(+)
>>>>   create mode 100644
>>>> drivers/media/platform/qcom/iris/vidc/src/msm_vidc_probe.c
>>>>
>>>> diff --git a/drivers/media/platform/qcom/iris/vidc/src/msm_vidc_probe.c
>>>> b/drivers/media/platform/qcom/iris/vidc/src/msm_vidc_probe.c
>>>> new file mode 100644
>>>> index 0000000..43439cb
>>>> --- /dev/null
>>>> +++ b/drivers/media/platform/qcom/iris/vidc/src/msm_vidc_probe.c
>>>> @@ -0,0 +1,660 @@
>>>> +// SPDX-License-Identifier: GPL-2.0-only
>>>> +/*
>>>> + * Copyright (c) 2020-2022, The Linux Foundation. All rights reserved.
>>>> + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
>>>> + */
>>>> +
>>>> +#include <linux/interrupt.h>
>>>> +#include <linux/io.h>
>>>> +#include <linux/iommu.h>
>>>> +#include <linux/module.h>
>>>> +#include <linux/of.h>
>>>> +#include <linux/of_platform.h>
>>>> +#include <linux/stringify.h>
>>>> +#include <linux/version.h>
>>>> +#include <linux/workqueue.h>
>>>> +
>>>> +#include "msm_vidc_core.h"
>>>> +#include "msm_vidc_debug.h"
>>>> +#include "msm_vidc_driver.h"
>>>> +#include "msm_vidc_internal.h"
>>>> +#include "msm_vidc_memory.h"
>>>> +#include "msm_vidc_platform.h"
>>>> +#include "msm_vidc_state.h"
>>>> +#include "venus_hfi.h"
>>>
>>> This files are not present yet, so this commit doesn't have a change of
>>> being compiled in any way.
>>>
>>>> +
>>>> +#define BASE_DEVICE_NUMBER 32
>>>> +
>>>> +struct msm_vidc_core *g_core;
>>>> +
>>>> +static inline bool is_video_device(struct device *dev)
>>>> +{
>>>> +    return !!(of_device_is_compatible(dev->of_node, "qcom,sm8550-vidc"));
>>>
>>> Are you going to add future platforms to this list? Please don't duplicate
>>> of_match_data here.
>>> Sure, Will remove this API in next version.
>>>> +}
>>>> +
>>>> +static inline bool is_video_context_bank_device(struct device *dev)
>>>> +{
>>>> +    return !!(of_device_is_compatible(dev->of_node, "qcom,vidc,cb-ns"));
>>>> +}
>>>> +
>>>> +static int msm_vidc_init_resources(struct msm_vidc_core *core)
>>>> +{
>>>> +    struct msm_vidc_resource *res = NULL;
>>>> +    int rc = 0;
>>>> +
>>>> +    res = devm_kzalloc(&core->pdev->dev, sizeof(*res), GFP_KERNEL);
>>>> +    if (!res) {
>>>> +        d_vpr_e("%s: failed to alloc memory for resource\n", __func__);
>>>
>>> Where is this macro defined? Please structure your comments in a logical
>>> way, so that one can read them from the beginning and understand what is
>>> going one.
>>>
>>> This is not to mention that adding such debugging wrappers doesn't have a
>>> lot of value.
>>>
>> I understand the concern here, will remove the custom debug wrappers in
>> next version.
>>>> +        return -ENOMEM;
>>>> +    }
>>>> +    core->resource = res;
>>>> +
>>>> +    rc = call_res_op(core, init, core);
>>>
>>> What is call_res_op?
>>>
>> This implements the resource ops, but as we don't need the abstraction for
>> resource ops, this will be removed in next version.
>>>> +    if (rc) {
>>>> +        d_vpr_e("%s: Failed to init resources: %d\n", __func__, rc);
>>>> +        return rc;
>>>> +    }
>>>> +
>>>> +    return 0;
>>>> +}
>>>> +
>>>> +static const struct of_device_id msm_vidc_dt_match[] = {
>>>> +    {.compatible = "qcom,sm8550-vidc"},
>>>> +    {.compatible = "qcom,vidc,cb-ns"},
>>>> +    MSM_VIDC_EMPTY_BRACE
>>>
>>> NO!!! Please use {} directly.
>>>
>> I Understand, will replace with {}.
>>>> +};
>>>> +MODULE_DEVICE_TABLE(of, msm_vidc_dt_match);
>>>> +
>>>> +static void msm_vidc_release_video_device(struct video_device *vdev)
>>>> +{
>>>> +    d_vpr_e("%s: video device released\n", __func__);
>>>> +}
>>>> +
>>>> +static void msm_vidc_unregister_video_device(struct msm_vidc_core *core,
>>>> +                         enum msm_vidc_domain_type type)
>>>> +{
>>>> +    int index;
>>>> +
>>>> +    if (type == MSM_VIDC_DECODER)
>>>> +        index = 0;
>>>> +    else if (type == MSM_VIDC_ENCODER)
>>>> +        index = 1;
>>>> +    else
>>>> +        return;
>>>
>>> You can index by the type instead of converting to index.
>>>
>> MSM_VIDC_DECODER/MSM_VIDC_ENCODER are bit masks hence can not be used as
>> array index and these bit mask values are being used in driver at multiple
>> places.
> 
> A subdevice can not be a decoder and an encoder at the same time, can
> it? So, please replace masks with indices.
> 
>>>> +
>>>> +    v4l2_m2m_release(core->vdev[index].m2m_dev);
>>>> +
>>>> +    video_set_drvdata(&core->vdev[index].vdev, NULL);
>>>> +    video_unregister_device(&core->vdev[index].vdev);
>>>> +}
>>>> +
>>>> +static int msm_vidc_register_video_device(struct msm_vidc_core *core,
>>>> +                      enum msm_vidc_domain_type type, int nr)
>>>> +{
>>>> +    int rc = 0;
>>>> +    int index;
>>>> +
>>>> +    d_vpr_h("%s: domain %d\n", __func__, type);
>>>> +
>>>> +    if (type == MSM_VIDC_DECODER)
>>>> +        index = 0;
>>>> +    else if (type == MSM_VIDC_ENCODER)
>>>> +        index = 1;
>>>> +    else
>>>> +        return -EINVAL;
>>>> +
>>>> +    core->vdev[index].vdev.release =
>>>> +        msm_vidc_release_video_device;
>>>> +    core->vdev[index].vdev.fops = core->v4l2_file_ops;
>>>> +    if (type == MSM_VIDC_DECODER)
>>>> +        core->vdev[index].vdev.ioctl_ops = core->v4l2_ioctl_ops_dec;
>>>> +    else
>>>> +        core->vdev[index].vdev.ioctl_ops = core->v4l2_ioctl_ops_enc;
>>>> +    core->vdev[index].vdev.vfl_dir = VFL_DIR_M2M;
>>>> +    core->vdev[index].type = type;
>>>> +    core->vdev[index].vdev.v4l2_dev = &core->v4l2_dev;
>>>> +    core->vdev[index].vdev.device_caps =
>>>> core->capabilities[DEVICE_CAPS].value;
>>>> +    rc = video_register_device(&core->vdev[index].vdev,
>>>> +                   VFL_TYPE_VIDEO, nr);
>>>> +    if (rc) {
>>>> +        d_vpr_e("Failed to register the video device\n");
>>>> +        return rc;
>>>> +    }
>>>> +    video_set_drvdata(&core->vdev[index].vdev, core);
>>>> +
>>>> +    core->vdev[index].m2m_dev = v4l2_m2m_init(core->v4l2_m2m_ops);
>>>> +    if (IS_ERR(core->vdev[index].m2m_dev)) {
>>>> +        d_vpr_e("Failed to initialize V4L2 M2M device\n");
>>>> +        rc = PTR_ERR(core->vdev[index].m2m_dev);
>>>> +        goto m2m_init_failed;
>>>> +    }
>>>> +
>>>> +    return 0;
>>>> +
>>>> +m2m_init_failed:
>>>> +    video_unregister_device(&core->vdev[index].vdev);
>>>> +    return rc;
>>>> +}
>>>> +
>>>> +static int msm_vidc_deinitialize_core(struct msm_vidc_core *core)
>>>> +{
>>>> +    int rc = 0;
>>>> +
>>>> +    if (!core) {
>>>> +        d_vpr_e("%s: invalid params\n", __func__);
>>>> +        return -EINVAL;
>>>> +    }
>>>> +
>>>> +    mutex_destroy(&core->lock);
>>>> +    msm_vidc_update_core_state(core, MSM_VIDC_CORE_DEINIT, __func__);
>>>> +
>>>> +    if (core->batch_workq)
>>>> +        destroy_workqueue(core->batch_workq);
>>>> +
>>>> +    if (core->pm_workq)
>>>> +        destroy_workqueue(core->pm_workq);
>>>> +
>>>> +    core->batch_workq = NULL;
>>>> +    core->pm_workq = NULL;
>>>> +
>>>> +    return rc;
>>>> +}
>>>> +
>>>> +static int msm_vidc_initialize_core(struct msm_vidc_core *core)
>>>> +{
>>>> +    int rc = 0;
>>>> +
>>>> +    msm_vidc_update_core_state(core, MSM_VIDC_CORE_DEINIT, __func__);
>>>> +
>>>> +    core->pm_workq = create_singlethread_workqueue("pm_workq");
>>>> +    if (!core->pm_workq) {
>>>> +        d_vpr_e("%s: create pm workq failed\n", __func__);
>>>> +        rc = -EINVAL;
>>>> +        goto exit;
>>>> +    }
>>>> +
>>>> +    core->batch_workq = create_singlethread_workqueue("batch_workq");
>>>> +    if (!core->batch_workq) {
>>>> +        d_vpr_e("%s: create batch workq failed\n", __func__);
>>>> +        rc = -EINVAL;
>>>> +        goto exit;
>>>> +    }
>>>> +
>>>> +    core->packet_size = VIDC_IFACEQ_VAR_HUGE_PKT_SIZE;
>>>> +    core->packet = devm_kzalloc(&core->pdev->dev, core->packet_size,
>>>> GFP_KERNEL);
>>>> +    if (!core->packet) {
>>>> +        d_vpr_e("%s: failed to alloc core packet\n", __func__);
>>>> +        rc = -ENOMEM;
>>>> +        goto exit;
>>>> +    }
>>>> +
>>>> +    core->response_packet = devm_kzalloc(&core->pdev->dev,
>>>> core->packet_size, GFP_KERNEL);
>>>> +    if (!core->packet) {
>>>> +        d_vpr_e("%s: failed to alloc core response packet\n", __func__);
>>>> +        rc = -ENOMEM;
>>>> +        goto exit;
>>>> +    }
>>>> +
>>>> +    mutex_init(&core->lock);
>>>> +    INIT_LIST_HEAD(&core->instances);
>>>> +    INIT_LIST_HEAD(&core->dangling_instances);
>>>> +
>>>> +    INIT_DELAYED_WORK(&core->pm_work, venus_hfi_pm_work_handler);
>>>> +    INIT_DELAYED_WORK(&core->fw_unload_work, msm_vidc_fw_unload_handler);
>>>> +
>>>> +    return 0;
>>>> +exit:
>>>> +    if (core->batch_workq)
>>>> +        destroy_workqueue(core->batch_workq);
>>>> +    if (core->pm_workq)
>>>> +        destroy_workqueue(core->pm_workq);
>>>> +    core->batch_workq = NULL;
>>>> +    core->pm_workq = NULL;
>>>> +
>>>> +    return rc;
>>>> +}
>>>> +
>>>> +static void msm_vidc_devm_deinit_core(void *res)
>>>> +{
>>>> +    struct msm_vidc_core *core = res;
>>>> +
>>>> +    msm_vidc_deinitialize_core(core);
>>>> +}
>>>> +
>>>> +static int msm_vidc_devm_init_core(struct device *dev, struct
>>>> msm_vidc_core *core)
>>>> +{
>>>> +    int rc = 0;
>>>> +
>>>> +    if (!dev || !core) {
>>>> +        d_vpr_e("%s: invalid params\n", __func__);
>>>> +        return -EINVAL;
>>>> +    }
>>>> +
>>>> +    rc = msm_vidc_initialize_core(core);
>>>> +    if (rc) {
>>>> +        d_vpr_e("%s: init failed with %d\n", __func__, rc);
>>>> +        return rc;
>>>> +    }
>>>> +
>>>> +    rc = devm_add_action_or_reset(dev, msm_vidc_devm_deinit_core, (void
>>>> *)core);
>>>> +    if (rc)
>>>> +        return -EINVAL;
>>>> +
>>>> +    return rc;
>>>> +}
>>>> +
>>>> +static void msm_vidc_devm_debugfs_put(void *res)
>>>> +{
>>>> +    struct dentry *parent = res;
>>>> +
>>>> +    debugfs_remove_recursive(parent);
>>>> +}
>>>> +
>>>> +static struct dentry *msm_vidc_devm_debugfs_get(struct device *dev)
>>>
>>> Why is it called get?
>>>
>> this will be removed in next version as part of debug wrappers removal
>>>
>>>> +{
>>>> +    struct dentry *parent = NULL;
>>>> +    int rc = 0;
>>>> +
>>>> +    if (!dev) {
>>>> +        d_vpr_e("%s: invalid params\n", __func__);
>>>> +        return NULL;
>>>> +    }
>>>> +
>>>> +    parent = msm_vidc_debugfs_init_drv();
>>>> +    if (!parent)
>>>> +        return NULL;
>>>> +
>>>> +    rc = devm_add_action_or_reset(dev, msm_vidc_devm_debugfs_put, (void
>>>> *)parent);
>>>> +    if (rc)
>>>> +        return NULL;
>>>> +
>>>> +    return parent;
>>>> +}
>>>> +
>>>> +static int msm_vidc_setup_context_bank(struct msm_vidc_core *core,
>>>> +                       struct device *dev)
>>>> +{
>>>> +    struct context_bank_info *cb = NULL;
>>>> +    int rc = 0;
>>>> +
>>>> +    cb = msm_vidc_get_context_bank_for_device(core, dev);
>>>> +    if (!cb) {
>>>> +        d_vpr_e("%s: Failed to get context bank device for %s\n",
>>>> +            __func__, dev_name(dev));
>>>> +        return -EIO;
>>>> +    }
>>>> +
>>>> +    /* populate dev & domain field */
>>>> +    cb->dev = dev;
>>>> +    cb->domain = iommu_get_domain_for_dev(cb->dev);
>>>> +    if (!cb->domain) {
>>>> +        d_vpr_e("%s: Failed to get iommu domain for %s\n", __func__,
>>>> dev_name(dev));
>>>> +        return -EIO;
>>>> +    }
>>>> +
>>>> +    if (cb->dma_mask) {
>>>> +        rc = dma_set_mask_and_coherent(cb->dev, cb->dma_mask);
>>>> +        if (rc) {
>>>> +            d_vpr_e("%s: dma_set_mask_and_coherent failed\n", __func__);
>>>> +            return rc;
>>>> +        }
>>>> +    }
>>>> +
>>>> +    /*
>>>> +     * configure device segment size and segment boundary to ensure
>>>> +     * iommu mapping returns one mapping (which is required for partial
>>>> +     * cache operations)
>>>> +     */
>>>> +    if (!dev->dma_parms)
>>>> +        dev->dma_parms =
>>>> +            devm_kzalloc(dev, sizeof(*dev->dma_parms), GFP_KERNEL);
>>>> +    dma_set_max_seg_size(dev, (unsigned int)DMA_BIT_MASK(32));
>>>> +    dma_set_seg_boundary(dev, (unsigned long)DMA_BIT_MASK(64));
>>>> +
>>>> +    iommu_set_fault_handler(cb->domain, msm_vidc_smmu_fault_handler,
>>>> (void *)core);
>>>> +
>>>> +    d_vpr_h("%s: name %s addr start %x size %x secure %d\n",
>>>> +        __func__, cb->name, cb->addr_range.start,
>>>> +        cb->addr_range.size, cb->secure);
>>>> +    d_vpr_h("%s: dma_coherant %d region %d dev_name %s domain %pK
>>>> dma_mask %llu\n",
>>>> +        __func__, cb->dma_coherant, cb->region, dev_name(cb->dev),
>>>> +        cb->domain, cb->dma_mask);
>>>> +
>>>> +    return rc;
>>>> +}
>>>> +
>>>> +static int msm_vidc_remove_video_device(struct platform_device *pdev)
>>>> +{
>>>> +    struct msm_vidc_core *core;
>>>> +
>>>> +    if (!pdev) {
>>>> +        d_vpr_e("%s: invalid input %pK", __func__, pdev);
>>>> +        return -EINVAL;
>>>> +    }
>>>> +
>>>> +    core = dev_get_drvdata(&pdev->dev);
>>>> +    if (!core) {
>>>> +        d_vpr_e("%s: invalid core\n", __func__);
>>>> +        return -EINVAL;
>>>> +    }
>>>> +
>>>> +    msm_vidc_core_deinit(core, true);
>>>> +    venus_hfi_queue_deinit(core);
>>>> +
>>>> +    msm_vidc_unregister_video_device(core, MSM_VIDC_ENCODER);
>>>> +    msm_vidc_unregister_video_device(core, MSM_VIDC_DECODER);
>>>> +
>>>> +    v4l2_device_unregister(&core->v4l2_dev);
>>>> +
>>>> +    d_vpr_h("depopulating sub devices\n");
>>>> +    /*
>>>> +     * Trigger remove for each sub-device i.e. qcom,context-bank,xxxx
>>>> +     * When msm_vidc_remove is called for each sub-device, destroy
>>>> +     * context-bank mappings.
>>>> +     */
>>>> +    of_platform_depopulate(&pdev->dev);
>>>> +
>>>> +    dev_set_drvdata(&pdev->dev, NULL);
>>>> +    g_core = NULL;
>>>> +    d_vpr_h("%s(): succssful\n", __func__);
>>>> +
>>>> +    return 0;
>>>> +}
>>>> +
>>>> +static int msm_vidc_remove_context_bank(struct platform_device *pdev)
>>>> +{
>>>> +    d_vpr_h("%s(): %s\n", __func__, dev_name(&pdev->dev));
>>>> +
>>>> +    return 0;
>>>> +}
>>>> +
>>>> +static int msm_vidc_remove(struct platform_device *pdev)
>>>> +{
>>>> +    /*
>>>> +     * Sub devices remove will be triggered by of_platform_depopulate()
>>>> +     * after core_deinit(). It return immediately after completing
>>>> +     * sub-device remove.
>>>> +     */
>>>> +    if (is_video_device(&pdev->dev))
>>>> +        return msm_vidc_remove_video_device(pdev);
>>>> +    else if (is_video_context_bank_device(&pdev->dev))
>>>> +        return msm_vidc_remove_context_bank(pdev);
>>>> +
>>>> +    /* How did we end up here? */
>>>> +    WARN_ON(1);
>>>> +    return -EINVAL;
>>>> +}
>>>> +
>>>> +static int msm_vidc_probe_video_device(struct platform_device *pdev)
>>>> +{
>>>> +    int rc = 0;
>>>> +    struct msm_vidc_core *core = NULL;
>>>> +    int nr = BASE_DEVICE_NUMBER;
>>>> +
>>>> +    d_vpr_h("%s: %s\n", __func__, dev_name(&pdev->dev));
>>>> +
>>>> +    core = devm_kzalloc(&pdev->dev, sizeof(struct msm_vidc_core),
>>>> GFP_KERNEL);
>>>> +    if (!core) {
>>>> +        d_vpr_e("%s: failed to alloc memory for core\n", __func__);
>>>> +        return -ENOMEM;
>>>> +    }
>>>> +    g_core = core;
>>>> +
>>>> +    core->pdev = pdev;
>>>> +    dev_set_drvdata(&pdev->dev, core);
>>>> +
>>>> +    core->debugfs_parent = msm_vidc_devm_debugfs_get(&pdev->dev);
>>>> +    if (!core->debugfs_parent)
>>>> +        d_vpr_h("Failed to create debugfs for msm_vidc\n");
>>>> +
>>>> +    rc = msm_vidc_devm_init_core(&pdev->dev, core);
>>>> +    if (rc) {
>>>> +        d_vpr_e("%s: init core failed with %d\n", __func__, rc);
>>>> +        goto init_core_failed;
>>>> +    }
>>>> +
>>>> +    rc = msm_vidc_init_platform(core);
>>>> +    if (rc) {
>>>> +        d_vpr_e("%s: init platform failed with %d\n", __func__, rc);
>>>> +        rc = -EINVAL;
>>>> +        goto init_plat_failed;
>>>> +    }
>>>> +
>>>> +    rc = msm_vidc_init_resources(core);
>>>> +    if (rc) {
>>>> +        d_vpr_e("%s: init resource failed with %d\n", __func__, rc);
>>>> +        goto init_res_failed;
>>>> +    }
>>>> +
>>>> +    rc = msm_vidc_init_core_caps(core);
>>>> +    if (rc) {
>>>> +        d_vpr_e("%s: init core caps failed with %d\n", __func__, rc);
>>>> +        goto init_res_failed;
>>>> +    }
>>>> +
>>>> +    rc = msm_vidc_init_instance_caps(core);
>>>> +    if (rc) {
>>>> +        d_vpr_e("%s: init inst cap failed with %d\n", __func__, rc);
>>>> +        goto init_inst_caps_fail;
>>>> +    }
>>>> +
>>>> +    core->debugfs_root = msm_vidc_debugfs_init_core(core);
>>>> +    if (!core->debugfs_root)
>>>> +        d_vpr_h("Failed to init debugfs core\n");
>>>> +
>>>> +    d_vpr_h("populating sub devices\n");
>>>> +    /*
>>>> +     * Trigger probe for each sub-device i.e. qcom,msm-vidc,context-bank.
>>>> +     * When msm_vidc_probe is called for each sub-device, parse the
>>>> +     * context-bank details.
>>>> +     */
>>>> +    rc = of_platform_populate(pdev->dev.of_node, msm_vidc_dt_match, NULL,
>>>> +                  &pdev->dev);
>>>> +    if (rc) {
>>>> +        d_vpr_e("Failed to trigger probe for sub-devices\n");
>>>> +        goto sub_dev_failed;
>>>> +    }
>>>> +
>>>> +    rc = v4l2_device_register(&pdev->dev, &core->v4l2_dev);
>>>> +    if (rc) {
>>>> +        d_vpr_e("Failed to register v4l2 device\n");
>>>> +        goto v4l2_reg_failed;
>>>> +    }
>>>> +
>>>> +    /* setup the decoder device */
>>>> +    rc = msm_vidc_register_video_device(core, MSM_VIDC_DECODER, nr);
>>>> +    if (rc) {
>>>> +        d_vpr_e("Failed to register video decoder\n");
>>>> +        goto dec_reg_failed;
>>>> +    }
>>>> +
>>>> +    /* setup the encoder device */
>>>> +    rc = msm_vidc_register_video_device(core, MSM_VIDC_ENCODER, nr + 1);
>>>> +    if (rc) {
>>>> +        d_vpr_e("Failed to register video encoder\n");
>>>> +        goto enc_reg_failed;
>>>> +    }
>>>> +
>>>> +    rc = venus_hfi_queue_init(core);
>>>> +    if (rc) {
>>>> +        d_vpr_e("%s: interface queues init failed\n", __func__);
>>>> +        goto queues_init_failed;
>>>> +    }
>>>> +
>>>> +    rc = msm_vidc_core_init(core);
>>>> +    if (rc) {
>>>> +        d_vpr_e("%s: sys init failed\n", __func__);
>>>> +        goto core_init_failed;
>>>> +    }
>>>> +
>>>> +    d_vpr_h("%s(): succssful\n", __func__);
>>>> +
>>>> +    return rc;
>>>> +
>>>> +core_init_failed:
>>>> +    venus_hfi_queue_deinit(core);
>>>> +queues_init_failed:
>>>> +    of_platform_depopulate(&pdev->dev);
>>>> +sub_dev_failed:
>>>> +    msm_vidc_unregister_video_device(core, MSM_VIDC_ENCODER);
>>>> +enc_reg_failed:
>>>> +    msm_vidc_unregister_video_device(core, MSM_VIDC_DECODER);
>>>> +dec_reg_failed:
>>>> +    v4l2_device_unregister(&core->v4l2_dev);
>>>> +v4l2_reg_failed:
>>>> +init_inst_caps_fail:
>>>> +init_res_failed:
>>>> +init_plat_failed:
>>>> +init_core_failed:
>>>> +    dev_set_drvdata(&pdev->dev, NULL);
>>>> +    g_core = NULL;
>>>> +
>>>> +    return rc;
>>>> +}
>>>> +
>>>> +static int msm_vidc_probe_context_bank(struct platform_device *pdev)
>>>> +{
>>>> +    struct msm_vidc_core *core = NULL;
>>>> +    int rc = 0;
>>>> +
>>>> +    if (!pdev) {
>>>> +        d_vpr_e("%s: Invalid platform device %pK", __func__, pdev);
>>>> +        return -EINVAL;
>>>> +    } else if (!pdev->dev.parent) {
>>>> +        d_vpr_e("%s: Failed to find a parent for %s\n",
>>>> +            __func__, dev_name(&pdev->dev));
>>>> +        return -ENODEV;
>>>> +    }
>>>> +
>>>> +    d_vpr_h("%s(): %s\n", __func__, dev_name(&pdev->dev));
>>>> +
>>>> +    core = dev_get_drvdata(pdev->dev.parent);
>>>> +    if (!core) {
>>>> +        d_vpr_e("%s: core not found in device %s",
>>>> +            __func__, dev_name(pdev->dev.parent));
>>>> +        return -EINVAL;
>>>> +    }
>>>> +
>>>> +    rc = msm_vidc_setup_context_bank(core, &pdev->dev);
>>>> +    if (rc) {
>>>> +        d_vpr_e("%s: Failed to probe context bank %s\n",
>>>> +            __func__, dev_name(&pdev->dev));
>>>> +        return rc;
>>>> +    }
>>>> +
>>>> +    return rc;
>>>> +}
>>>> +
>>>> +static int msm_vidc_probe(struct platform_device *pdev)
>>>> +{
>>>> +    if (!pdev) {
>>>> +        d_vpr_e("%s: invalid params\n", __func__);
>>>> +        return -EINVAL;
>>>> +    }
>>>> +
>>>> +    /*
>>>> +     * Sub devices probe will be triggered by of_platform_populate()
>>>> towards
>>>> +     * the end of the probe function after msm-vidc device probe is
>>>> +     * completed. Return immediately after completing sub-device probe.
>>>> +     */
>>>> +    if (is_video_device(&pdev->dev))
>>>> +        return msm_vidc_probe_video_device(pdev);
>>>> +    else if (is_video_context_bank_device(&pdev->dev))
>>>> +        return msm_vidc_probe_context_bank(pdev);
>>>> +
>>>> +    /* How did we end up here? */
>>>> +    WARN_ON(1);
>>>> +    return -EINVAL;
>>>
>>> No. Please don't hack around the driver infrastructure and register two
>>> separate drivers. They can even come in two separate commits, simplifying
>>> the review.
>>>
>> Sure, will remove the separate probe for context bank in next version.
>>>> +}
>>>> +
>>>> +static int msm_vidc_pm_suspend(struct device *dev)
>>>> +{
>>>> +    int rc = 0;
>>>> +    struct msm_vidc_core *core;
>>>> +    enum msm_vidc_allow allow = MSM_VIDC_DISALLOW;
>>>> +
>>>> +    /*
>>>> +     * Bail out if
>>>> +     * - driver possibly not probed yet
>>>> +     * - not the main device. We don't support power management on
>>>> +     *   subdevices (e.g. context banks)
>>>> +     */
>>>> +    if (!dev || !dev->driver || !is_video_device(dev))
>>>> +        return 0;
>>>> +
>>>> +    core = dev_get_drvdata(dev);
>>>> +    if (!core) {
>>>> +        d_vpr_e("%s: invalid core\n", __func__);
>>>> +        return -EINVAL;
>>>> +    }
>>>> +
>>>> +    core_lock(core, __func__);
>>>> +    allow = msm_vidc_allow_pm_suspend(core);
>>>> +
>>>> +    if (allow == MSM_VIDC_IGNORE) {
>>>> +        d_vpr_h("%s: pm already suspended\n", __func__);
>>>> +        msm_vidc_change_core_sub_state(core, 0,
>>>> CORE_SUBSTATE_PM_SUSPEND, __func__);
>>>> +        rc = 0;
>>>> +        goto unlock;
>>>> +    } else if (allow != MSM_VIDC_ALLOW) {
>>>> +        d_vpr_h("%s: pm suspend not allowed\n", __func__);
>>>> +        rc = 0;
>>>> +        goto unlock;
>>>> +    }
>>>> +
>>>> +    rc = msm_vidc_suspend(core);
>>>> +    if (rc == -EOPNOTSUPP)
>>>> +        rc = 0;
>>>> +    else if (rc)
>>>> +        d_vpr_e("Failed to suspend: %d\n", rc);
>>>> +    else
>>>> +        msm_vidc_change_core_sub_state(core, 0,
>>>> CORE_SUBSTATE_PM_SUSPEND, __func__);
>>>> +
>>>> +unlock:
>>>> +    core_unlock(core, __func__);
>>>> +    return rc;
>>>> +}
>>>> +
>>>> +static int msm_vidc_pm_resume(struct device *dev)
>>>> +{
>>>> +    struct msm_vidc_core *core;
>>>> +
>>>> +    /*
>>>> +     * Bail out if
>>>> +     * - driver possibly not probed yet
>>>> +     * - not the main device. We don't support power management on
>>>> +     *   subdevices (e.g. context banks)
>>>> +     */
>>>> +    if (!dev || !dev->driver || !is_video_device(dev))
>>>> +        return 0;
>>>> +
>>>> +    core = dev_get_drvdata(dev);
>>>> +    if (!core) {
>>>> +        d_vpr_e("%s: invalid core\n", __func__);
>>>> +        return -EINVAL;
>>>> +    }
>>>> +
>>>> +    /* remove PM suspend from core sub_state */
>>>> +    core_lock(core, __func__);
>>>> +    msm_vidc_change_core_sub_state(core, CORE_SUBSTATE_PM_SUSPEND, 0,
>>>> __func__);
>>>> +    core_unlock(core, __func__);
>>>> +
>>>> +    return 0;
>>>> +}
>>>> +
>>>> +static const struct dev_pm_ops msm_vidc_pm_ops = {
>>>> +    SET_SYSTEM_SLEEP_PM_OPS(msm_vidc_pm_suspend, msm_vidc_pm_resume)
>>>
>>> No runtime PM?
>> runtime PM is not added in this series, but we plan to add it at later
>> point of time.
>>>
>>>> +};
>>>> +
>>>> +struct platform_driver msm_vidc_driver = {
>>>> +    .probe = msm_vidc_probe,
>>>> +    .remove = msm_vidc_remove,
>>>> +    .driver = {
>>>> +        .name = "msm_vidc_v4l2",
>>>> +        .of_match_table = msm_vidc_dt_match,
>>>> +        .pm = &msm_vidc_pm_ops,
>>>> +    },
>>>> +};
>>>> +
>>>> +module_platform_driver(msm_vidc_driver);
>>>> +MODULE_LICENSE("GPL");
>>>
>>> Unfortunately, after taking a glance at first two patches, I have to stop.
>>> It is nearly impossible to review it.
>>>
>>> Please start from the beginning, split the driver according to the logical
>>> functions, not per-file. Ideally something should be compillable starting
>>> from one of the first patches, if not the very first one. This would
>>> guarantee that your patchset is structured logically.

I agree on this. We are working on restructuring the patches as functional split
rather than file by file. As we plan to do this in the next revision, it might
take some time for V2.

>>>
>>> Please add DT bindings. New driver series should start from the bindings
>>> anyway.
>>>
>>> Please drop your custom debugging wrappers. Use dev_info, dev_warn, dev_err
>>> and dev_dbg instead.
>>>
>>> Please drop the custom multi-device-single-driver scheme. If there are
>>> different kinds of devices, there should be different drivers.
>>>
>>> Please take a look around. If you are pushing your driver for kernel
>>> inclusion, it should not stand out by the style and by the typical code
>>> seuqences.
>>
>> Thanks a lot for all your comments, will take care of these in next version.

Thanks,
Vikash