From 0ccbe8bcc70daf3629425ce0e99fb3e8c62d1554 Mon Sep 17 00:00:00 2001 From: FantasyGmm <16450052+FantasyGmm@users.noreply.github.com> Date: Fri, 14 Mar 2025 10:13:54 +0800 Subject: [PATCH] Update Odin2 Config --- config/boards/ayn-odin2.csc | 139 +- config/kernel/linux-arm64-sm8550.config | 1267 ---- config/kernel/linux-sm8550-current.config | 842 +++ config/kernel/linux-sm8550-edge.config | 846 +++ config/sources/families/sm8550.conf | 32 + packages/bsp/ayn-odin2/AYN-Odin2.conf | 31 + packages/bsp/ayn-odin2/HiFi.conf | 91 + packages/bsp/ayn-odin2/LinuxLoader.cfg | 10 +- packages/bsp/ayn-odin2/bt-fixed-mac.service | 11 - packages/bsp/ayn-odin2/bt-fixed-mac.sh | 11 - .../sm8550-6.12/0000.patching_config.yaml | 27 + ...edia--Add-video-support-for-QCOM-SM8.patch | 189 + ...dd-platform-driver-for-iris-video-de.patch | 470 ++ ...--iris--implement-iris-v4l2-file-ops.patch | 450 ++ ...ntroduce-iris-core-state-management-.patch | 636 ++ ...implement-video-firmware-load-unload.patch | 289 + ...mplement-the-boot-sequence-of-the-fi.patch | 213 + ...ntroduce-host-firmware-interface-wit.patch | 1697 +++++ ...ia--iris--implement-power-management.patch | 1246 ++++ ...mplement-reqbuf-ioctl-with-vb2_queue.patch | 1651 +++++ ...mplement-s_fmt,-g_fmt-and-try_fmt-io.patch | 248 + ...a--iris--implement-g_selection-ioctl.patch | 70 + ...mplement-enum_fmt-and-enum_framesize.patch | 168 + ...mplement-subscribe_event-and-unsubsc.patch | 110 + ...--iris--implement-iris-v4l2_ctrl_ops.patch | 539 ++ ...dia--iris--implement-query_cap-ioctl.patch | 50 + ...a--iris--implement-vb2-streaming-ops.patch | 1083 +++ ...mplement-set-properties-to-firmware-.patch | 1863 +++++ ...ubscribe-parameters-and-properties-t.patch | 331 + ...llocate,-initialize-and-queue-intern.patch | 1477 ++++ ...mplement-vb2-ops-for-buf_queue-and-f.patch | 1478 ++++ ...dd-support-for-dynamic-resolution-ch.patch | 985 +++ ...andle-streamoff-on-from-client-in-dy.patch | 343 + ...iris--add-support-for-drain-sequence.patch | 654 ++ ...dd-check-whether-the-video-session-i.patch | 171 + ...mplement-power-scaling-for-vpu2-and-.patch | 515 ++ ...dd-check-to-allow-sub-states-transit.patch | 141 + ...nable-video-driver-probe-of-SM8250-S.patch | 223 + ...NERS--add-Qualcomm-iris-video-accele.patch | 44 + ...om--sm8550--Add-iris-video-codec-nod.patch | 100 + ...arm64--dts--qcom--sm8550--add-UART15.patch | 53 + ...nput--Add-driver-for-RSInput-Gamepad.patch | 467 ++ ...-panel-driver-for-Chipone-ICNA3512-b.patch | 530 ++ ..._leds--Add-driver-for-HEROIC-HTR3212.patch | 353 + ...--audioreach--Set-lpaif_type-for-i2s.patch | 25 + ...apm-lpass-dais--Add-set_fmt-to-q6i2s.patch | 25 + ...sc8280xp-Add-support-for-Primary-I2S.patch | 97 + ...hy--qcom,sc8280xp-qmp-usb43dp--Refer.patch | 52 + ...-qmp-combo--store-DP-phy-power-state.patch | 46 + ...qcom--qmp-combo--introduce-QPHY_MODE.patch | 91 + ...-combo--register-a-typec-mux-to-chan.patch | 199 + ...mc--qcom--Document-level-shifter-fla.patch | 39 + ...--Enable-tuning-for-SDR50-mode-for-S.patch | 67 + ...--Limit-HS-mode-frequency-to-37.5MHz.patch | 62 + ...--Toggle-the-FIFO-write-clock-after-.patch | 99 + ...-sm8550--Keep-UFS-PHY-GDSCs-ALWAYS_O.patch | 53 + ...codecs--Add-aw88166-amplifier-driver.patch | 2528 +++++++ ...aw88166--AYN-Odin2-Specific-modifica.patch | 494 ++ .../0049_Synaptics-TD4328-LCD-panel.patch | 304 + ...0050_arm64--dts--qcom--Add-AYN-Odin2.patch | 368 + .../sm8550-6.12/0051_pmk8550-pwm.patch | 20 + .../0052_qcom-downstream-sdhci-driver.patch | 6183 +++++++++++++++++ .../sm8550-6.12/0053-battery-name.patch | 21 + .../sm8550-6.12/0054_sn3112-pwm-driver.patch | 390 ++ .../5000_enable_ayn_odin2_device_tree.patch | 12 + .../sm8550-6.12/9997-set-boot-fanspeed.patch | 12 + .../9998-fix-wifi-and-bt-mac.patch | 305 + .../sm8550-6.12/dt/qcs8550-ayn-common.dtsi | 1383 ++++ .../dt/qcs8550-ayn-odin2portal.dts | 338 + patch/kernel/archive/sm8550-6.7/.placeholder | 0 70 files changed, 33981 insertions(+), 1376 deletions(-) delete mode 100644 config/kernel/linux-arm64-sm8550.config create mode 100644 config/kernel/linux-sm8550-current.config create mode 100644 config/kernel/linux-sm8550-edge.config create mode 100644 config/sources/families/sm8550.conf create mode 100644 packages/bsp/ayn-odin2/AYN-Odin2.conf create mode 100644 packages/bsp/ayn-odin2/HiFi.conf delete mode 100644 packages/bsp/ayn-odin2/bt-fixed-mac.service delete mode 100644 packages/bsp/ayn-odin2/bt-fixed-mac.sh create mode 100644 patch/kernel/archive/sm8550-6.12/0000.patching_config.yaml create mode 100644 patch/kernel/archive/sm8550-6.12/0001_dt-bindings--media--Add-video-support-for-QCOM-SM8.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0002_media--iris--add-platform-driver-for-iris-video-de.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0003_media--iris--implement-iris-v4l2-file-ops.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0004_media--iris--introduce-iris-core-state-management-.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0005_media--iris--implement-video-firmware-load-unload.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0006_media--iris--implement-the-boot-sequence-of-the-fi.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0007_media--iris--introduce-host-firmware-interface-wit.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0008_media--iris--implement-power-management.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0009_media--iris--implement-reqbuf-ioctl-with-vb2_queue.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0010_media--iris--implement-s_fmt,-g_fmt-and-try_fmt-io.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0011_media--iris--implement-g_selection-ioctl.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0012_media--iris--implement-enum_fmt-and-enum_framesize.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0013_media--iris--implement-subscribe_event-and-unsubsc.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0014_media--iris--implement-iris-v4l2_ctrl_ops.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0015_media--iris--implement-query_cap-ioctl.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0016_media--iris--implement-vb2-streaming-ops.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0017_media--iris--implement-set-properties-to-firmware-.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0018_media--iris--subscribe-parameters-and-properties-t.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0019_media--iris--allocate,-initialize-and-queue-intern.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0020_media--iris--implement-vb2-ops-for-buf_queue-and-f.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0021_media--iris--add-support-for-dynamic-resolution-ch.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0022_media--iris--handle-streamoff-on-from-client-in-dy.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0023_media--iris--add-support-for-drain-sequence.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0024_media--iris--add-check-whether-the-video-session-i.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0025_media--iris--implement-power-scaling-for-vpu2-and-.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0026_media--iris--add-check-to-allow-sub-states-transit.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0027_media--iris--enable-video-driver-probe-of-SM8250-S.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0028_media--MAINTAINERS--add-Qualcomm-iris-video-accele.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0029_arm64--dts--qcom--sm8550--Add-iris-video-codec-nod.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0030_arm64--dts--qcom--sm8550--add-UART15.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0031_input--Add-driver-for-RSInput-Gamepad.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0032_drm-panel--Add-panel-driver-for-Chipone-ICNA3512-b.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0033_leds--Add-driver-for-HEROIC-HTR3212.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0034_ASoC--qcom--audioreach--Set-lpaif_type-for-i2s.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0035_ASoC--qcom--q6apm-lpass-dais--Add-set_fmt-to-q6i2s.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0036_ASoC--qcom--sc8280xp-Add-support-for-Primary-I2S.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0037_dt-bindings--phy--qcom,sc8280xp-qmp-usb43dp--Refer.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0038_phy--qcom--qmp-combo--store-DP-phy-power-state.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0039_phy--qcom--qmp-combo--introduce-QPHY_MODE.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0040_phy--qcom--qmp-combo--register-a-typec-mux-to-chan.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0041_dt-bindings--mmc--qcom--Document-level-shifter-fla.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0042_mmc--sdhci-msm--Enable-tuning-for-SDR50-mode-for-S.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0043_mmc--sdhci-msm--Limit-HS-mode-frequency-to-37.5MHz.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0044_mmc--sdhci-msm--Toggle-the-FIFO-write-clock-after-.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0045_clk--qcom--gcc-sm8550--Keep-UFS-PHY-GDSCs-ALWAYS_O.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0046_ASoC--codecs--Add-aw88166-amplifier-driver.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0047_ASoC--codecs--aw88166--AYN-Odin2-Specific-modifica.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0049_Synaptics-TD4328-LCD-panel.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0050_arm64--dts--qcom--Add-AYN-Odin2.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0051_pmk8550-pwm.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0052_qcom-downstream-sdhci-driver.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0053-battery-name.patch create mode 100644 patch/kernel/archive/sm8550-6.12/0054_sn3112-pwm-driver.patch create mode 100644 patch/kernel/archive/sm8550-6.12/5000_enable_ayn_odin2_device_tree.patch create mode 100644 patch/kernel/archive/sm8550-6.12/9997-set-boot-fanspeed.patch create mode 100644 patch/kernel/archive/sm8550-6.12/9998-fix-wifi-and-bt-mac.patch create mode 100644 patch/kernel/archive/sm8550-6.12/dt/qcs8550-ayn-common.dtsi create mode 100644 patch/kernel/archive/sm8550-6.12/dt/qcs8550-ayn-odin2portal.dts delete mode 100644 patch/kernel/archive/sm8550-6.7/.placeholder diff --git a/config/boards/ayn-odin2.csc b/config/boards/ayn-odin2.csc index a29f4f5f4..6473119a5 100644 --- a/config/boards/ayn-odin2.csc +++ b/config/boards/ayn-odin2.csc @@ -1,35 +1,62 @@ -# Generate kernel and rootfs image for Qcom ABL Custom booting +# Ayn Odin2 Configuration declare -g BOARD_NAME="Ayn Odin2" declare -g BOARD_MAINTAINER="FantasyGmm" -declare -g BOARDFAMILY="qcom-abl" -declare -g KERNEL_TARGET="sm8550" -declare -g KERNELPATCHDIR="sm8550-6.7" +declare -g BOARDFAMILY="sm8550" +declare -g KERNEL_TARGET="current,edge" +declare -g KERNEL_TEST_TARGET="edge" declare -g EXTRAWIFI="no" declare -g BOOTCONFIG="none" declare -g BOOTFS_TYPE="fat" declare -g BOOTSIZE="256" -declare -g BOOTIMG_CMDLINE_EXTRA="clk_ignore_unused pd_ignore_unused panic=30 audit=0 allow_mismatched_32bit_el0 rw mem_sleep_default=s2idle" declare -g IMAGE_PARTITION_TABLE="gpt" +declare -g BOOTIMG_CMDLINE_EXTRA="clk_ignore_unused pd_ignore_unused rw quiet rootwait" # Use the full firmware, complete linux-firmware plus Armbian's declare -g BOARD_FIRMWARE_INSTALL="-full" - declare -g DESKTOP_AUTOLOGIN="yes" -function post_family_config_branch_sm8550__edk2_kernel() { - declare -g KERNELSOURCE='https://github.com/edk2-porting/linux-next' - declare -g KERNEL_MAJOR_MINOR="6.7" # Major and minor versions of this kernel. - declare -g KERNELBRANCH="branch:ci/odin2/stable" - declare -g LINUXCONFIG="linux-${ARCH}-${BRANCH}" # for this board: linux-arm64-sm8550 - display_alert "Setting up kernel ${KERNEL_MAJOR_MINOR} for" "${BOARD}" "info" -} - function ayn-odin2_is_userspace_supported() { - [[ "${RELEASE}" == "trixie" || "${RELEASE}" == "sid" || "${RELEASE}" == "mantic" || "${RELEASE}" == "noble" ]] && return 0 + [[ "${RELEASE}" == "jammy" ]] && return 0 + [[ "${RELEASE}" == "trixie" ]] && return 0 + [[ "${RELEASE}" == "noble" ]] && return 0 return 1 } -function post_family_tweaks__enable_services() { +function pre_customize_image__ayn-odin2_alsa_ucm_conf() { + if ! ayn-odin2_is_userspace_supported; then + return 0 + fi + + display_alert "Add alsa-ucm-conf for ${BOARD}" "${RELEASE}" "warn" + ( + cd "${SDCARD}/usr/share/alsa" || exit 6 + curl -L -o temp.zip "https://github.com/AYNTechnologies/alsa-ucm-conf/archive/refs/heads/ayn/v1.2.13.zip" + unzip -o temp.zip + unzip_dir=$(unzip -Z1 temp.zip | head -n1 | cut -d/ -f1) + cp -rf "${unzip_dir}/"* . + rm -rf "$unzip_dir" temp.zip + ) +} + +function post_family_tweaks_bsp__ayn-odin2_firmware() { + display_alert "Install firmwares for ${BOARD}" "${RELEASE}" "warn" + + # USB Gadget Network service + mkdir -p $destination/usr/local/bin/ + mkdir -p $destination/usr/lib/systemd/system/ + mkdir -p $destination/etc/initramfs-tools/scripts/init-bottom/ + install -Dm655 $SRC/packages/bsp/usb-gadget-network/setup-usbgadget-network.sh $destination/usr/local/bin/ + install -Dm655 $SRC/packages/bsp/usb-gadget-network/remove-usbgadget-network.sh $destination/usr/local/bin/ + install -Dm644 $SRC/packages/bsp/usb-gadget-network/usbgadget-rndis.service $destination/usr/lib/systemd/system/ + install -Dm655 $SRC/packages/bsp/usb-gadget-network/usb-gadget-initramfs-hook $destination/etc/initramfs-tools/hooks/usb-gadget + install -Dm655 $SRC/packages/bsp/usb-gadget-network/usb-gadget-initramfs-premount $destination/etc/initramfs-tools/scripts/init-premount/usb-gadget + install -Dm655 $SRC/packages/bsp/usb-gadget-network/dropbear $destination/etc/initramfs-tools/scripts/init-premount/ + install -Dm655 $SRC/packages/bsp/usb-gadget-network/kill-dropbear $destination/etc/initramfs-tools/scripts/init-bottom/ + + return 0 +} + +function post_family_tweaks__ayn-odin2_enable_services() { if ! ayn-odin2_is_userspace_supported; then if [[ "${RELEASE}" != "" ]]; then display_alert "Missing userspace for ${BOARD}" "${RELEASE} does not have the userspace necessary to support the ${BOARD}" "warn" @@ -37,95 +64,47 @@ function post_family_tweaks__enable_services() { return 0 fi - if [[ "${RELEASE}" == "noble" ]]; then - display_alert "Adding Mesa PPA For Ubuntu " "${BOARD}" "info" - do_with_retries 3 chroot_sdcard add-apt-repository ppa:oibaf/graphics-drivers --yes --no-update + if [[ "${RELEASE}" == "jammy" ]] || [[ "${RELEASE}" == "noble" ]]; then + display_alert "Adding Mesa PPA For Ubuntu ${BOARD}" "warn" + do_with_retries 3 chroot_sdcard add-apt-repository ppa:liujianfeng1994/qcom-mainline --yes --no-update fi # We need unudhcpd from armbian repo, so enable it mv "${SDCARD}"/etc/apt/sources.list.d/armbian.sources.disabled "${SDCARD}"/etc/apt/sources.list.d/armbian.sources - # Add Gamepad udev rule - echo 'SUBSYSTEM=="input", ATTRS{name}=="Ayn Odin2 Gamepad", MODE="0666", ENV{ID_INPUT_MOUSE}="0", ENV{ID_INPUT_JOYSTICK}="1"' > "${SDCARD}"/etc/udev/rules.d/99-ignore-gamepad.rules - # No driver support for suspend - chroot_sdcard systemctl mask suspend.target - # Add Bt Mac Fixed service - install -Dm655 $SRC/packages/bsp/ayn-odin2/bt-fixed-mac.sh "${SDCARD}"/usr/local/bin/ - install -Dm644 $SRC/packages/bsp/ayn-odin2/bt-fixed-mac.service "${SDCARD}"/usr/lib/systemd/system/ - chroot_sdcard systemctl enable bt-fixed-mac - do_with_retries 3 chroot_sdcard_apt_get_update - display_alert "$BOARD" "Installing board tweaks" "info" - do_with_retries 3 chroot_sdcard_apt_get_install alsa-ucm-conf unudhcpd mkbootimg git - - # Disable armbian repo back + display_alert "Installing ${BOARD} tweaks" "warn" + do_with_retries 3 chroot_sdcard_apt_get_install alsa-ucm-conf qbootctl qrtr-tools unudhcpd mkbootimg + # disable armbian repo back mv "${SDCARD}"/etc/apt/sources.list.d/armbian.sources "${SDCARD}"/etc/apt/sources.list.d/armbian.sources.disabled do_with_retries 3 chroot_sdcard_apt_get_update + chroot_sdcard systemctl enable qbootctl.service - do_with_retries 3 chroot_sdcard_apt_get_install mesa-vulkan-drivers qbootctl qrtr-tools protection-domain-mapper tqftpserv - - # Kernel postinst script to update abl boot partition - install -Dm655 $SRC/packages/bsp/ayn-odin2/zz-update-abl-kernel "${SDCARD}"/etc/kernel/postinst.d/ + # Add Gamepad udev rule + echo 'SUBSYSTEM=="input", ATTRS{name}=="AYN Odin2 Gamepad", MODE="0666", ENV{ID_INPUT_JOYSTICK}="1"' > "${SDCARD}"/etc/udev/rules.d/99-ignore-gamepad.rules + # Not Any driver support suspend mode + chroot_sdcard systemctl mask suspend.target + chroot_sdcard systemctl enable usbgadget-rndis.service cp $SRC/packages/bsp/ayn-odin2/LinuxLoader.cfg "${SDCARD}"/boot/ return 0 } -function post_family_tweaks__preset_configs() { - display_alert "$BOARD" "preset configs for rootfs" "info" - # Set PRESET_NET_CHANGE_DEFAULTS to 1 to apply any network related settings below - echo "PRESET_NET_CHANGE_DEFAULTS=1" > "${SDCARD}"/root/.not_logged_in_yet - - # Enable WiFi or Ethernet. - # NB: If both are enabled, WiFi will take priority and Ethernet will be disabled. - echo "PRESET_NET_ETHERNET_ENABLED=0" >> "${SDCARD}"/root/.not_logged_in_yet - echo "PRESET_NET_WIFI_ENABLED=1" >> "${SDCARD}"/root/.not_logged_in_yet - - # Preset user default shell, you can choose bash or zsh - echo "PRESET_USER_SHELL=zsh" >> "${SDCARD}"/root/.not_logged_in_yet - - # Set PRESET_CONNECT_WIRELESS=y if you want to connect wifi manually at first login - echo "PRESET_CONNECT_WIRELESS=n" >> "${SDCARD}"/root/.not_logged_in_yet - - # Set SET_LANG_BASED_ON_LOCATION=n if you want to choose "Set user language based on your location?" with "n" at first login - echo "SET_LANG_BASED_ON_LOCATION=y" >> "${SDCARD}"/root/.not_logged_in_yet - - # Preset default locale - echo "PRESET_LOCALE=en_US.UTF-8" >> "${SDCARD}"/root/.not_logged_in_yet - - # Preset timezone - echo "PRESET_TIMEZONE=Etc/UTC" >> "${SDCARD}"/root/.not_logged_in_yet - - # Preset root password - echo "PRESET_ROOT_PASSWORD=admin" >> "${SDCARD}"/root/.not_logged_in_yet - - # Preset username - echo "PRESET_USER_NAME=odin" >> "${SDCARD}"/root/.not_logged_in_yet - - # Preset user password - echo "PRESET_USER_PASSWORD=admin" >> "${SDCARD}"/root/.not_logged_in_yet - - # Preset user default realname - echo "PRESET_DEFAULT_REALNAME=Odin" >> "${SDCARD}"/root/.not_logged_in_yet -} - -function post_family_tweaks_bsp__firmware_in_initrd() { - random_mac=$(openssl rand -hex 6 | sed 's/\(..\)/\1:/g; s/.$//') - declare -g BOOTIMG_CMDLINE_EXTRA="${BOOTIMG_CMDLINE_EXTRA} bt_mac=${random_mac}" - display_alert "Generate a random Bluetooth MAC address, Mac:${random_mac}" "info" - display_alert "Adding to bsp-cli" "${BOARD}: firmware in initrd" "info" +function post_family_tweaks_bsp__ayn-odin2_bsp_firmware_in_initrd() { + display_alert "Adding to bsp-cli" "${BOARD}: firmware in initrd" "warn" declare file_added_to_bsp_destination # Will be filled in by add_file_from_stdin_to_bsp_destination # Using odin2's firmware for now add_file_from_stdin_to_bsp_destination "/etc/initramfs-tools/hooks/ayn-odin2-firmware" <<- 'FIRMWARE_HOOK' #!/bin/bash [[ "$1" == "prereqs" ]] && exit 0 . /usr/share/initramfs-tools/hook-functions - for f in /lib/firmware/qcom/sm8550/ayn/odin2/* ; do + for f in /lib/firmware/qcom/sm8550/ayn/odin2portal/* ; do add_firmware "${f#/lib/firmware/}" done add_firmware "qcom/a740_sqe.fw" # Extra one for dpu add_firmware "qcom/gmu_gen70200.bin" # Extra one for gpu + add_firmware "qcom/vpu/vpu30_p4.mbn" # Extra one for vpu # Extra one for wifi for f in /lib/firmware/ath12k/WCN7850/hw2.0/* ; do add_firmware "${f#/lib/firmware/}" diff --git a/config/kernel/linux-arm64-sm8550.config b/config/kernel/linux-arm64-sm8550.config deleted file mode 100644 index f00ed10c8..000000000 --- a/config/kernel/linux-arm64-sm8550.config +++ /dev/null @@ -1,1267 +0,0 @@ -# CONFIG_LOCALVERSION_AUTO is not set -CONFIG_DEFAULT_HOSTNAME="ohmyqcom" -CONFIG_SYSVIPC=y -CONFIG_POSIX_MQUEUE=y -CONFIG_WATCH_QUEUE=y -CONFIG_AUDIT=y -# CONFIG_CONTEXT_TRACKING_USER_FORCE is not set -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_BPF_SYSCALL=y -CONFIG_BPF_JIT=y -CONFIG_BPF_JIT_ALWAYS_ON=y -CONFIG_BPF_PRELOAD=y -CONFIG_BPF_PRELOAD_UMD=y -CONFIG_BPF_LSM=y -CONFIG_PREEMPT_VOLUNTARY=y -CONFIG_PREEMPT_DYNAMIC=y -CONFIG_SCHED_CORE=y -CONFIG_VIRT_CPU_ACCOUNTING_GEN=y -CONFIG_IRQ_TIME_ACCOUNTING=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_BSD_PROCESS_ACCT_V3=y -CONFIG_TASKSTATS=y -CONFIG_TASK_DELAY_ACCT=y -CONFIG_TASK_XACCT=y -CONFIG_TASK_IO_ACCOUNTING=y -CONFIG_PSI=y -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_LOG_BUF_SHIFT=20 -CONFIG_PRINTK_INDEX=y -CONFIG_UCLAMP_TASK=y -CONFIG_NUMA_BALANCING=y -CONFIG_MEMCG=y -CONFIG_BLK_CGROUP=y -CONFIG_CFS_BANDWIDTH=y -CONFIG_UCLAMP_TASK_GROUP=y -CONFIG_CGROUP_PIDS=y -CONFIG_CGROUP_RDMA=y -CONFIG_CGROUP_FREEZER=y -CONFIG_CPUSETS=y -CONFIG_CGROUP_DEVICE=y -CONFIG_CGROUP_CPUACCT=y -CONFIG_CGROUP_PERF=y -CONFIG_CGROUP_BPF=y -CONFIG_CGROUP_MISC=y -CONFIG_NAMESPACES=y -CONFIG_USER_NS=y -CONFIG_CHECKPOINT_RESTORE=y -CONFIG_SCHED_AUTOGROUP=y -# CONFIG_RD_BZIP2 is not set -# CONFIG_RD_LZMA is not set -# CONFIG_RD_LZO is not set -# CONFIG_RD_LZ4 is not set -# CONFIG_INITRAMFS_PRESERVE_MTIME is not set -CONFIG_EXPERT=y -CONFIG_SGETMASK_SYSCALL=y -CONFIG_PROFILING=y -CONFIG_KEXEC=y -CONFIG_KEXEC_FILE=y -CONFIG_KEXEC_SIG=y -CONFIG_ARCH_QCOM=y -# CONFIG_ARM64_ERRATUM_2658417 is not set -# CONFIG_ARM64_ERRATUM_3117295 is not set -CONFIG_ARM64_VA_BITS_48=y -CONFIG_SCHED_MC=y -CONFIG_SCHED_SMT=y -CONFIG_NUMA=y -CONFIG_NODES_SHIFT=9 -CONFIG_PARAVIRT_TIME_ACCOUNTING=y -CONFIG_ARM64_SW_TTBR0_PAN=y -CONFIG_COMPAT=y -CONFIG_ARMV8_DEPRECATED=y -CONFIG_SWP_EMULATION=y -CONFIG_CP15_BARRIER_EMULATION=y -CONFIG_SETEND_EMULATION=y -CONFIG_ARM64_PMEM=y -CONFIG_RANDOMIZE_BASE=y -CONFIG_PM_DEBUG=y -CONFIG_PM_TEST_SUSPEND=y -CONFIG_ENERGY_MODEL=y -CONFIG_CPU_IDLE=y -CONFIG_ARM_PSCI_CPUIDLE=y -CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_STAT=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_ARM_QCOM_CPUFREQ_HW=y -CONFIG_VIRTUALIZATION=y -CONFIG_KVM=y -CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT=y -CONFIG_MODULES=y -CONFIG_MODULE_FORCE_LOAD=y -CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -CONFIG_MODVERSIONS=y -CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS=y -CONFIG_BLK_DEV_ZONED=y -CONFIG_BLK_DEV_THROTTLING=y -CONFIG_BLK_DEV_THROTTLING_LOW=y -CONFIG_BLK_WBT=y -CONFIG_BLK_CGROUP_IOLATENCY=y -CONFIG_BLK_CGROUP_IOCOST=y -CONFIG_BLK_CGROUP_IOPRIO=y -CONFIG_BLK_SED_OPAL=y -CONFIG_BLK_INLINE_ENCRYPTION=y -CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y -# CONFIG_MQ_IOSCHED_KYBER is not set -CONFIG_BINFMT_MISC=y -CONFIG_ZSWAP=y -CONFIG_ZSWAP_COMPRESSOR_DEFAULT_ZSTD=y -CONFIG_ZBUD=y -CONFIG_Z3FOLD=y -# CONFIG_SLAB_MERGE_DEFAULT is not set -CONFIG_SLAB_FREELIST_RANDOM=y -CONFIG_SLAB_FREELIST_HARDENED=y -CONFIG_SHUFFLE_PAGE_ALLOCATOR=y -# CONFIG_COMPAT_BRK is not set -CONFIG_MEMORY_HOTPLUG=y -CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE=y -CONFIG_MEMORY_HOTREMOVE=y -CONFIG_PAGE_REPORTING=y -CONFIG_KSM=y -CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 -CONFIG_MEMORY_FAILURE=y -CONFIG_TRANSPARENT_HUGEPAGE=y -CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y -CONFIG_CMA=y -CONFIG_CMA_SYSFS=y -CONFIG_CMA_AREAS=7 -CONFIG_IDLE_PAGE_TRACKING=y -CONFIG_ZONE_DEVICE=y -CONFIG_DEVICE_PRIVATE=y -CONFIG_USERFAULTFD=y -CONFIG_LRU_GEN=y -CONFIG_LRU_GEN_ENABLED=y -CONFIG_DAMON=y -CONFIG_DAMON_VADDR=y -CONFIG_DAMON_PADDR=y -CONFIG_DAMON_SYSFS=y -CONFIG_DAMON_DBGFS_DEPRECATED=y -CONFIG_DAMON_RECLAIM=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_PACKET_DIAG=y -CONFIG_UNIX=y -CONFIG_UNIX_DIAG=y -CONFIG_TLS=y -CONFIG_TLS_DEVICE=y -CONFIG_TLS_TOE=y -CONFIG_XFRM_USER=y -CONFIG_XFRM_INTERFACE=y -CONFIG_XFRM_SUB_POLICY=y -CONFIG_XFRM_STATISTICS=y -CONFIG_NET_KEY=y -CONFIG_NET_KEY_MIGRATE=y -CONFIG_XDP_SOCKETS=y -CONFIG_XDP_SOCKETS_DIAG=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -CONFIG_IP_MROUTE=y -CONFIG_IP_PIMSM_V1=y -CONFIG_IP_PIMSM_V2=y -CONFIG_INET_AH=y -CONFIG_INET_ESP=y -CONFIG_INET_ESP_OFFLOAD=y -CONFIG_INET_ESPINTCP=y -CONFIG_INET_UDP_DIAG=y -CONFIG_INET_RAW_DIAG=y -CONFIG_INET_DIAG_DESTROY=y -CONFIG_TCP_CONG_ADVANCED=y -CONFIG_TCP_CONG_BIC=y -CONFIG_TCP_CONG_WESTWOOD=y -CONFIG_TCP_CONG_HTCP=y -CONFIG_TCP_CONG_HSTCP=y -CONFIG_TCP_CONG_HYBLA=y -CONFIG_TCP_CONG_NV=y -CONFIG_TCP_CONG_SCALABLE=y -CONFIG_TCP_CONG_LP=y -CONFIG_TCP_CONG_VENO=y -CONFIG_TCP_CONG_YEAH=y -CONFIG_TCP_CONG_ILLINOIS=y -CONFIG_TCP_CONG_DCTCP=y -CONFIG_TCP_CONG_CDG=y -CONFIG_TCP_CONG_BBR=y -CONFIG_IPV6_ROUTER_PREF=y -CONFIG_IPV6_ROUTE_INFO=y -CONFIG_IPV6_OPTIMISTIC_DAD=y -CONFIG_INET6_AH=y -CONFIG_INET6_ESP=y -CONFIG_INET6_ESP_OFFLOAD=y -CONFIG_INET6_ESPINTCP=y -# CONFIG_IPV6_SIT is not set -CONFIG_IPV6_SUBTREES=y -CONFIG_IPV6_MROUTE=y -CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y -CONFIG_IPV6_PIMSM_V2=y -CONFIG_IPV6_SEG6_LWTUNNEL=y -CONFIG_IPV6_SEG6_HMAC=y -CONFIG_IPV6_RPL_LWTUNNEL=y -CONFIG_IPV6_IOAM6_LWTUNNEL=y -CONFIG_NETFILTER=y -CONFIG_BRIDGE_NETFILTER=y -CONFIG_NETFILTER_NETLINK_HOOK=y -CONFIG_NF_CONNTRACK=y -CONFIG_NF_CONNTRACK_SECMARK=y -CONFIG_NF_CONNTRACK_ZONES=y -CONFIG_NF_CONNTRACK_PROCFS=y -CONFIG_NF_CONNTRACK_EVENTS=y -CONFIG_NF_CONNTRACK_TIMEOUT=y -CONFIG_NF_CONNTRACK_TIMESTAMP=y -CONFIG_NF_CONNTRACK_AMANDA=y -CONFIG_NF_CONNTRACK_FTP=y -CONFIG_NF_CONNTRACK_H323=y -CONFIG_NF_CONNTRACK_IRC=y -CONFIG_NF_CONNTRACK_NETBIOS_NS=y -CONFIG_NF_CONNTRACK_SNMP=y -CONFIG_NF_CONNTRACK_PPTP=y -CONFIG_NF_CONNTRACK_SANE=y -CONFIG_NF_CONNTRACK_SIP=y -CONFIG_NF_CONNTRACK_TFTP=y -CONFIG_NF_CT_NETLINK=y -CONFIG_NF_CT_NETLINK_TIMEOUT=y -CONFIG_NF_CT_NETLINK_HELPER=y -CONFIG_NETFILTER_NETLINK_GLUE_CT=y -CONFIG_NF_TABLES=y -CONFIG_NF_TABLES_INET=y -CONFIG_NF_TABLES_NETDEV=y -CONFIG_NFT_NUMGEN=y -CONFIG_NFT_CT=y -CONFIG_NFT_FLOW_OFFLOAD=y -CONFIG_NFT_CONNLIMIT=y -CONFIG_NFT_LOG=y -CONFIG_NFT_LIMIT=y -CONFIG_NFT_MASQ=y -CONFIG_NFT_REDIR=y -CONFIG_NFT_NAT=y -CONFIG_NFT_TUNNEL=y -CONFIG_NFT_QUEUE=y -CONFIG_NFT_QUOTA=y -CONFIG_NFT_REJECT=y -CONFIG_NFT_COMPAT=y -CONFIG_NFT_HASH=y -CONFIG_NFT_FIB_INET=y -CONFIG_NFT_XFRM=y -CONFIG_NFT_SOCKET=y -CONFIG_NFT_OSF=y -CONFIG_NFT_TPROXY=y -CONFIG_NFT_SYNPROXY=y -CONFIG_NFT_DUP_NETDEV=y -CONFIG_NFT_FWD_NETDEV=y -CONFIG_NFT_FIB_NETDEV=y -CONFIG_NFT_REJECT_NETDEV=y -CONFIG_NF_FLOW_TABLE_INET=y -CONFIG_NF_FLOW_TABLE=y -CONFIG_NF_FLOW_TABLE_PROCFS=y -CONFIG_NETFILTER_XTABLES_COMPAT=y -CONFIG_NETFILTER_XT_SET=y -CONFIG_NETFILTER_XT_TARGET_AUDIT=y -CONFIG_NETFILTER_XT_TARGET_CHECKSUM=y -CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y -CONFIG_NETFILTER_XT_TARGET_CONNMARK=y -CONFIG_NETFILTER_XT_TARGET_DSCP=y -CONFIG_NETFILTER_XT_TARGET_HMARK=y -CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y -CONFIG_NETFILTER_XT_TARGET_LED=y -CONFIG_NETFILTER_XT_TARGET_LOG=y -CONFIG_NETFILTER_XT_TARGET_MARK=y -CONFIG_NETFILTER_XT_TARGET_NFLOG=y -CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y -CONFIG_NETFILTER_XT_TARGET_NOTRACK=y -CONFIG_NETFILTER_XT_TARGET_TEE=y -CONFIG_NETFILTER_XT_TARGET_TPROXY=y -CONFIG_NETFILTER_XT_TARGET_TRACE=y -CONFIG_NETFILTER_XT_TARGET_SECMARK=y -CONFIG_NETFILTER_XT_TARGET_TCPMSS=y -CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=y -CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y -CONFIG_NETFILTER_XT_MATCH_BPF=y -CONFIG_NETFILTER_XT_MATCH_CGROUP=y -CONFIG_NETFILTER_XT_MATCH_CLUSTER=y -CONFIG_NETFILTER_XT_MATCH_COMMENT=y -CONFIG_NETFILTER_XT_MATCH_CONNBYTES=y -CONFIG_NETFILTER_XT_MATCH_CONNLABEL=y -CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y -CONFIG_NETFILTER_XT_MATCH_CONNMARK=y -CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y -CONFIG_NETFILTER_XT_MATCH_CPU=y -CONFIG_NETFILTER_XT_MATCH_DCCP=y -CONFIG_NETFILTER_XT_MATCH_DEVGROUP=y -CONFIG_NETFILTER_XT_MATCH_DSCP=y -CONFIG_NETFILTER_XT_MATCH_ESP=y -CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y -CONFIG_NETFILTER_XT_MATCH_HELPER=y -CONFIG_NETFILTER_XT_MATCH_IPCOMP=y -CONFIG_NETFILTER_XT_MATCH_IPRANGE=y -CONFIG_NETFILTER_XT_MATCH_L2TP=y -CONFIG_NETFILTER_XT_MATCH_LENGTH=y -CONFIG_NETFILTER_XT_MATCH_LIMIT=y -CONFIG_NETFILTER_XT_MATCH_MAC=y -CONFIG_NETFILTER_XT_MATCH_MARK=y -CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y -CONFIG_NETFILTER_XT_MATCH_NFACCT=y -CONFIG_NETFILTER_XT_MATCH_OSF=y -CONFIG_NETFILTER_XT_MATCH_OWNER=y -CONFIG_NETFILTER_XT_MATCH_POLICY=y -CONFIG_NETFILTER_XT_MATCH_PHYSDEV=y -CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y -CONFIG_NETFILTER_XT_MATCH_QUOTA=y -CONFIG_NETFILTER_XT_MATCH_RATEEST=y -CONFIG_NETFILTER_XT_MATCH_REALM=y -CONFIG_NETFILTER_XT_MATCH_RECENT=y -CONFIG_NETFILTER_XT_MATCH_SOCKET=y -CONFIG_NETFILTER_XT_MATCH_STATE=y -CONFIG_NETFILTER_XT_MATCH_STATISTIC=y -CONFIG_NETFILTER_XT_MATCH_STRING=y -CONFIG_NETFILTER_XT_MATCH_TCPMSS=y -CONFIG_NETFILTER_XT_MATCH_TIME=y -CONFIG_NETFILTER_XT_MATCH_U32=y -CONFIG_IP_SET=y -CONFIG_IP_SET_BITMAP_IP=y -CONFIG_IP_SET_BITMAP_IPMAC=y -CONFIG_IP_SET_BITMAP_PORT=y -CONFIG_IP_SET_HASH_IP=y -CONFIG_IP_SET_HASH_IPMARK=y -CONFIG_IP_SET_HASH_IPPORT=y -CONFIG_IP_SET_HASH_IPPORTIP=y -CONFIG_IP_SET_HASH_IPPORTNET=y -CONFIG_IP_SET_HASH_IPMAC=y -CONFIG_IP_SET_HASH_MAC=y -CONFIG_IP_SET_HASH_NETPORTNET=y -CONFIG_IP_SET_HASH_NET=y -CONFIG_IP_SET_HASH_NETNET=y -CONFIG_IP_SET_HASH_NETPORT=y -CONFIG_IP_SET_HASH_NETIFACE=y -CONFIG_IP_SET_LIST_SET=y -CONFIG_NFT_DUP_IPV4=y -CONFIG_NFT_FIB_IPV4=y -CONFIG_NF_TABLES_ARP=y -CONFIG_NF_LOG_ARP=y -CONFIG_NF_LOG_IPV4=y -CONFIG_IP_NF_IPTABLES=y -CONFIG_IP_NF_MATCH_AH=y -CONFIG_IP_NF_MATCH_ECN=y -CONFIG_IP_NF_MATCH_RPFILTER=y -CONFIG_IP_NF_MATCH_TTL=y -CONFIG_IP_NF_FILTER=y -CONFIG_IP_NF_TARGET_REJECT=y -CONFIG_IP_NF_TARGET_SYNPROXY=y -CONFIG_IP_NF_NAT=y -CONFIG_IP_NF_TARGET_MASQUERADE=y -CONFIG_IP_NF_TARGET_NETMAP=y -CONFIG_IP_NF_TARGET_REDIRECT=y -CONFIG_IP_NF_MANGLE=y -CONFIG_IP_NF_TARGET_ECN=y -CONFIG_IP_NF_TARGET_TTL=y -CONFIG_IP_NF_RAW=y -CONFIG_IP_NF_SECURITY=y -CONFIG_IP_NF_ARPFILTER=y -CONFIG_IP_NF_ARP_MANGLE=y -CONFIG_NFT_DUP_IPV6=y -CONFIG_NFT_FIB_IPV6=y -CONFIG_IP6_NF_IPTABLES=y -CONFIG_IP6_NF_MATCH_AH=y -CONFIG_IP6_NF_MATCH_EUI64=y -CONFIG_IP6_NF_MATCH_FRAG=y -CONFIG_IP6_NF_MATCH_OPTS=y -CONFIG_IP6_NF_MATCH_HL=y -CONFIG_IP6_NF_MATCH_IPV6HEADER=y -CONFIG_IP6_NF_MATCH_MH=y -CONFIG_IP6_NF_MATCH_RPFILTER=y -CONFIG_IP6_NF_MATCH_RT=y -CONFIG_IP6_NF_MATCH_SRH=y -CONFIG_IP6_NF_TARGET_HL=y -CONFIG_IP6_NF_FILTER=y -CONFIG_IP6_NF_TARGET_REJECT=y -CONFIG_IP6_NF_TARGET_SYNPROXY=y -CONFIG_IP6_NF_MANGLE=y -CONFIG_IP6_NF_RAW=y -CONFIG_IP6_NF_SECURITY=y -CONFIG_IP6_NF_NAT=y -CONFIG_IP6_NF_TARGET_MASQUERADE=y -CONFIG_IP6_NF_TARGET_NPT=y -CONFIG_NF_TABLES_BRIDGE=y -CONFIG_NF_CONNTRACK_BRIDGE=y -CONFIG_BRIDGE_NF_EBTABLES=y -CONFIG_BRIDGE_EBT_BROUTE=y -CONFIG_BRIDGE_EBT_T_FILTER=y -CONFIG_BRIDGE_EBT_T_NAT=y -CONFIG_BRIDGE_EBT_802_3=y -CONFIG_BRIDGE_EBT_AMONG=y -CONFIG_BRIDGE_EBT_ARP=y -CONFIG_BRIDGE_EBT_IP=y -CONFIG_BRIDGE_EBT_IP6=y -CONFIG_BRIDGE_EBT_LIMIT=y -CONFIG_BRIDGE_EBT_MARK=y -CONFIG_BRIDGE_EBT_PKTTYPE=y -CONFIG_BRIDGE_EBT_STP=y -CONFIG_BRIDGE_EBT_VLAN=y -CONFIG_BRIDGE_EBT_ARPREPLY=y -CONFIG_BRIDGE_EBT_DNAT=y -CONFIG_BRIDGE_EBT_MARK_T=y -CONFIG_BRIDGE_EBT_REDIRECT=y -CONFIG_BRIDGE_EBT_SNAT=y -CONFIG_BRIDGE_EBT_LOG=y -CONFIG_BRIDGE_EBT_NFLOG=y -CONFIG_BRIDGE=y -CONFIG_BRIDGE_VLAN_FILTERING=y -CONFIG_VLAN_8021Q=y -CONFIG_VLAN_8021Q_GVRP=y -CONFIG_VLAN_8021Q_MVRP=y -CONFIG_NET_SCHED=y -CONFIG_NET_SCH_FQ_CODEL=y -CONFIG_NET_SCH_DEFAULT=y -CONFIG_DEFAULT_FQ_CODEL=y -CONFIG_NET_EMATCH=y -CONFIG_NET_CLS_ACT=y -CONFIG_NET_ACT_GATE=y -CONFIG_NET_TC_SKB_EXT=y -CONFIG_NET_SWITCHDEV=y -CONFIG_QRTR_SMD=y -CONFIG_QRTR_TUN=y -CONFIG_BT=y -CONFIG_BT_RFCOMM=y -CONFIG_BT_RFCOMM_TTY=y -CONFIG_BT_BNEP=y -CONFIG_BT_BNEP_MC_FILTER=y -CONFIG_BT_BNEP_PROTO_FILTER=y -CONFIG_BT_HIDP=y -CONFIG_BT_LEDS=y -CONFIG_BT_MSFTEXT=y -CONFIG_BT_AOSPEXT=y -CONFIG_BT_HCIUART=y -CONFIG_BT_HCIUART_QCA=y -CONFIG_CFG80211=y -CONFIG_MAC80211=y -CONFIG_MAC80211_LEDS=y -CONFIG_RFKILL=y -CONFIG_NFC=y -CONFIG_NFC_NCI=y -CONFIG_PAGE_POOL_STATS=y -CONFIG_PCI=y -CONFIG_PCIEPORTBUS=y -CONFIG_PCIEAER=y -CONFIG_PCIEASPM_POWER_SUPERSAVE=y -CONFIG_PCIE_QCOM=y -CONFIG_PCI_PWRCTL_PWRSEQ=y -CONFIG_DEVTMPFS=y -CONFIG_DEVTMPFS_MOUNT=y -CONFIG_DEVTMPFS_SAFE=y -CONFIG_FW_LOADER_COMPRESS=y -CONFIG_FW_LOADER_COMPRESS_ZSTD=y -CONFIG_FW_UPLOAD=y -# CONFIG_QCOM_EBI2 is not set -CONFIG_MHI_BUS_DEBUG=y -CONFIG_MHI_BUS_PCI_GENERIC=y -CONFIG_ARM_SCMI_PROTOCOL=y -CONFIG_ARM_SCMI_POWER_CONTROL=y -CONFIG_ARM_SCPI_PROTOCOL=y -CONFIG_DMI_SYSFS=y -CONFIG_SYSFB_SIMPLEFB=y -CONFIG_EFI_CAPSULE_LOADER=y -CONFIG_QCOM_QSEECOM=y -# CONFIG_ARM_SMCCC_SOC_ID is not set -CONFIG_OF_OVERLAY=y -CONFIG_ZRAM=y -CONFIG_ZRAM_DEF_COMP_ZSTD=y -CONFIG_ZRAM_WRITEBACK=y -CONFIG_ZRAM_MULTI_COMP=y -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_NBD=y -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_COUNT=0 -CONFIG_VIRTIO_BLK=y -CONFIG_QCOM_COINCELL=y -CONFIG_QCOM_FASTRPC=y -CONFIG_SRAM=y -CONFIG_EEPROM_AT24=y -CONFIG_EEPROM_AT25=y -CONFIG_UACCE=y -CONFIG_RAID_ATTRS=y -CONFIG_SCSI=y -CONFIG_BLK_DEV_SD=y -CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y -CONFIG_SCSI_SCAN_ASYNC=y -CONFIG_SCSI_SAS_LIBSAS=y -CONFIG_MD=y -# CONFIG_MD_AUTODETECT is not set -CONFIG_MD_CLUSTER=y -CONFIG_BCACHE=y -CONFIG_BCACHE_ASYNC_REGISTRATION=y -CONFIG_BLK_DEV_DM=y -CONFIG_DM_DEBUG_BLOCK_MANAGER_LOCKING=y -CONFIG_DM_UNSTRIPED=y -CONFIG_DM_CRYPT=y -CONFIG_DM_SNAPSHOT=y -CONFIG_DM_THIN_PROVISIONING=y -CONFIG_DM_CACHE=y -CONFIG_DM_WRITECACHE=y -CONFIG_DM_EBS=y -CONFIG_DM_ERA=y -CONFIG_DM_CLONE=y -CONFIG_DM_MIRROR=y -CONFIG_DM_LOG_USERSPACE=y -CONFIG_DM_RAID=y -CONFIG_DM_ZERO=y -CONFIG_DM_MULTIPATH=y -CONFIG_DM_MULTIPATH_QL=y -CONFIG_DM_MULTIPATH_ST=y -CONFIG_DM_MULTIPATH_HST=y -CONFIG_DM_MULTIPATH_IOA=y -CONFIG_DM_DELAY=y -CONFIG_DM_DUST=y -CONFIG_DM_INIT=y -CONFIG_DM_UEVENT=y -CONFIG_DM_FLAKEY=y -CONFIG_DM_VERITY=y -CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG=y -CONFIG_DM_VERITY_FEC=y -CONFIG_DM_SWITCH=y -CONFIG_DM_LOG_WRITES=y -CONFIG_DM_INTEGRITY=y -CONFIG_DM_ZONED=y -CONFIG_DM_VDO=y -CONFIG_TARGET_CORE=y -CONFIG_TCM_IBLOCK=y -CONFIG_TCM_PSCSI=y -CONFIG_NETDEVICES=y -CONFIG_MACVLAN=y -CONFIG_MACVTAP=y -CONFIG_TUN=y -CONFIG_VETH=y -CONFIG_VIRTIO_NET=y -CONFIG_MHI_NET=y -# CONFIG_NET_VENDOR_3COM is not set -# CONFIG_NET_VENDOR_ADAPTEC is not set -# CONFIG_NET_VENDOR_AGERE is not set -# CONFIG_NET_VENDOR_ALACRITECH is not set -# CONFIG_NET_VENDOR_ALTEON is not set -# CONFIG_NET_VENDOR_AMAZON is not set -# CONFIG_NET_VENDOR_AMD is not set -# CONFIG_NET_VENDOR_AQUANTIA is not set -# CONFIG_NET_VENDOR_ARC is not set -# CONFIG_NET_VENDOR_ASIX is not set -# CONFIG_NET_VENDOR_ATHEROS is not set -# CONFIG_NET_VENDOR_BROADCOM is not set -# CONFIG_NET_VENDOR_CADENCE is not set -# CONFIG_NET_VENDOR_CAVIUM is not set -# CONFIG_NET_VENDOR_CHELSIO is not set -# CONFIG_NET_VENDOR_CISCO is not set -# CONFIG_NET_VENDOR_CORTINA is not set -# CONFIG_NET_VENDOR_DAVICOM is not set -# CONFIG_NET_VENDOR_DEC is not set -# CONFIG_NET_VENDOR_DLINK is not set -# CONFIG_NET_VENDOR_EMULEX is not set -# CONFIG_NET_VENDOR_ENGLEDER is not set -# CONFIG_NET_VENDOR_EZCHIP is not set -# CONFIG_NET_VENDOR_FUNGIBLE is not set -# CONFIG_NET_VENDOR_GOOGLE is not set -# CONFIG_NET_VENDOR_HISILICON is not set -# CONFIG_NET_VENDOR_HUAWEI is not set -# CONFIG_NET_VENDOR_INTEL is not set -# CONFIG_NET_VENDOR_ADI is not set -# CONFIG_NET_VENDOR_LITEX is not set -# CONFIG_NET_VENDOR_MARVELL is not set -# CONFIG_NET_VENDOR_MELLANOX is not set -# CONFIG_NET_VENDOR_MICREL is not set -# CONFIG_NET_VENDOR_MICROCHIP is not set -# CONFIG_NET_VENDOR_MICROSEMI is not set -# CONFIG_NET_VENDOR_MICROSOFT is not set -# CONFIG_NET_VENDOR_MYRI is not set -# CONFIG_NET_VENDOR_NI is not set -# CONFIG_NET_VENDOR_NATSEMI is not set -# CONFIG_NET_VENDOR_NETERION is not set -# CONFIG_NET_VENDOR_NETRONOME is not set -# CONFIG_NET_VENDOR_NVIDIA is not set -# CONFIG_NET_VENDOR_OKI is not set -# CONFIG_NET_VENDOR_PACKET_ENGINES is not set -# CONFIG_NET_VENDOR_PENSANDO is not set -# CONFIG_NET_VENDOR_QLOGIC is not set -# CONFIG_NET_VENDOR_BROCADE is not set -# CONFIG_NET_VENDOR_QUALCOMM is not set -# CONFIG_NET_VENDOR_RDC is not set -CONFIG_R8169=y -# CONFIG_NET_VENDOR_RENESAS is not set -# CONFIG_NET_VENDOR_ROCKER is not set -# CONFIG_NET_VENDOR_SAMSUNG is not set -# CONFIG_NET_VENDOR_SEEQ is not set -# CONFIG_NET_VENDOR_SILAN is not set -# CONFIG_NET_VENDOR_SIS is not set -# CONFIG_NET_VENDOR_SOLARFLARE is not set -# CONFIG_NET_VENDOR_SMSC is not set -# CONFIG_NET_VENDOR_SOCIONEXT is not set -# CONFIG_NET_VENDOR_STMICRO is not set -# CONFIG_NET_VENDOR_SUN is not set -# CONFIG_NET_VENDOR_SYNOPSYS is not set -# CONFIG_NET_VENDOR_TEHUTI is not set -# CONFIG_NET_VENDOR_TI is not set -# CONFIG_NET_VENDOR_VERTEXCOM is not set -# CONFIG_NET_VENDOR_VIA is not set -# CONFIG_NET_VENDOR_WANGXUN is not set -# CONFIG_NET_VENDOR_WIZNET is not set -# CONFIG_NET_VENDOR_XILINX is not set -CONFIG_QCOM_IPA=y -CONFIG_USB_RTL8152=y -CONFIG_USB_USBNET=y -# CONFIG_USB_NET_AX8817X is not set -# CONFIG_USB_NET_AX88179_178A is not set -CONFIG_USB_NET_CDC_EEM=y -CONFIG_USB_NET_SMSC95XX=y -# CONFIG_USB_NET_NET1080 is not set -CONFIG_USB_NET_RNDIS_HOST=y -# CONFIG_USB_NET_CDC_SUBSET is not set -# CONFIG_USB_NET_ZAURUS is not set -# CONFIG_WLAN_VENDOR_ADMTEK is not set -CONFIG_ATH12K=y -# CONFIG_WLAN_VENDOR_ATMEL is not set -# CONFIG_WLAN_VENDOR_BROADCOM is not set -# CONFIG_WLAN_VENDOR_INTEL is not set -# CONFIG_WLAN_VENDOR_INTERSIL is not set -# CONFIG_WLAN_VENDOR_MARVELL is not set -# CONFIG_WLAN_VENDOR_MEDIATEK is not set -# CONFIG_WLAN_VENDOR_MICROCHIP is not set -# CONFIG_WLAN_VENDOR_PURELIFI is not set -# CONFIG_WLAN_VENDOR_RALINK is not set -# CONFIG_RTL_CARDS is not set -CONFIG_RTW88=y -CONFIG_RTW88_8821CU=y -# CONFIG_WLAN_VENDOR_RSI is not set -# CONFIG_WLAN_VENDOR_SILABS is not set -# CONFIG_WLAN_VENDOR_ST is not set -# CONFIG_WLAN_VENDOR_TI is not set -# CONFIG_WLAN_VENDOR_ZYDAS is not set -# CONFIG_WLAN_VENDOR_QUANTENNA is not set -CONFIG_WWAN=y -CONFIG_MHI_WWAN_CTRL=y -CONFIG_MHI_WWAN_MBIM=y -CONFIG_INPUT_MATRIXKMAP=y -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1920 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=1080 -CONFIG_INPUT_JOYDEV=y -CONFIG_INPUT_EVDEV=y -CONFIG_KEYBOARD_ADC=y -CONFIG_KEYBOARD_GPIO=y -CONFIG_MOUSE_ELAN_I2C=y -CONFIG_INPUT_JOYSTICK=y -CONFIG_JOYSTICK_ODIN2=y -CONFIG_INPUT_TOUCHSCREEN=y -CONFIG_TOUCHSCREEN_ATMEL_MXT=y -CONFIG_TOUCHSCREEN_GOODIX=y -CONFIG_TOUCHSCREEN_ELAN=y -CONFIG_TOUCHSCREEN_EDT_FT5X06=y -CONFIG_INPUT_MISC=y -CONFIG_INPUT_PM8941_PWRKEY=y -CONFIG_RMI4_I2C=y -CONFIG_RMI4_F3A=y -CONFIG_RMI4_F54=y -# CONFIG_SERIO_SERPORT is not set -CONFIG_SERIO_AMBAKMI=y -# CONFIG_LEGACY_PTYS is not set -CONFIG_SERIAL_8250=y -# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set -CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_8250_EXTENDED=y -CONFIG_SERIAL_8250_SHARE_IRQ=y -CONFIG_SERIAL_8250_DW=y -CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_SERIAL_AMBA_PL011=y -CONFIG_SERIAL_AMBA_PL011_CONSOLE=y -CONFIG_SERIAL_MSM=y -CONFIG_SERIAL_MSM_CONSOLE=y -CONFIG_SERIAL_QCOM_GENI=y -CONFIG_SERIAL_QCOM_GENI_CONSOLE=y -CONFIG_RPMSG_TTY=y -CONFIG_SERIAL_DEV_BUS=y -CONFIG_VIRTIO_CONSOLE=y -CONFIG_HW_RANDOM=y -CONFIG_HW_RANDOM_VIRTIO=y -CONFIG_TCG_TIS=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_MUX_PCA954x=y -CONFIG_I2C_GPIO=y -CONFIG_I2C_QCOM_GENI=y -CONFIG_I2C_SLAVE=y -CONFIG_SPI=y -CONFIG_SPI_MEM=y -CONFIG_SPI_CADENCE_QUADSPI=y -CONFIG_SPI_PL022=y -CONFIG_SPI_QCOM_QSPI=y -CONFIG_SPI_QUP=y -CONFIG_SPI_QCOM_GENI=y -CONFIG_SPI_SPIDEV=y -CONFIG_SPMI=y -# CONFIG_PTP_1588_CLOCK_KVM is not set -CONFIG_PINCTRL_SINGLE=y -CONFIG_PINCTRL_MSM=y -CONFIG_PINCTRL_SDM845=y -CONFIG_PINCTRL_SM8250=y -CONFIG_PINCTRL_SM8350=y -CONFIG_PINCTRL_SM8450=y -CONFIG_PINCTRL_SM8550=y -CONFIG_PINCTRL_QCOM_SPMI_PMIC=y -CONFIG_PINCTRL_LPASS_LPI=y -CONFIG_PINCTRL_SM8250_LPASS_LPI=y -CONFIG_PINCTRL_SM8350_LPASS_LPI=y -CONFIG_PINCTRL_SM8550_LPASS_LPI=y -CONFIG_GPIO_SYSFS=y -CONFIG_GPIO_ALTERA=y -CONFIG_GPIO_DWAPB=y -CONFIG_GPIO_GENERIC_PLATFORM=y -CONFIG_GPIO_WCD934X=y -CONFIG_GPIO_XGENE=y -CONFIG_GPIO_MAX732X=y -CONFIG_GPIO_PCA953X=y -CONFIG_GPIO_PCA953X_IRQ=y -CONFIG_POWER_RESET_MSM=y -CONFIG_POWER_RESET_QCOM_PON=y -CONFIG_POWER_RESET_SYSCON=y -CONFIG_SYSCON_REBOOT_MODE=y -CONFIG_NVMEM_REBOOT_MODE=y -CONFIG_POWER_SEQUENCING_QCOM_WCN=y -CONFIG_BATTERY_QCOM_BATTMGR=y -CONFIG_BATTERY_SBS=y -CONFIG_SENSORS_ARM_SCMI=y -CONFIG_SENSORS_ARM_SCPI=y -CONFIG_SENSORS_GPIO_FAN=y -CONFIG_SENSORS_JC42=y -CONFIG_SENSORS_LM75=y -CONFIG_SENSORS_LM90=y -CONFIG_SENSORS_PWM_FAN=y -CONFIG_SENSORS_INA2XX=y -CONFIG_SENSORS_INA3221=y -CONFIG_THERMAL=y -CONFIG_THERMAL_NETLINK=y -CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y -CONFIG_CPU_THERMAL=y -CONFIG_DEVFREQ_THERMAL=y -CONFIG_THERMAL_EMULATION=y -CONFIG_GENERIC_ADC_THERMAL=y -CONFIG_QCOM_TSENS=y -CONFIG_QCOM_SPMI_ADC_TM5=y -CONFIG_QCOM_SPMI_TEMP_ALARM=y -CONFIG_QCOM_LMH=y -CONFIG_WATCHDOG=y -CONFIG_WATCHDOG_SYSFS=y -CONFIG_ARM_SP805_WATCHDOG=y -CONFIG_ARM_SBSA_WATCHDOG=y -CONFIG_DW_WATCHDOG=y -CONFIG_QCOM_WDT=y -CONFIG_ARM_SMC_WATCHDOG=y -CONFIG_PM8916_WATCHDOG=y -CONFIG_MFD_AXP20X_I2C=y -CONFIG_MFD_SPMI_PMIC=y -CONFIG_MFD_RK8XX_I2C=y -CONFIG_MFD_RK8XX_SPI=y -CONFIG_MFD_WCD934X=y -CONFIG_REGULATOR_FIXED_VOLTAGE=y -CONFIG_REGULATOR_VIRTUAL_CONSUMER=y -CONFIG_REGULATOR_USERSPACE_CONSUMER=y -CONFIG_REGULATOR_GPIO=y -CONFIG_REGULATOR_PWM=y -CONFIG_REGULATOR_QCOM_REFGEN=y -CONFIG_REGULATOR_QCOM_RPMH=y -CONFIG_REGULATOR_QCOM_SMD_RPM=y -CONFIG_REGULATOR_QCOM_SPMI=y -CONFIG_REGULATOR_QCOM_USB_VBUS=y -CONFIG_REGULATOR_VCTRL=y -CONFIG_REGULATOR_QCOM_LABIBB=y -CONFIG_RC_CORE=y -CONFIG_LIRC=y -# CONFIG_RC_MAP is not set -CONFIG_RC_DECODERS=y -CONFIG_RC_DEVICES=y -CONFIG_IR_SPI=y -CONFIG_MEDIA_SUPPORT=y -CONFIG_MEDIA_SUPPORT_FILTER=y -CONFIG_MEDIA_CAMERA_SUPPORT=y -CONFIG_MEDIA_PLATFORM_SUPPORT=y -CONFIG_VIDEO_ADV_DEBUG=y -CONFIG_MEDIA_USB_SUPPORT=y -CONFIG_USB_VIDEO_CLASS=y -CONFIG_V4L_PLATFORM_DRIVERS=y -CONFIG_V4L_MEM2MEM_DRIVERS=y -CONFIG_VIDEO_MEM2MEM_DEINTERLACE=y -CONFIG_VIDEO_MUX=y -CONFIG_DRM=y -CONFIG_DRM_LOAD_EDID_FIRMWARE=y -CONFIG_DRM_DP_AUX_CHARDEV=y -CONFIG_DRM_DP_CEC=y -CONFIG_DRM_MSM=y -# CONFIG_DRM_MSM_MDP4 is not set -# CONFIG_DRM_MSM_MDP5 is not set -# CONFIG_DRM_MSM_DSI_28NM_PHY is not set -# CONFIG_DRM_MSM_DSI_20NM_PHY is not set -# CONFIG_DRM_MSM_DSI_28NM_8960_PHY is not set -# CONFIG_DRM_MSM_DSI_14NM_PHY is not set -# CONFIG_DRM_MSM_HDMI is not set -CONFIG_DRM_PANEL_NOVATEK_NT36523=y -CONFIG_DRM_PANEL_EDP=y -CONFIG_DRM_PANEL_SIMPLE=y -CONFIG_DRM_PANEL_SYNAPTICS_TD4328=y -CONFIG_DRM_PANEL_VISIONOX_R66451=y -CONFIG_DRM_DISPLAY_CONNECTOR=y -CONFIG_DRM_LONTIUM_LT8912B=y -CONFIG_DRM_LONTIUM_LT9611=y -CONFIG_DRM_SIMPLE_BRIDGE=y -CONFIG_DRM_SIMPLEDRM=y -CONFIG_FB=y -CONFIG_FB_EFI=y -CONFIG_FB_MODE_HELPERS=y -CONFIG_BACKLIGHT_CLASS_DEVICE=y -CONFIG_BACKLIGHT_KTZ8866=y -CONFIG_BACKLIGHT_PWM=y -CONFIG_BACKLIGHT_QCOM_WLED=y -CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION=y -CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y -CONFIG_LOGO=y -# CONFIG_LOGO_LINUX_MONO is not set -# CONFIG_LOGO_LINUX_VGA16 is not set -CONFIG_SOUND=y -CONFIG_SND=y -# CONFIG_SND_SUPPORT_OLD_API is not set -CONFIG_SND_VERBOSE_PRINTK=y -# CONFIG_SND_SPI is not set -CONFIG_SND_USB_AUDIO=y -CONFIG_SND_USB_AUDIO_MIDI_V2=y -CONFIG_SND_SOC=y -CONFIG_SND_SOC_QCOM=y -CONFIG_SND_SOC_SC8280XP=y -CONFIG_SND_SOC_SOF_TOPLEVEL=y -CONFIG_SND_SOC_SOF_OF=y -CONFIG_SND_SOC_SIMPLE_AMPLIFIER=y -CONFIG_SND_SOC_SIMPLE_MUX=y -CONFIG_SND_SOC_WCD938X_SDW=y -CONFIG_SND_SOC_LPASS_WSA_MACRO=y -CONFIG_SND_SOC_LPASS_VA_MACRO=y -CONFIG_SND_SOC_LPASS_RX_MACRO=y -CONFIG_SND_SOC_LPASS_TX_MACRO=y -CONFIG_SND_SIMPLE_CARD=y -CONFIG_SND_AUDIO_GRAPH_CARD=y -CONFIG_SND_AUDIO_GRAPH_CARD2=y -CONFIG_HID_BATTERY_STRENGTH=y -CONFIG_HIDRAW=y -CONFIG_UHID=y -CONFIG_HID_A4TECH=y -CONFIG_HID_APPLE=y -CONFIG_HID_BELKIN=y -CONFIG_HID_CHERRY=y -CONFIG_HID_CHICONY=y -CONFIG_HID_CYPRESS=y -CONFIG_HID_EZKEY=y -CONFIG_HID_ITE=y -CONFIG_HID_KENSINGTON=y -CONFIG_HID_LOGITECH=y -CONFIG_HID_LOGITECH_DJ=y -CONFIG_LOGITECH_FF=y -CONFIG_LOGIRUMBLEPAD2_FF=y -CONFIG_LOGIG940_FF=y -CONFIG_HID_REDRAGON=y -CONFIG_HID_MICROSOFT=y -CONFIG_HID_MONTEREY=y -CONFIG_HID_MULTITOUCH=y -CONFIG_HID_NINTENDO=y -CONFIG_NINTENDO_FF=y -CONFIG_HID_RMI=y -CONFIG_HID_PID=y -CONFIG_USB_HIDDEV=y -CONFIG_I2C_HID_OF=y -CONFIG_USB_ULPI_BUS=y -CONFIG_USB_CONN_GPIO=y -CONFIG_USB=y -CONFIG_USB_ANNOUNCE_NEW_DEVICES=y -CONFIG_USB_OTG=y -CONFIG_USB_MON=y -CONFIG_USB_XHCI_HCD=y -CONFIG_USB_EHCI_HCD=y -CONFIG_USB_EHCI_ROOT_HUB_TT=y -CONFIG_USB_EHCI_HCD_PLATFORM=y -CONFIG_USB_OHCI_HCD=y -CONFIG_USB_OHCI_HCD_PLATFORM=y -CONFIG_USB_ACM=y -CONFIG_USB_STORAGE=y -CONFIG_USB_UAS=y -CONFIG_USB_DWC3=y -CONFIG_USB_DWC3_ULPI=y -# CONFIG_USB_DWC3_HAPS is not set -CONFIG_USB_SERIAL=y -CONFIG_USB_SERIAL_CONSOLE=y -CONFIG_USB_SERIAL_GENERIC=y -CONFIG_USB_SERIAL_SIMPLE=y -CONFIG_USB_SERIAL_CH341=y -CONFIG_USB_SERIAL_CP210X=y -CONFIG_USB_SERIAL_FTDI_SIO=y -CONFIG_USB_SERIAL_OPTION=y -CONFIG_USB_ONBOARD_HUB=y -CONFIG_NOP_USB_XCEIV=y -CONFIG_USB_ULPI=y -CONFIG_USB_GADGET=y -CONFIG_USB_CONFIGFS=y -CONFIG_USB_CONFIGFS_SERIAL=y -CONFIG_USB_CONFIGFS_ACM=y -CONFIG_USB_CONFIGFS_OBEX=y -CONFIG_USB_CONFIGFS_NCM=y -CONFIG_USB_CONFIGFS_ECM=y -CONFIG_USB_CONFIGFS_ECM_SUBSET=y -CONFIG_USB_CONFIGFS_RNDIS=y -CONFIG_USB_CONFIGFS_EEM=y -CONFIG_USB_CONFIGFS_MASS_STORAGE=y -CONFIG_USB_CONFIGFS_F_FS=y -CONFIG_USB_CONFIGFS_F_HID=y -CONFIG_USB_CONFIGFS_F_TCM=y -CONFIG_TYPEC=y -CONFIG_TYPEC_TCPM=y -CONFIG_TYPEC_QCOM_PMIC=y -CONFIG_TYPEC_UCSI=y -CONFIG_UCSI_PMIC_GLINK=y -CONFIG_TYPEC_MUX_FSA4480=y -CONFIG_TYPEC_MUX_GPIO_SBU=y -CONFIG_TYPEC_MUX_NB7VPQ904M=y -CONFIG_TYPEC_DP_ALTMODE=y -CONFIG_MMC=y -CONFIG_MMC_CRYPTO=y -CONFIG_MMC_SDHCI=y -CONFIG_MMC_SDHCI_PLTFM=y -CONFIG_MMC_SDHCI_MSM=y -CONFIG_MMC_SDHCI_MSM_DOWNSTREAM=y -CONFIG_MMC_HSQ=y -CONFIG_SCSI_UFSHCD=y -CONFIG_SCSI_UFS_BSG=y -CONFIG_SCSI_UFS_CRYPTO=y -CONFIG_SCSI_UFS_HWMON=y -CONFIG_SCSI_UFSHCD_PLATFORM=y -CONFIG_SCSI_UFS_QCOM=y -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y -CONFIG_LEDS_CLASS_MULTICOLOR=y -CONFIG_LEDS_LM3692X=y -CONFIG_LEDS_PCA9532=y -CONFIG_LEDS_GPIO=y -CONFIG_LEDS_PWM=y -CONFIG_LEDS_SYSCON=y -CONFIG_LEDS_PWM_MULTICOLOR=y -CONFIG_LEDS_QCOM_LPG=y -CONFIG_LEDS_TRIGGER_TIMER=y -CONFIG_LEDS_TRIGGER_HEARTBEAT=y -CONFIG_LEDS_TRIGGER_CPU=y -CONFIG_LEDS_TRIGGER_DEFAULT_ON=y -CONFIG_LEDS_TRIGGER_PANIC=y -CONFIG_EDAC=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_EFI=y -CONFIG_RTC_DRV_PM8XXX=y -CONFIG_DMADEVICES=y -CONFIG_FSL_EDMA=y -CONFIG_MV_XOR_V2=y -CONFIG_PL330_DMA=y -CONFIG_QCOM_BAM_DMA=y -CONFIG_QCOM_GPI_DMA=y -CONFIG_QCOM_HIDMA_MGMT=y -CONFIG_QCOM_HIDMA=y -CONFIG_UDMABUF=y -CONFIG_DMABUF_HEAPS=y -CONFIG_DMABUF_HEAPS_SYSTEM=y -CONFIG_DMABUF_HEAPS_CMA=y -CONFIG_VFIO=y -CONFIG_VIRT_DRIVERS=y -# CONFIG_VIRTIO_MENU is not set -# CONFIG_VHOST_MENU is not set -CONFIG_STAGING=y -# CONFIG_SURFACE_PLATFORMS is not set -CONFIG_COMMON_CLK_SCMI=y -CONFIG_COMMON_CLK_SCPI=y -CONFIG_COMMON_CLK_PWM=y -CONFIG_COMMON_CLK_QCOM=y -CONFIG_QCOM_CLK_RPMH=y -CONFIG_SM_CAMCC_8550=y -CONFIG_SM_DISPCC_8550=y -CONFIG_SM_GPUCC_8550=y -CONFIG_SM_TCSRCC_8550=y -CONFIG_SM_VIDEOCC_8550=y -CONFIG_SPMI_PMIC_CLKDIV=y -CONFIG_HWSPINLOCK=y -CONFIG_HWSPINLOCK_QCOM=y -CONFIG_MAILBOX=y -CONFIG_QCOM_APCS_IPC=y -CONFIG_QCOM_IPCC=y -CONFIG_IOMMU_IO_PGTABLE_ARMV7S=y -CONFIG_ARM_SMMU=y -CONFIG_ARM_SMMU_V3=y -CONFIG_QCOM_IOMMU=y -CONFIG_REMOTEPROC=y -CONFIG_REMOTEPROC_CDEV=y -CONFIG_QCOM_Q6V5_ADSP=y -CONFIG_QCOM_Q6V5_MSS=y -CONFIG_QCOM_Q6V5_PAS=y -CONFIG_QCOM_SYSMON=y -CONFIG_QCOM_WCNSS_PIL=y -CONFIG_RPMSG_CHAR=y -CONFIG_RPMSG_CTRL=y -CONFIG_RPMSG_NS=y -CONFIG_RPMSG_QCOM_GLINK_RPM=y -CONFIG_RPMSG_QCOM_GLINK_SMEM=y -CONFIG_RPMSG_QCOM_SMD=y -CONFIG_SOUNDWIRE=y -CONFIG_SOUNDWIRE_QCOM=y -CONFIG_QCOM_AOSS_QMP=y -CONFIG_QCOM_COMMAND_DB=y -CONFIG_QCOM_GENI_SE=y -CONFIG_QCOM_LLCC=y -CONFIG_QCOM_OCMEM=y -CONFIG_QCOM_PMIC_GLINK=y -CONFIG_QCOM_RMTFS_MEM=y -CONFIG_QCOM_RPMH=y -CONFIG_QCOM_SMEM=y -CONFIG_QCOM_SMD_RPM=y -CONFIG_QCOM_SMP2P=y -CONFIG_QCOM_SMSM=y -CONFIG_QCOM_SOCINFO=y -CONFIG_QCOM_SPM=y -CONFIG_QCOM_STATS=y -CONFIG_QCOM_APR=y -CONFIG_QCOM_ICC_BWMON=y -CONFIG_QCOM_PBS=y -CONFIG_QCOM_CPR=y -CONFIG_QCOM_RPMHPD=y -CONFIG_QCOM_RPMPD=y -CONFIG_DEVFREQ_GOV_PERFORMANCE=y -CONFIG_DEVFREQ_GOV_USERSPACE=y -CONFIG_DEVFREQ_GOV_PASSIVE=y -CONFIG_PM_DEVFREQ_EVENT=y -CONFIG_EXTCON_QCOM_SPMI_MISC=y -CONFIG_EXTCON_USB_GPIO=y -CONFIG_MEMORY=y -CONFIG_IIO=y -CONFIG_IIO_BUFFER_CB=y -CONFIG_IIO_BUFFER_DMAENGINE=y -CONFIG_IIO_BUFFER_HW_CONSUMER=y -CONFIG_IIO_CONFIGFS=y -CONFIG_MAX9611=y -CONFIG_QCOM_SPMI_RRADC=y -CONFIG_QCOM_SPMI_IADC=y -CONFIG_QCOM_SPMI_VADC=y -CONFIG_QCOM_SPMI_ADC5=y -CONFIG_TI_ADS1015=y -CONFIG_MPL3115=y -CONFIG_PWM=y -CONFIG_PWM_SN3112=y -CONFIG_QCOM_PDC=y -CONFIG_QCOM_MPM=y -CONFIG_RESET_QCOM_AOSS=y -CONFIG_RESET_QCOM_PDC=y -CONFIG_PHY_QCOM_QMP=y -# CONFIG_PHY_QCOM_QMP_PCIE_8996 is not set -CONFIG_PHY_QCOM_SNPS_EUSB2=y -CONFIG_PHY_QCOM_EUSB2_REPEATER=y -CONFIG_ARM_SMMU_V3_PMU=y -CONFIG_ARM_SPE_PMU=y -CONFIG_ANDROID_BINDER_IPC=y -CONFIG_ANDROID_BINDERFS=y -CONFIG_NVMEM_QCOM_QFPROM=y -CONFIG_NVMEM_RMEM=y -CONFIG_NVMEM_SPMI_SDAM=y -CONFIG_TEE=y -CONFIG_SLIM_QCOM_CTRL=y -CONFIG_SLIM_QCOM_NGD_CTRL=y -CONFIG_INTERCONNECT=y -CONFIG_INTERCONNECT_QCOM=y -CONFIG_INTERCONNECT_QCOM_OSM_L3=y -CONFIG_INTERCONNECT_QCOM_SM8550=y -CONFIG_COUNTER=y -CONFIG_VALIDATE_FS_PARSER=y -CONFIG_EXT4_FS=y -CONFIG_EXT4_FS_POSIX_ACL=y -CONFIG_EXT4_FS_SECURITY=y -CONFIG_BTRFS_FS=y -CONFIG_BTRFS_FS_POSIX_ACL=y -CONFIG_F2FS_FS=y -CONFIG_F2FS_FS_SECURITY=y -CONFIG_F2FS_CHECK_FS=y -CONFIG_F2FS_FS_COMPRESSION=y -CONFIG_F2FS_UNFAIR_RWSEM=y -CONFIG_FS_DAX=y -CONFIG_EXPORTFS_BLOCK_OPS=y -CONFIG_FS_ENCRYPTION=y -CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y -CONFIG_FS_VERITY=y -CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y -CONFIG_FANOTIFY=y -CONFIG_QUOTA=y -CONFIG_QUOTA_NETLINK_INTERFACE=y -CONFIG_AUTOFS_FS=y -CONFIG_FUSE_FS=y -CONFIG_CUSE=y -CONFIG_OVERLAY_FS=y -# CONFIG_OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW is not set -CONFIG_OVERLAY_FS_INDEX=y -CONFIG_OVERLAY_FS_XINO_AUTO=y -CONFIG_OVERLAY_FS_METACOPY=y -CONFIG_ISO9660_FS=y -CONFIG_JOLIET=y -CONFIG_ZISOFS=y -CONFIG_UDF_FS=y -CONFIG_VFAT_FS=y -CONFIG_EXFAT_FS=y -CONFIG_NTFS3_FS=y -CONFIG_NTFS3_LZX_XPRESS=y -CONFIG_PROC_KCORE=y -CONFIG_TMPFS_POSIX_ACL=y -CONFIG_TMPFS_INODE64=y -CONFIG_HUGETLBFS=y -CONFIG_EFIVAR_FS=y -CONFIG_SQUASHFS=y -CONFIG_SQUASHFS_FILE_DIRECT=y -CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT=y -CONFIG_SQUASHFS_XATTR=y -CONFIG_SQUASHFS_LZ4=y -CONFIG_SQUASHFS_LZO=y -CONFIG_SQUASHFS_XZ=y -CONFIG_SQUASHFS_ZSTD=y -CONFIG_PSTORE=y -CONFIG_PSTORE_CONSOLE=y -CONFIG_PSTORE_PMSG=y -CONFIG_PSTORE_RAM=y -CONFIG_EROFS_FS=y -CONFIG_EROFS_FS_ZIP_LZMA=y -CONFIG_EROFS_FS_ZIP_DEFLATE=y -CONFIG_EROFS_FS_PCPU_KTHREAD=y -CONFIG_NFS_FS=y -CONFIG_NFS_V4=y -CONFIG_NFS_V4_1=y -CONFIG_NFS_V4_2=y -CONFIG_ROOT_NFS=y -CONFIG_NLS_CODEPAGE_437=y -CONFIG_NLS_ISO8859_1=y -CONFIG_DLM=y -CONFIG_UNICODE=y -CONFIG_KEYS_REQUEST_CACHE=y -CONFIG_PERSISTENT_KEYRINGS=y -CONFIG_BIG_KEYS=y -CONFIG_TRUSTED_KEYS=y -CONFIG_KEY_DH_OPERATIONS=y -CONFIG_KEY_NOTIFICATIONS=y -CONFIG_SECURITY=y -CONFIG_HARDENED_USERCOPY=y -CONFIG_SECURITY_SELINUX=y -CONFIG_SECURITY_SELINUX_BOOTPARAM=y -CONFIG_SECURITY_YAMA=y -CONFIG_SECURITY_LANDLOCK=y -CONFIG_INTEGRITY_SIGNATURE=y -CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y -CONFIG_IMA=y -CONFIG_IMA_KEXEC=y -CONFIG_IMA_DEFAULT_HASH_SHA256=y -CONFIG_IMA_WRITE_POLICY=y -CONFIG_IMA_APPRAISE=y -CONFIG_IMA_ARCH_POLICY=y -CONFIG_EVM=y -CONFIG_LSM="lockdown,yama,integrity,selinux,bpf,landlock" -CONFIG_BUG_ON_DATA_CORRUPTION=y -CONFIG_CRYPTO_USER=y -CONFIG_CRYPTO_PCRYPT=y -CONFIG_CRYPTO_CRYPTD=y -CONFIG_CRYPTO_DH_RFC7919_GROUPS=y -CONFIG_CRYPTO_ECDSA=y -CONFIG_CRYPTO_SM2=y -CONFIG_CRYPTO_CURVE25519=y -CONFIG_CRYPTO_AES_TI=y -CONFIG_CRYPTO_BLOWFISH=y -CONFIG_CRYPTO_CAMELLIA=y -CONFIG_CRYPTO_CAST5=y -CONFIG_CRYPTO_CAST6=y -CONFIG_CRYPTO_DES=y -CONFIG_CRYPTO_FCRYPT=y -CONFIG_CRYPTO_KHAZAD=y -CONFIG_CRYPTO_SEED=y -CONFIG_CRYPTO_SERPENT=y -CONFIG_CRYPTO_SM4_GENERIC=y -CONFIG_CRYPTO_TWOFISH=y -# CONFIG_CRYPTO_CTS is not set -CONFIG_CRYPTO_SM3_GENERIC=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_ANSI_CPRNG=y -CONFIG_CRYPTO_DRBG_HASH=y -CONFIG_CRYPTO_DRBG_CTR=y -CONFIG_CRYPTO_USER_API_RNG=y -CONFIG_CRYPTO_NHPOLY1305_NEON=y -CONFIG_CRYPTO_CHACHA20_NEON=y -CONFIG_CRYPTO_GHASH_ARM64_CE=y -CONFIG_CRYPTO_POLY1305_NEON=y -CONFIG_CRYPTO_SHA1_ARM64_CE=y -CONFIG_CRYPTO_SHA2_ARM64_CE=y -CONFIG_CRYPTO_SHA512_ARM64_CE=y -CONFIG_CRYPTO_SHA3_ARM64=y -CONFIG_CRYPTO_SM3_NEON=y -CONFIG_CRYPTO_SM3_ARM64_CE=y -CONFIG_CRYPTO_POLYVAL_ARM64_CE=y -CONFIG_CRYPTO_AES_ARM64=y -CONFIG_CRYPTO_AES_ARM64_BS=y -CONFIG_CRYPTO_SM4_ARM64_CE=y -CONFIG_CRYPTO_SM4_ARM64_NEON_BLK=y -CONFIG_CRYPTO_AES_ARM64_CE_CCM=y -CONFIG_CRYPTO_SM4_ARM64_CE_CCM=y -CONFIG_CRYPTO_SM4_ARM64_CE_GCM=y -CONFIG_CRYPTO_CRCT10DIF_ARM64_CE=y -CONFIG_CRYPTO_DEV_QCE=y -CONFIG_CRYPTO_DEV_QCOM_RNG=y -CONFIG_SIGNED_PE_FILE_VERIFICATION=y -# CONFIG_RAID6_PQ_BENCHMARK is not set -CONFIG_CRYPTO_LIB_CURVE25519=y -CONFIG_CRYPTO_LIB_CHACHA20POLY1305=y -CONFIG_CRC_CCITT=y -CONFIG_CRC7=y -# CONFIG_XZ_DEC_X86 is not set -# CONFIG_XZ_DEC_POWERPC is not set -# CONFIG_XZ_DEC_SPARC is not set -CONFIG_DMA_CMA=y -CONFIG_DMA_NUMA_CMA=y -CONFIG_CMA_SIZE_MBYTES=64 -CONFIG_IRQ_POLL=y -CONFIG_PRINTK_TIME=y -CONFIG_CONSOLE_LOGLEVEL_QUIET=3 -CONFIG_BOOT_PRINTK_DELAY=y -CONFIG_DYNAMIC_DEBUG=y -# CONFIG_DEBUG_MISC is not set -CONFIG_DEBUG_INFO_DWARF5=y -CONFIG_DEBUG_INFO_BTF=y -CONFIG_STRIP_ASM_SYMS=y -CONFIG_HEADERS_INSTALL=y -CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x0 -CONFIG_KGDB=y -CONFIG_KGDB_TESTS=y -CONFIG_PAGE_OWNER=y -CONFIG_PAGE_POISONING=y -CONFIG_DEBUG_WX=y -CONFIG_SCHED_STACK_END_CHECK=y -CONFIG_DEBUG_MEMORY_INIT=y -CONFIG_KFENCE=y -CONFIG_DEBUG_SHIRQ=y -CONFIG_PANIC_TIMEOUT=10 -CONFIG_HARDLOCKUP_DETECTOR=y -# CONFIG_DETECT_HUNG_TASK is not set -CONFIG_DEBUG_LIST=y -CONFIG_RCU_CPU_STALL_TIMEOUT=60 -# CONFIG_RCU_TRACE is not set -CONFIG_LATENCYTOP=y -CONFIG_BOOTTIME_TRACING=y -CONFIG_FUNCTION_GRAPH_RETVAL=y -CONFIG_FUNCTION_PROFILER=y -CONFIG_STACK_TRACER=y -CONFIG_SCHED_TRACER=y -CONFIG_HWLAT_TRACER=y -CONFIG_TIMERLAT_TRACER=y -CONFIG_FTRACE_SYSCALLS=y -CONFIG_BLK_DEV_IO_TRACE=y -CONFIG_HIST_TRIGGERS=y -CONFIG_TRACE_EVAL_MAP_FILE=y -CONFIG_RV=y -CONFIG_RV_MON_WWNR=y -# CONFIG_STRICT_DEVMEM is not set -# CONFIG_RUNTIME_TESTING_MENU is not set -CONFIG_MEMTEST=y diff --git a/config/kernel/linux-sm8550-current.config b/config/kernel/linux-sm8550-current.config new file mode 100644 index 000000000..ac5ce0750 --- /dev/null +++ b/config/kernel/linux-sm8550-current.config @@ -0,0 +1,842 @@ +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_DEFAULT_HOSTNAME="@DEVICENAME@" +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_AUDIT=y +CONFIG_NO_HZ_IDLE=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_BPF_SYSCALL=y +CONFIG_BPF_JIT=y +CONFIG_PREEMPT=y +CONFIG_IRQ_TIME_ACCOUNTING=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_TASKSTATS=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_NUMA_BALANCING=y +CONFIG_MEMCG=y +CONFIG_BLK_CGROUP=y +CONFIG_CGROUP_PIDS=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_HUGETLB=y +CONFIG_CPUSETS=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_PERF=y +CONFIG_CGROUP_BPF=y +CONFIG_NAMESPACES=y +CONFIG_USER_NS=y +CONFIG_SCHED_AUTOGROUP=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_EXPERT=y +CONFIG_KALLSYMS_ALL=y +CONFIG_PROFILING=y +CONFIG_KEXEC=y +CONFIG_KEXEC_FILE=y +CONFIG_ARCH_QCOM=y +# CONFIG_NVIDIA_CARMEL_CNP_ERRATUM is not set +# CONFIG_ROCKCHIP_ERRATUM_3588001 is not set +CONFIG_ARM64_VA_BITS_48=y +CONFIG_SCHED_MC=y +CONFIG_SCHED_SMT=y +CONFIG_NUMA=y +CONFIG_PARAVIRT=y +CONFIG_COMPAT=y +CONFIG_RANDOMIZE_BASE=y +CONFIG_HIBERNATION=y +CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y +CONFIG_ENERGY_MODEL=y +CONFIG_ARM_PSCI_CPUIDLE=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y +CONFIG_CPUFREQ_DT=y +CONFIG_ARM_SCPI_CPUFREQ=y +CONFIG_ARM_QCOM_CPUFREQ_NVMEM=y +CONFIG_ARM_QCOM_CPUFREQ_HW=y +CONFIG_ARM_SCMI_CPUFREQ=y +CONFIG_ACPI_CPPC_CPUFREQ=m +CONFIG_ACPI=y +CONFIG_ACPI_HOTPLUG_MEMORY=y +CONFIG_ACPI_HMAT=y +CONFIG_ACPI_APEI=y +CONFIG_ACPI_APEI_GHES=y +CONFIG_ACPI_APEI_PCIEAER=y +CONFIG_ACPI_APEI_MEMORY_FAILURE=y +CONFIG_ACPI_APEI_EINJ=y +CONFIG_VIRTUALIZATION=y +CONFIG_KVM=y +CONFIG_JUMP_LABEL=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_BLK_DEV_INTEGRITY=y +CONFIG_PARTITION_ADVANCED=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_BINFMT_MISC=y +# CONFIG_COMPAT_BRK is not set +CONFIG_MEMORY_HOTPLUG=y +CONFIG_MEMORY_HOTREMOVE=y +CONFIG_KSM=y +CONFIG_MEMORY_FAILURE=y +CONFIG_TRANSPARENT_HUGEPAGE=y +CONFIG_CMA=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IPV6_SIT=m +CONFIG_NETFILTER=y +CONFIG_BRIDGE_NETFILTER=m +CONFIG_NF_CONNTRACK=m +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NETFILTER_XT_MARK=m +CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m +CONFIG_NETFILTER_XT_TARGET_LOG=m +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_IPVS=m +CONFIG_IP_VS=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_NAT=m +CONFIG_IP6_NF_TARGET_MASQUERADE=m +CONFIG_BRIDGE=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_CBS=m +CONFIG_NET_SCH_ETF=m +CONFIG_NET_SCH_TAPRIO=m +CONFIG_NET_SCH_MQPRIO=m +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_FLOWER=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_GACT=m +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_GATE=m +CONFIG_DNS_RESOLVER=y +CONFIG_NET_SWITCHDEV=y +CONFIG_QRTR=y +CONFIG_QRTR_SMD=y +CONFIG_QRTR_TUN=y +CONFIG_QRTR_MHI=y +CONFIG_NET_NCSI=y +CONFIG_BT=m +CONFIG_BT_HIDP=m +# CONFIG_BT_LE is not set +CONFIG_BT_LEDS=y +# CONFIG_BT_DEBUGFS is not set +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_LL=y +CONFIG_BT_HCIUART_QCA=y +CONFIG_CFG80211=m +CONFIG_MAC80211=m +CONFIG_MAC80211_LEDS=y +CONFIG_RFKILL=m +CONFIG_RFKILL_INPUT=y +CONFIG_PAGE_POOL_STATS=y +CONFIG_PCI=y +CONFIG_PCIEPORTBUS=y +CONFIG_PCIEAER=y +CONFIG_PCI_IOV=y +CONFIG_PCI_PASID=y +CONFIG_HOTPLUG_PCI=y +CONFIG_HOTPLUG_PCI_ACPI=y +CONFIG_PCIE_ALTERA=y +CONFIG_PCIE_ALTERA_MSI=y +CONFIG_PCI_HOST_THUNDER_PEM=y +CONFIG_PCI_HOST_THUNDER_ECAM=y +CONFIG_PCI_HOST_GENERIC=y +CONFIG_PCI_MESON=m +CONFIG_PCI_HISI=y +CONFIG_PCIE_KIRIN=y +CONFIG_PCIE_QCOM=y +CONFIG_PCI_ENDPOINT=y +CONFIG_PCI_ENDPOINT_CONFIGFS=y +CONFIG_PCI_EPF_TEST=m +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_FW_LOADER_USER_HELPER=y +CONFIG_VEXPRESS_CONFIG=y +CONFIG_MHI_BUS=y +CONFIG_MHI_BUS_PCI_GENERIC=m +CONFIG_ARM_SCMI_PROTOCOL=y +CONFIG_ARM_SCPI_PROTOCOL=y +CONFIG_QCOM_TZMEM_MODE_SHMBRIDGE=y +CONFIG_QCOM_QSEECOM=y +CONFIG_QCOM_QSEECOM_UEFISECAPP=y +CONFIG_MTD=y +CONFIG_MTD_QCOMSMEM_PARTS=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_CFI=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_OF=y +CONFIG_MTD_DATAFLASH=y +CONFIG_MTD_SST25L=y +CONFIG_MTD_RAW_NAND=y +CONFIG_MTD_NAND_DENALI_DT=y +CONFIG_MTD_NAND_BRCMNAND=m +CONFIG_MTD_NAND_BRCMNAND_BCMBCA=m +CONFIG_MTD_NAND_BRCMNAND_BRCMSTB=m +CONFIG_MTD_NAND_BRCMNAND_IPROC=m +CONFIG_MTD_NAND_QCOM=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_UBI=m +CONFIG_MTD_HYPERBUS=m +CONFIG_OF_OVERLAY=y +CONFIG_ZRAM=m +CONFIG_ZRAM_BACKEND_LZ4=y +CONFIG_ZRAM_BACKEND_LZ4HC=y +CONFIG_ZRAM_BACKEND_ZSTD=y +CONFIG_ZRAM_BACKEND_LZO=y +CONFIG_ZRAM_MULTI_COMP=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_VIRTIO_BLK=y +CONFIG_QCOM_COINCELL=m +CONFIG_QCOM_FASTRPC=y +CONFIG_SRAM=y +CONFIG_PCI_ENDPOINT_TEST=m +CONFIG_EEPROM_AT24=m +CONFIG_EEPROM_AT25=m +CONFIG_EEPROM_93CX6=y +CONFIG_UACCE=m +CONFIG_SCSI=y +# CONFIG_SCSI_PROC_FS is not set +CONFIG_BLK_DEV_SD=y +CONFIG_MD=y +# CONFIG_MD_BITMAP_FILE is not set +CONFIG_NETDEVICES=y +CONFIG_WIREGUARD=m +CONFIG_TUN=y +CONFIG_VETH=m +CONFIG_VIRTIO_NET=y +CONFIG_MHI_NET=m +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_NET_VENDOR_ADAPTEC is not set +# CONFIG_NET_VENDOR_AGERE is not set +# CONFIG_NET_VENDOR_ALACRITECH is not set +# CONFIG_NET_VENDOR_ALTEON is not set +# CONFIG_NET_VENDOR_AMAZON is not set +# CONFIG_NET_VENDOR_AMD is not set +# CONFIG_NET_VENDOR_AQUANTIA is not set +# CONFIG_NET_VENDOR_ARC is not set +# CONFIG_NET_VENDOR_ASIX is not set +# CONFIG_NET_VENDOR_ATHEROS is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_CADENCE is not set +# CONFIG_NET_VENDOR_CAVIUM is not set +# CONFIG_NET_VENDOR_CHELSIO is not set +# CONFIG_NET_VENDOR_CISCO is not set +# CONFIG_NET_VENDOR_CORTINA is not set +# CONFIG_NET_VENDOR_DAVICOM is not set +# CONFIG_NET_VENDOR_DEC is not set +# CONFIG_NET_VENDOR_DLINK is not set +# CONFIG_NET_VENDOR_EMULEX is not set +# CONFIG_NET_VENDOR_ENGLEDER is not set +# CONFIG_NET_VENDOR_EZCHIP is not set +# CONFIG_NET_VENDOR_FUNGIBLE is not set +# CONFIG_NET_VENDOR_GOOGLE is not set +# CONFIG_NET_VENDOR_HISILICON is not set +# CONFIG_NET_VENDOR_HUAWEI is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_ADI is not set +# CONFIG_NET_VENDOR_LITEX is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MELLANOX is not set +# CONFIG_NET_VENDOR_META is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_MICROSEMI is not set +# CONFIG_NET_VENDOR_MICROSOFT is not set +# CONFIG_NET_VENDOR_MYRI is not set +# CONFIG_NET_VENDOR_NI is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NETERION is not set +# CONFIG_NET_VENDOR_NETRONOME is not set +# CONFIG_NET_VENDOR_NVIDIA is not set +# CONFIG_NET_VENDOR_OKI is not set +# CONFIG_NET_VENDOR_PACKET_ENGINES is not set +# CONFIG_NET_VENDOR_PENSANDO is not set +# CONFIG_NET_VENDOR_QLOGIC is not set +# CONFIG_NET_VENDOR_BROCADE is not set +# CONFIG_NET_VENDOR_QUALCOMM is not set +# CONFIG_NET_VENDOR_RDC is not set +# CONFIG_NET_VENDOR_REALTEK is not set +# CONFIG_NET_VENDOR_RENESAS is not set +# CONFIG_NET_VENDOR_ROCKER is not set +# CONFIG_NET_VENDOR_SAMSUNG is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SILAN is not set +# CONFIG_NET_VENDOR_SIS is not set +# CONFIG_NET_VENDOR_SOLARFLARE is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_SOCIONEXT is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_SUN is not set +# CONFIG_NET_VENDOR_SYNOPSYS is not set +# CONFIG_NET_VENDOR_TEHUTI is not set +# CONFIG_NET_VENDOR_TI is not set +# CONFIG_NET_VENDOR_VERTEXCOM is not set +# CONFIG_NET_VENDOR_VIA is not set +# CONFIG_NET_VENDOR_WANGXUN is not set +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_NET_VENDOR_XILINX is not set +CONFIG_REALTEK_PHY=m +CONFIG_USB_RTL8150=m +CONFIG_USB_RTL8152=m +CONFIG_USB_USBNET=m +# CONFIG_USB_NET_NET1080 is not set +CONFIG_USB_NET_RNDIS_HOST=m +# CONFIG_USB_BELKIN is not set +# CONFIG_USB_ARMLINUX is not set +# CONFIG_USB_NET_ZAURUS is not set +CONFIG_USB_IPHETH=m +# CONFIG_WLAN_VENDOR_ADMTEK is not set +CONFIG_ATH12K=m +# CONFIG_WLAN_VENDOR_ATMEL is not set +# CONFIG_WLAN_VENDOR_BROADCOM is not set +# CONFIG_WLAN_VENDOR_INTEL is not set +# CONFIG_WLAN_VENDOR_INTERSIL is not set +# CONFIG_WLAN_VENDOR_MARVELL is not set +# CONFIG_WLAN_VENDOR_MEDIATEK is not set +# CONFIG_WLAN_VENDOR_MICROCHIP is not set +# CONFIG_WLAN_VENDOR_PURELIFI is not set +# CONFIG_WLAN_VENDOR_RALINK is not set +# CONFIG_WLAN_VENDOR_REALTEK is not set +# CONFIG_WLAN_VENDOR_RSI is not set +# CONFIG_WLAN_VENDOR_SILABS is not set +# CONFIG_WLAN_VENDOR_ST is not set +# CONFIG_WLAN_VENDOR_TI is not set +# CONFIG_WLAN_VENDOR_ZYDAS is not set +# CONFIG_WLAN_VENDOR_QUANTENNA is not set +CONFIG_INPUT_MATRIXKMAP=y +CONFIG_INPUT_EVDEV=y +CONFIG_KEYBOARD_ADC=m +CONFIG_KEYBOARD_GPIO=y +CONFIG_KEYBOARD_GPIO_POLLED=m +CONFIG_MOUSE_ELAN_I2C=m +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_XPAD=y +CONFIG_JOYSTICK_XPAD_FF=y +CONFIG_JOYSTICK_XPAD_LEDS=y +CONFIG_JOYSTICK_RSINPUT=y +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_EDT_FT5X06=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_PM8941_PWRKEY=y +CONFIG_INPUT_PM8XXX_VIBRATOR=m +CONFIG_INPUT_UINPUT=y +CONFIG_INPUT_PWM_VIBRA=m +CONFIG_RMI4_CORE=y +CONFIG_RMI4_I2C=y +CONFIG_RMI4_F03=y +CONFIG_RMI4_F11=y +CONFIG_RMI4_F12=y +CONFIG_RMI4_F30=y +CONFIG_RMI4_F3A=y +CONFIG_RMI4_F54=y +# CONFIG_SERIO_SERPORT is not set +CONFIG_LEGACY_PTY_COUNT=16 +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=8 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DW=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SERIAL_MSM=y +CONFIG_SERIAL_MSM_CONSOLE=y +CONFIG_SERIAL_QCOM_GENI=y +CONFIG_SERIAL_QCOM_GENI_CONSOLE=y +CONFIG_SERIAL_XILINX_PS_UART=y +CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y +CONFIG_SERIAL_FSL_LPUART=y +CONFIG_SERIAL_FSL_LPUART_CONSOLE=y +CONFIG_SERIAL_FSL_LINFLEXUART=y +CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE=y +CONFIG_SERIAL_DEV_BUS=y +CONFIG_VIRTIO_CONSOLE=y +CONFIG_IPMI_HANDLER=m +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_SI=m +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_VIRTIO=y +CONFIG_TCG_TPM=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_DESIGNWARE_CORE=y +CONFIG_I2C_GPIO=m +CONFIG_I2C_QCOM_CCI=m +CONFIG_I2C_QCOM_GENI=y +CONFIG_I2C_QUP=y +CONFIG_I2C_RK3X=y +CONFIG_I2C_SLAVE=y +CONFIG_SPI=y +CONFIG_SPI_DESIGNWARE=m +CONFIG_SPI_DW_DMA=y +CONFIG_SPI_DW_MMIO=m +CONFIG_SPI_QCOM_QSPI=y +CONFIG_SPI_QUP=y +CONFIG_SPI_QCOM_GENI=y +CONFIG_SPI_SPIDEV=m +CONFIG_SPMI=y +CONFIG_PINCTRL_SINGLE=y +CONFIG_PINCTRL_MSM=y +CONFIG_PINCTRL_SM8550=y +CONFIG_PINCTRL_QCOM_SPMI_PMIC=y +CONFIG_PINCTRL_LPASS_LPI=m +CONFIG_PINCTRL_SM8550_LPASS_LPI=m +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_AGGREGATOR=m +CONFIG_POWER_RESET_MSM=y +CONFIG_POWER_RESET_QCOM_PON=y +CONFIG_SYSCON_REBOOT_MODE=y +CONFIG_NVMEM_REBOOT_MODE=m +CONFIG_BATTERY_QCOM_BATTMGR=m +CONFIG_BATTERY_SBS=m +CONFIG_SENSORS_ARM_SCMI=y +CONFIG_SENSORS_ARM_SCPI=y +CONFIG_SENSORS_JC42=m +CONFIG_SENSORS_PWM_FAN=m +CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y +CONFIG_CPU_THERMAL=y +CONFIG_DEVFREQ_THERMAL=y +CONFIG_THERMAL_EMULATION=y +CONFIG_GENERIC_ADC_THERMAL=m +CONFIG_QCOM_TSENS=y +CONFIG_QCOM_SPMI_ADC_TM5=y +CONFIG_QCOM_SPMI_TEMP_ALARM=y +CONFIG_QCOM_LMH=y +CONFIG_WATCHDOG=y +CONFIG_ARM_SP805_WATCHDOG=y +CONFIG_ARM_SBSA_WATCHDOG=y +CONFIG_DW_WATCHDOG=y +CONFIG_QCOM_WDT=y +CONFIG_ARM_SMC_WATCHDOG=y +CONFIG_MFD_SPMI_PMIC=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_ARM_SCMI=y +CONFIG_REGULATOR_GPIO=y +CONFIG_REGULATOR_PWM=y +CONFIG_REGULATOR_QCOM_REFGEN=y +CONFIG_REGULATOR_QCOM_RPMH=y +CONFIG_REGULATOR_QCOM_SMD_RPM=y +CONFIG_REGULATOR_QCOM_SPMI=y +CONFIG_REGULATOR_QCOM_USB_VBUS=y +CONFIG_REGULATOR_VCTRL=m +CONFIG_MEDIA_SUPPORT=y +CONFIG_MEDIA_SUPPORT_FILTER=y +CONFIG_MEDIA_PLATFORM_SUPPORT=y +CONFIG_MEDIA_USB_SUPPORT=y +CONFIG_V4L_PLATFORM_DRIVERS=y +CONFIG_V4L_MEM2MEM_DRIVERS=y +CONFIG_VIDEO_QCOM_CAMSS=m +CONFIG_VIDEO_QCOM_IRIS=m +CONFIG_VIDEO_QCOM_VENUS=m +CONFIG_DRM=y +CONFIG_DRM_LOAD_EDID_FIRMWARE=y +CONFIG_DRM_DISPLAY_DP_AUX_CHARDEV=y +CONFIG_DRM_I2C_CH7006=m +CONFIG_DRM_I2C_SIL164=m +CONFIG_DRM_I2C_NXP_TDA998X=m +CONFIG_DRM_MSM=y +CONFIG_DRM_PANEL_CHIPONE_ICNA3512=y +CONFIG_DRM_PANEL_LVDS=m +CONFIG_DRM_PANEL_EDP=y +CONFIG_DRM_PANEL_SIMPLE=m +CONFIG_DRM_PANEL_SYNAPTICS_TD4328=y +CONFIG_DRM_DISPLAY_CONNECTOR=y +CONFIG_DRM_SIMPLE_BRIDGE=m +CONFIG_DRM_SIMPLEDRM=y +CONFIG_FB=y +CONFIG_FB_MODE_HELPERS=y +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_PWM=y +CONFIG_BACKLIGHT_QCOM_WLED=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_ALOOP=m +# CONFIG_SND_SPI is not set +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_SOC=y +CONFIG_SND_SOC_FSL_ASRC=m +CONFIG_SND_SOC_FSL_SAI=m +CONFIG_SND_SOC_FSL_AUDMIX=m +CONFIG_SND_SOC_FSL_SSI=m +CONFIG_SND_SOC_FSL_SPDIF=m +CONFIG_SND_SOC_FSL_ESAI=m +CONFIG_SND_SOC_FSL_MICFIL=m +CONFIG_SND_SOC_FSL_EASRC=m +CONFIG_SND_SOC_IMX_AUDMUX=m +CONFIG_SND_SOC_QCOM=m +CONFIG_SND_SOC_APQ8016_SBC=m +CONFIG_SND_SOC_SC8280XP=m +CONFIG_SND_SOC_SOF_TOPLEVEL=y +CONFIG_SND_SOC_SOF_OF=y +CONFIG_SND_SOC_SOF_MTK_TOPLEVEL=y +CONFIG_SND_SOC_AW88166=y +CONFIG_SND_SOC_BT_SCO=m +CONFIG_SND_SOC_DMIC=m +CONFIG_SND_SOC_SIMPLE_AMPLIFIER=m +CONFIG_SND_SOC_SIMPLE_MUX=m +CONFIG_SND_SOC_SPDIF=m +CONFIG_SND_SOC_WCD938X_SDW=m +CONFIG_SND_SOC_LPASS_WSA_MACRO=m +CONFIG_SND_SOC_LPASS_VA_MACRO=m +CONFIG_SND_SOC_LPASS_RX_MACRO=m +CONFIG_SND_SOC_LPASS_TX_MACRO=m +CONFIG_SND_SIMPLE_CARD=m +CONFIG_SND_AUDIO_GRAPH_CARD=m +CONFIG_SND_AUDIO_GRAPH_CARD2=m +CONFIG_HIDRAW=y +CONFIG_HID_A4TECH=y +CONFIG_HID_BELKIN=y +CONFIG_HID_CHERRY=y +CONFIG_HID_EZKEY=y +CONFIG_HID_ITE=y +CONFIG_HID_KENSINGTON=y +CONFIG_HID_LOGITECH=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MULTITOUCH=m +CONFIG_HID_NINTENDO=y +CONFIG_NINTENDO_FF=y +CONFIG_HID_PLAYSTATION=y +CONFIG_PLAYSTATION_FF=y +CONFIG_HID_SONY=y +CONFIG_SONY_FF=y +CONFIG_USB_HIDDEV=y +CONFIG_I2C_HID_ACPI=m +CONFIG_I2C_HID_OF=m +CONFIG_I2C_HID_OF_ELAN=m +CONFIG_USB_ULPI_BUS=y +CONFIG_USB_CONN_GPIO=y +CONFIG_USB_OTG=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_HCD_PLATFORM=y +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_HCD_PLATFORM=y +CONFIG_USB_ACM=m +CONFIG_USB_STORAGE=y +CONFIG_USB_DWC3=y +# CONFIG_USB_DWC3_PCI is not set +# CONFIG_USB_DWC3_HAPS is not set +CONFIG_USB_QCOM_EUD=y +CONFIG_USB_ONBOARD_DEV=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_ULPI=y +CONFIG_USB_GADGET=y +CONFIG_USB_SNP_UDC_PLAT=y +CONFIG_USB_BDC_UDC=y +CONFIG_USB_CONFIGFS=y +CONFIG_USB_CONFIGFS_NCM=y +CONFIG_USB_CONFIGFS_ECM=y +CONFIG_USB_CONFIGFS_RNDIS=y +CONFIG_USB_CONFIGFS_MASS_STORAGE=y +CONFIG_USB_CONFIGFS_F_FS=y +CONFIG_TYPEC=y +CONFIG_TYPEC_TCPM=y +CONFIG_TYPEC_TCPCI=m +CONFIG_TYPEC_FUSB302=m +CONFIG_TYPEC_QCOM_PMIC=y +CONFIG_TYPEC_UCSI=y +CONFIG_UCSI_CCG=m +CONFIG_UCSI_PMIC_GLINK=y +CONFIG_TYPEC_TPS6598X=m +CONFIG_TYPEC_HD3SS3220=m +CONFIG_TYPEC_MUX_FSA4480=y +CONFIG_TYPEC_MUX_GPIO_SBU=y +CONFIG_TYPEC_MUX_NB7VPQ904M=m +CONFIG_TYPEC_DP_ALTMODE=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_ARMMMCI=y +# CONFIG_MMC_STM32_SDMMC is not set +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_ACPI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_MSM=y +CONFIG_MMC_SDHCI_MSM_DOWNSTREAM=y +CONFIG_MMC_SPI=y +CONFIG_MMC_DW=y +CONFIG_MMC_HSQ=y +CONFIG_SCSI_UFSHCD=y +CONFIG_SCSI_UFS_BSG=y +CONFIG_SCSI_UFSHCD_PLATFORM=y +CONFIG_SCSI_UFS_QCOM=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_CLASS_MULTICOLOR=y +CONFIG_LEDS_HTR3212=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_PWM=y +CONFIG_LEDS_PWM_MULTICOLOR=y +CONFIG_LEDS_QCOM_LPG=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_CPU=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +CONFIG_LEDS_TRIGGER_PANIC=y +CONFIG_EDAC=y +CONFIG_EDAC_GHES=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_PM8XXX=y +CONFIG_DMADEVICES=y +CONFIG_QCOM_BAM_DMA=y +CONFIG_QCOM_GPI_DMA=y +CONFIG_QCOM_HIDMA_MGMT=y +CONFIG_QCOM_HIDMA=y +CONFIG_VFIO=y +CONFIG_VFIO_PCI=y +CONFIG_VIRTIO_PCI=y +CONFIG_VIRTIO_BALLOON=y +CONFIG_VIRTIO_MMIO=y +CONFIG_STAGING=y +CONFIG_STAGING_MEDIA=y +CONFIG_VIDEO_MAX96712=m +# CONFIG_SURFACE_PLATFORMS is not set +CONFIG_CLK_VEXPRESS_OSC=y +CONFIG_COMMON_CLK_SCMI=y +CONFIG_COMMON_CLK_SCPI=y +CONFIG_COMMON_CLK_PWM=y +CONFIG_COMMON_CLK_QCOM=y +CONFIG_QCOM_A53PLL=y +CONFIG_QCOM_CLK_SMD_RPM=y +CONFIG_QCOM_CLK_RPMH=y +CONFIG_SM_CAMCC_8550=y +CONFIG_SM_DISPCC_8550=y +CONFIG_SM_GPUCC_8550=y +CONFIG_SM_TCSRCC_8550=y +CONFIG_SM_VIDEOCC_8550=y +CONFIG_SPMI_PMIC_CLKDIV=y +CONFIG_QCOM_HFPLL=y +CONFIG_HWSPINLOCK=y +CONFIG_HWSPINLOCK_QCOM=y +# CONFIG_FSL_ERRATUM_A008585 is not set +# CONFIG_HISILICON_ERRATUM_161010101 is not set +CONFIG_ARM_MHU=y +CONFIG_PLATFORM_MHU=y +CONFIG_QCOM_APCS_IPC=y +CONFIG_QCOM_IPCC=y +CONFIG_IOMMU_IO_PGTABLE_ARMV7S=y +CONFIG_IOMMU_IO_PGTABLE_DART=y +CONFIG_ARM_SMMU=y +CONFIG_ARM_SMMU_V3=y +CONFIG_QCOM_IOMMU=y +CONFIG_REMOTEPROC=y +CONFIG_QCOM_Q6V5_ADSP=m +CONFIG_QCOM_Q6V5_MSS=m +CONFIG_QCOM_Q6V5_PAS=m +CONFIG_QCOM_SYSMON=m +CONFIG_QCOM_WCNSS_PIL=m +CONFIG_RPMSG_CHAR=y +CONFIG_RPMSG_CTRL=y +CONFIG_RPMSG_QCOM_GLINK_RPM=y +CONFIG_RPMSG_QCOM_GLINK_SMEM=y +CONFIG_RPMSG_QCOM_SMD=y +CONFIG_RPMSG_VIRTIO=y +CONFIG_SOUNDWIRE=m +CONFIG_SOUNDWIRE_QCOM=m +CONFIG_QCOM_AOSS_QMP=y +CONFIG_QCOM_COMMAND_DB=y +CONFIG_QCOM_GENI_SE=y +CONFIG_QCOM_LLCC=y +CONFIG_QCOM_OCMEM=y +CONFIG_QCOM_PD_MAPPER=y +CONFIG_QCOM_PMIC_GLINK=y +CONFIG_QCOM_RMTFS_MEM=y +CONFIG_QCOM_RPMH=y +CONFIG_QCOM_SMEM=y +CONFIG_QCOM_SMD_RPM=y +CONFIG_QCOM_SMP2P=y +CONFIG_QCOM_SMSM=y +CONFIG_QCOM_SOCINFO=y +CONFIG_QCOM_SPM=y +CONFIG_QCOM_STATS=y +CONFIG_QCOM_WCNSS_CTRL=m +CONFIG_QCOM_APR=y +CONFIG_QCOM_ICC_BWMON=y +CONFIG_QCOM_PBS=y +CONFIG_QCOM_CPR=y +CONFIG_QCOM_RPMHPD=y +CONFIG_QCOM_RPMPD=y +CONFIG_DEVFREQ_GOV_PERFORMANCE=y +CONFIG_DEVFREQ_GOV_POWERSAVE=y +CONFIG_DEVFREQ_GOV_USERSPACE=y +CONFIG_DEVFREQ_GOV_PASSIVE=m +CONFIG_EXTCON_USB_GPIO=y +CONFIG_MEMORY=y +CONFIG_IIO=y +CONFIG_IIO_BUFFER=y +CONFIG_IIO_TRIGGERED_BUFFER=m +CONFIG_QCOM_SPMI_VADC=y +CONFIG_QCOM_SPMI_ADC5=y +CONFIG_PWM=y +CONFIG_PWM_SN3112=y +CONFIG_QCOM_PDC=y +CONFIG_QCOM_MPM=y +CONFIG_RESET_GPIO=m +CONFIG_RESET_QCOM_AOSS=y +CONFIG_RESET_QCOM_PDC=y +CONFIG_PHY_CAN_TRANSCEIVER=m +CONFIG_PHY_CADENCE_TORRENT=m +CONFIG_PHY_CADENCE_DPHY_RX=m +CONFIG_PHY_CADENCE_SIERRA=m +CONFIG_PHY_CADENCE_SALVO=m +CONFIG_PHY_QCOM_EDP=y +CONFIG_PHY_QCOM_PCIE2=m +CONFIG_PHY_QCOM_QMP=y +CONFIG_PHY_QCOM_QMP_PCIE_8996=m +CONFIG_PHY_QCOM_QUSB2=m +CONFIG_PHY_QCOM_SNPS_EUSB2=y +CONFIG_PHY_QCOM_EUSB2_REPEATER=y +CONFIG_PHY_QCOM_M31_USB=m +CONFIG_PHY_QCOM_USB_HS=m +CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2=m +CONFIG_PHY_QCOM_USB_HS_28NM=m +CONFIG_PHY_QCOM_USB_SS=m +CONFIG_PHY_QCOM_SGMII_ETH=m +CONFIG_ARM_CCI_PMU=m +CONFIG_ARM_CCN=m +CONFIG_ARM_CMN=m +CONFIG_ARM_SMMU_V3_PMU=m +CONFIG_ARM_DSU_PMU=m +CONFIG_QCOM_L2_PMU=y +CONFIG_QCOM_L3_PMU=y +CONFIG_ARM_SPE_PMU=m +CONFIG_ARM_DMC620_PMU=m +CONFIG_HISI_PMU=y +CONFIG_ARM_CORESIGHT_PMU_ARCH_SYSTEM_PMU=m +CONFIG_NVIDIA_CORESIGHT_PMU_ARCH_SYSTEM_PMU=m +CONFIG_NVMEM_LAYOUT_SL28_VPD=m +CONFIG_NVMEM_QCOM_QFPROM=y +CONFIG_NVMEM_QCOM_SEC_QFPROM=y +CONFIG_NVMEM_RMEM=m +CONFIG_NVMEM_SPMI_SDAM=y +CONFIG_STM=y +CONFIG_TEE=y +CONFIG_OPTEE=y +CONFIG_MUX_GPIO=m +CONFIG_MUX_MMIO=m +CONFIG_SLIM_QCOM_CTRL=m +CONFIG_SLIM_QCOM_NGD_CTRL=m +CONFIG_INTERCONNECT_QCOM=y +CONFIG_INTERCONNECT_QCOM_OSM_L3=y +CONFIG_INTERCONNECT_QCOM_SM8550=y +CONFIG_COUNTER=m +CONFIG_HTE=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_BTRFS_FS=y +CONFIG_BTRFS_FS_POSIX_ACL=y +CONFIG_F2FS_FS=y +CONFIG_FANOTIFY=y +CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y +CONFIG_QUOTA=y +CONFIG_AUTOFS_FS=y +CONFIG_FUSE_FS=y +CONFIG_CUSE=m +CONFIG_OVERLAY_FS=m +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +CONFIG_EXFAT_FS=y +CONFIG_NTFS_FS=m +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_HUGETLBFS=y +CONFIG_EFIVAR_FS=y +CONFIG_UBIFS_FS=m +CONFIG_SQUASHFS=y +CONFIG_SQUASHFS_FILE_DIRECT=y +CONFIG_SQUASHFS_XATTR=y +CONFIG_SQUASHFS_LZ4=y +CONFIG_SQUASHFS_LZO=y +CONFIG_SQUASHFS_XZ=y +CONFIG_SQUASHFS_ZSTD=y +CONFIG_PSTORE_RAM=m +CONFIG_NFS_FS=y +CONFIG_NFSD=y +CONFIG_NLS_DEFAULT="utf-8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_SECURITY=y +CONFIG_LSM="landlock,lockdown,yama,loadpin,safesetid,bpf" +CONFIG_CRYPTO_USER=y +CONFIG_CRYPTO_TEST=m +CONFIG_CRYPTO_ECDH=y +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_CCM=y +CONFIG_CRYPTO_GCM=y +CONFIG_CRYPTO_ECHAINIV=y +CONFIG_CRYPTO_CMAC=y +CONFIG_CRYPTO_MICHAEL_MIC=y +CONFIG_CRYPTO_ANSI_CPRNG=y +CONFIG_CRYPTO_USER_API_RNG=m +CONFIG_CRYPTO_GHASH_ARM64_CE=y +CONFIG_CRYPTO_SHA1_ARM64_CE=y +CONFIG_CRYPTO_SHA2_ARM64_CE=y +CONFIG_CRYPTO_SHA512_ARM64_CE=m +CONFIG_CRYPTO_SHA3_ARM64=m +CONFIG_CRYPTO_SM3_ARM64_CE=m +CONFIG_CRYPTO_AES_ARM64_BS=m +CONFIG_CRYPTO_AES_ARM64_CE_CCM=y +CONFIG_CRYPTO_CRCT10DIF_ARM64_CE=y +CONFIG_CRYPTO_DEV_QCE=y +CONFIG_CRYPTO_DEV_QCOM_RNG=y +CONFIG_CRYPTO_DEV_CCREE=m +CONFIG_CRYPTO_DEV_HISI_SEC2=m +CONFIG_CRYPTO_DEV_HISI_ZIP=m +CONFIG_CRYPTO_DEV_HISI_HPRE=m +CONFIG_CRYPTO_DEV_HISI_TRNG=m +CONFIG_CRYPTO_DEV_AMLOGIC_GXL=m +CONFIG_PACKING=y +CONFIG_INDIRECT_PIO=y +CONFIG_CRC_CCITT=m +CONFIG_DMA_RESTRICTED_POOL=y +CONFIG_DMA_CMA=y +CONFIG_CMA_SIZE_MBYTES=32 +CONFIG_IRQ_POLL=y +CONFIG_PRINTK_TIME=y +CONFIG_CONSOLE_LOGLEVEL_DEFAULT=4 +CONFIG_CONSOLE_LOGLEVEL_QUIET=1 +CONFIG_BOOT_PRINTK_DELAY=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DEBUG_INFO_DWARF5=y +CONFIG_DEBUG_INFO_REDUCED=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_FS=y +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_SCHED_DEBUG is not set +# CONFIG_FTRACE is not set +CONFIG_MEMTEST=y diff --git a/config/kernel/linux-sm8550-edge.config b/config/kernel/linux-sm8550-edge.config new file mode 100644 index 000000000..79053d008 --- /dev/null +++ b/config/kernel/linux-sm8550-edge.config @@ -0,0 +1,846 @@ +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_DEFAULT_HOSTNAME="@DEVICENAME@" +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_AUDIT=y +CONFIG_NO_HZ_IDLE=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_BPF_SYSCALL=y +CONFIG_BPF_JIT=y +CONFIG_PREEMPT=y +CONFIG_IRQ_TIME_ACCOUNTING=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_TASKSTATS=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_NUMA_BALANCING=y +CONFIG_MEMCG=y +CONFIG_BLK_CGROUP=y +CONFIG_CGROUP_PIDS=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_HUGETLB=y +CONFIG_CPUSETS=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_PERF=y +CONFIG_CGROUP_BPF=y +CONFIG_NAMESPACES=y +CONFIG_USER_NS=y +CONFIG_SCHED_AUTOGROUP=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_EXPERT=y +CONFIG_KALLSYMS_ALL=y +CONFIG_PROFILING=y +CONFIG_KEXEC=y +CONFIG_KEXEC_FILE=y +CONFIG_ARCH_QCOM=y +# CONFIG_NVIDIA_CARMEL_CNP_ERRATUM is not set +# CONFIG_ROCKCHIP_ERRATUM_3588001 is not set +CONFIG_ARM64_VA_BITS_48=y +CONFIG_SCHED_MC=y +CONFIG_SCHED_SMT=y +CONFIG_NUMA=y +CONFIG_PARAVIRT=y +CONFIG_COMPAT=y +CONFIG_RANDOMIZE_BASE=y +CONFIG_HIBERNATION=y +CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y +CONFIG_ENERGY_MODEL=y +CONFIG_ARM_PSCI_CPUIDLE=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y +CONFIG_CPUFREQ_DT=y +CONFIG_ARM_SCPI_CPUFREQ=y +CONFIG_ARM_QCOM_CPUFREQ_NVMEM=y +CONFIG_ARM_QCOM_CPUFREQ_HW=y +CONFIG_ARM_SCMI_CPUFREQ=y +CONFIG_ACPI_CPPC_CPUFREQ=m +CONFIG_ACPI=y +CONFIG_ACPI_HOTPLUG_MEMORY=y +CONFIG_ACPI_HMAT=y +CONFIG_ACPI_APEI=y +CONFIG_ACPI_APEI_GHES=y +CONFIG_ACPI_APEI_PCIEAER=y +CONFIG_ACPI_APEI_MEMORY_FAILURE=y +CONFIG_ACPI_APEI_EINJ=y +CONFIG_VIRTUALIZATION=y +CONFIG_KVM=y +CONFIG_JUMP_LABEL=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_BLK_DEV_INTEGRITY=y +CONFIG_PARTITION_ADVANCED=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_BINFMT_MISC=y +# CONFIG_COMPAT_BRK is not set +CONFIG_MEMORY_HOTPLUG=y +CONFIG_MEMORY_HOTREMOVE=y +CONFIG_KSM=y +CONFIG_MEMORY_FAILURE=y +CONFIG_TRANSPARENT_HUGEPAGE=y +CONFIG_CMA=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IPV6_SIT=m +CONFIG_NETFILTER=y +CONFIG_BRIDGE_NETFILTER=m +CONFIG_NF_CONNTRACK=m +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NETFILTER_XT_MARK=m +CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m +CONFIG_NETFILTER_XT_TARGET_LOG=m +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_IPVS=m +CONFIG_IP_VS=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_NAT=m +CONFIG_IP6_NF_TARGET_MASQUERADE=m +CONFIG_BRIDGE=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_CBS=m +CONFIG_NET_SCH_ETF=m +CONFIG_NET_SCH_TAPRIO=m +CONFIG_NET_SCH_MQPRIO=m +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_FLOWER=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_GACT=m +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_GATE=m +CONFIG_DNS_RESOLVER=y +CONFIG_NET_SWITCHDEV=y +CONFIG_QRTR=y +CONFIG_QRTR_SMD=y +CONFIG_QRTR_TUN=y +CONFIG_QRTR_MHI=y +CONFIG_NET_NCSI=y +CONFIG_BT=m +CONFIG_BT_HIDP=m +# CONFIG_BT_LE is not set +CONFIG_BT_LEDS=y +# CONFIG_BT_DEBUGFS is not set +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_LL=y +CONFIG_BT_HCIUART_QCA=y +CONFIG_CFG80211=m +CONFIG_MAC80211=m +CONFIG_MAC80211_LEDS=y +CONFIG_RFKILL=m +CONFIG_RFKILL_INPUT=y +CONFIG_PAGE_POOL_STATS=y +CONFIG_PCI=y +CONFIG_PCIEPORTBUS=y +CONFIG_PCIEAER=y +CONFIG_PCI_IOV=y +CONFIG_PCI_PASID=y +CONFIG_HOTPLUG_PCI=y +CONFIG_HOTPLUG_PCI_ACPI=y +CONFIG_PCIE_ALTERA=y +CONFIG_PCIE_ALTERA_MSI=y +CONFIG_PCI_HOST_THUNDER_PEM=y +CONFIG_PCI_HOST_THUNDER_ECAM=y +CONFIG_PCI_HOST_GENERIC=y +CONFIG_PCI_MESON=m +CONFIG_PCI_HISI=y +CONFIG_PCIE_KIRIN=y +CONFIG_PCIE_QCOM=y +CONFIG_PCI_ENDPOINT=y +CONFIG_PCI_ENDPOINT_CONFIGFS=y +CONFIG_PCI_EPF_TEST=m +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_FW_LOADER_USER_HELPER=y +CONFIG_VEXPRESS_CONFIG=y +CONFIG_MHI_BUS=y +CONFIG_MHI_BUS_PCI_GENERIC=m +CONFIG_ARM_SCMI_PROTOCOL=y +CONFIG_ARM_SCPI_PROTOCOL=y +CONFIG_EFI_CAPSULE_LOADER=m +CONFIG_QCOM_TZMEM_MODE_SHMBRIDGE=y +CONFIG_QCOM_QSEECOM=y +CONFIG_QCOM_QSEECOM_UEFISECAPP=y +CONFIG_MTD=y +CONFIG_MTD_QCOMSMEM_PARTS=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_CFI=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_OF=y +CONFIG_MTD_DATAFLASH=y +CONFIG_MTD_SST25L=y +CONFIG_MTD_RAW_NAND=y +CONFIG_MTD_NAND_DENALI_DT=y +CONFIG_MTD_NAND_BRCMNAND=m +CONFIG_MTD_NAND_BRCMNAND_BCMBCA=m +CONFIG_MTD_NAND_BRCMNAND_BRCMSTB=m +CONFIG_MTD_NAND_BRCMNAND_IPROC=m +CONFIG_MTD_NAND_QCOM=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_UBI=m +CONFIG_MTD_HYPERBUS=m +CONFIG_OF_OVERLAY=y +CONFIG_ZRAM=m +CONFIG_ZRAM_BACKEND_LZ4=y +CONFIG_ZRAM_BACKEND_LZ4HC=y +CONFIG_ZRAM_BACKEND_ZSTD=y +CONFIG_ZRAM_BACKEND_LZO=y +CONFIG_ZRAM_MULTI_COMP=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_VIRTIO_BLK=y +CONFIG_QCOM_COINCELL=m +CONFIG_QCOM_FASTRPC=y +CONFIG_SRAM=y +CONFIG_PCI_ENDPOINT_TEST=m +CONFIG_EEPROM_AT24=m +CONFIG_EEPROM_AT25=m +CONFIG_EEPROM_93CX6=y +CONFIG_UACCE=m +CONFIG_SCSI=y +# CONFIG_SCSI_PROC_FS is not set +CONFIG_BLK_DEV_SD=y +CONFIG_MD=y +# CONFIG_MD_BITMAP_FILE is not set +CONFIG_NETDEVICES=y +CONFIG_WIREGUARD=m +CONFIG_TUN=y +CONFIG_VETH=m +CONFIG_VIRTIO_NET=y +CONFIG_MHI_NET=m +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_NET_VENDOR_ADAPTEC is not set +# CONFIG_NET_VENDOR_AGERE is not set +# CONFIG_NET_VENDOR_ALACRITECH is not set +# CONFIG_NET_VENDOR_ALTEON is not set +# CONFIG_NET_VENDOR_AMAZON is not set +# CONFIG_NET_VENDOR_AMD is not set +# CONFIG_NET_VENDOR_AQUANTIA is not set +# CONFIG_NET_VENDOR_ARC is not set +# CONFIG_NET_VENDOR_ASIX is not set +# CONFIG_NET_VENDOR_ATHEROS is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_CADENCE is not set +# CONFIG_NET_VENDOR_CAVIUM is not set +# CONFIG_NET_VENDOR_CHELSIO is not set +# CONFIG_NET_VENDOR_CISCO is not set +# CONFIG_NET_VENDOR_CORTINA is not set +# CONFIG_NET_VENDOR_DAVICOM is not set +# CONFIG_NET_VENDOR_DEC is not set +# CONFIG_NET_VENDOR_DLINK is not set +# CONFIG_NET_VENDOR_EMULEX is not set +# CONFIG_NET_VENDOR_ENGLEDER is not set +# CONFIG_NET_VENDOR_EZCHIP is not set +# CONFIG_NET_VENDOR_FUNGIBLE is not set +# CONFIG_NET_VENDOR_GOOGLE is not set +# CONFIG_NET_VENDOR_HISILICON is not set +# CONFIG_NET_VENDOR_HUAWEI is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_ADI is not set +# CONFIG_NET_VENDOR_LITEX is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MELLANOX is not set +# CONFIG_NET_VENDOR_META is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_MICROSEMI is not set +# CONFIG_NET_VENDOR_MICROSOFT is not set +# CONFIG_NET_VENDOR_MYRI is not set +# CONFIG_NET_VENDOR_NI is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NETERION is not set +# CONFIG_NET_VENDOR_NETRONOME is not set +# CONFIG_NET_VENDOR_NVIDIA is not set +# CONFIG_NET_VENDOR_OKI is not set +# CONFIG_NET_VENDOR_PACKET_ENGINES is not set +# CONFIG_NET_VENDOR_PENSANDO is not set +# CONFIG_NET_VENDOR_QLOGIC is not set +# CONFIG_NET_VENDOR_BROCADE is not set +# CONFIG_NET_VENDOR_QUALCOMM is not set +# CONFIG_NET_VENDOR_RDC is not set +# CONFIG_NET_VENDOR_REALTEK is not set +# CONFIG_NET_VENDOR_RENESAS is not set +# CONFIG_NET_VENDOR_ROCKER is not set +# CONFIG_NET_VENDOR_SAMSUNG is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SILAN is not set +# CONFIG_NET_VENDOR_SIS is not set +# CONFIG_NET_VENDOR_SOLARFLARE is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_SOCIONEXT is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_SUN is not set +# CONFIG_NET_VENDOR_SYNOPSYS is not set +# CONFIG_NET_VENDOR_TEHUTI is not set +# CONFIG_NET_VENDOR_TI is not set +# CONFIG_NET_VENDOR_VERTEXCOM is not set +# CONFIG_NET_VENDOR_VIA is not set +# CONFIG_NET_VENDOR_WANGXUN is not set +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_NET_VENDOR_XILINX is not set +CONFIG_REALTEK_PHY=m +CONFIG_USB_RTL8150=m +CONFIG_USB_RTL8152=m +CONFIG_USB_USBNET=m +# CONFIG_USB_NET_NET1080 is not set +CONFIG_USB_NET_RNDIS_HOST=m +# CONFIG_USB_BELKIN is not set +# CONFIG_USB_ARMLINUX is not set +# CONFIG_USB_NET_ZAURUS is not set +CONFIG_USB_IPHETH=m +# CONFIG_WLAN_VENDOR_ADMTEK is not set +CONFIG_ATH12K=m +# CONFIG_WLAN_VENDOR_ATMEL is not set +# CONFIG_WLAN_VENDOR_BROADCOM is not set +# CONFIG_WLAN_VENDOR_INTEL is not set +# CONFIG_WLAN_VENDOR_INTERSIL is not set +# CONFIG_WLAN_VENDOR_MARVELL is not set +# CONFIG_WLAN_VENDOR_MEDIATEK is not set +# CONFIG_WLAN_VENDOR_MICROCHIP is not set +# CONFIG_WLAN_VENDOR_PURELIFI is not set +# CONFIG_WLAN_VENDOR_RALINK is not set +# CONFIG_WLAN_VENDOR_REALTEK is not set +# CONFIG_WLAN_VENDOR_RSI is not set +# CONFIG_WLAN_VENDOR_SILABS is not set +# CONFIG_WLAN_VENDOR_ST is not set +# CONFIG_WLAN_VENDOR_TI is not set +# CONFIG_WLAN_VENDOR_ZYDAS is not set +# CONFIG_WLAN_VENDOR_QUANTENNA is not set +CONFIG_INPUT_MATRIXKMAP=y +CONFIG_INPUT_EVDEV=y +CONFIG_KEYBOARD_ADC=m +CONFIG_KEYBOARD_GPIO=y +CONFIG_KEYBOARD_GPIO_POLLED=m +CONFIG_MOUSE_ELAN_I2C=m +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_XPAD=y +CONFIG_JOYSTICK_XPAD_FF=y +CONFIG_JOYSTICK_XPAD_LEDS=y +CONFIG_JOYSTICK_RSINPUT=y +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_EDT_FT5X06=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_PM8941_PWRKEY=y +CONFIG_INPUT_PM8XXX_VIBRATOR=m +CONFIG_INPUT_UINPUT=y +CONFIG_INPUT_PWM_VIBRA=m +CONFIG_RMI4_CORE=y +CONFIG_RMI4_I2C=y +CONFIG_RMI4_F03=y +CONFIG_RMI4_F11=y +CONFIG_RMI4_F12=y +CONFIG_RMI4_F30=y +CONFIG_RMI4_F3A=y +CONFIG_RMI4_F54=y +# CONFIG_SERIO_SERPORT is not set +CONFIG_LEGACY_PTY_COUNT=16 +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=8 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DW=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SERIAL_MSM=y +CONFIG_SERIAL_MSM_CONSOLE=y +CONFIG_SERIAL_QCOM_GENI=y +CONFIG_SERIAL_QCOM_GENI_CONSOLE=y +CONFIG_SERIAL_XILINX_PS_UART=y +CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y +CONFIG_SERIAL_FSL_LPUART=y +CONFIG_SERIAL_FSL_LPUART_CONSOLE=y +CONFIG_SERIAL_FSL_LINFLEXUART=y +CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE=y +CONFIG_SERIAL_DEV_BUS=y +CONFIG_VIRTIO_CONSOLE=y +CONFIG_IPMI_HANDLER=m +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_SI=m +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_VIRTIO=y +CONFIG_TCG_TPM=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_DESIGNWARE_CORE=y +CONFIG_I2C_GPIO=m +CONFIG_I2C_QCOM_CCI=m +CONFIG_I2C_QCOM_GENI=y +CONFIG_I2C_QUP=y +CONFIG_I2C_RK3X=y +CONFIG_I2C_SLAVE=y +CONFIG_SPI=y +CONFIG_SPI_DESIGNWARE=m +CONFIG_SPI_DW_DMA=y +CONFIG_SPI_DW_MMIO=m +CONFIG_SPI_QCOM_QSPI=y +CONFIG_SPI_QUP=y +CONFIG_SPI_QCOM_GENI=y +CONFIG_SPI_SPIDEV=m +CONFIG_SPMI=y +CONFIG_PINCTRL_SINGLE=y +CONFIG_PINCTRL_MSM=y +CONFIG_PINCTRL_SM8550=y +CONFIG_PINCTRL_QCOM_SPMI_PMIC=y +CONFIG_PINCTRL_LPASS_LPI=m +CONFIG_PINCTRL_SM8550_LPASS_LPI=m +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_AGGREGATOR=m +CONFIG_POWER_RESET_MSM=y +CONFIG_POWER_RESET_QCOM_PON=y +CONFIG_SYSCON_REBOOT_MODE=y +CONFIG_NVMEM_REBOOT_MODE=m +CONFIG_BATTERY_QCOM_BATTMGR=m +CONFIG_BATTERY_SBS=m +CONFIG_SENSORS_ARM_SCMI=y +CONFIG_SENSORS_ARM_SCPI=y +CONFIG_SENSORS_JC42=m +CONFIG_SENSORS_PWM_FAN=m +CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y +CONFIG_CPU_THERMAL=y +CONFIG_DEVFREQ_THERMAL=y +CONFIG_THERMAL_EMULATION=y +CONFIG_GENERIC_ADC_THERMAL=m +CONFIG_QCOM_TSENS=y +CONFIG_QCOM_SPMI_ADC_TM5=y +CONFIG_QCOM_SPMI_TEMP_ALARM=y +CONFIG_QCOM_LMH=y +CONFIG_WATCHDOG=y +CONFIG_ARM_SP805_WATCHDOG=y +CONFIG_ARM_SBSA_WATCHDOG=y +CONFIG_DW_WATCHDOG=y +CONFIG_QCOM_WDT=y +CONFIG_ARM_SMC_WATCHDOG=y +CONFIG_MFD_SPMI_PMIC=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_ARM_SCMI=y +CONFIG_REGULATOR_GPIO=y +CONFIG_REGULATOR_PWM=y +CONFIG_REGULATOR_QCOM_REFGEN=y +CONFIG_REGULATOR_QCOM_RPMH=y +CONFIG_REGULATOR_QCOM_SMD_RPM=y +CONFIG_REGULATOR_QCOM_SPMI=y +CONFIG_REGULATOR_QCOM_USB_VBUS=y +CONFIG_REGULATOR_VCTRL=m +CONFIG_MEDIA_SUPPORT=y +CONFIG_MEDIA_SUPPORT_FILTER=y +CONFIG_MEDIA_PLATFORM_SUPPORT=y +CONFIG_MEDIA_USB_SUPPORT=y +CONFIG_V4L_PLATFORM_DRIVERS=y +CONFIG_V4L_MEM2MEM_DRIVERS=y +CONFIG_VIDEO_QCOM_CAMSS=m +CONFIG_VIDEO_QCOM_IRIS=m +CONFIG_VIDEO_QCOM_VENUS=m +CONFIG_DRM=y +CONFIG_DRM_LOAD_EDID_FIRMWARE=y +CONFIG_DRM_DISPLAY_DP_AUX_CHARDEV=y +CONFIG_DRM_I2C_CH7006=m +CONFIG_DRM_I2C_SIL164=m +CONFIG_DRM_I2C_NXP_TDA998X=m +CONFIG_DRM_MSM=y +CONFIG_DRM_PANEL_CHIPONE_ICNA3512=y +CONFIG_DRM_PANEL_LVDS=m +CONFIG_DRM_PANEL_EDP=y +CONFIG_DRM_PANEL_SIMPLE=m +CONFIG_DRM_PANEL_SYNAPTICS_TD4328=y +CONFIG_DRM_DISPLAY_CONNECTOR=y +CONFIG_DRM_SIMPLE_BRIDGE=m +CONFIG_DRM_SIMPLEDRM=y +CONFIG_FB=y +CONFIG_FB_EFI=y +CONFIG_FB_MODE_HELPERS=y +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_PWM=y +CONFIG_BACKLIGHT_QCOM_WLED=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_ALOOP=m +# CONFIG_SND_SPI is not set +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_SOC=y +CONFIG_SND_SOC_FSL_ASRC=m +CONFIG_SND_SOC_FSL_SAI=m +CONFIG_SND_SOC_FSL_AUDMIX=m +CONFIG_SND_SOC_FSL_SSI=m +CONFIG_SND_SOC_FSL_SPDIF=m +CONFIG_SND_SOC_FSL_ESAI=m +CONFIG_SND_SOC_FSL_MICFIL=m +CONFIG_SND_SOC_FSL_EASRC=m +CONFIG_SND_SOC_IMX_AUDMUX=m +CONFIG_SND_SOC_QCOM=m +CONFIG_SND_SOC_APQ8016_SBC=m +CONFIG_SND_SOC_SC8280XP=m +CONFIG_SND_SOC_SOF_TOPLEVEL=y +CONFIG_SND_SOC_SOF_OF=y +CONFIG_SND_SOC_SOF_MTK_TOPLEVEL=y +CONFIG_SND_SOC_AW88166=y +CONFIG_SND_SOC_BT_SCO=m +CONFIG_SND_SOC_DMIC=m +CONFIG_SND_SOC_SIMPLE_AMPLIFIER=m +CONFIG_SND_SOC_SIMPLE_MUX=m +CONFIG_SND_SOC_SPDIF=m +CONFIG_SND_SOC_WCD938X_SDW=m +CONFIG_SND_SOC_LPASS_WSA_MACRO=m +CONFIG_SND_SOC_LPASS_VA_MACRO=m +CONFIG_SND_SOC_LPASS_RX_MACRO=m +CONFIG_SND_SOC_LPASS_TX_MACRO=m +CONFIG_SND_SIMPLE_CARD=m +CONFIG_SND_AUDIO_GRAPH_CARD=m +CONFIG_SND_AUDIO_GRAPH_CARD2=m +CONFIG_HIDRAW=y +CONFIG_HID_A4TECH=y +CONFIG_HID_BELKIN=y +CONFIG_HID_CHERRY=y +CONFIG_HID_EZKEY=y +CONFIG_HID_ITE=y +CONFIG_HID_KENSINGTON=y +CONFIG_HID_LOGITECH=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MULTITOUCH=m +CONFIG_HID_NINTENDO=y +CONFIG_NINTENDO_FF=y +CONFIG_HID_PLAYSTATION=y +CONFIG_PLAYSTATION_FF=y +CONFIG_HID_SONY=y +CONFIG_SONY_FF=y +CONFIG_USB_HIDDEV=y +CONFIG_I2C_HID_ACPI=m +CONFIG_I2C_HID_OF=m +CONFIG_I2C_HID_OF_ELAN=m +CONFIG_USB_ULPI_BUS=y +CONFIG_USB_CONN_GPIO=y +CONFIG_USB_OTG=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_HCD_PLATFORM=y +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_HCD_PLATFORM=y +CONFIG_USB_ACM=m +CONFIG_USB_STORAGE=y +CONFIG_USB_DWC3=y +# CONFIG_USB_DWC3_PCI is not set +# CONFIG_USB_DWC3_HAPS is not set +CONFIG_USB_QCOM_EUD=y +CONFIG_USB_ONBOARD_DEV=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_ULPI=y +CONFIG_USB_GADGET=y +CONFIG_USB_SNP_UDC_PLAT=y +CONFIG_USB_BDC_UDC=y +CONFIG_USB_CONFIGFS=y +CONFIG_USB_CONFIGFS_NCM=y +CONFIG_USB_CONFIGFS_ECM=y +CONFIG_USB_CONFIGFS_RNDIS=y +CONFIG_USB_CONFIGFS_MASS_STORAGE=y +CONFIG_USB_CONFIGFS_F_FS=y +CONFIG_TYPEC=y +CONFIG_TYPEC_TCPM=y +CONFIG_TYPEC_TCPCI=m +CONFIG_TYPEC_FUSB302=m +CONFIG_TYPEC_QCOM_PMIC=y +CONFIG_TYPEC_UCSI=y +CONFIG_UCSI_CCG=m +CONFIG_UCSI_PMIC_GLINK=y +CONFIG_TYPEC_TPS6598X=m +CONFIG_TYPEC_HD3SS3220=m +CONFIG_TYPEC_MUX_FSA4480=y +CONFIG_TYPEC_MUX_GPIO_SBU=y +CONFIG_TYPEC_MUX_NB7VPQ904M=m +CONFIG_TYPEC_DP_ALTMODE=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_ARMMMCI=y +# CONFIG_MMC_STM32_SDMMC is not set +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_ACPI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_MSM=y +CONFIG_MMC_SDHCI_MSM_DOWNSTREAM=y +CONFIG_MMC_SPI=y +CONFIG_MMC_DW=y +CONFIG_MMC_HSQ=y +CONFIG_SCSI_UFSHCD=y +CONFIG_SCSI_UFS_BSG=y +CONFIG_SCSI_UFSHCD_PLATFORM=y +CONFIG_SCSI_UFS_QCOM=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_CLASS_MULTICOLOR=y +CONFIG_LEDS_HTR3212=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_PWM=y +CONFIG_LEDS_PWM_MULTICOLOR=y +CONFIG_LEDS_QCOM_LPG=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_CPU=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +CONFIG_LEDS_TRIGGER_PANIC=y +CONFIG_EDAC=y +CONFIG_EDAC_GHES=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_EFI=y +CONFIG_RTC_DRV_PM8XXX=y +CONFIG_DMADEVICES=y +CONFIG_QCOM_BAM_DMA=y +CONFIG_QCOM_GPI_DMA=y +CONFIG_QCOM_HIDMA_MGMT=y +CONFIG_QCOM_HIDMA=y +CONFIG_VFIO=y +CONFIG_VFIO_PCI=y +CONFIG_VIRTIO_PCI=y +CONFIG_VIRTIO_BALLOON=y +CONFIG_VIRTIO_MMIO=y +CONFIG_STAGING=y +CONFIG_STAGING_MEDIA=y +CONFIG_VIDEO_MAX96712=m +# CONFIG_SURFACE_PLATFORMS is not set +CONFIG_CLK_VEXPRESS_OSC=y +CONFIG_COMMON_CLK_SCMI=y +CONFIG_COMMON_CLK_SCPI=y +CONFIG_COMMON_CLK_PWM=y +CONFIG_COMMON_CLK_QCOM=y +CONFIG_QCOM_A53PLL=y +CONFIG_QCOM_CLK_SMD_RPM=y +CONFIG_QCOM_CLK_RPMH=y +CONFIG_SM_CAMCC_8550=y +CONFIG_SM_DISPCC_8550=y +CONFIG_SM_GPUCC_8550=y +CONFIG_SM_TCSRCC_8550=y +CONFIG_SM_VIDEOCC_8550=y +CONFIG_SPMI_PMIC_CLKDIV=y +CONFIG_QCOM_HFPLL=y +CONFIG_CLK_GFM_LPASS_SM8250=m +CONFIG_HWSPINLOCK=y +CONFIG_HWSPINLOCK_QCOM=y +# CONFIG_FSL_ERRATUM_A008585 is not set +# CONFIG_HISILICON_ERRATUM_161010101 is not set +CONFIG_ARM_MHU=y +CONFIG_PLATFORM_MHU=y +CONFIG_QCOM_APCS_IPC=y +CONFIG_QCOM_IPCC=y +CONFIG_IOMMU_IO_PGTABLE_ARMV7S=y +CONFIG_IOMMU_IO_PGTABLE_DART=y +CONFIG_ARM_SMMU=y +CONFIG_ARM_SMMU_V3=y +CONFIG_QCOM_IOMMU=y +CONFIG_REMOTEPROC=y +CONFIG_QCOM_Q6V5_ADSP=m +CONFIG_QCOM_Q6V5_MSS=m +CONFIG_QCOM_Q6V5_PAS=m +CONFIG_QCOM_SYSMON=m +CONFIG_QCOM_WCNSS_PIL=m +CONFIG_RPMSG_CHAR=y +CONFIG_RPMSG_CTRL=y +CONFIG_RPMSG_QCOM_GLINK_RPM=y +CONFIG_RPMSG_QCOM_GLINK_SMEM=y +CONFIG_RPMSG_QCOM_SMD=y +CONFIG_RPMSG_VIRTIO=y +CONFIG_SOUNDWIRE=m +CONFIG_SOUNDWIRE_QCOM=m +CONFIG_QCOM_AOSS_QMP=y +CONFIG_QCOM_COMMAND_DB=y +CONFIG_QCOM_GENI_SE=y +CONFIG_QCOM_LLCC=y +CONFIG_QCOM_OCMEM=y +CONFIG_QCOM_PD_MAPPER=y +CONFIG_QCOM_PMIC_GLINK=y +CONFIG_QCOM_RMTFS_MEM=y +CONFIG_QCOM_RPMH=y +CONFIG_QCOM_SMEM=y +CONFIG_QCOM_SMD_RPM=y +CONFIG_QCOM_SMP2P=y +CONFIG_QCOM_SMSM=y +CONFIG_QCOM_SOCINFO=y +CONFIG_QCOM_SPM=y +CONFIG_QCOM_STATS=y +CONFIG_QCOM_WCNSS_CTRL=m +CONFIG_QCOM_APR=y +CONFIG_QCOM_ICC_BWMON=y +CONFIG_QCOM_PBS=y +CONFIG_QCOM_CPR=y +CONFIG_QCOM_RPMHPD=y +CONFIG_QCOM_RPMPD=y +CONFIG_DEVFREQ_GOV_PERFORMANCE=y +CONFIG_DEVFREQ_GOV_POWERSAVE=y +CONFIG_DEVFREQ_GOV_USERSPACE=y +CONFIG_DEVFREQ_GOV_PASSIVE=m +CONFIG_EXTCON_USB_GPIO=y +CONFIG_MEMORY=y +CONFIG_IIO=y +CONFIG_IIO_BUFFER=y +CONFIG_IIO_TRIGGERED_BUFFER=m +CONFIG_QCOM_SPMI_VADC=y +CONFIG_QCOM_SPMI_ADC5=y +CONFIG_PWM=y +CONFIG_PWM_SN3112=y +CONFIG_QCOM_PDC=y +CONFIG_QCOM_MPM=y +CONFIG_RESET_GPIO=m +CONFIG_RESET_QCOM_AOSS=y +CONFIG_RESET_QCOM_PDC=y +CONFIG_PHY_CAN_TRANSCEIVER=m +CONFIG_PHY_CADENCE_TORRENT=m +CONFIG_PHY_CADENCE_DPHY_RX=m +CONFIG_PHY_CADENCE_SIERRA=m +CONFIG_PHY_CADENCE_SALVO=m +CONFIG_PHY_QCOM_EDP=y +CONFIG_PHY_QCOM_PCIE2=m +CONFIG_PHY_QCOM_QMP=y +CONFIG_PHY_QCOM_QMP_PCIE_8996=m +CONFIG_PHY_QCOM_QUSB2=m +CONFIG_PHY_QCOM_SNPS_EUSB2=y +CONFIG_PHY_QCOM_EUSB2_REPEATER=y +CONFIG_PHY_QCOM_M31_USB=m +CONFIG_PHY_QCOM_USB_HS=m +CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2=m +CONFIG_PHY_QCOM_USB_HS_28NM=m +CONFIG_PHY_QCOM_USB_SS=m +CONFIG_PHY_QCOM_SGMII_ETH=m +CONFIG_ARM_CCI_PMU=m +CONFIG_ARM_CCN=m +CONFIG_ARM_CMN=m +CONFIG_ARM_SMMU_V3_PMU=m +CONFIG_ARM_DSU_PMU=m +CONFIG_QCOM_L2_PMU=y +CONFIG_QCOM_L3_PMU=y +CONFIG_ARM_SPE_PMU=m +CONFIG_ARM_DMC620_PMU=m +CONFIG_HISI_PMU=y +CONFIG_ARM_CORESIGHT_PMU_ARCH_SYSTEM_PMU=m +CONFIG_NVIDIA_CORESIGHT_PMU_ARCH_SYSTEM_PMU=m +CONFIG_NVMEM_LAYOUT_SL28_VPD=m +CONFIG_NVMEM_QCOM_QFPROM=y +CONFIG_NVMEM_QCOM_SEC_QFPROM=y +CONFIG_NVMEM_RMEM=m +CONFIG_NVMEM_SPMI_SDAM=y +CONFIG_STM=y +CONFIG_TEE=y +CONFIG_OPTEE=y +CONFIG_MUX_GPIO=m +CONFIG_MUX_MMIO=m +CONFIG_SLIM_QCOM_CTRL=m +CONFIG_SLIM_QCOM_NGD_CTRL=m +CONFIG_INTERCONNECT_QCOM=y +CONFIG_INTERCONNECT_QCOM_OSM_L3=y +CONFIG_INTERCONNECT_QCOM_SM8550=y +CONFIG_COUNTER=m +CONFIG_HTE=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_BTRFS_FS=y +CONFIG_BTRFS_FS_POSIX_ACL=y +CONFIG_F2FS_FS=y +CONFIG_FANOTIFY=y +CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y +CONFIG_QUOTA=y +CONFIG_AUTOFS_FS=y +CONFIG_FUSE_FS=y +CONFIG_CUSE=m +CONFIG_OVERLAY_FS=m +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +CONFIG_EXFAT_FS=y +CONFIG_NTFS_FS=m +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_HUGETLBFS=y +CONFIG_EFIVAR_FS=y +CONFIG_UBIFS_FS=m +CONFIG_SQUASHFS=y +CONFIG_SQUASHFS_FILE_DIRECT=y +CONFIG_SQUASHFS_XATTR=y +CONFIG_SQUASHFS_LZ4=y +CONFIG_SQUASHFS_LZO=y +CONFIG_SQUASHFS_XZ=y +CONFIG_SQUASHFS_ZSTD=y +CONFIG_PSTORE_RAM=m +CONFIG_NFS_FS=y +CONFIG_NFSD=y +CONFIG_NLS_DEFAULT="utf-8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_SECURITY=y +CONFIG_LSM="landlock,lockdown,yama,loadpin,safesetid,bpf" +CONFIG_CRYPTO_USER=y +CONFIG_CRYPTO_TEST=m +CONFIG_CRYPTO_ECDH=y +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_CCM=y +CONFIG_CRYPTO_GCM=y +CONFIG_CRYPTO_ECHAINIV=y +CONFIG_CRYPTO_CMAC=y +CONFIG_CRYPTO_MICHAEL_MIC=y +CONFIG_CRYPTO_ANSI_CPRNG=y +CONFIG_CRYPTO_USER_API_RNG=m +CONFIG_CRYPTO_GHASH_ARM64_CE=y +CONFIG_CRYPTO_SHA1_ARM64_CE=y +CONFIG_CRYPTO_SHA2_ARM64_CE=y +CONFIG_CRYPTO_SHA512_ARM64_CE=m +CONFIG_CRYPTO_SHA3_ARM64=m +CONFIG_CRYPTO_SM3_ARM64_CE=m +CONFIG_CRYPTO_AES_ARM64_BS=m +CONFIG_CRYPTO_AES_ARM64_CE_CCM=y +CONFIG_CRYPTO_CRCT10DIF_ARM64_CE=y +CONFIG_CRYPTO_DEV_QCE=y +CONFIG_CRYPTO_DEV_QCOM_RNG=y +CONFIG_CRYPTO_DEV_CCREE=m +CONFIG_CRYPTO_DEV_HISI_SEC2=m +CONFIG_CRYPTO_DEV_HISI_ZIP=m +CONFIG_CRYPTO_DEV_HISI_HPRE=m +CONFIG_CRYPTO_DEV_HISI_TRNG=m +CONFIG_CRYPTO_DEV_AMLOGIC_GXL=m +CONFIG_PACKING=y +CONFIG_INDIRECT_PIO=y +CONFIG_CRC_CCITT=m +CONFIG_DMA_RESTRICTED_POOL=y +CONFIG_DMA_CMA=y +CONFIG_CMA_SIZE_MBYTES=32 +CONFIG_IRQ_POLL=y +CONFIG_PRINTK_TIME=y +CONFIG_CONSOLE_LOGLEVEL_DEFAULT=4 +CONFIG_CONSOLE_LOGLEVEL_QUIET=1 +CONFIG_BOOT_PRINTK_DELAY=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DEBUG_INFO_DWARF5=y +CONFIG_DEBUG_INFO_REDUCED=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_FS=y +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_SCHED_DEBUG is not set +# CONFIG_FTRACE is not set +CONFIG_MEMTEST=y diff --git a/config/sources/families/sm8550.conf b/config/sources/families/sm8550.conf new file mode 100644 index 000000000..ef54eb53d --- /dev/null +++ b/config/sources/families/sm8550.conf @@ -0,0 +1,32 @@ +# +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (c) 2013-2023 Igor Pecovnik, igor@armbian.com +# +# This file is a part of the Armbian Build Framework +# https://github.com/armbian/build/ +# + +declare -g LINUXFAMILY="sm8550" +declare -g OVERLAY_DIR="/boot/dtb/qcom/overlay" +declare -g ARCH="arm64" +declare -g BOOTENV_FILE="qcom-abl.txt" +enable_extension "image-output-abl" + +case $BRANCH in + + current) + declare -g KERNEL_MAJOR_MINOR="6.12" # Major and minor versions of this kernel. + declare -g KERNELBRANCH='branch:linux-6.12.y' + declare -g -i KERNEL_GIT_CACHE_TTL=120 # 2 minutes; this is a high-traffic repo + ;; + + edge) + declare -g KERNEL_MAJOR_MINOR="6.12" # Major and minor versions of this kernel. + ;; + +esac + +family_tweaks_bsp() { + : +} diff --git a/packages/bsp/ayn-odin2/AYN-Odin2.conf b/packages/bsp/ayn-odin2/AYN-Odin2.conf new file mode 100644 index 000000000..e4054ba63 --- /dev/null +++ b/packages/bsp/ayn-odin2/AYN-Odin2.conf @@ -0,0 +1,31 @@ +# Use case configuration for AYN Odin2 +# Author: Teguh Sobirin + +Syntax 4 + +SectionUseCase."HiFi" { + File "/AYN/Odin2/HiFi.conf" + Comment "HiFi quality Music." +} + +BootSequence [ + cset "name='RX_RX0 Digital Volume' 84" + cset "name='RX_RX1 Digital Volume' 84" + cset "name='HPHL Volume' 20" + cset "name='HPHR Volume' 20" + cset "name='ADC2 Volume' 10" +] + +LibraryConfig.remap.Config { + + ctl.default.map { + "name='HP Volume'" { + "name='HPHL Volume'".vindex.0 0 + "name='HPHR Volume'".vindex.1 0 + } + } +} + +Include.card-init.File "/lib/card-init.conf" +Include.ctl-remap.File "/lib/ctl-remap.conf" +Include.wcd-init.File "/codecs/wcd938x/init.conf" diff --git a/packages/bsp/ayn-odin2/HiFi.conf b/packages/bsp/ayn-odin2/HiFi.conf new file mode 100644 index 000000000..dc5211e12 --- /dev/null +++ b/packages/bsp/ayn-odin2/HiFi.conf @@ -0,0 +1,91 @@ +# Use case configuration for AYN Odin2 +# Author: Teguh Sobirin + +SectionVerb { + EnableSequence [ + cset "name='PRIMARY_MI2S_RX Audio Mixer MultiMedia1' 1" + cset "name='RX_CODEC_DMA_RX_0 Audio Mixer MultiMedia2' 1" + cset "name='DISPLAY_PORT_RX_0 Audio Mixer MultiMedia2' 0" + cset "name='MultiMedia3 Mixer TX_CODEC_DMA_TX_3' 1" + ] + + DisableSequence [ + cset "name='PRIMARY_MI2S_RX Audio Mixer MultiMedia1' 0" + cset "name='RX_CODEC_DMA_RX_0 Audio Mixer MultiMedia2' 0" + cset "name='DISPLAY_PORT_RX_0 Audio Mixer MultiMedia2' 0" + cset "name='MultiMedia3 Mixer TX_CODEC_DMA_TX_3' 0" + ] + + Value { + TQ "HiFi" + } +} + +SectionDevice."Speaker" { + Comment "Speaker playback" + + Value { + PlaybackPriority 150 + PlaybackPCM "hw:${CardId},0" + PlaybackChannels 2 + } +} + +SectionDevice."Headphones" { + Comment "Headphones Playback" + + Include.wcdhpe.File "/codecs/wcd938x/HeadphoneEnableSeq.conf" + Include.wcdhpd.File "/codecs/wcd938x/HeadphoneDisableSeq.conf" + Include.rxmhpe.File "/codecs/qcom-lpass/rx-macro/HeadphoneEnableSeq.conf" + Include.rxmhpd.File "/codecs/qcom-lpass/rx-macro/HeadphoneDisableSeq.conf" + + Value { + PlaybackPriority 200 + PlaybackPCM "hw:${CardId},1" + PlaybackMixer "default:${CardId}" + PlaybackMixerElem "HP" + PlaybackChannels 2 + JackControl "Headphone Jack" + JackHWMute "Speaker" + } +} + +SectionDevice."Headset" { + Comment "Headphone Microphone" + + Include.wcdmice.File "/codecs/wcd938x/HeadphoneMicEnableSeq.conf" + Include.wcdmicd.File "/codecs/wcd938x/HeadphoneMicDisableSeq.conf" + Include.txmhpe.File "/codecs/qcom-lpass/tx-macro/SoundwireMic1EnableSeq.conf" + Include.txmhpd.File "/codecs/qcom-lpass/tx-macro/HeadphoneMicDisableSeq.conf" + + Value { + CapturePriority 200 + CapturePCM "hw:${CardId},2" + CaptureMixerElem "ADC2" + CaptureChannels 1 + JackControl "Mic Jack" + } +} + +SectionDevice."DisplayPort" { + Comment "DisplayPort playback" + + EnableSequence [ + cset "name='PRIMARY_MI2S_RX Audio Mixer MultiMedia1' 0" + cset "name='RX_CODEC_DMA_RX_0 Audio Mixer MultiMedia2' 0" + cset "name='DISPLAY_PORT_RX_0 Audio Mixer MultiMedia2' 1" + ] + + DisableSequence [ + cset "name='PRIMARY_MI2S_RX Audio Mixer MultiMedia1' 1" + cset "name='DISPLAY_PORT_RX_0 Audio Mixer MultiMedia2' 0" + cset "name='RX_CODEC_DMA_RX_0 Audio Mixer MultiMedia2' 1" + ] + + Value { + PlaybackPriority 100 + PlaybackPCM "hw:${CardId},1" + JackControl "DP0 Jack" + JackHWMute "Speaker" + } +} diff --git a/packages/bsp/ayn-odin2/LinuxLoader.cfg b/packages/bsp/ayn-odin2/LinuxLoader.cfg index 2d80f60db..7e7cdb312 100755 --- a/packages/bsp/ayn-odin2/LinuxLoader.cfg +++ b/packages/bsp/ayn-odin2/LinuxLoader.cfg @@ -6,7 +6,7 @@ # Controls on-screen logging # This setting can persist without config file or sdcard being present -Debug = false +Debug = true # Boot target. Can be one of the following: # "default" (ABL default) @@ -53,10 +53,6 @@ DisableDisplayHW = true # Accept both gzipped and non-gzipped kernel images Image = "Image" initrd = "initrd.img-INITRD_PLACEHOLDER" -devicetree = "dtb/qcom/qcs8550-ayn-odin2-hypdtbo.dtb" -cmdline = "clk_ignore_unused pd_ignore_unused panic=30 audit=0 allow_mismatched_32bit_el0 rw mem_sleep_default=s2idle root=UUID=UUID_PLACEHOLDER" +devicetree = "dtb/qcom/qcs8550-ayn-odin2.dtb" +cmdline = "clk_ignore_unused pd_ignore_unused quiet rw rootwait root=UUID=UUID_PLACEHOLDER" -[EFI] -Image = "EFI/BOOT/BOOTAA64.EFI" -# Options to be passed to the EFI Application, could be left empty -Options = "earlycon=efifb,mem" diff --git a/packages/bsp/ayn-odin2/bt-fixed-mac.service b/packages/bsp/ayn-odin2/bt-fixed-mac.service deleted file mode 100644 index ac801f185..000000000 --- a/packages/bsp/ayn-odin2/bt-fixed-mac.service +++ /dev/null @@ -1,11 +0,0 @@ -[Unit] -Description=Bluetooth Fixed Mac Address -After=bluetooth.service -Wants=bluetooth.service -[Service] -Type=oneshot -RemainAfterExit=yes -SyslogIdentifier=bt-fixed-mac -ExecStart=/usr/local/bin/bt-fixed-mac.sh -[Install] -WantedBy=bluetooth.target diff --git a/packages/bsp/ayn-odin2/bt-fixed-mac.sh b/packages/bsp/ayn-odin2/bt-fixed-mac.sh deleted file mode 100644 index b124c0c59..000000000 --- a/packages/bsp/ayn-odin2/bt-fixed-mac.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -cmdline=$(cat /proc/cmdline) - -if [[ $cmdline == *'bt_mac='* ]]; then - bt_mac=$(echo $cmdline | grep -o 'bt_mac=[^ ]*' | cut -d'=' -f2) -else - bt_mac="2C:6D:C1:F1:93:32" -fi - -/usr/bin/bluetoothctl mgmt.public-addr $bt_mac diff --git a/patch/kernel/archive/sm8550-6.12/0000.patching_config.yaml b/patch/kernel/archive/sm8550-6.12/0000.patching_config.yaml new file mode 100644 index 000000000..4fc665201 --- /dev/null +++ b/patch/kernel/archive/sm8550-6.12/0000.patching_config.yaml @@ -0,0 +1,27 @@ +config: # This is file 'patch/kernel/archive/sm8250-6.7/0000.patching_config.yaml' + + # Just some info stuff; not used by the patching scripts + name: sm8550-6.12 + kind: kernel + type: mainline # or: vendor + branch: linux-6.12.y + last-known-good-tag: v6.12.17 + + # .dts files in these directories will be copied as-is to the build tree; later ones overwrite earlier ones. + # This is meant to provide a way to "add a board DTS" without having to null-patch them in. + dts-directories: + - { source: "dt", target: "arch/arm64/boot/dts/qcom" } + + # the Makefile in each of these directories will be magically patched to include the dts files copied + # or patched-in; overlay subdir will be included "-y" if it exists. + # No more Makefile patching needed, yay! + auto-patch-dt-makefile: + - { directory: "arch/arm64/boot/dts/qcom", config-var: "CONFIG_ARCH_QCOM" } + + # configuration for when applying patches to git / auto-rewriting patches (development cycle helpers) + patches-to-git: + do-not-commit-files: + - "MAINTAINERS" # constant churn, drop them. sorry. + do-not-commit-regexes: # Python-style regexes + - "^arch/([a-zA-Z0-9]+)/boot/dts/([a-zA-Z0-9]+)/Makefile$" # ignore DT Makefile patches, we've an auto-patcher now + diff --git a/patch/kernel/archive/sm8550-6.12/0001_dt-bindings--media--Add-video-support-for-QCOM-SM8.patch b/patch/kernel/archive/sm8550-6.12/0001_dt-bindings--media--Add-video-support-for-QCOM-SM8.patch new file mode 100644 index 000000000..fbf063097 --- /dev/null +++ b/patch/kernel/archive/sm8550-6.12/0001_dt-bindings--media--Add-video-support-for-QCOM-SM8.patch @@ -0,0 +1,189 @@ +From a9472b31293c4aa544519883eb600ca9176ae55e Mon Sep 17 00:00:00 2001 +From: Dikshita Agarwal +Date: Fri, 7 Feb 2025 13:24:41 +0530 +Subject: [PATCH] dt-bindings: media: Add video support for QCOM SM8550 SoC + +Introduce support for Qualcomm new video acceleration hardware i.e. +iris, used for video stream decoding and encoding on QCOM SM8550 SoC. + +Cc: devicetree@vger.kernel.org +Reviewed-by: Krzysztof Kozlowski +Tested-by: Stefan Schmidt # x1e80100 (Dell XPS 13 9345) +Reviewed-by: Stefan Schmidt +Tested-by: Neil Armstrong # on SM8550-QRD +Tested-by: Neil Armstrong # on SM8550-HDK +Signed-off-by: Dikshita Agarwal +Link: https://lore.kernel.org/r/20250207-qcom-video-iris-v10-1-ab66eeffbd20@quicinc.com +Signed-off-by: Neil Armstrong +--- + .../bindings/media/qcom,sm8550-iris.yaml | 158 ++++++++++++++++++ + 1 file changed, 158 insertions(+) + create mode 100644 Documentation/devicetree/bindings/media/qcom,sm8550-iris.yaml + +diff --git a/Documentation/devicetree/bindings/media/qcom,sm8550-iris.yaml b/Documentation/devicetree/bindings/media/qcom,sm8550-iris.yaml +new file mode 100644 +index 000000000000..e424ea84c211 +--- /dev/null ++++ b/Documentation/devicetree/bindings/media/qcom,sm8550-iris.yaml +@@ -0,0 +1,158 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/media/qcom,sm8550-iris.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Qualcomm iris video encode and decode accelerators ++ ++maintainers: ++ - Vikash Garodia ++ - Dikshita Agarwal ++ ++description: ++ The iris video processing unit is a video encode and decode accelerator ++ present on Qualcomm platforms. ++ ++allOf: ++ - $ref: qcom,venus-common.yaml# ++ ++properties: ++ compatible: ++ const: qcom,sm8550-iris ++ ++ power-domains: ++ maxItems: 4 ++ ++ power-domain-names: ++ items: ++ - const: venus ++ - const: vcodec0 ++ - const: mxc ++ - const: mmcx ++ ++ clocks: ++ maxItems: 3 ++ ++ clock-names: ++ items: ++ - const: iface ++ - const: core ++ - const: vcodec0_core ++ ++ interconnects: ++ maxItems: 2 ++ ++ interconnect-names: ++ items: ++ - const: cpu-cfg ++ - const: video-mem ++ ++ resets: ++ maxItems: 1 ++ ++ reset-names: ++ items: ++ - const: bus ++ ++ iommus: ++ maxItems: 2 ++ ++ dma-coherent: true ++ ++ operating-points-v2: true ++ ++ opp-table: ++ type: object ++ ++required: ++ - compatible ++ - power-domain-names ++ - interconnects ++ - interconnect-names ++ - resets ++ - reset-names ++ - iommus ++ - dma-coherent ++ ++unevaluatedProperties: false ++ ++examples: ++ - | ++ #include ++ #include ++ #include ++ #include ++ #include ++ #include ++ #include ++ #include ++ ++ video-codec@aa00000 { ++ compatible = "qcom,sm8550-iris"; ++ reg = <0x0aa00000 0xf0000>; ++ interrupts = ; ++ ++ power-domains = <&videocc VIDEO_CC_MVS0C_GDSC>, ++ <&videocc VIDEO_CC_MVS0_GDSC>, ++ <&rpmhpd RPMHPD_MXC>, ++ <&rpmhpd RPMHPD_MMCX>; ++ power-domain-names = "venus", "vcodec0", "mxc", "mmcx"; ++ ++ clocks = <&gcc GCC_VIDEO_AXI0_CLK>, ++ <&videocc VIDEO_CC_MVS0C_CLK>, ++ <&videocc VIDEO_CC_MVS0_CLK>; ++ clock-names = "iface", "core", "vcodec0_core"; ++ ++ interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS ++ &config_noc SLAVE_VENUS_CFG QCOM_ICC_TAG_ALWAYS>, ++ <&mmss_noc MASTER_VIDEO QCOM_ICC_TAG_ALWAYS ++ &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; ++ interconnect-names = "cpu-cfg", "video-mem"; ++ ++ memory-region = <&video_mem>; ++ ++ resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>; ++ reset-names = "bus"; ++ ++ iommus = <&apps_smmu 0x1940 0x0000>, ++ <&apps_smmu 0x1947 0x0000>; ++ dma-coherent; ++ ++ operating-points-v2 = <&iris_opp_table>; ++ ++ iris_opp_table: opp-table { ++ compatible = "operating-points-v2"; ++ ++ opp-240000000 { ++ opp-hz = /bits/ 64 <240000000>; ++ required-opps = <&rpmhpd_opp_svs>, ++ <&rpmhpd_opp_low_svs>; ++ }; ++ ++ opp-338000000 { ++ opp-hz = /bits/ 64 <338000000>; ++ required-opps = <&rpmhpd_opp_svs>, ++ <&rpmhpd_opp_svs>; ++ }; ++ ++ opp-366000000 { ++ opp-hz = /bits/ 64 <366000000>; ++ required-opps = <&rpmhpd_opp_svs_l1>, ++ <&rpmhpd_opp_svs_l1>; ++ }; ++ ++ opp-444000000 { ++ opp-hz = /bits/ 64 <444000000>; ++ required-opps = <&rpmhpd_opp_turbo>, ++ <&rpmhpd_opp_turbo>; ++ }; ++ ++ opp-533333334 { ++ opp-hz = /bits/ 64 <533333334>; ++ required-opps = <&rpmhpd_opp_turbo_l1>, ++ <&rpmhpd_opp_turbo_l1>; ++ }; ++ }; ++ }; ++... +-- +2.34.1 + diff --git a/patch/kernel/archive/sm8550-6.12/0002_media--iris--add-platform-driver-for-iris-video-de.patch b/patch/kernel/archive/sm8550-6.12/0002_media--iris--add-platform-driver-for-iris-video-de.patch new file mode 100644 index 000000000..d3c8ab062 --- /dev/null +++ b/patch/kernel/archive/sm8550-6.12/0002_media--iris--add-platform-driver-for-iris-video-de.patch @@ -0,0 +1,470 @@ +From 6c0d38b27062f15b4a20ece8dbcae548e41a37a6 Mon Sep 17 00:00:00 2001 +From: Dikshita Agarwal +Date: Fri, 7 Feb 2025 13:24:42 +0530 +Subject: [PATCH] media: iris: add platform driver for iris video device + +In preparation for adding H264 decode functionality, add the probe and +remove functions and platform data to initialize iris resources, which +are clocks, interconnects, power domains, reset clocks, and clock +frequencies used for the iris hardware. + +Reviewed-by: Bryan O'Donoghue +Reviewed-by: Hans Verkuil +Tested-by: Stefan Schmidt # x1e80100 (Dell XPS 13 9345) +Reviewed-by: Stefan Schmidt +Tested-by: Neil Armstrong # on SM8550-QRD +Tested-by: Neil Armstrong # on SM8550-HDK +Signed-off-by: Dikshita Agarwal +Link: https://lore.kernel.org/r/20250207-qcom-video-iris-v10-2-ab66eeffbd20@quicinc.com +Signed-off-by: Neil Armstrong +--- + drivers/media/platform/qcom/Kconfig | 1 + + drivers/media/platform/qcom/Makefile | 1 + + drivers/media/platform/qcom/iris/Kconfig | 9 + + drivers/media/platform/qcom/iris/Makefile | 4 + + drivers/media/platform/qcom/iris/iris_core.h | 54 ++++ + .../platform/qcom/iris/iris_platform_common.h | 35 +++ + .../platform/qcom/iris/iris_platform_sm8550.c | 37 +++ + drivers/media/platform/qcom/iris/iris_probe.c | 237 ++++++++++++++++++ + 8 files changed, 378 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/iris_core.h + create mode 100644 drivers/media/platform/qcom/iris/iris_platform_common.h + create mode 100644 drivers/media/platform/qcom/iris/iris_platform_sm8550.c + create mode 100644 drivers/media/platform/qcom/iris/iris_probe.c + +diff --git a/drivers/media/platform/qcom/Kconfig b/drivers/media/platform/qcom/Kconfig +index cc5799b9ea00..4f4d3a68e6e5 100644 +--- a/drivers/media/platform/qcom/Kconfig ++++ b/drivers/media/platform/qcom/Kconfig +@@ -3,4 +3,5 @@ + comment "Qualcomm media platform drivers" + + source "drivers/media/platform/qcom/camss/Kconfig" ++source "drivers/media/platform/qcom/iris/Kconfig" + source "drivers/media/platform/qcom/venus/Kconfig" +diff --git a/drivers/media/platform/qcom/Makefile b/drivers/media/platform/qcom/Makefile +index 4f055c396e04..ea2221a202c0 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 += iris/ + obj-y += venus/ +diff --git a/drivers/media/platform/qcom/iris/Kconfig b/drivers/media/platform/qcom/iris/Kconfig +new file mode 100644 +index 000000000000..34a2f81c5db3 +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/Kconfig +@@ -0,0 +1,9 @@ ++config VIDEO_QCOM_IRIS ++ tristate "Qualcomm iris V4L2 decoder driver" ++ depends on VIDEO_DEV ++ depends on ARCH_QCOM || COMPILE_TEST ++ help ++ This is a V4L2 driver for Qualcomm iris video accelerator ++ hardware. It accelerates 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 000000000000..7e701361492e +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/Makefile +@@ -0,0 +1,4 @@ ++iris-objs += iris_platform_sm8550.o \ ++ iris_probe.o \ ++ ++obj-$(CONFIG_VIDEO_QCOM_IRIS) += iris.o +diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h +new file mode 100644 +index 000000000000..27bc2ca71e1b +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_core.h +@@ -0,0 +1,54 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef __IRIS_CORE_H__ ++#define __IRIS_CORE_H__ ++ ++#include ++#include ++ ++#include "iris_platform_common.h" ++ ++struct icc_info { ++ const char *name; ++ u32 bw_min_kbps; ++ u32 bw_max_kbps; ++}; ++ ++/** ++ * struct iris_core - holds core parameters valid for all instances ++ * ++ * @dev: reference to device structure ++ * @reg_base: IO memory base address ++ * @irq: iris irq ++ * @v4l2_dev: a holder for v4l2 device structure ++ * @vdev_dec: iris video device structure for decoder ++ * @icc_tbl: table of iris interconnects ++ * @icc_count: count of iris interconnects ++ * @pmdomain_tbl: table of iris power domains ++ * @opp_pmdomain_tbl: table of opp power domains ++ * @clock_tbl: table of iris clocks ++ * @clk_count: count of iris clocks ++ * @resets: table of iris reset clocks ++ * @iris_platform_data: a structure for platform data ++ */ ++ ++struct iris_core { ++ struct device *dev; ++ void __iomem *reg_base; ++ int irq; ++ struct v4l2_device v4l2_dev; ++ struct video_device *vdev_dec; ++ struct icc_bulk_data *icc_tbl; ++ u32 icc_count; ++ struct dev_pm_domain_list *pmdomain_tbl; ++ struct dev_pm_domain_list *opp_pmdomain_tbl; ++ struct clk_bulk_data *clock_tbl; ++ u32 clk_count; ++ struct reset_control_bulk_data *resets; ++ const struct iris_platform_data *iris_platform_data; ++}; ++ ++#endif +diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h +new file mode 100644 +index 000000000000..31c53dad8136 +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_platform_common.h +@@ -0,0 +1,35 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef __IRIS_PLATFORM_COMMON_H__ ++#define __IRIS_PLATFORM_COMMON_H__ ++ ++extern struct iris_platform_data sm8550_data; ++ ++enum platform_clk_type { ++ IRIS_AXI_CLK, ++ IRIS_CTRL_CLK, ++ IRIS_HW_CLK, ++}; ++ ++struct platform_clk_data { ++ enum platform_clk_type clk_type; ++ const char *clk_name; ++}; ++ ++struct iris_platform_data { ++ const struct icc_info *icc_tbl; ++ unsigned int icc_tbl_size; ++ const char * const *pmdomain_tbl; ++ unsigned int pmdomain_tbl_size; ++ const char * const *opp_pd_tbl; ++ unsigned int opp_pd_tbl_size; ++ const struct platform_clk_data *clk_tbl; ++ unsigned int clk_tbl_size; ++ const char * const *clk_rst_tbl; ++ unsigned int clk_rst_tbl_size; ++}; ++ ++#endif +diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +new file mode 100644 +index 000000000000..3dd91523d783 +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +@@ -0,0 +1,37 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include "iris_core.h" ++#include "iris_platform_common.h" ++ ++static const struct icc_info sm8550_icc_table[] = { ++ { "cpu-cfg", 1000, 1000 }, ++ { "video-mem", 1000, 15000000 }, ++}; ++ ++static const char * const sm8550_clk_reset_table[] = { "bus" }; ++ ++static const char * const sm8550_pmdomain_table[] = { "venus", "vcodec0" }; ++ ++static const char * const sm8550_opp_pd_table[] = { "mxc", "mmcx" }; ++ ++static const struct platform_clk_data sm8550_clk_table[] = { ++ {IRIS_AXI_CLK, "iface" }, ++ {IRIS_CTRL_CLK, "core" }, ++ {IRIS_HW_CLK, "vcodec0_core" }, ++}; ++ ++struct iris_platform_data sm8550_data = { ++ .icc_tbl = sm8550_icc_table, ++ .icc_tbl_size = ARRAY_SIZE(sm8550_icc_table), ++ .clk_rst_tbl = sm8550_clk_reset_table, ++ .clk_rst_tbl_size = ARRAY_SIZE(sm8550_clk_reset_table), ++ .pmdomain_tbl = sm8550_pmdomain_table, ++ .pmdomain_tbl_size = ARRAY_SIZE(sm8550_pmdomain_table), ++ .opp_pd_tbl = sm8550_opp_pd_table, ++ .opp_pd_tbl_size = ARRAY_SIZE(sm8550_opp_pd_table), ++ .clk_tbl = sm8550_clk_table, ++ .clk_tbl_size = ARRAY_SIZE(sm8550_clk_table), ++}; +diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c +new file mode 100644 +index 000000000000..911e3bc1b434 +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_probe.c +@@ -0,0 +1,237 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "iris_core.h" ++ ++static int iris_init_icc(struct iris_core *core) ++{ ++ const struct icc_info *icc_tbl; ++ u32 i = 0; ++ ++ icc_tbl = core->iris_platform_data->icc_tbl; ++ ++ core->icc_count = core->iris_platform_data->icc_tbl_size; ++ core->icc_tbl = devm_kzalloc(core->dev, ++ sizeof(struct icc_bulk_data) * core->icc_count, ++ GFP_KERNEL); ++ if (!core->icc_tbl) ++ return -ENOMEM; ++ ++ for (i = 0; i < core->icc_count; i++) { ++ core->icc_tbl[i].name = icc_tbl[i].name; ++ core->icc_tbl[i].avg_bw = icc_tbl[i].bw_min_kbps; ++ core->icc_tbl[i].peak_bw = 0; ++ } ++ ++ return devm_of_icc_bulk_get(core->dev, core->icc_count, core->icc_tbl); ++} ++ ++static int iris_init_power_domains(struct iris_core *core) ++{ ++ const struct platform_clk_data *clk_tbl; ++ u32 clk_cnt, i; ++ int ret; ++ ++ struct dev_pm_domain_attach_data iris_pd_data = { ++ .pd_names = core->iris_platform_data->pmdomain_tbl, ++ .num_pd_names = core->iris_platform_data->pmdomain_tbl_size, ++ .pd_flags = PD_FLAG_NO_DEV_LINK, ++ }; ++ ++ struct dev_pm_domain_attach_data iris_opp_pd_data = { ++ .pd_names = core->iris_platform_data->opp_pd_tbl, ++ .num_pd_names = core->iris_platform_data->opp_pd_tbl_size, ++ .pd_flags = PD_FLAG_DEV_LINK_ON, ++ }; ++ ++ ret = devm_pm_domain_attach_list(core->dev, &iris_pd_data, &core->pmdomain_tbl); ++ if (ret < 0) ++ return ret; ++ ++ ret = devm_pm_domain_attach_list(core->dev, &iris_opp_pd_data, &core->opp_pmdomain_tbl); ++ if (ret < 0) ++ return ret; ++ ++ clk_tbl = core->iris_platform_data->clk_tbl; ++ clk_cnt = core->iris_platform_data->clk_tbl_size; ++ ++ for (i = 0; i < clk_cnt; i++) { ++ if (clk_tbl[i].clk_type == IRIS_HW_CLK) { ++ ret = devm_pm_opp_set_clkname(core->dev, clk_tbl[i].clk_name); ++ if (ret) ++ return ret; ++ } ++ } ++ ++ return devm_pm_opp_of_add_table(core->dev); ++} ++ ++static int iris_init_clocks(struct iris_core *core) ++{ ++ int ret; ++ ++ ret = devm_clk_bulk_get_all(core->dev, &core->clock_tbl); ++ if (ret < 0) ++ return ret; ++ ++ core->clk_count = ret; ++ ++ return 0; ++} ++ ++static int iris_init_resets(struct iris_core *core) ++{ ++ const char * const *rst_tbl; ++ u32 rst_tbl_size; ++ u32 i = 0; ++ ++ rst_tbl = core->iris_platform_data->clk_rst_tbl; ++ rst_tbl_size = core->iris_platform_data->clk_rst_tbl_size; ++ ++ core->resets = devm_kzalloc(core->dev, ++ sizeof(*core->resets) * rst_tbl_size, ++ GFP_KERNEL); ++ if (!core->resets) ++ return -ENOMEM; ++ ++ for (i = 0; i < rst_tbl_size; i++) ++ core->resets[i].id = rst_tbl[i]; ++ ++ return devm_reset_control_bulk_get_exclusive(core->dev, rst_tbl_size, core->resets); ++} ++ ++static int iris_init_resources(struct iris_core *core) ++{ ++ int ret; ++ ++ ret = iris_init_icc(core); ++ if (ret) ++ return ret; ++ ++ ret = iris_init_power_domains(core); ++ if (ret) ++ return ret; ++ ++ ret = iris_init_clocks(core); ++ if (ret) ++ return ret; ++ ++ return iris_init_resets(core); ++} ++ ++static int iris_register_video_device(struct iris_core *core) ++{ ++ struct video_device *vdev; ++ int ret; ++ ++ vdev = video_device_alloc(); ++ if (!vdev) ++ return -ENOMEM; ++ ++ strscpy(vdev->name, "qcom-iris-decoder", sizeof(vdev->name)); ++ vdev->release = video_device_release; ++ vdev->vfl_dir = VFL_DIR_M2M; ++ vdev->v4l2_dev = &core->v4l2_dev; ++ vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; ++ ++ ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); ++ if (ret) ++ goto err_vdev_release; ++ ++ core->vdev_dec = vdev; ++ video_set_drvdata(vdev, core); ++ ++ return 0; ++ ++err_vdev_release: ++ video_device_release(vdev); ++ ++ return ret; ++} ++ ++static void iris_remove(struct platform_device *pdev) ++{ ++ struct iris_core *core; ++ ++ core = platform_get_drvdata(pdev); ++ if (!core) ++ return; ++ ++ video_unregister_device(core->vdev_dec); ++ ++ v4l2_device_unregister(&core->v4l2_dev); ++} ++ ++static int iris_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct iris_core *core; ++ int ret; ++ ++ core = devm_kzalloc(&pdev->dev, sizeof(*core), GFP_KERNEL); ++ if (!core) ++ return -ENOMEM; ++ core->dev = dev; ++ ++ core->reg_base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(core->reg_base)) ++ return PTR_ERR(core->reg_base); ++ ++ core->irq = platform_get_irq(pdev, 0); ++ if (core->irq < 0) ++ return core->irq; ++ ++ core->iris_platform_data = of_device_get_match_data(core->dev); ++ ++ ret = iris_init_resources(core); ++ if (ret) ++ return ret; ++ ++ ret = v4l2_device_register(dev, &core->v4l2_dev); ++ if (ret) ++ return ret; ++ ++ ret = iris_register_video_device(core); ++ if (ret) ++ goto err_v4l2_unreg; ++ ++ platform_set_drvdata(pdev, core); ++ ++ return 0; ++ ++err_v4l2_unreg: ++ v4l2_device_unregister(&core->v4l2_dev); ++ ++ return ret; ++} ++ ++static const struct of_device_id iris_dt_match[] = { ++ { ++ .compatible = "qcom,sm8550-iris", ++ .data = &sm8550_data, ++ }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, iris_dt_match); ++ ++static struct platform_driver qcom_iris_driver = { ++ .probe = iris_probe, ++ .remove = iris_remove, ++ .driver = { ++ .name = "qcom-iris", ++ .of_match_table = iris_dt_match, ++ }, ++}; ++ ++module_platform_driver(qcom_iris_driver); ++MODULE_DESCRIPTION("Qualcomm iris video driver"); ++MODULE_LICENSE("GPL"); +-- +2.34.1 + diff --git a/patch/kernel/archive/sm8550-6.12/0003_media--iris--implement-iris-v4l2-file-ops.patch b/patch/kernel/archive/sm8550-6.12/0003_media--iris--implement-iris-v4l2-file-ops.patch new file mode 100644 index 000000000..36dee97e6 --- /dev/null +++ b/patch/kernel/archive/sm8550-6.12/0003_media--iris--implement-iris-v4l2-file-ops.patch @@ -0,0 +1,450 @@ +From abaac8cb912c2c187c6c049012af5029d5ed3b38 Mon Sep 17 00:00:00 2001 +From: Dikshita Agarwal +Date: Fri, 7 Feb 2025 13:24:43 +0530 +Subject: [PATCH] media: iris: implement iris v4l2 file ops + +Implement open, close and poll ops. + +Open: +Configure the vb2 queue and v4l2 file handler. Allocate a video instance +and add the instance to core instance list. + +Close: +Free the instance and remove it from core instance list. + +Poll: +Wait for an event on vb2 src and vb2 dst queues. + +Reviewed-by: Bryan O'Donoghue +Reviewed-by: Hans Verkuil +Tested-by: Stefan Schmidt # x1e80100 (Dell XPS 13 9345) +Reviewed-by: Stefan Schmidt +Tested-by: Neil Armstrong # on SM8550-QRD +Tested-by: Neil Armstrong # on SM8550-HDK +Signed-off-by: Dikshita Agarwal +Link: https://lore.kernel.org/r/20250207-qcom-video-iris-v10-3-ab66eeffbd20@quicinc.com +Signed-off-by: Neil Armstrong +--- + drivers/media/platform/qcom/iris/Kconfig | 1 + + drivers/media/platform/qcom/iris/Makefile | 5 +- + drivers/media/platform/qcom/iris/iris_core.h | 2 + + .../media/platform/qcom/iris/iris_hfi_gen1.h | 13 ++ + .../qcom/iris/iris_hfi_gen1_command.c | 12 ++ + .../media/platform/qcom/iris/iris_hfi_gen2.h | 22 +++ + .../qcom/iris/iris_hfi_gen2_command.c | 11 ++ + .../media/platform/qcom/iris/iris_instance.h | 31 ++++ + .../platform/qcom/iris/iris_platform_common.h | 1 + + .../platform/qcom/iris/iris_platform_sm8550.c | 2 + + drivers/media/platform/qcom/iris/iris_probe.c | 3 + + drivers/media/platform/qcom/iris/iris_vidc.c | 147 ++++++++++++++++++ + drivers/media/platform/qcom/iris/iris_vidc.h | 15 ++ + 13 files changed, 264 insertions(+), 1 deletion(-) + create mode 100644 drivers/media/platform/qcom/iris/iris_hfi_gen1.h + create mode 100644 drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c + create mode 100644 drivers/media/platform/qcom/iris/iris_hfi_gen2.h + create mode 100644 drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c + create mode 100644 drivers/media/platform/qcom/iris/iris_instance.h + create mode 100644 drivers/media/platform/qcom/iris/iris_vidc.c + create mode 100644 drivers/media/platform/qcom/iris/iris_vidc.h + +diff --git a/drivers/media/platform/qcom/iris/Kconfig b/drivers/media/platform/qcom/iris/Kconfig +index 34a2f81c5db3..8debddec87a5 100644 +--- a/drivers/media/platform/qcom/iris/Kconfig ++++ b/drivers/media/platform/qcom/iris/Kconfig +@@ -2,6 +2,7 @@ config VIDEO_QCOM_IRIS + tristate "Qualcomm iris V4L2 decoder driver" + depends on VIDEO_DEV + depends on ARCH_QCOM || COMPILE_TEST ++ select V4L2_MEM2MEM_DEV + help + This is a V4L2 driver for Qualcomm iris video accelerator + hardware. It accelerates decoding operations on various +diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile +index 7e701361492e..6de584090a3a 100644 +--- a/drivers/media/platform/qcom/iris/Makefile ++++ b/drivers/media/platform/qcom/iris/Makefile +@@ -1,4 +1,7 @@ +-iris-objs += iris_platform_sm8550.o \ ++iris-objs += iris_hfi_gen1_command.o \ ++ iris_hfi_gen2_command.o \ ++ iris_platform_sm8550.o \ + iris_probe.o \ ++ iris_vidc.o \ + + obj-$(CONFIG_VIDEO_QCOM_IRIS) += iris.o +diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h +index 27bc2ca71e1b..aebb4eba7e15 100644 +--- a/drivers/media/platform/qcom/iris/iris_core.h ++++ b/drivers/media/platform/qcom/iris/iris_core.h +@@ -25,6 +25,7 @@ struct icc_info { + * @irq: iris irq + * @v4l2_dev: a holder for v4l2 device structure + * @vdev_dec: iris video device structure for decoder ++ * @iris_v4l2_file_ops: iris v4l2 file ops + * @icc_tbl: table of iris interconnects + * @icc_count: count of iris interconnects + * @pmdomain_tbl: table of iris power domains +@@ -41,6 +42,7 @@ struct iris_core { + int irq; + struct v4l2_device v4l2_dev; + struct video_device *vdev_dec; ++ const struct v4l2_file_operations *iris_v4l2_file_ops; + struct icc_bulk_data *icc_tbl; + u32 icc_count; + struct dev_pm_domain_list *pmdomain_tbl; +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1.h +new file mode 100644 +index 000000000000..5d05be7470e0 +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1.h +@@ -0,0 +1,13 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef __IRIS_HFI_GEN1_H__ ++#define __IRIS_HFI_GEN1_H__ ++ ++struct iris_inst; ++ ++struct iris_inst *iris_hfi_gen1_get_instance(void); ++ ++#endif +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +new file mode 100644 +index 000000000000..20c68f4ffb72 +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +@@ -0,0 +1,12 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include "iris_hfi_gen1.h" ++#include "iris_instance.h" ++ ++struct iris_inst *iris_hfi_gen1_get_instance(void) ++{ ++ return kzalloc(sizeof(struct iris_inst), GFP_KERNEL); ++} +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2.h +new file mode 100644 +index 000000000000..c159ed7f64f9 +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2.h +@@ -0,0 +1,22 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef __IRIS_HFI_GEN2_H__ ++#define __IRIS_HFI_GEN2_H__ ++ ++#include "iris_instance.h" ++ ++/** ++ * struct iris_inst_hfi_gen2 - holds per video instance parameters for hfi_gen2 ++ * ++ * @inst: pointer to iris_instance structure ++ */ ++struct iris_inst_hfi_gen2 { ++ struct iris_inst inst; ++}; ++ ++struct iris_inst *iris_hfi_gen2_get_instance(void); ++ ++#endif +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +new file mode 100644 +index 000000000000..3ee33c8befae +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +@@ -0,0 +1,11 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include "iris_hfi_gen2.h" ++ ++struct iris_inst *iris_hfi_gen2_get_instance(void) ++{ ++ return kzalloc(sizeof(struct iris_inst_hfi_gen2), GFP_KERNEL); ++} +diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/drivers/media/platform/qcom/iris/iris_instance.h +new file mode 100644 +index 000000000000..527a270f12d4 +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_instance.h +@@ -0,0 +1,31 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef __IRIS_INSTANCE_H__ ++#define __IRIS_INSTANCE_H__ ++ ++#include "iris_core.h" ++ ++/** ++ * struct iris_inst - holds per video instance parameters ++ * ++ * @core: pointer to core structure ++ * @ctx_q_lock: lock to serialize queues related ioctls ++ * @lock: lock to seralise forward and reverse threads ++ * @fh: reference of v4l2 file handler ++ * @m2m_dev: a reference to m2m device structure ++ * @m2m_ctx: a reference to m2m context structure ++ */ ++ ++struct iris_inst { ++ struct iris_core *core; ++ struct mutex ctx_q_lock;/* lock to serialize queues related ioctls */ ++ struct mutex lock; /* lock to serialize forward and reverse threads */ ++ struct v4l2_fh fh; ++ struct v4l2_m2m_dev *m2m_dev; ++ struct v4l2_m2m_ctx *m2m_ctx; ++}; ++ ++#endif +diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h +index 31c53dad8136..f82081ea135f 100644 +--- a/drivers/media/platform/qcom/iris/iris_platform_common.h ++++ b/drivers/media/platform/qcom/iris/iris_platform_common.h +@@ -20,6 +20,7 @@ struct platform_clk_data { + }; + + struct iris_platform_data { ++ struct iris_inst *(*get_instance)(void); + const struct icc_info *icc_tbl; + unsigned int icc_tbl_size; + const char * const *pmdomain_tbl; +diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +index 3dd91523d783..dba8d3c22ce5 100644 +--- a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c ++++ b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +@@ -4,6 +4,7 @@ + */ + + #include "iris_core.h" ++#include "iris_hfi_gen2.h" + #include "iris_platform_common.h" + + static const struct icc_info sm8550_icc_table[] = { +@@ -24,6 +25,7 @@ static const struct platform_clk_data sm8550_clk_table[] = { + }; + + struct iris_platform_data sm8550_data = { ++ .get_instance = iris_hfi_gen2_get_instance, + .icc_tbl = sm8550_icc_table, + .icc_tbl_size = ARRAY_SIZE(sm8550_icc_table), + .clk_rst_tbl = sm8550_clk_reset_table, +diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c +index 911e3bc1b434..ce16d894c809 100644 +--- a/drivers/media/platform/qcom/iris/iris_probe.c ++++ b/drivers/media/platform/qcom/iris/iris_probe.c +@@ -11,6 +11,7 @@ + #include + + #include "iris_core.h" ++#include "iris_vidc.h" + + static int iris_init_icc(struct iris_core *core) + { +@@ -139,6 +140,7 @@ static int iris_register_video_device(struct iris_core *core) + + strscpy(vdev->name, "qcom-iris-decoder", sizeof(vdev->name)); + vdev->release = video_device_release; ++ vdev->fops = core->iris_v4l2_file_ops; + vdev->vfl_dir = VFL_DIR_M2M; + vdev->v4l2_dev = &core->v4l2_dev; + vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; +@@ -192,6 +194,7 @@ static int iris_probe(struct platform_device *pdev) + + core->iris_platform_data = of_device_get_match_data(core->dev); + ++ iris_init_ops(core); + ret = iris_init_resources(core); + if (ret) + return ret; +diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c +new file mode 100644 +index 000000000000..e91d661c6280 +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_vidc.c +@@ -0,0 +1,147 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include ++#include ++ ++#include "iris_vidc.h" ++#include "iris_instance.h" ++#include "iris_platform_common.h" ++ ++#define IRIS_DRV_NAME "iris_driver" ++#define IRIS_BUS_NAME "platform:iris_icc" ++#define STEP_WIDTH 1 ++#define STEP_HEIGHT 1 ++ ++static void iris_v4l2_fh_init(struct iris_inst *inst) ++{ ++ v4l2_fh_init(&inst->fh, inst->core->vdev_dec); ++ v4l2_fh_add(&inst->fh); ++} ++ ++static void iris_v4l2_fh_deinit(struct iris_inst *inst) ++{ ++ v4l2_fh_del(&inst->fh); ++ v4l2_fh_exit(&inst->fh); ++} ++ ++static inline struct iris_inst *iris_get_inst(struct file *filp, void *fh) ++{ ++ return container_of(filp->private_data, struct iris_inst, fh); ++} ++ ++static void iris_m2m_device_run(void *priv) ++{ ++} ++ ++static void iris_m2m_job_abort(void *priv) ++{ ++ struct iris_inst *inst = priv; ++ struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; ++ ++ v4l2_m2m_job_finish(inst->m2m_dev, m2m_ctx); ++} ++ ++static const struct v4l2_m2m_ops iris_m2m_ops = { ++ .device_run = iris_m2m_device_run, ++ .job_abort = iris_m2m_job_abort, ++}; ++ ++static int ++iris_m2m_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq) ++{ ++ struct iris_inst *inst = priv; ++ int ret; ++ ++ src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; ++ src_vq->io_modes = VB2_MMAP | VB2_DMABUF; ++ src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; ++ src_vq->drv_priv = inst; ++ src_vq->dev = inst->core->dev; ++ src_vq->lock = &inst->ctx_q_lock; ++ ret = vb2_queue_init(src_vq); ++ if (ret) ++ return ret; ++ ++ dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; ++ dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; ++ dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; ++ dst_vq->drv_priv = inst; ++ dst_vq->dev = inst->core->dev; ++ dst_vq->lock = &inst->ctx_q_lock; ++ ++ return vb2_queue_init(dst_vq); ++} ++ ++int iris_open(struct file *filp) ++{ ++ struct iris_core *core = video_drvdata(filp); ++ struct iris_inst *inst; ++ int ret; ++ ++ inst = core->iris_platform_data->get_instance(); ++ if (!inst) ++ return -ENOMEM; ++ ++ inst->core = core; ++ ++ mutex_init(&inst->ctx_q_lock); ++ ++ iris_v4l2_fh_init(inst); ++ ++ inst->m2m_dev = v4l2_m2m_init(&iris_m2m_ops); ++ if (IS_ERR_OR_NULL(inst->m2m_dev)) { ++ ret = -EINVAL; ++ goto fail_v4l2_fh_deinit; ++ } ++ ++ inst->m2m_ctx = v4l2_m2m_ctx_init(inst->m2m_dev, inst, iris_m2m_queue_init); ++ if (IS_ERR_OR_NULL(inst->m2m_ctx)) { ++ ret = -EINVAL; ++ goto fail_m2m_release; ++ } ++ ++ inst->fh.m2m_ctx = inst->m2m_ctx; ++ filp->private_data = &inst->fh; ++ ++ return 0; ++ ++fail_m2m_release: ++ v4l2_m2m_release(inst->m2m_dev); ++fail_v4l2_fh_deinit: ++ iris_v4l2_fh_deinit(inst); ++ mutex_destroy(&inst->ctx_q_lock); ++ kfree(inst); ++ ++ return ret; ++} ++ ++int iris_close(struct file *filp) ++{ ++ struct iris_inst *inst = iris_get_inst(filp, NULL); ++ ++ v4l2_m2m_ctx_release(inst->m2m_ctx); ++ v4l2_m2m_release(inst->m2m_dev); ++ iris_v4l2_fh_deinit(inst); ++ mutex_destroy(&inst->ctx_q_lock); ++ kfree(inst); ++ filp->private_data = NULL; ++ ++ return 0; ++} ++ ++static struct v4l2_file_operations iris_v4l2_file_ops = { ++ .owner = THIS_MODULE, ++ .open = iris_open, ++ .release = iris_close, ++ .unlocked_ioctl = video_ioctl2, ++ .poll = v4l2_m2m_fop_poll, ++ .mmap = v4l2_m2m_fop_mmap, ++}; ++ ++void iris_init_ops(struct iris_core *core) ++{ ++ core->iris_v4l2_file_ops = &iris_v4l2_file_ops; ++} +diff --git a/drivers/media/platform/qcom/iris/iris_vidc.h b/drivers/media/platform/qcom/iris/iris_vidc.h +new file mode 100644 +index 000000000000..a26054ff55b5 +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_vidc.h +@@ -0,0 +1,15 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef __IRIS_VIDC_H__ ++#define __IRIS_VIDC_H__ ++ ++struct iris_core; ++ ++void iris_init_ops(struct iris_core *core); ++int iris_open(struct file *filp); ++int iris_close(struct file *filp); ++ ++#endif +-- +2.34.1 + diff --git a/patch/kernel/archive/sm8550-6.12/0004_media--iris--introduce-iris-core-state-management-.patch b/patch/kernel/archive/sm8550-6.12/0004_media--iris--introduce-iris-core-state-management-.patch new file mode 100644 index 000000000..67d109f52 --- /dev/null +++ b/patch/kernel/archive/sm8550-6.12/0004_media--iris--introduce-iris-core-state-management-.patch @@ -0,0 +1,636 @@ +From 3daede024ad4c5fe44a1bcc4d121385271788d13 Mon Sep 17 00:00:00 2001 +From: Dikshita Agarwal +Date: Fri, 7 Feb 2025 13:24:44 +0530 +Subject: [PATCH] media: iris: introduce iris core state management with shared + queues + +Introduce a core state management for iris driver with the necessary +queues needed for the host firmware communication. + +There are 3 types of queues: +Command queue - driver to write any command to firmware. +Message queue - firmware to send any response to the driver. +Debug queue - for the firmware to write debug messages. +Initialize and configure the shared queues during probe. + +Different states for core: +IRIS_CORE_DEINIT - default state. +IRIS_CORE_INIT - core state with core initialized. FW loaded and HW + brought out of reset, shared queues established + between host driver and firmware. +IRIS_CORE_ERROR - error state. + ----------- + | + V + ----------- + | DEINIT | + ----------- + ^ + / \ + / \ + / \ + / \ + v v + ----------- ----------. + | INIT |-->| ERROR | + ----------- ----------. + +Tested-by: Stefan Schmidt # x1e80100 (Dell XPS 13 9345) +Reviewed-by: Stefan Schmidt +Tested-by: Neil Armstrong # on SM8550-QRD +Tested-by: Neil Armstrong # on SM8550-HDK +Signed-off-by: Dikshita Agarwal +Link: https://lore.kernel.org/r/20250207-qcom-video-iris-v10-4-ab66eeffbd20@quicinc.com +Signed-off-by: Neil Armstrong +--- + drivers/media/platform/qcom/iris/Makefile | 4 +- + drivers/media/platform/qcom/iris/iris_core.c | 46 +++++ + drivers/media/platform/qcom/iris/iris_core.h | 23 +++ + .../media/platform/qcom/iris/iris_hfi_queue.c | 127 +++++++++++++ + .../media/platform/qcom/iris/iris_hfi_queue.h | 177 ++++++++++++++++++ + .../platform/qcom/iris/iris_platform_common.h | 1 + + .../platform/qcom/iris/iris_platform_sm8550.c | 2 + + drivers/media/platform/qcom/iris/iris_probe.c | 19 ++ + drivers/media/platform/qcom/iris/iris_state.h | 41 ++++ + drivers/media/platform/qcom/iris/iris_vidc.c | 6 + + 10 files changed, 445 insertions(+), 1 deletion(-) + create mode 100644 drivers/media/platform/qcom/iris/iris_core.c + create mode 100644 drivers/media/platform/qcom/iris/iris_hfi_queue.c + create mode 100644 drivers/media/platform/qcom/iris/iris_hfi_queue.h + create mode 100644 drivers/media/platform/qcom/iris/iris_state.h + +diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile +index 6de584090a3a..93711f108a77 100644 +--- a/drivers/media/platform/qcom/iris/Makefile ++++ b/drivers/media/platform/qcom/iris/Makefile +@@ -1,5 +1,7 @@ +-iris-objs += iris_hfi_gen1_command.o \ ++iris-objs += iris_core.o \ ++ iris_hfi_gen1_command.o \ + iris_hfi_gen2_command.o \ ++ iris_hfi_queue.o \ + iris_platform_sm8550.o \ + iris_probe.o \ + iris_vidc.o \ +diff --git a/drivers/media/platform/qcom/iris/iris_core.c b/drivers/media/platform/qcom/iris/iris_core.c +new file mode 100644 +index 000000000000..360a54909ef6 +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_core.c +@@ -0,0 +1,46 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include "iris_core.h" ++#include "iris_state.h" ++ ++void iris_core_deinit(struct iris_core *core) ++{ ++ mutex_lock(&core->lock); ++ iris_hfi_queues_deinit(core); ++ core->state = IRIS_CORE_DEINIT; ++ mutex_unlock(&core->lock); ++} ++ ++int iris_core_init(struct iris_core *core) ++{ ++ int ret; ++ ++ mutex_lock(&core->lock); ++ if (core->state == IRIS_CORE_INIT) { ++ ret = 0; ++ goto exit; ++ } else if (core->state == IRIS_CORE_ERROR) { ++ ret = -EINVAL; ++ goto error; ++ } ++ ++ core->state = IRIS_CORE_INIT; ++ ++ ret = iris_hfi_queues_init(core); ++ if (ret) ++ goto error; ++ ++ mutex_unlock(&core->lock); ++ ++ return 0; ++ ++error: ++ core->state = IRIS_CORE_DEINIT; ++exit: ++ mutex_unlock(&core->lock); ++ ++ return ret; ++} +diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h +index aebb4eba7e15..516082aa58c9 100644 +--- a/drivers/media/platform/qcom/iris/iris_core.h ++++ b/drivers/media/platform/qcom/iris/iris_core.h +@@ -9,7 +9,9 @@ + #include + #include + ++#include "iris_hfi_queue.h" + #include "iris_platform_common.h" ++#include "iris_state.h" + + struct icc_info { + const char *name; +@@ -34,6 +36,15 @@ struct icc_info { + * @clk_count: count of iris clocks + * @resets: table of iris reset clocks + * @iris_platform_data: a structure for platform data ++ * @state: current state of core ++ * @iface_q_table_daddr: device address for interface queue table memory ++ * @sfr_daddr: device address for SFR (Sub System Failure Reason) register memory ++ * @iface_q_table_vaddr: virtual address for interface queue table memory ++ * @sfr_vaddr: virtual address for SFR (Sub System Failure Reason) register memory ++ * @command_queue: shared interface queue to send commands to firmware ++ * @message_queue: shared interface queue to receive responses from firmware ++ * @debug_queue: shared interface queue to receive debug info from firmware ++ * @lock: a lock for this strucure + */ + + struct iris_core { +@@ -51,6 +62,18 @@ struct iris_core { + u32 clk_count; + struct reset_control_bulk_data *resets; + const struct iris_platform_data *iris_platform_data; ++ enum iris_core_state state; ++ dma_addr_t iface_q_table_daddr; ++ dma_addr_t sfr_daddr; ++ void *iface_q_table_vaddr; ++ void *sfr_vaddr; ++ struct iris_iface_q_info command_queue; ++ struct iris_iface_q_info message_queue; ++ struct iris_iface_q_info debug_queue; ++ struct mutex lock; /* lock for core related operations */ + }; + ++int iris_core_init(struct iris_core *core); ++void iris_core_deinit(struct iris_core *core); ++ + #endif +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_queue.c b/drivers/media/platform/qcom/iris/iris_hfi_queue.c +new file mode 100644 +index 000000000000..494ef205133d +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_hfi_queue.c +@@ -0,0 +1,127 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include "iris_core.h" ++#include "iris_hfi_queue.h" ++ ++static void iris_hfi_queue_set_header(struct iris_core *core, u32 queue_id, ++ struct iris_iface_q_info *iface_q) ++{ ++ iface_q->qhdr->status = 0x1; ++ iface_q->qhdr->start_addr = iface_q->device_addr; ++ iface_q->qhdr->header_type = IFACEQ_DFLT_QHDR; ++ iface_q->qhdr->queue_type = queue_id; ++ iface_q->qhdr->q_size = IFACEQ_QUEUE_SIZE / sizeof(u32); ++ iface_q->qhdr->pkt_size = 0; /* variable packet size */ ++ iface_q->qhdr->rx_wm = 0x1; ++ iface_q->qhdr->tx_wm = 0x1; ++ iface_q->qhdr->rx_req = 0x1; ++ iface_q->qhdr->tx_req = 0x0; ++ iface_q->qhdr->rx_irq_status = 0x0; ++ iface_q->qhdr->tx_irq_status = 0x0; ++ iface_q->qhdr->read_idx = 0x0; ++ iface_q->qhdr->write_idx = 0x0; ++ ++ /* ++ * Set receive request to zero on debug queue as there is no ++ * need of interrupt from video hardware for debug messages ++ */ ++ if (queue_id == IFACEQ_DBGQ_ID) ++ iface_q->qhdr->rx_req = 0; ++} ++ ++static void ++iris_hfi_queue_init(struct iris_core *core, u32 queue_id, struct iris_iface_q_info *iface_q) ++{ ++ struct iris_hfi_queue_table_header *q_tbl_hdr = core->iface_q_table_vaddr; ++ u32 offset = sizeof(*q_tbl_hdr) + (queue_id * IFACEQ_QUEUE_SIZE); ++ ++ iface_q->device_addr = core->iface_q_table_daddr + offset; ++ iface_q->kernel_vaddr = ++ (void *)((char *)core->iface_q_table_vaddr + offset); ++ iface_q->qhdr = &q_tbl_hdr->q_hdr[queue_id]; ++ ++ iris_hfi_queue_set_header(core, queue_id, iface_q); ++} ++ ++static void iris_hfi_queue_deinit(struct iris_iface_q_info *iface_q) ++{ ++ iface_q->qhdr = NULL; ++ iface_q->kernel_vaddr = NULL; ++ iface_q->device_addr = 0; ++} ++ ++int iris_hfi_queues_init(struct iris_core *core) ++{ ++ struct iris_hfi_queue_table_header *q_tbl_hdr; ++ u32 queue_size; ++ ++ /* Iris hardware requires 4K queue alignment */ ++ queue_size = ALIGN((sizeof(*q_tbl_hdr) + (IFACEQ_QUEUE_SIZE * IFACEQ_NUMQ)), SZ_4K); ++ core->iface_q_table_vaddr = dma_alloc_attrs(core->dev, queue_size, ++ &core->iface_q_table_daddr, ++ GFP_KERNEL, DMA_ATTR_WRITE_COMBINE); ++ if (!core->iface_q_table_vaddr) { ++ dev_err(core->dev, "queues alloc and map failed\n"); ++ return -ENOMEM; ++ } ++ ++ core->sfr_vaddr = dma_alloc_attrs(core->dev, SFR_SIZE, ++ &core->sfr_daddr, ++ GFP_KERNEL, DMA_ATTR_WRITE_COMBINE); ++ if (!core->sfr_vaddr) { ++ dev_err(core->dev, "sfr alloc and map failed\n"); ++ dma_free_attrs(core->dev, sizeof(*q_tbl_hdr), core->iface_q_table_vaddr, ++ core->iface_q_table_daddr, DMA_ATTR_WRITE_COMBINE); ++ return -ENOMEM; ++ } ++ ++ iris_hfi_queue_init(core, IFACEQ_CMDQ_ID, &core->command_queue); ++ iris_hfi_queue_init(core, IFACEQ_MSGQ_ID, &core->message_queue); ++ iris_hfi_queue_init(core, IFACEQ_DBGQ_ID, &core->debug_queue); ++ ++ q_tbl_hdr = (struct iris_hfi_queue_table_header *)core->iface_q_table_vaddr; ++ q_tbl_hdr->version = 0; ++ q_tbl_hdr->device_addr = (void *)core; ++ strscpy(q_tbl_hdr->name, "iris-hfi-queues", sizeof(q_tbl_hdr->name)); ++ q_tbl_hdr->size = sizeof(*q_tbl_hdr); ++ q_tbl_hdr->qhdr0_offset = sizeof(*q_tbl_hdr) - ++ (IFACEQ_NUMQ * sizeof(struct iris_hfi_queue_header)); ++ q_tbl_hdr->qhdr_size = sizeof(q_tbl_hdr->q_hdr[0]); ++ q_tbl_hdr->num_q = IFACEQ_NUMQ; ++ q_tbl_hdr->num_active_q = IFACEQ_NUMQ; ++ ++ /* Write sfr size in first word to be used by firmware */ ++ *((u32 *)core->sfr_vaddr) = SFR_SIZE; ++ ++ return 0; ++} ++ ++void iris_hfi_queues_deinit(struct iris_core *core) ++{ ++ u32 queue_size; ++ ++ if (!core->iface_q_table_vaddr) ++ return; ++ ++ iris_hfi_queue_deinit(&core->debug_queue); ++ iris_hfi_queue_deinit(&core->message_queue); ++ iris_hfi_queue_deinit(&core->command_queue); ++ ++ dma_free_attrs(core->dev, SFR_SIZE, core->sfr_vaddr, ++ core->sfr_daddr, DMA_ATTR_WRITE_COMBINE); ++ ++ core->sfr_vaddr = NULL; ++ core->sfr_daddr = 0; ++ ++ queue_size = ALIGN(sizeof(struct iris_hfi_queue_table_header) + ++ (IFACEQ_QUEUE_SIZE * IFACEQ_NUMQ), SZ_4K); ++ ++ dma_free_attrs(core->dev, queue_size, core->iface_q_table_vaddr, ++ core->iface_q_table_daddr, DMA_ATTR_WRITE_COMBINE); ++ ++ core->iface_q_table_vaddr = NULL; ++ core->iface_q_table_daddr = 0; ++} +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_queue.h b/drivers/media/platform/qcom/iris/iris_hfi_queue.h +new file mode 100644 +index 000000000000..99a3b83d063f +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_hfi_queue.h +@@ -0,0 +1,177 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef __IRIS_HFI_QUEUE_H__ ++#define __IRIS_HFI_QUEUE_H__ ++ ++struct iris_core; ++ ++/* ++ * Max 64 Buffers ( 32 input buffers and 32 output buffers) ++ * can be queued by v4l2 framework at any given time. ++ */ ++#define IFACEQ_MAX_BUF_COUNT 64 ++/* ++ * Max session supported are 16. ++ * this value is used to calcualte the size of ++ * individual shared queue. ++ */ ++#define IFACE_MAX_PARALLEL_SESSIONS 16 ++#define IFACEQ_DFLT_QHDR 0x0101 ++#define IFACEQ_MAX_PKT_SIZE 1024 /* Maximum size of a packet in the queue */ ++ ++/* ++ * SFR: Subsystem Failure Reason ++ * when hardware goes into bad state/failure, firmware fills this memory ++ * and driver will get to know the actual failure reason from this SFR buffer. ++ */ ++#define SFR_SIZE SZ_4K /* Iris hardware requires 4K queue alignment */ ++ ++#define IFACEQ_QUEUE_SIZE (IFACEQ_MAX_PKT_SIZE * \ ++ IFACEQ_MAX_BUF_COUNT * IFACE_MAX_PARALLEL_SESSIONS) ++ ++/* ++ * Memory layout of the shared queues: ++ * ++ * ||=================|| ^ ^ ^ ++ * || || | | | ++ * || Queue Table || 288 Bytes | | ++ * || Header || | | | ++ * || || | | | ++ * ||-----------------|| V | | ++ * ||-----------------|| ^ | | ++ * || || | | | ++ * || Command Queue || 56 Bytes | | ++ * || Header || | | | ++ * || || | | | ++ * ||-----------------|| V 456 Bytes | ++ * ||-----------------|| ^ | | ++ * || || | | | ++ * || Message Queue || 56 Bytes | | ++ * || Header || | | | ++ * || || | | | ++ * ||-----------------|| V | Buffer size aligned to 4k ++ * ||-----------------|| ^ | Overall Queue Size = 2,404 KB ++ * || || | | | ++ * || Debug Queue || 56 Bytes | | ++ * || Header || | | | ++ * || || | | | ++ * ||=================|| V V | ++ * ||=================|| ^ | ++ * || || | | ++ * || Command || 800 KB | ++ * || Queue || | | ++ * || || | | ++ * ||=================|| V | ++ * ||=================|| ^ | ++ * || || | | ++ * || Message || 800 KB | ++ * || Queue || | | ++ * || || | | ++ * ||=================|| V | ++ * ||=================|| ^ | ++ * || || | | ++ * || Debug || 800 KB | ++ * || Queue || | | ++ * || || | | ++ * ||=================|| V | ++ * || || | ++ * ||=================|| V ++ */ ++ ++/* ++ * Shared queues are used for communication between driver and firmware. ++ * There are 3 types of queues: ++ * Command queue - driver to write any command to firmware. ++ * Message queue - firmware to send any response to driver. ++ * Debug queue - firmware to write debug message. ++ */ ++ ++/* Host-firmware shared queue ids */ ++enum iris_iface_queue { ++ IFACEQ_CMDQ_ID, ++ IFACEQ_MSGQ_ID, ++ IFACEQ_DBGQ_ID, ++ IFACEQ_NUMQ, /* not an index */ ++}; ++ ++/** ++ * struct iris_hfi_queue_header ++ * ++ * @status: Queue status, bits (7:0), 0x1 - active, 0x0 - inactive ++ * @start_addr: Queue start address in non cached memory ++ * @queue_type: Queue ID ++ * @header_type: Default queue header ++ * @q_size: Queue size ++ * Number of queue packets if pkt_size is non-zero ++ * Queue size in bytes if pkt_size is zero ++ * @pkt_size: Size of queue packet entries ++ * 0x0: variable queue packet size ++ * non zero: size of queue packet entry, fixed ++ * @pkt_drop_cnt: Number of packets dropped by sender ++ * @rx_wm: Receiver watermark, applicable in event driven mode ++ * @tx_wm: Sender watermark, applicable in event driven mode ++ * @rx_req: Receiver sets this bit if queue is empty ++ * @tx_req: Sender sets this bit if queue is full ++ * @rx_irq_status: Receiver sets this bit and triggers an interrupt to ++ * the sender after packets are dequeued. Sender clears this bit ++ * @tx_irq_status: Sender sets this bit and triggers an interrupt to ++ * the receiver after packets are queued. Receiver clears this bit ++ * @read_idx: Index till where receiver has consumed the packets from the queue. ++ * @write_idx: Index till where sender has written the packets into the queue. ++ */ ++struct iris_hfi_queue_header { ++ u32 status; ++ u32 start_addr; ++ u16 queue_type; ++ u16 header_type; ++ u32 q_size; ++ u32 pkt_size; ++ u32 pkt_drop_cnt; ++ u32 rx_wm; ++ u32 tx_wm; ++ u32 rx_req; ++ u32 tx_req; ++ u32 rx_irq_status; ++ u32 tx_irq_status; ++ u32 read_idx; ++ u32 write_idx; ++}; ++ ++/** ++ * struct iris_hfi_queue_table_header ++ * ++ * @version: Queue table version number ++ * @size: Queue table size from version to last parametr in qhdr entry ++ * @qhdr0_offset: Offset to the start of first qhdr ++ * @qhdr_size: Queue header size in bytes ++ * @num_q: Total number of queues in Queue table ++ * @num_active_q: Total number of active queues ++ * @device_addr: Device address of the queue ++ * @name: Queue name in characters ++ * @q_hdr: Array of queue headers ++ */ ++struct iris_hfi_queue_table_header { ++ u32 version; ++ u32 size; ++ u32 qhdr0_offset; ++ u32 qhdr_size; ++ u32 num_q; ++ u32 num_active_q; ++ void *device_addr; ++ char name[256]; /* NUL-terminated array of characters */ ++ struct iris_hfi_queue_header q_hdr[IFACEQ_NUMQ]; ++}; ++ ++struct iris_iface_q_info { ++ struct iris_hfi_queue_header *qhdr; ++ dma_addr_t device_addr; ++ void *kernel_vaddr; ++}; ++ ++int iris_hfi_queues_init(struct iris_core *core); ++void iris_hfi_queues_deinit(struct iris_core *core); ++ ++#endif +diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h +index f82081ea135f..b4d63d6677c5 100644 +--- a/drivers/media/platform/qcom/iris/iris_platform_common.h ++++ b/drivers/media/platform/qcom/iris/iris_platform_common.h +@@ -31,6 +31,7 @@ struct iris_platform_data { + unsigned int clk_tbl_size; + const char * const *clk_rst_tbl; + unsigned int clk_rst_tbl_size; ++ u64 dma_mask; + }; + + #endif +diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +index dba8d3c22ce5..ddaa4991d645 100644 +--- a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c ++++ b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +@@ -36,4 +36,6 @@ struct iris_platform_data sm8550_data = { + .opp_pd_tbl_size = ARRAY_SIZE(sm8550_opp_pd_table), + .clk_tbl = sm8550_clk_table, + .clk_tbl_size = ARRAY_SIZE(sm8550_clk_table), ++ /* Upper bound of DMA address range */ ++ .dma_mask = 0xe0000000 - 1, + }; +diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c +index ce16d894c809..3015e6cb347f 100644 +--- a/drivers/media/platform/qcom/iris/iris_probe.c ++++ b/drivers/media/platform/qcom/iris/iris_probe.c +@@ -168,15 +168,20 @@ static void iris_remove(struct platform_device *pdev) + if (!core) + return; + ++ iris_core_deinit(core); ++ + video_unregister_device(core->vdev_dec); + + v4l2_device_unregister(&core->v4l2_dev); ++ ++ mutex_destroy(&core->lock); + } + + static int iris_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; + struct iris_core *core; ++ u64 dma_mask; + int ret; + + core = devm_kzalloc(&pdev->dev, sizeof(*core), GFP_KERNEL); +@@ -184,6 +189,9 @@ static int iris_probe(struct platform_device *pdev) + return -ENOMEM; + core->dev = dev; + ++ core->state = IRIS_CORE_DEINIT; ++ mutex_init(&core->lock); ++ + core->reg_base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(core->reg_base)) + return PTR_ERR(core->reg_base); +@@ -209,8 +217,19 @@ static int iris_probe(struct platform_device *pdev) + + platform_set_drvdata(pdev, core); + ++ dma_mask = core->iris_platform_data->dma_mask; ++ ++ ret = dma_set_mask_and_coherent(dev, dma_mask); ++ if (ret) ++ goto err_vdev_unreg; ++ ++ dma_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32)); ++ dma_set_seg_boundary(&pdev->dev, DMA_BIT_MASK(32)); ++ + return 0; + ++err_vdev_unreg: ++ video_unregister_device(core->vdev_dec); + err_v4l2_unreg: + v4l2_device_unregister(&core->v4l2_dev); + +diff --git a/drivers/media/platform/qcom/iris/iris_state.h b/drivers/media/platform/qcom/iris/iris_state.h +new file mode 100644 +index 000000000000..1ffe6fe706bd +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_state.h +@@ -0,0 +1,41 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef __IRIS_STATE_H__ ++#define __IRIS_STATE_H__ ++ ++/** ++ * enum iris_core_state ++ * ++ * @IRIS_CORE_DEINIT: default state. ++ * @IRIS_CORE_INIT: core state with core initialized. FW loaded and ++ * HW brought out of reset, shared queues established ++ * between host driver and firmware. ++ * @IRIS_CORE_ERROR: error state. ++ * ++ * ----------- ++ * | ++ * V ++ * ----------- ++ * +--->| DEINIT |<---+ ++ * | ----------- | ++ * | | | ++ * | v | ++ * | ----------- | ++ * | / \ | ++ * | / \ | ++ * | / \ | ++ * | v v v ++ * ----------- ----------- ++ * | INIT |--->| ERROR | ++ * ----------- ----------- ++ */ ++enum iris_core_state { ++ IRIS_CORE_DEINIT, ++ IRIS_CORE_INIT, ++ IRIS_CORE_ERROR, ++}; ++ ++#endif +diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c +index e91d661c6280..5dd0ccbaa2fb 100644 +--- a/drivers/media/platform/qcom/iris/iris_vidc.c ++++ b/drivers/media/platform/qcom/iris/iris_vidc.c +@@ -81,6 +81,12 @@ int iris_open(struct file *filp) + struct iris_inst *inst; + int ret; + ++ ret = iris_core_init(core); ++ if (ret) { ++ dev_err(core->dev, "core init failed\n"); ++ return ret; ++ } ++ + inst = core->iris_platform_data->get_instance(); + if (!inst) + return -ENOMEM; +-- +2.34.1 + diff --git a/patch/kernel/archive/sm8550-6.12/0005_media--iris--implement-video-firmware-load-unload.patch b/patch/kernel/archive/sm8550-6.12/0005_media--iris--implement-video-firmware-load-unload.patch new file mode 100644 index 000000000..1ed676df2 --- /dev/null +++ b/patch/kernel/archive/sm8550-6.12/0005_media--iris--implement-video-firmware-load-unload.patch @@ -0,0 +1,289 @@ +From a8c9526f7d4aae9c3308767e8932aa53cc6b5e4a Mon Sep 17 00:00:00 2001 +From: Dikshita Agarwal +Date: Fri, 7 Feb 2025 13:24:45 +0530 +Subject: [PATCH] media: iris: implement video firmware load/unload + +Load/unload the firmware into/from memory via the MDT loader. +The firmware is loaded as part of core initialization and unloaded as +part of core de-initialization. + +Tested-by: Stefan Schmidt # x1e80100 (Dell XPS 13 9345) +Reviewed-by: Stefan Schmidt +Tested-by: Neil Armstrong # on SM8550-QRD +Tested-by: Neil Armstrong # on SM8550-HDK +Signed-off-by: Dikshita Agarwal +Link: https://lore.kernel.org/r/20250207-qcom-video-iris-v10-5-ab66eeffbd20@quicinc.com +Signed-off-by: Neil Armstrong +--- + drivers/media/platform/qcom/iris/Kconfig | 2 + + drivers/media/platform/qcom/iris/Makefile | 1 + + drivers/media/platform/qcom/iris/iris_core.c | 8 ++ + .../media/platform/qcom/iris/iris_firmware.c | 111 ++++++++++++++++++ + .../media/platform/qcom/iris/iris_firmware.h | 14 +++ + .../platform/qcom/iris/iris_platform_common.h | 12 ++ + .../platform/qcom/iris/iris_platform_sm8550.c | 10 ++ + 7 files changed, 158 insertions(+) + create mode 100644 drivers/media/platform/qcom/iris/iris_firmware.c + create mode 100644 drivers/media/platform/qcom/iris/iris_firmware.h + +diff --git a/drivers/media/platform/qcom/iris/Kconfig b/drivers/media/platform/qcom/iris/Kconfig +index 8debddec87a5..f92cc7fe9378 100644 +--- a/drivers/media/platform/qcom/iris/Kconfig ++++ b/drivers/media/platform/qcom/iris/Kconfig +@@ -3,6 +3,8 @@ config VIDEO_QCOM_IRIS + depends on VIDEO_DEV + depends on ARCH_QCOM || COMPILE_TEST + select V4L2_MEM2MEM_DEV ++ select QCOM_MDT_LOADER if ARCH_QCOM ++ select QCOM_SCM + help + This is a V4L2 driver for Qualcomm iris video accelerator + hardware. It accelerates decoding operations on various +diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile +index 93711f108a77..6906caa2c481 100644 +--- a/drivers/media/platform/qcom/iris/Makefile ++++ b/drivers/media/platform/qcom/iris/Makefile +@@ -1,4 +1,5 @@ + iris-objs += iris_core.o \ ++ iris_firmware.o \ + iris_hfi_gen1_command.o \ + iris_hfi_gen2_command.o \ + iris_hfi_queue.o \ +diff --git a/drivers/media/platform/qcom/iris/iris_core.c b/drivers/media/platform/qcom/iris/iris_core.c +index 360a54909ef6..8c7d53c57086 100644 +--- a/drivers/media/platform/qcom/iris/iris_core.c ++++ b/drivers/media/platform/qcom/iris/iris_core.c +@@ -4,11 +4,13 @@ + */ + + #include "iris_core.h" ++#include "iris_firmware.h" + #include "iris_state.h" + + void iris_core_deinit(struct iris_core *core) + { + mutex_lock(&core->lock); ++ iris_fw_unload(core); + iris_hfi_queues_deinit(core); + core->state = IRIS_CORE_DEINIT; + mutex_unlock(&core->lock); +@@ -33,10 +35,16 @@ int iris_core_init(struct iris_core *core) + if (ret) + goto error; + ++ ret = iris_fw_load(core); ++ if (ret) ++ goto error_queue_deinit; ++ + mutex_unlock(&core->lock); + + return 0; + ++error_queue_deinit: ++ iris_hfi_queues_deinit(core); + error: + core->state = IRIS_CORE_DEINIT; + exit: +diff --git a/drivers/media/platform/qcom/iris/iris_firmware.c b/drivers/media/platform/qcom/iris/iris_firmware.c +new file mode 100644 +index 000000000000..3d14e596a471 +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_firmware.c +@@ -0,0 +1,111 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "iris_core.h" ++#include "iris_firmware.h" ++ ++#define MAX_FIRMWARE_NAME_SIZE 128 ++ ++static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name) ++{ ++ u32 pas_id = core->iris_platform_data->pas_id; ++ const struct firmware *firmware = NULL; ++ struct device *dev = core->dev; ++ struct reserved_mem *rmem; ++ struct device_node *node; ++ phys_addr_t mem_phys; ++ size_t res_size; ++ ssize_t fw_size; ++ void *mem_virt; ++ int ret; ++ ++ if (strlen(fw_name) >= MAX_FIRMWARE_NAME_SIZE - 4) ++ return -EINVAL; ++ ++ node = of_parse_phandle(dev->of_node, "memory-region", 0); ++ if (!node) ++ return -EINVAL; ++ ++ rmem = of_reserved_mem_lookup(node); ++ of_node_put(node); ++ if (!rmem) ++ return -EINVAL; ++ ++ mem_phys = rmem->base; ++ res_size = rmem->size; ++ ++ ret = request_firmware(&firmware, fw_name, dev); ++ if (ret) ++ return ret; ++ ++ fw_size = qcom_mdt_get_size(firmware); ++ if (fw_size < 0 || res_size < (size_t)fw_size) { ++ ret = -EINVAL; ++ goto err_release_fw; ++ } ++ ++ mem_virt = memremap(mem_phys, res_size, MEMREMAP_WC); ++ if (!mem_virt) ++ goto err_release_fw; ++ ++ ret = qcom_mdt_load(dev, firmware, fw_name, ++ pas_id, mem_virt, mem_phys, res_size, NULL); ++ if (ret) ++ goto err_mem_unmap; ++ ++ ret = qcom_scm_pas_auth_and_reset(pas_id); ++ if (ret) ++ goto err_mem_unmap; ++ ++ return ret; ++ ++err_mem_unmap: ++ memunmap(mem_virt); ++err_release_fw: ++ release_firmware(firmware); ++ ++ return ret; ++} ++ ++int iris_fw_load(struct iris_core *core) ++{ ++ struct tz_cp_config *cp_config = core->iris_platform_data->tz_cp_config_data; ++ const char *fwpath = NULL; ++ int ret; ++ ++ ret = of_property_read_string_index(core->dev->of_node, "firmware-name", 0, ++ &fwpath); ++ if (ret) ++ fwpath = core->iris_platform_data->fwname; ++ ++ ret = iris_load_fw_to_memory(core, fwpath); ++ if (ret) { ++ dev_err(core->dev, "firmware download failed\n"); ++ return -ENOMEM; ++ } ++ ++ ret = qcom_scm_mem_protect_video_var(cp_config->cp_start, ++ cp_config->cp_size, ++ cp_config->cp_nonpixel_start, ++ cp_config->cp_nonpixel_size); ++ if (ret) { ++ dev_err(core->dev, "protect memory failed\n"); ++ qcom_scm_pas_shutdown(core->iris_platform_data->pas_id); ++ return ret; ++ } ++ ++ return ret; ++} ++ ++int iris_fw_unload(struct iris_core *core) ++{ ++ return qcom_scm_pas_shutdown(core->iris_platform_data->pas_id); ++} +diff --git a/drivers/media/platform/qcom/iris/iris_firmware.h b/drivers/media/platform/qcom/iris/iris_firmware.h +new file mode 100644 +index 000000000000..266bdd92a124 +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_firmware.h +@@ -0,0 +1,14 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef __IRIS_FIRMWARE_H__ ++#define __IRIS_FIRMWARE_H__ ++ ++struct iris_core; ++ ++int iris_fw_load(struct iris_core *core); ++int iris_fw_unload(struct iris_core *core); ++ ++#endif +diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h +index b4d63d6677c5..42c1fe8e4fa6 100644 +--- a/drivers/media/platform/qcom/iris/iris_platform_common.h ++++ b/drivers/media/platform/qcom/iris/iris_platform_common.h +@@ -6,6 +6,8 @@ + #ifndef __IRIS_PLATFORM_COMMON_H__ + #define __IRIS_PLATFORM_COMMON_H__ + ++#define IRIS_PAS_ID 9 ++ + extern struct iris_platform_data sm8550_data; + + enum platform_clk_type { +@@ -19,6 +21,13 @@ struct platform_clk_data { + const char *clk_name; + }; + ++struct tz_cp_config { ++ u32 cp_start; ++ u32 cp_size; ++ u32 cp_nonpixel_start; ++ u32 cp_nonpixel_size; ++}; ++ + struct iris_platform_data { + struct iris_inst *(*get_instance)(void); + const struct icc_info *icc_tbl; +@@ -32,6 +41,9 @@ struct iris_platform_data { + const char * const *clk_rst_tbl; + unsigned int clk_rst_tbl_size; + u64 dma_mask; ++ const char *fwname; ++ u32 pas_id; ++ struct tz_cp_config *tz_cp_config_data; + }; + + #endif +diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +index ddaa4991d645..bf389181d8cc 100644 +--- a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c ++++ b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +@@ -24,6 +24,13 @@ static const struct platform_clk_data sm8550_clk_table[] = { + {IRIS_HW_CLK, "vcodec0_core" }, + }; + ++static struct tz_cp_config tz_cp_config_sm8550 = { ++ .cp_start = 0, ++ .cp_size = 0x25800000, ++ .cp_nonpixel_start = 0x01000000, ++ .cp_nonpixel_size = 0x24800000, ++}; ++ + struct iris_platform_data sm8550_data = { + .get_instance = iris_hfi_gen2_get_instance, + .icc_tbl = sm8550_icc_table, +@@ -38,4 +45,7 @@ struct iris_platform_data sm8550_data = { + .clk_tbl_size = ARRAY_SIZE(sm8550_clk_table), + /* Upper bound of DMA address range */ + .dma_mask = 0xe0000000 - 1, ++ .fwname = "qcom/vpu/vpu30_p4.mbn", ++ .pas_id = IRIS_PAS_ID, ++ .tz_cp_config_data = &tz_cp_config_sm8550, + }; +-- +2.34.1 + diff --git a/patch/kernel/archive/sm8550-6.12/0006_media--iris--implement-the-boot-sequence-of-the-fi.patch b/patch/kernel/archive/sm8550-6.12/0006_media--iris--implement-the-boot-sequence-of-the-fi.patch new file mode 100644 index 000000000..0df845ea9 --- /dev/null +++ b/patch/kernel/archive/sm8550-6.12/0006_media--iris--implement-the-boot-sequence-of-the-fi.patch @@ -0,0 +1,213 @@ +From e07ed986c1e7c280e556c6a070fddd70300e2aa1 Mon Sep 17 00:00:00 2001 +From: Dikshita Agarwal +Date: Fri, 7 Feb 2025 13:24:46 +0530 +Subject: [PATCH] media: iris: implement the boot sequence of the firmware + +Set the memory region on the firmware and implement the boot sequence. + +Tested-by: Stefan Schmidt # x1e80100 (Dell XPS 13 9345) +Reviewed-by: Stefan Schmidt +Tested-by: Neil Armstrong # on SM8550-QRD +Tested-by: Neil Armstrong # on SM8550-HDK +Signed-off-by: Dikshita Agarwal +Link: https://lore.kernel.org/r/20250207-qcom-video-iris-v10-6-ab66eeffbd20@quicinc.com +Signed-off-by: Neil Armstrong +--- + drivers/media/platform/qcom/iris/Makefile | 1 + + drivers/media/platform/qcom/iris/iris_core.c | 7 ++ + .../platform/qcom/iris/iris_platform_common.h | 1 + + .../platform/qcom/iris/iris_platform_sm8550.c | 3 + + .../platform/qcom/iris/iris_vpu_common.c | 89 +++++++++++++++++++ + .../platform/qcom/iris/iris_vpu_common.h | 13 +++ + 6 files changed, 114 insertions(+) + create mode 100644 drivers/media/platform/qcom/iris/iris_vpu_common.c + create mode 100644 drivers/media/platform/qcom/iris/iris_vpu_common.h + +diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile +index 6906caa2c481..792f1d6ac8f3 100644 +--- a/drivers/media/platform/qcom/iris/Makefile ++++ b/drivers/media/platform/qcom/iris/Makefile +@@ -6,5 +6,6 @@ iris-objs += iris_core.o \ + iris_platform_sm8550.o \ + iris_probe.o \ + iris_vidc.o \ ++ iris_vpu_common.o \ + + obj-$(CONFIG_VIDEO_QCOM_IRIS) += iris.o +diff --git a/drivers/media/platform/qcom/iris/iris_core.c b/drivers/media/platform/qcom/iris/iris_core.c +index 8c7d53c57086..5ad66ac113ae 100644 +--- a/drivers/media/platform/qcom/iris/iris_core.c ++++ b/drivers/media/platform/qcom/iris/iris_core.c +@@ -6,6 +6,7 @@ + #include "iris_core.h" + #include "iris_firmware.h" + #include "iris_state.h" ++#include "iris_vpu_common.h" + + void iris_core_deinit(struct iris_core *core) + { +@@ -39,10 +40,16 @@ int iris_core_init(struct iris_core *core) + if (ret) + goto error_queue_deinit; + ++ ret = iris_vpu_boot_firmware(core); ++ if (ret) ++ goto error_unload_fw; ++ + mutex_unlock(&core->lock); + + return 0; + ++error_unload_fw: ++ iris_fw_unload(core); + error_queue_deinit: + iris_hfi_queues_deinit(core); + error: +diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h +index 42c1fe8e4fa6..7e661e8928bd 100644 +--- a/drivers/media/platform/qcom/iris/iris_platform_common.h ++++ b/drivers/media/platform/qcom/iris/iris_platform_common.h +@@ -44,6 +44,7 @@ struct iris_platform_data { + const char *fwname; + u32 pas_id; + struct tz_cp_config *tz_cp_config_data; ++ u32 core_arch; + }; + + #endif +diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +index bf389181d8cc..237f932946d6 100644 +--- a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c ++++ b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +@@ -7,6 +7,8 @@ + #include "iris_hfi_gen2.h" + #include "iris_platform_common.h" + ++#define VIDEO_ARCH_LX 1 ++ + static const struct icc_info sm8550_icc_table[] = { + { "cpu-cfg", 1000, 1000 }, + { "video-mem", 1000, 15000000 }, +@@ -48,4 +50,5 @@ struct iris_platform_data sm8550_data = { + .fwname = "qcom/vpu/vpu30_p4.mbn", + .pas_id = IRIS_PAS_ID, + .tz_cp_config_data = &tz_cp_config_sm8550, ++ .core_arch = VIDEO_ARCH_LX, + }; +diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.c b/drivers/media/platform/qcom/iris/iris_vpu_common.c +new file mode 100644 +index 000000000000..959ed46e8f47 +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_vpu_common.c +@@ -0,0 +1,89 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include ++ ++#include "iris_core.h" ++#include "iris_vpu_common.h" ++ ++#define CPU_BASE_OFFS 0x000A0000 ++ ++#define CPU_CS_BASE_OFFS (CPU_BASE_OFFS) ++ ++#define CTRL_INIT (CPU_CS_BASE_OFFS + 0x48) ++#define CTRL_STATUS (CPU_CS_BASE_OFFS + 0x4C) ++ ++#define CTRL_ERROR_STATUS__M 0xfe ++ ++#define QTBL_INFO (CPU_CS_BASE_OFFS + 0x50) ++#define QTBL_ENABLE BIT(0) ++ ++#define QTBL_ADDR (CPU_CS_BASE_OFFS + 0x54) ++#define CPU_CS_SCIACMDARG3 (CPU_CS_BASE_OFFS + 0x58) ++#define SFR_ADDR (CPU_CS_BASE_OFFS + 0x5C) ++#define UC_REGION_ADDR (CPU_CS_BASE_OFFS + 0x64) ++#define UC_REGION_SIZE (CPU_CS_BASE_OFFS + 0x68) ++ ++#define CPU_CS_H2XSOFTINTEN (CPU_CS_BASE_OFFS + 0x148) ++#define HOST2XTENSA_INTR_ENABLE BIT(0) ++ ++#define CPU_CS_X2RPMH (CPU_CS_BASE_OFFS + 0x168) ++ ++static void iris_vpu_setup_ucregion_memory_map(struct iris_core *core) ++{ ++ u32 queue_size, value; ++ ++ /* Iris hardware requires 4K queue alignment */ ++ queue_size = ALIGN(sizeof(struct iris_hfi_queue_table_header) + ++ (IFACEQ_QUEUE_SIZE * IFACEQ_NUMQ), SZ_4K); ++ ++ value = (u32)core->iface_q_table_daddr; ++ writel(value, core->reg_base + UC_REGION_ADDR); ++ ++ /* Iris hardware requires 1M queue alignment */ ++ value = ALIGN(SFR_SIZE + queue_size, SZ_1M); ++ writel(value, core->reg_base + UC_REGION_SIZE); ++ ++ value = (u32)core->iface_q_table_daddr; ++ writel(value, core->reg_base + QTBL_ADDR); ++ ++ writel(QTBL_ENABLE, core->reg_base + QTBL_INFO); ++ ++ if (core->sfr_daddr) { ++ value = (u32)core->sfr_daddr + core->iris_platform_data->core_arch; ++ writel(value, core->reg_base + SFR_ADDR); ++ } ++} ++ ++int iris_vpu_boot_firmware(struct iris_core *core) ++{ ++ u32 ctrl_init = BIT(0), ctrl_status = 0, count = 0, max_tries = 1000; ++ ++ iris_vpu_setup_ucregion_memory_map(core); ++ ++ writel(ctrl_init, core->reg_base + CTRL_INIT); ++ writel(0x1, core->reg_base + CPU_CS_SCIACMDARG3); ++ ++ while (!ctrl_status && count < max_tries) { ++ ctrl_status = readl(core->reg_base + CTRL_STATUS); ++ if ((ctrl_status & CTRL_ERROR_STATUS__M) == 0x4) { ++ dev_err(core->dev, "invalid setting for uc_region\n"); ++ break; ++ } ++ ++ usleep_range(50, 100); ++ count++; ++ } ++ ++ if (count >= max_tries) { ++ dev_err(core->dev, "error booting up iris firmware\n"); ++ return -ETIME; ++ } ++ ++ writel(HOST2XTENSA_INTR_ENABLE, core->reg_base + CPU_CS_H2XSOFTINTEN); ++ writel(0x0, core->reg_base + CPU_CS_X2RPMH); ++ ++ return 0; ++} +diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.h b/drivers/media/platform/qcom/iris/iris_vpu_common.h +new file mode 100644 +index 000000000000..bafcf46520fd +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_vpu_common.h +@@ -0,0 +1,13 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef __IRIS_VPU_COMMON_H__ ++#define __IRIS_VPU_COMMON_H__ ++ ++struct iris_core; ++ ++int iris_vpu_boot_firmware(struct iris_core *core); ++ ++#endif +-- +2.34.1 + diff --git a/patch/kernel/archive/sm8550-6.12/0007_media--iris--introduce-host-firmware-interface-wit.patch b/patch/kernel/archive/sm8550-6.12/0007_media--iris--introduce-host-firmware-interface-wit.patch new file mode 100644 index 000000000..15189fa00 --- /dev/null +++ b/patch/kernel/archive/sm8550-6.12/0007_media--iris--introduce-host-firmware-interface-wit.patch @@ -0,0 +1,1697 @@ +From 7d344e57a0cb46998f3008df4f6e2d20e17aa94f Mon Sep 17 00:00:00 2001 +From: Dikshita Agarwal +Date: Fri, 7 Feb 2025 13:24:47 +0530 +Subject: [PATCH] media: iris: introduce host firmware interface with necessary + hooks + +The Host firmware interface (HFI) is a well defined set of interfaces +for the communication between the host driver and the firmware. The +commands and responses are exchanged in form of packets. One or multiple +packets are grouped under the packet header. Each packet has a packet +type which describes the specific HFI and the payload, which holds the +corresponding value for that HFI. + +Tested-by: Stefan Schmidt # x1e80100 (Dell XPS 13 9345) +Reviewed-by: Stefan Schmidt +Tested-by: Neil Armstrong # on SM8550-QRD +Tested-by: Neil Armstrong # on SM8550-HDK +Signed-off-by: Dikshita Agarwal +Link: https://lore.kernel.org/r/20250207-qcom-video-iris-v10-7-ab66eeffbd20@quicinc.com +Signed-off-by: Neil Armstrong +--- + drivers/media/platform/qcom/iris/Makefile | 4 + + drivers/media/platform/qcom/iris/iris_core.c | 24 +- + drivers/media/platform/qcom/iris/iris_core.h | 20 ++ + .../platform/qcom/iris/iris_hfi_common.c | 50 ++++ + .../platform/qcom/iris/iris_hfi_common.h | 60 +++++ + .../media/platform/qcom/iris/iris_hfi_gen1.h | 3 + + .../qcom/iris/iris_hfi_gen1_command.c | 61 +++++ + .../qcom/iris/iris_hfi_gen1_defines.h | 94 ++++++++ + .../qcom/iris/iris_hfi_gen1_response.c | 176 ++++++++++++++ + .../media/platform/qcom/iris/iris_hfi_gen2.h | 4 + + .../qcom/iris/iris_hfi_gen2_command.c | 74 ++++++ + .../qcom/iris/iris_hfi_gen2_defines.h | 46 ++++ + .../platform/qcom/iris/iris_hfi_gen2_packet.c | 161 +++++++++++++ + .../platform/qcom/iris/iris_hfi_gen2_packet.h | 69 ++++++ + .../qcom/iris/iris_hfi_gen2_response.c | 215 ++++++++++++++++++ + .../media/platform/qcom/iris/iris_hfi_queue.c | 173 ++++++++++++++ + .../media/platform/qcom/iris/iris_hfi_queue.h | 5 + + .../platform/qcom/iris/iris_platform_common.h | 17 ++ + .../platform/qcom/iris/iris_platform_sm8550.c | 14 ++ + drivers/media/platform/qcom/iris/iris_probe.c | 26 +++ + .../platform/qcom/iris/iris_vpu_common.c | 43 ++++ + .../platform/qcom/iris/iris_vpu_common.h | 3 + + 22 files changed, 1341 insertions(+), 1 deletion(-) + create mode 100644 drivers/media/platform/qcom/iris/iris_hfi_common.c + create mode 100644 drivers/media/platform/qcom/iris/iris_hfi_common.h + create mode 100644 drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h + create mode 100644 drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c + create mode 100644 drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h + create mode 100644 drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c + create mode 100644 drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h + create mode 100644 drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c + +diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile +index 792f1d6ac8f3..76ca5287c49f 100644 +--- a/drivers/media/platform/qcom/iris/Makefile ++++ b/drivers/media/platform/qcom/iris/Makefile +@@ -1,7 +1,11 @@ + iris-objs += iris_core.o \ + iris_firmware.o \ ++ iris_hfi_common.o \ + iris_hfi_gen1_command.o \ ++ iris_hfi_gen1_response.o \ + iris_hfi_gen2_command.o \ ++ iris_hfi_gen2_packet.o \ ++ iris_hfi_gen2_response.o \ + iris_hfi_queue.o \ + iris_platform_sm8550.o \ + iris_probe.o \ +diff --git a/drivers/media/platform/qcom/iris/iris_core.c b/drivers/media/platform/qcom/iris/iris_core.c +index 5ad66ac113ae..7e19bdd0a19b 100644 +--- a/drivers/media/platform/qcom/iris/iris_core.c ++++ b/drivers/media/platform/qcom/iris/iris_core.c +@@ -17,6 +17,24 @@ void iris_core_deinit(struct iris_core *core) + mutex_unlock(&core->lock); + } + ++static int iris_wait_for_system_response(struct iris_core *core) ++{ ++ u32 hw_response_timeout_val = core->iris_platform_data->hw_response_timeout; ++ int ret; ++ ++ if (core->state == IRIS_CORE_ERROR) ++ return -EIO; ++ ++ ret = wait_for_completion_timeout(&core->core_init_done, ++ msecs_to_jiffies(hw_response_timeout_val)); ++ if (!ret) { ++ core->state = IRIS_CORE_ERROR; ++ return -ETIMEDOUT; ++ } ++ ++ return 0; ++} ++ + int iris_core_init(struct iris_core *core) + { + int ret; +@@ -44,9 +62,13 @@ int iris_core_init(struct iris_core *core) + if (ret) + goto error_unload_fw; + ++ ret = iris_hfi_core_init(core); ++ if (ret) ++ goto error_unload_fw; ++ + mutex_unlock(&core->lock); + +- return 0; ++ return iris_wait_for_system_response(core); + + error_unload_fw: + iris_fw_unload(core); +diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h +index 516082aa58c9..c0f3c189d779 100644 +--- a/drivers/media/platform/qcom/iris/iris_core.h ++++ b/drivers/media/platform/qcom/iris/iris_core.h +@@ -9,6 +9,7 @@ + #include + #include + ++#include "iris_hfi_common.h" + #include "iris_hfi_queue.h" + #include "iris_platform_common.h" + #include "iris_state.h" +@@ -19,6 +20,9 @@ struct icc_info { + u32 bw_max_kbps; + }; + ++#define IRIS_FW_VERSION_LENGTH 128 ++#define IFACEQ_CORE_PKT_SIZE (1024 * 4) ++ + /** + * struct iris_core - holds core parameters valid for all instances + * +@@ -45,6 +49,14 @@ struct icc_info { + * @message_queue: shared interface queue to receive responses from firmware + * @debug_queue: shared interface queue to receive debug info from firmware + * @lock: a lock for this strucure ++ * @response_packet: a pointer to response packet from fw to driver ++ * @header_id: id of packet header ++ * @packet_id: id of packet ++ * @hfi_ops: iris hfi command ops ++ * @hfi_response_ops: iris hfi response ops ++ * @core_init_done: structure of signal completion for system response ++ * @intr_status: interrupt status ++ * @sys_error_handler: a delayed work for handling system fatal error + */ + + struct iris_core { +@@ -71,6 +83,14 @@ struct iris_core { + struct iris_iface_q_info message_queue; + struct iris_iface_q_info debug_queue; + struct mutex lock; /* lock for core related operations */ ++ u8 *response_packet; ++ u32 header_id; ++ u32 packet_id; ++ const struct iris_hfi_command_ops *hfi_ops; ++ const struct iris_hfi_response_ops *hfi_response_ops; ++ struct completion core_init_done; ++ u32 intr_status; ++ struct delayed_work sys_error_handler; + }; + + int iris_core_init(struct iris_core *core); +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.c b/drivers/media/platform/qcom/iris/iris_hfi_common.c +new file mode 100644 +index 000000000000..a19b988c9a88 +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_hfi_common.c +@@ -0,0 +1,50 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include "iris_core.h" ++#include "iris_hfi_common.h" ++#include "iris_vpu_common.h" ++ ++int iris_hfi_core_init(struct iris_core *core) ++{ ++ const struct iris_hfi_command_ops *hfi_ops = core->hfi_ops; ++ int ret; ++ ++ ret = hfi_ops->sys_init(core); ++ if (ret) ++ return ret; ++ ++ ret = hfi_ops->sys_image_version(core); ++ if (ret) ++ return ret; ++ ++ return hfi_ops->sys_interframe_powercollapse(core); ++} ++ ++irqreturn_t iris_hfi_isr(int irq, void *data) ++{ ++ disable_irq_nosync(irq); ++ ++ return IRQ_WAKE_THREAD; ++} ++ ++irqreturn_t iris_hfi_isr_handler(int irq, void *data) ++{ ++ struct iris_core *core = data; ++ ++ if (!core) ++ return IRQ_NONE; ++ ++ mutex_lock(&core->lock); ++ iris_vpu_clear_interrupt(core); ++ mutex_unlock(&core->lock); ++ ++ core->hfi_response_ops->hfi_response_handler(core); ++ ++ if (!iris_vpu_watchdog(core, core->intr_status)) ++ enable_irq(irq); ++ ++ return IRQ_HANDLED; ++} +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.h b/drivers/media/platform/qcom/iris/iris_hfi_common.h +new file mode 100644 +index 000000000000..b46a2f21102a +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_hfi_common.h +@@ -0,0 +1,60 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef __IRIS_HFI_COMMON_H__ ++#define __IRIS_HFI_COMMON_H__ ++ ++#include ++#include ++ ++struct iris_core; ++ ++enum hfi_packet_port_type { ++ HFI_PORT_NONE = 0x00000000, ++ HFI_PORT_BITSTREAM = 0x00000001, ++ HFI_PORT_RAW = 0x00000002, ++}; ++ ++enum hfi_packet_payload_info { ++ HFI_PAYLOAD_NONE = 0x00000000, ++ HFI_PAYLOAD_U32 = 0x00000001, ++ HFI_PAYLOAD_S32 = 0x00000002, ++ HFI_PAYLOAD_U64 = 0x00000003, ++ HFI_PAYLOAD_S64 = 0x00000004, ++ HFI_PAYLOAD_STRUCTURE = 0x00000005, ++ HFI_PAYLOAD_BLOB = 0x00000006, ++ HFI_PAYLOAD_STRING = 0x00000007, ++ HFI_PAYLOAD_Q16 = 0x00000008, ++ HFI_PAYLOAD_U32_ENUM = 0x00000009, ++ HFI_PAYLOAD_32_PACKED = 0x0000000a, ++ HFI_PAYLOAD_U32_ARRAY = 0x0000000b, ++ HFI_PAYLOAD_S32_ARRAY = 0x0000000c, ++ HFI_PAYLOAD_64_PACKED = 0x0000000d, ++}; ++ ++enum hfi_packet_host_flags { ++ HFI_HOST_FLAGS_NONE = 0x00000000, ++ HFI_HOST_FLAGS_INTR_REQUIRED = 0x00000001, ++ HFI_HOST_FLAGS_RESPONSE_REQUIRED = 0x00000002, ++ HFI_HOST_FLAGS_NON_DISCARDABLE = 0x00000004, ++ HFI_HOST_FLAGS_GET_PROPERTY = 0x00000008, ++}; ++ ++struct iris_hfi_command_ops { ++ int (*sys_init)(struct iris_core *core); ++ int (*sys_image_version)(struct iris_core *core); ++ int (*sys_interframe_powercollapse)(struct iris_core *core); ++}; ++ ++struct iris_hfi_response_ops { ++ void (*hfi_response_handler)(struct iris_core *core); ++}; ++ ++int iris_hfi_core_init(struct iris_core *core); ++ ++irqreturn_t iris_hfi_isr(int irq, void *data); ++irqreturn_t iris_hfi_isr_handler(int irq, void *data); ++ ++#endif +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1.h +index 5d05be7470e0..19b8e9054a75 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1.h +@@ -6,8 +6,11 @@ + #ifndef __IRIS_HFI_GEN1_H__ + #define __IRIS_HFI_GEN1_H__ + ++struct iris_core; + struct iris_inst; + ++void iris_hfi_gen1_command_ops_init(struct iris_core *core); ++void iris_hfi_gen1_response_ops_init(struct iris_core *core); + struct iris_inst *iris_hfi_gen1_get_instance(void); + + #endif +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +index 20c68f4ffb72..07007d8812ba 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +@@ -4,8 +4,69 @@ + */ + + #include "iris_hfi_gen1.h" ++#include "iris_hfi_gen1_defines.h" + #include "iris_instance.h" + ++static int iris_hfi_gen1_sys_init(struct iris_core *core) ++{ ++ struct hfi_sys_init_pkt sys_init_pkt; ++ ++ sys_init_pkt.hdr.size = sizeof(sys_init_pkt); ++ sys_init_pkt.hdr.pkt_type = HFI_CMD_SYS_INIT; ++ sys_init_pkt.arch_type = HFI_VIDEO_ARCH_OX; ++ ++ return iris_hfi_queue_cmd_write_locked(core, &sys_init_pkt, sys_init_pkt.hdr.size); ++} ++ ++static int iris_hfi_gen1_sys_image_version(struct iris_core *core) ++{ ++ struct hfi_sys_get_property_pkt packet; ++ ++ packet.hdr.size = sizeof(packet); ++ packet.hdr.pkt_type = HFI_CMD_SYS_GET_PROPERTY; ++ packet.num_properties = 1; ++ packet.data = HFI_PROPERTY_SYS_IMAGE_VERSION; ++ ++ return iris_hfi_queue_cmd_write_locked(core, &packet, packet.hdr.size); ++} ++ ++static int iris_hfi_gen1_sys_interframe_powercollapse(struct iris_core *core) ++{ ++ struct hfi_sys_set_property_pkt *pkt; ++ struct hfi_enable *hfi; ++ u32 packet_size; ++ int ret; ++ ++ packet_size = struct_size(pkt, data, 1) + sizeof(*hfi); ++ pkt = kzalloc(packet_size, GFP_KERNEL); ++ if (!pkt) ++ return -ENOMEM; ++ ++ hfi = (struct hfi_enable *)&pkt->data[1]; ++ ++ pkt->hdr.size = packet_size; ++ pkt->hdr.pkt_type = HFI_CMD_SYS_SET_PROPERTY; ++ pkt->num_properties = 1; ++ pkt->data[0] = HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL; ++ hfi->enable = true; ++ ++ ret = iris_hfi_queue_cmd_write_locked(core, pkt, pkt->hdr.size); ++ kfree(pkt); ++ ++ return ret; ++} ++ ++static const struct iris_hfi_command_ops iris_hfi_gen1_command_ops = { ++ .sys_init = iris_hfi_gen1_sys_init, ++ .sys_image_version = iris_hfi_gen1_sys_image_version, ++ .sys_interframe_powercollapse = iris_hfi_gen1_sys_interframe_powercollapse, ++}; ++ ++void iris_hfi_gen1_command_ops_init(struct iris_core *core) ++{ ++ core->hfi_ops = &iris_hfi_gen1_command_ops; ++} ++ + struct iris_inst *iris_hfi_gen1_get_instance(void) + { + return kzalloc(sizeof(struct iris_inst), GFP_KERNEL); +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +new file mode 100644 +index 000000000000..8af824a42bcf +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +@@ -0,0 +1,94 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef __IRIS_HFI_GEN1_DEFINES_H__ ++#define __IRIS_HFI_GEN1_DEFINES_H__ ++ ++#include ++ ++#define HFI_VIDEO_ARCH_OX 0x1 ++#define HFI_ERR_NONE 0x0 ++ ++#define HFI_CMD_SYS_INIT 0x10001 ++#define HFI_CMD_SYS_SET_PROPERTY 0x10005 ++#define HFI_CMD_SYS_GET_PROPERTY 0x10006 ++ ++#define HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL 0x5 ++#define HFI_PROPERTY_SYS_IMAGE_VERSION 0x6 ++ ++#define HFI_EVENT_SYS_ERROR 0x1 ++ ++#define HFI_MSG_SYS_INIT 0x20001 ++#define HFI_MSG_SYS_COV 0x20009 ++#define HFI_MSG_SYS_PROPERTY_INFO 0x2000a ++ ++#define HFI_MSG_EVENT_NOTIFY 0x21001 ++ ++struct hfi_pkt_hdr { ++ u32 size; ++ u32 pkt_type; ++}; ++ ++struct hfi_sys_init_pkt { ++ struct hfi_pkt_hdr hdr; ++ u32 arch_type; ++}; ++ ++struct hfi_sys_set_property_pkt { ++ struct hfi_pkt_hdr hdr; ++ u32 num_properties; ++ u32 data[]; ++}; ++ ++struct hfi_sys_get_property_pkt { ++ struct hfi_pkt_hdr hdr; ++ u32 num_properties; ++ u32 data; ++}; ++ ++struct hfi_msg_event_notify_pkt { ++ struct hfi_pkt_hdr hdr; ++ u32 event_id; ++ u32 event_data1; ++ u32 event_data2; ++ u32 ext_event_data[]; ++}; ++ ++struct hfi_msg_sys_init_done_pkt { ++ struct hfi_pkt_hdr hdr; ++ u32 error_type; ++ u32 num_properties; ++ u32 data[]; ++}; ++ ++struct hfi_msg_sys_property_info_pkt { ++ struct hfi_pkt_hdr hdr; ++ u32 num_properties; ++ u32 property; ++ u8 data[]; ++}; ++ ++struct hfi_enable { ++ u32 enable; ++}; ++ ++struct hfi_msg_sys_debug_pkt { ++ struct hfi_pkt_hdr hdr; ++ u32 msg_type; ++ u32 msg_size; ++ u32 time_stamp_hi; ++ u32 time_stamp_lo; ++ u8 msg_data[]; ++}; ++ ++struct hfi_msg_sys_coverage_pkt { ++ struct hfi_pkt_hdr hdr; ++ u32 msg_size; ++ u32 time_stamp_hi; ++ u32 time_stamp_lo; ++ u8 msg_data[]; ++}; ++ ++#endif +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c +new file mode 100644 +index 000000000000..78fefa4176f9 +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c +@@ -0,0 +1,176 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include "iris_hfi_gen1.h" ++#include "iris_hfi_gen1_defines.h" ++#include "iris_instance.h" ++ ++static void ++iris_hfi_gen1_sys_event_notify(struct iris_core *core, void *packet) ++{ ++ struct hfi_msg_event_notify_pkt *pkt = packet; ++ ++ if (pkt->event_id == HFI_EVENT_SYS_ERROR) ++ dev_err(core->dev, "sys error (type: %x, data1:%x, data2:%x)\n", ++ pkt->event_id, pkt->event_data1, pkt->event_data2); ++ ++ core->state = IRIS_CORE_ERROR; ++ schedule_delayed_work(&core->sys_error_handler, msecs_to_jiffies(10)); ++} ++ ++static void iris_hfi_gen1_sys_init_done(struct iris_core *core, void *packet) ++{ ++ struct hfi_msg_sys_init_done_pkt *pkt = packet; ++ ++ if (pkt->error_type != HFI_ERR_NONE) { ++ core->state = IRIS_CORE_ERROR; ++ return; ++ } ++ ++ complete(&core->core_init_done); ++} ++ ++static void ++iris_hfi_gen1_sys_get_prop_image_version(struct iris_core *core, ++ struct hfi_msg_sys_property_info_pkt *pkt) ++{ ++ int req_bytes = pkt->hdr.size - sizeof(*pkt); ++ char fw_version[IRIS_FW_VERSION_LENGTH]; ++ u8 *str_image_version; ++ u32 i; ++ ++ if (req_bytes < IRIS_FW_VERSION_LENGTH - 1 || !pkt->data[0] || pkt->num_properties > 1) { ++ dev_err(core->dev, "bad packet\n"); ++ return; ++ } ++ ++ str_image_version = pkt->data; ++ if (!str_image_version) { ++ dev_err(core->dev, "firmware version not available\n"); ++ return; ++ } ++ ++ for (i = 0; i < IRIS_FW_VERSION_LENGTH - 1; i++) { ++ if (str_image_version[i] != '\0') ++ fw_version[i] = str_image_version[i]; ++ else ++ fw_version[i] = ' '; ++ } ++ fw_version[i] = '\0'; ++ dev_dbg(core->dev, "firmware version: %s\n", fw_version); ++} ++ ++static void iris_hfi_gen1_sys_property_info(struct iris_core *core, void *packet) ++{ ++ struct hfi_msg_sys_property_info_pkt *pkt = packet; ++ ++ if (!pkt->num_properties) { ++ dev_dbg(core->dev, "no properties\n"); ++ return; ++ } ++ ++ switch (pkt->property) { ++ case HFI_PROPERTY_SYS_IMAGE_VERSION: ++ iris_hfi_gen1_sys_get_prop_image_version(core, pkt); ++ break; ++ default: ++ dev_dbg(core->dev, "unknown property data\n"); ++ break; ++ } ++} ++ ++struct iris_hfi_gen1_response_pkt_info { ++ u32 pkt; ++ u32 pkt_sz; ++}; ++ ++static const struct iris_hfi_gen1_response_pkt_info pkt_infos[] = { ++ { ++ .pkt = HFI_MSG_EVENT_NOTIFY, ++ .pkt_sz = sizeof(struct hfi_msg_event_notify_pkt), ++ }, ++ { ++ .pkt = HFI_MSG_SYS_INIT, ++ .pkt_sz = sizeof(struct hfi_msg_sys_init_done_pkt), ++ }, ++ { ++ .pkt = HFI_MSG_SYS_PROPERTY_INFO, ++ .pkt_sz = sizeof(struct hfi_msg_sys_property_info_pkt), ++ }, ++}; ++ ++static void iris_hfi_gen1_handle_response(struct iris_core *core, void *response) ++{ ++ struct hfi_pkt_hdr *hdr = (struct hfi_pkt_hdr *)response; ++ const struct iris_hfi_gen1_response_pkt_info *pkt_info; ++ struct device *dev = core->dev; ++ bool found = false; ++ u32 i; ++ ++ for (i = 0; i < ARRAY_SIZE(pkt_infos); i++) { ++ pkt_info = &pkt_infos[i]; ++ if (pkt_info->pkt != hdr->pkt_type) ++ continue; ++ found = true; ++ break; ++ } ++ ++ if (!found || hdr->size < pkt_info->pkt_sz) { ++ dev_err(dev, "bad packet size (%d should be %d, pkt type:%x, found %d)\n", ++ hdr->size, pkt_info->pkt_sz, hdr->pkt_type, found); ++ ++ return; ++ } ++ ++ switch (hdr->pkt_type) { ++ case HFI_MSG_SYS_INIT: ++ iris_hfi_gen1_sys_init_done(core, hdr); ++ break; ++ case HFI_MSG_SYS_PROPERTY_INFO: ++ iris_hfi_gen1_sys_property_info(core, hdr); ++ break; ++ case HFI_MSG_EVENT_NOTIFY: ++ iris_hfi_gen1_sys_event_notify(core, hdr); ++ break; ++ default: ++ break; ++ } ++} ++ ++static void iris_hfi_gen1_flush_debug_queue(struct iris_core *core, u8 *packet) ++{ ++ struct hfi_msg_sys_coverage_pkt *pkt; ++ ++ while (!iris_hfi_queue_dbg_read(core, packet)) { ++ pkt = (struct hfi_msg_sys_coverage_pkt *)packet; ++ ++ if (pkt->hdr.pkt_type != HFI_MSG_SYS_COV) { ++ struct hfi_msg_sys_debug_pkt *pkt = ++ (struct hfi_msg_sys_debug_pkt *)packet; ++ ++ dev_dbg(core->dev, "%s", pkt->msg_data); ++ } ++ } ++} ++ ++static void iris_hfi_gen1_response_handler(struct iris_core *core) ++{ ++ memset(core->response_packet, 0, sizeof(struct hfi_pkt_hdr)); ++ while (!iris_hfi_queue_msg_read(core, core->response_packet)) { ++ iris_hfi_gen1_handle_response(core, core->response_packet); ++ memset(core->response_packet, 0, sizeof(struct hfi_pkt_hdr)); ++ } ++ ++ iris_hfi_gen1_flush_debug_queue(core, core->response_packet); ++} ++ ++static const struct iris_hfi_response_ops iris_hfi_gen1_response_ops = { ++ .hfi_response_handler = iris_hfi_gen1_response_handler, ++}; ++ ++void iris_hfi_gen1_response_ops_init(struct iris_core *core) ++{ ++ core->hfi_response_ops = &iris_hfi_gen1_response_ops; ++} +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2.h +index c159ed7f64f9..c43b51774978 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2.h +@@ -8,6 +8,8 @@ + + #include "iris_instance.h" + ++struct iris_core; ++ + /** + * struct iris_inst_hfi_gen2 - holds per video instance parameters for hfi_gen2 + * +@@ -17,6 +19,8 @@ struct iris_inst_hfi_gen2 { + struct iris_inst inst; + }; + ++void iris_hfi_gen2_command_ops_init(struct iris_core *core); ++void iris_hfi_gen2_response_ops_init(struct iris_core *core); + struct iris_inst *iris_hfi_gen2_get_instance(void); + + #endif +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +index 3ee33c8befae..5eaebe170214 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +@@ -4,6 +4,80 @@ + */ + + #include "iris_hfi_gen2.h" ++#include "iris_hfi_gen2_packet.h" ++ ++#define NUM_SYS_INIT_PACKETS 8 ++ ++#define SYS_INIT_PKT_SIZE (sizeof(struct iris_hfi_header) + \ ++ NUM_SYS_INIT_PACKETS * (sizeof(struct iris_hfi_packet) + sizeof(u32))) ++ ++#define SYS_IFPC_PKT_SIZE (sizeof(struct iris_hfi_header) + \ ++ sizeof(struct iris_hfi_packet) + sizeof(u32)) ++ ++#define SYS_NO_PAYLOAD_PKT_SIZE (sizeof(struct iris_hfi_header) + \ ++ sizeof(struct iris_hfi_packet)) ++ ++static int iris_hfi_gen2_sys_init(struct iris_core *core) ++{ ++ struct iris_hfi_header *hdr; ++ int ret; ++ ++ hdr = kzalloc(SYS_INIT_PKT_SIZE, GFP_KERNEL); ++ if (!hdr) ++ return -ENOMEM; ++ ++ iris_hfi_gen2_packet_sys_init(core, hdr); ++ ret = iris_hfi_queue_cmd_write_locked(core, hdr, hdr->size); ++ ++ kfree(hdr); ++ ++ return ret; ++} ++ ++static int iris_hfi_gen2_sys_image_version(struct iris_core *core) ++{ ++ struct iris_hfi_header *hdr; ++ int ret; ++ ++ hdr = kzalloc(SYS_NO_PAYLOAD_PKT_SIZE, GFP_KERNEL); ++ if (!hdr) ++ return -ENOMEM; ++ ++ iris_hfi_gen2_packet_image_version(core, hdr); ++ ret = iris_hfi_queue_cmd_write_locked(core, hdr, hdr->size); ++ ++ kfree(hdr); ++ ++ return ret; ++} ++ ++static int iris_hfi_gen2_sys_interframe_powercollapse(struct iris_core *core) ++{ ++ struct iris_hfi_header *hdr; ++ int ret; ++ ++ hdr = kzalloc(SYS_IFPC_PKT_SIZE, GFP_KERNEL); ++ if (!hdr) ++ return -ENOMEM; ++ ++ iris_hfi_gen2_packet_sys_interframe_powercollapse(core, hdr); ++ ret = iris_hfi_queue_cmd_write_locked(core, hdr, hdr->size); ++ ++ kfree(hdr); ++ ++ return ret; ++} ++ ++static const struct iris_hfi_command_ops iris_hfi_gen2_command_ops = { ++ .sys_init = iris_hfi_gen2_sys_init, ++ .sys_image_version = iris_hfi_gen2_sys_image_version, ++ .sys_interframe_powercollapse = iris_hfi_gen2_sys_interframe_powercollapse, ++}; ++ ++void iris_hfi_gen2_command_ops_init(struct iris_core *core) ++{ ++ core->hfi_ops = &iris_hfi_gen2_command_ops; ++} + + struct iris_inst *iris_hfi_gen2_get_instance(void) + { +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +new file mode 100644 +index 000000000000..2640caa7f9c0 +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +@@ -0,0 +1,46 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef __IRIS_HFI_GEN2_DEFINES_H__ ++#define __IRIS_HFI_GEN2_DEFINES_H__ ++ ++#include ++ ++#define HFI_VIDEO_ARCH_LX 0x1 ++ ++#define HFI_CMD_BEGIN 0x01000000 ++#define HFI_CMD_INIT 0x01000001 ++#define HFI_CMD_END 0x01FFFFFF ++ ++#define HFI_PROP_BEGIN 0x03000000 ++#define HFI_PROP_IMAGE_VERSION 0x03000001 ++#define HFI_PROP_INTRA_FRAME_POWER_COLLAPSE 0x03000002 ++#define HFI_PROP_UBWC_MAX_CHANNELS 0x03000003 ++#define HFI_PROP_UBWC_MAL_LENGTH 0x03000004 ++#define HFI_PROP_UBWC_HBB 0x03000005 ++#define HFI_PROP_UBWC_BANK_SWZL_LEVEL1 0x03000006 ++#define HFI_PROP_UBWC_BANK_SWZL_LEVEL2 0x03000007 ++#define HFI_PROP_UBWC_BANK_SWZL_LEVEL3 0x03000008 ++#define HFI_PROP_UBWC_BANK_SPREADING 0x03000009 ++#define HFI_PROP_END 0x03FFFFFF ++ ++#define HFI_SYSTEM_ERROR_BEGIN 0x05000000 ++#define HFI_SYS_ERROR_WD_TIMEOUT 0x05000001 ++#define HFI_SYSTEM_ERROR_END 0x05FFFFFF ++ ++enum hfi_packet_firmware_flags { ++ HFI_FW_FLAGS_SUCCESS = 0x00000001, ++ HFI_FW_FLAGS_INFORMATION = 0x00000002, ++ HFI_FW_FLAGS_SESSION_ERROR = 0x00000004, ++ HFI_FW_FLAGS_SYSTEM_ERROR = 0x00000008, ++}; ++ ++struct hfi_debug_header { ++ u32 size; ++ u32 debug_level; ++ u32 reserved[2]; ++}; ++ ++#endif +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c +new file mode 100644 +index 000000000000..986013aa62df +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c +@@ -0,0 +1,161 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include "iris_hfi_common.h" ++#include "iris_hfi_gen2.h" ++#include "iris_hfi_gen2_packet.h" ++ ++static void iris_hfi_gen2_create_header(struct iris_hfi_header *hdr, ++ u32 session_id, u32 header_id) ++{ ++ memset(hdr, 0, sizeof(*hdr)); ++ ++ hdr->size = sizeof(*hdr); ++ hdr->session_id = session_id; ++ hdr->header_id = header_id; ++ hdr->num_packets = 0; ++} ++ ++static void iris_hfi_gen2_create_packet(struct iris_hfi_header *hdr, u32 pkt_type, ++ u32 pkt_flags, u32 payload_type, u32 port, ++ u32 packet_id, void *payload, u32 payload_size) ++{ ++ struct iris_hfi_packet *pkt = (struct iris_hfi_packet *)((u8 *)hdr + hdr->size); ++ u32 pkt_size = sizeof(*pkt) + payload_size; ++ ++ memset(pkt, 0, pkt_size); ++ pkt->size = pkt_size; ++ pkt->type = pkt_type; ++ pkt->flags = pkt_flags; ++ pkt->payload_info = payload_type; ++ pkt->port = port; ++ pkt->packet_id = packet_id; ++ if (payload_size) ++ memcpy(&pkt->payload[0], payload, payload_size); ++ ++ hdr->num_packets++; ++ hdr->size += pkt->size; ++} ++ ++void iris_hfi_gen2_packet_sys_init(struct iris_core *core, struct iris_hfi_header *hdr) ++{ ++ u32 payload = 0; ++ ++ iris_hfi_gen2_create_header(hdr, 0, core->header_id++); ++ ++ payload = HFI_VIDEO_ARCH_LX; ++ iris_hfi_gen2_create_packet(hdr, ++ HFI_CMD_INIT, ++ (HFI_HOST_FLAGS_RESPONSE_REQUIRED | ++ HFI_HOST_FLAGS_INTR_REQUIRED | ++ HFI_HOST_FLAGS_NON_DISCARDABLE), ++ HFI_PAYLOAD_U32, ++ HFI_PORT_NONE, ++ core->packet_id++, ++ &payload, ++ sizeof(u32)); ++ ++ payload = core->iris_platform_data->ubwc_config->max_channels; ++ iris_hfi_gen2_create_packet(hdr, ++ HFI_PROP_UBWC_MAX_CHANNELS, ++ HFI_HOST_FLAGS_NONE, ++ HFI_PAYLOAD_U32, ++ HFI_PORT_NONE, ++ core->packet_id++, ++ &payload, ++ sizeof(u32)); ++ ++ payload = core->iris_platform_data->ubwc_config->mal_length; ++ iris_hfi_gen2_create_packet(hdr, ++ HFI_PROP_UBWC_MAL_LENGTH, ++ HFI_HOST_FLAGS_NONE, ++ HFI_PAYLOAD_U32, ++ HFI_PORT_NONE, ++ core->packet_id++, ++ &payload, ++ sizeof(u32)); ++ ++ payload = core->iris_platform_data->ubwc_config->highest_bank_bit; ++ iris_hfi_gen2_create_packet(hdr, ++ HFI_PROP_UBWC_HBB, ++ HFI_HOST_FLAGS_NONE, ++ HFI_PAYLOAD_U32, ++ HFI_PORT_NONE, ++ core->packet_id++, ++ &payload, ++ sizeof(u32)); ++ ++ payload = core->iris_platform_data->ubwc_config->bank_swzl_level; ++ iris_hfi_gen2_create_packet(hdr, ++ HFI_PROP_UBWC_BANK_SWZL_LEVEL1, ++ HFI_HOST_FLAGS_NONE, ++ HFI_PAYLOAD_U32, ++ HFI_PORT_NONE, ++ core->packet_id++, ++ &payload, ++ sizeof(u32)); ++ ++ payload = core->iris_platform_data->ubwc_config->bank_swz2_level; ++ iris_hfi_gen2_create_packet(hdr, ++ HFI_PROP_UBWC_BANK_SWZL_LEVEL2, ++ HFI_HOST_FLAGS_NONE, ++ HFI_PAYLOAD_U32, ++ HFI_PORT_NONE, ++ core->packet_id++, ++ &payload, ++ sizeof(u32)); ++ ++ payload = core->iris_platform_data->ubwc_config->bank_swz3_level; ++ iris_hfi_gen2_create_packet(hdr, ++ HFI_PROP_UBWC_BANK_SWZL_LEVEL3, ++ HFI_HOST_FLAGS_NONE, ++ HFI_PAYLOAD_U32, ++ HFI_PORT_NONE, ++ core->packet_id++, ++ &payload, ++ sizeof(u32)); ++ ++ payload = core->iris_platform_data->ubwc_config->bank_spreading; ++ iris_hfi_gen2_create_packet(hdr, ++ HFI_PROP_UBWC_BANK_SPREADING, ++ HFI_HOST_FLAGS_NONE, ++ HFI_PAYLOAD_U32, ++ HFI_PORT_NONE, ++ core->packet_id++, ++ &payload, ++ sizeof(u32)); ++} ++ ++void iris_hfi_gen2_packet_image_version(struct iris_core *core, struct iris_hfi_header *hdr) ++{ ++ iris_hfi_gen2_create_header(hdr, 0, core->header_id++); ++ ++ iris_hfi_gen2_create_packet(hdr, ++ HFI_PROP_IMAGE_VERSION, ++ (HFI_HOST_FLAGS_RESPONSE_REQUIRED | ++ HFI_HOST_FLAGS_INTR_REQUIRED | ++ HFI_HOST_FLAGS_GET_PROPERTY), ++ HFI_PAYLOAD_NONE, ++ HFI_PORT_NONE, ++ core->packet_id++, ++ NULL, 0); ++} ++ ++void iris_hfi_gen2_packet_sys_interframe_powercollapse(struct iris_core *core, ++ struct iris_hfi_header *hdr) ++{ ++ u32 payload = 1; /* HFI_TRUE */ ++ ++ iris_hfi_gen2_create_header(hdr, 0 /*session_id*/, core->header_id++); ++ ++ iris_hfi_gen2_create_packet(hdr, ++ HFI_PROP_INTRA_FRAME_POWER_COLLAPSE, ++ HFI_HOST_FLAGS_NONE, ++ HFI_PAYLOAD_U32, ++ HFI_PORT_NONE, ++ core->packet_id++, ++ &payload, ++ sizeof(u32)); ++} +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h +new file mode 100644 +index 000000000000..10dcb6e4c3d9 +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h +@@ -0,0 +1,69 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef __IRIS_HFI_GEN2_PACKET_H__ ++#define __IRIS_HFI_GEN2_PACKET_H__ ++ ++#include "iris_hfi_gen2_defines.h" ++ ++struct iris_core; ++ ++/** ++ * struct iris_hfi_header ++ * ++ * @size: size of the total packet in bytes including hfi_header ++ * @session_id: For session level hfi_header session_id is non-zero. ++ * For system level hfi_header session_id is zero. ++ * @header_id: unique header id for each hfi_header ++ * @reserved: reserved for future use ++ * @num_packets: number of hfi_packet that are included with the hfi_header ++ */ ++struct iris_hfi_header { ++ u32 size; ++ u32 session_id; ++ u32 header_id; ++ u32 reserved[4]; ++ u32 num_packets; ++}; ++ ++/** ++ * struct iris_hfi_packet ++ * ++ * @size: size of the hfi_packet in bytes including payload ++ * @type: one of the below hfi_packet types: ++ * HFI_CMD_*, ++ * HFI_PROP_*, ++ * HFI_ERROR_*, ++ * HFI_INFO_*, ++ * HFI_SYS_ERROR_* ++ * @flags: hfi_packet flags. It is represented as bit masks. ++ * host packet flags are "enum hfi_packet_host_flags" ++ * firmware packet flags are "enum hfi_packet_firmware_flags" ++ * @payload_info: payload information indicated by "enum hfi_packet_payload_info" ++ * @port: hfi_packet port type indicated by "enum hfi_packet_port_type" ++ * This is bitmask and may be applicable to multiple ports. ++ * @packet_id: host hfi_packet contains unique packet id. ++ * firmware returns host packet id in response packet ++ * wherever applicable. If not applicable firmware sets it to zero. ++ * @reserved: reserved for future use. ++ * @payload: flexible array of payload having additional packet information. ++ */ ++struct iris_hfi_packet { ++ u32 size; ++ u32 type; ++ u32 flags; ++ u32 payload_info; ++ u32 port; ++ u32 packet_id; ++ u32 reserved[2]; ++ u32 payload[]; ++}; ++ ++void iris_hfi_gen2_packet_sys_init(struct iris_core *core, struct iris_hfi_header *hdr); ++void iris_hfi_gen2_packet_image_version(struct iris_core *core, struct iris_hfi_header *hdr); ++void iris_hfi_gen2_packet_sys_interframe_powercollapse(struct iris_core *core, ++ struct iris_hfi_header *hdr); ++ ++#endif +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c +new file mode 100644 +index 000000000000..007e4a7b6782 +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c +@@ -0,0 +1,215 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include "iris_hfi_gen2.h" ++#include "iris_hfi_gen2_defines.h" ++#include "iris_hfi_gen2_packet.h" ++#include "iris_vpu_common.h" ++ ++struct iris_hfi_gen2_core_hfi_range { ++ u32 begin; ++ u32 end; ++ int (*handle)(struct iris_core *core, struct iris_hfi_packet *pkt); ++}; ++ ++static int iris_hfi_gen2_validate_packet(u8 *response_pkt, u8 *core_resp_pkt) ++{ ++ u8 *response_limit = core_resp_pkt + IFACEQ_CORE_PKT_SIZE; ++ u32 response_pkt_size = *(u32 *)response_pkt; ++ ++ if (!response_pkt_size) ++ return -EINVAL; ++ ++ if (response_pkt_size < sizeof(struct iris_hfi_packet)) ++ return -EINVAL; ++ ++ if (response_pkt + response_pkt_size > response_limit) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static int iris_hfi_gen2_validate_hdr_packet(struct iris_core *core, struct iris_hfi_header *hdr) ++{ ++ struct iris_hfi_packet *packet; ++ int ret; ++ u8 *pkt; ++ u32 i; ++ ++ if (hdr->size < sizeof(*hdr) + sizeof(*packet)) ++ return -EINVAL; ++ ++ pkt = (u8 *)((u8 *)hdr + sizeof(*hdr)); ++ ++ for (i = 0; i < hdr->num_packets; i++) { ++ packet = (struct iris_hfi_packet *)pkt; ++ ret = iris_hfi_gen2_validate_packet(pkt, core->response_packet); ++ if (ret) ++ return ret; ++ ++ pkt += packet->size; ++ } ++ ++ return 0; ++} ++ ++static int iris_hfi_gen2_handle_system_error(struct iris_core *core, ++ struct iris_hfi_packet *pkt) ++{ ++ dev_err(core->dev, "received system error of type %#x\n", pkt->type); ++ ++ core->state = IRIS_CORE_ERROR; ++ schedule_delayed_work(&core->sys_error_handler, msecs_to_jiffies(10)); ++ ++ return 0; ++} ++ ++static int iris_hfi_gen2_handle_system_init(struct iris_core *core, ++ struct iris_hfi_packet *pkt) ++{ ++ if (!(pkt->flags & HFI_FW_FLAGS_SUCCESS)) { ++ core->state = IRIS_CORE_ERROR; ++ return 0; ++ } ++ ++ complete(&core->core_init_done); ++ ++ return 0; ++} ++ ++static int iris_hfi_gen2_handle_image_version_property(struct iris_core *core, ++ struct iris_hfi_packet *pkt) ++{ ++ u8 *str_image_version = (u8 *)pkt + sizeof(*pkt); ++ u32 req_bytes = pkt->size - sizeof(*pkt); ++ char fw_version[IRIS_FW_VERSION_LENGTH]; ++ u32 i; ++ ++ if (req_bytes < IRIS_FW_VERSION_LENGTH - 1) ++ return -EINVAL; ++ ++ for (i = 0; i < IRIS_FW_VERSION_LENGTH - 1; i++) { ++ if (str_image_version[i] != '\0') ++ fw_version[i] = str_image_version[i]; ++ else ++ fw_version[i] = ' '; ++ } ++ fw_version[i] = '\0'; ++ dev_dbg(core->dev, "firmware version: %s\n", fw_version); ++ ++ return 0; ++} ++ ++static int iris_hfi_gen2_handle_system_property(struct iris_core *core, ++ struct iris_hfi_packet *pkt) ++{ ++ switch (pkt->type) { ++ case HFI_PROP_IMAGE_VERSION: ++ return iris_hfi_gen2_handle_image_version_property(core, pkt); ++ default: ++ return 0; ++ } ++} ++ ++static int iris_hfi_gen2_handle_system_response(struct iris_core *core, ++ struct iris_hfi_header *hdr) ++{ ++ u8 *start_pkt = (u8 *)((u8 *)hdr + sizeof(*hdr)); ++ struct iris_hfi_packet *packet; ++ u32 i, j; ++ u8 *pkt; ++ int ret; ++ static const struct iris_hfi_gen2_core_hfi_range range[] = { ++ {HFI_SYSTEM_ERROR_BEGIN, HFI_SYSTEM_ERROR_END, iris_hfi_gen2_handle_system_error }, ++ {HFI_PROP_BEGIN, HFI_PROP_END, iris_hfi_gen2_handle_system_property }, ++ {HFI_CMD_BEGIN, HFI_CMD_END, iris_hfi_gen2_handle_system_init }, ++ }; ++ ++ for (i = 0; i < ARRAY_SIZE(range); i++) { ++ pkt = start_pkt; ++ for (j = 0; j < hdr->num_packets; j++) { ++ packet = (struct iris_hfi_packet *)pkt; ++ if (packet->flags & HFI_FW_FLAGS_SYSTEM_ERROR) { ++ ret = iris_hfi_gen2_handle_system_error(core, packet); ++ return ret; ++ } ++ ++ if (packet->type > range[i].begin && packet->type < range[i].end) { ++ ret = range[i].handle(core, packet); ++ if (ret) ++ return ret; ++ ++ if (packet->type > HFI_SYSTEM_ERROR_BEGIN && ++ packet->type < HFI_SYSTEM_ERROR_END) ++ return 0; ++ } ++ pkt += packet->size; ++ } ++ } ++ ++ return 0; ++} ++ ++static int iris_hfi_gen2_handle_response(struct iris_core *core, void *response) ++{ ++ struct iris_hfi_header *hdr = (struct iris_hfi_header *)response; ++ int ret; ++ ++ ret = iris_hfi_gen2_validate_hdr_packet(core, hdr); ++ if (ret) ++ return iris_hfi_gen2_handle_system_error(core, NULL); ++ ++ return iris_hfi_gen2_handle_system_response(core, hdr); ++} ++ ++static void iris_hfi_gen2_flush_debug_queue(struct iris_core *core, u8 *packet) ++{ ++ struct hfi_debug_header *pkt; ++ u8 *log; ++ ++ while (!iris_hfi_queue_dbg_read(core, packet)) { ++ pkt = (struct hfi_debug_header *)packet; ++ ++ if (pkt->size < sizeof(*pkt)) ++ continue; ++ ++ if (pkt->size >= IFACEQ_CORE_PKT_SIZE) ++ continue; ++ ++ packet[pkt->size] = '\0'; ++ log = (u8 *)packet + sizeof(*pkt) + 1; ++ dev_dbg(core->dev, "%s", log); ++ } ++} ++ ++static void iris_hfi_gen2_response_handler(struct iris_core *core) ++{ ++ if (iris_vpu_watchdog(core, core->intr_status)) { ++ struct iris_hfi_packet pkt = {.type = HFI_SYS_ERROR_WD_TIMEOUT}; ++ ++ dev_err(core->dev, "cpu watchdog error received\n"); ++ core->state = IRIS_CORE_ERROR; ++ iris_hfi_gen2_handle_system_error(core, &pkt); ++ ++ return; ++ } ++ ++ memset(core->response_packet, 0, sizeof(struct iris_hfi_header)); ++ while (!iris_hfi_queue_msg_read(core, core->response_packet)) { ++ iris_hfi_gen2_handle_response(core, core->response_packet); ++ memset(core->response_packet, 0, sizeof(struct iris_hfi_header)); ++ } ++ ++ iris_hfi_gen2_flush_debug_queue(core, core->response_packet); ++} ++ ++static const struct iris_hfi_response_ops iris_hfi_gen2_response_ops = { ++ .hfi_response_handler = iris_hfi_gen2_response_handler, ++}; ++ ++void iris_hfi_gen2_response_ops_init(struct iris_core *core) ++{ ++ core->hfi_response_ops = &iris_hfi_gen2_response_ops; ++} +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_queue.c b/drivers/media/platform/qcom/iris/iris_hfi_queue.c +index 494ef205133d..ee245c540ce7 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_queue.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_queue.c +@@ -5,6 +5,179 @@ + + #include "iris_core.h" + #include "iris_hfi_queue.h" ++#include "iris_vpu_common.h" ++ ++static int iris_hfi_queue_write(struct iris_iface_q_info *qinfo, void *packet, u32 packet_size) ++{ ++ struct iris_hfi_queue_header *queue = qinfo->qhdr; ++ u32 write_idx = queue->write_idx * sizeof(u32); ++ u32 read_idx = queue->read_idx * sizeof(u32); ++ u32 empty_space, new_write_idx, residue; ++ u32 *write_ptr; ++ ++ if (write_idx < read_idx) ++ empty_space = read_idx - write_idx; ++ else ++ empty_space = IFACEQ_QUEUE_SIZE - (write_idx - read_idx); ++ if (empty_space < packet_size) ++ return -ENOSPC; ++ ++ queue->tx_req = 0; ++ ++ new_write_idx = write_idx + packet_size; ++ write_ptr = (u32 *)((u8 *)qinfo->kernel_vaddr + write_idx); ++ ++ if (write_ptr < (u32 *)qinfo->kernel_vaddr || ++ write_ptr > (u32 *)(qinfo->kernel_vaddr + ++ IFACEQ_QUEUE_SIZE)) ++ return -EINVAL; ++ ++ if (new_write_idx < IFACEQ_QUEUE_SIZE) { ++ memcpy(write_ptr, packet, packet_size); ++ } else { ++ residue = new_write_idx - IFACEQ_QUEUE_SIZE; ++ memcpy(write_ptr, packet, (packet_size - residue)); ++ memcpy(qinfo->kernel_vaddr, ++ packet + (packet_size - residue), residue); ++ new_write_idx = residue; ++ } ++ ++ /* Make sure packet is written before updating the write index */ ++ mb(); ++ queue->write_idx = new_write_idx / sizeof(u32); ++ ++ /* Make sure write index is updated before an interrupt is raised */ ++ mb(); ++ ++ return 0; ++} ++ ++static int iris_hfi_queue_read(struct iris_iface_q_info *qinfo, void *packet) ++{ ++ struct iris_hfi_queue_header *queue = qinfo->qhdr; ++ u32 write_idx = queue->write_idx * sizeof(u32); ++ u32 read_idx = queue->read_idx * sizeof(u32); ++ u32 packet_size, receive_request = 0; ++ u32 new_read_idx, residue; ++ u32 *read_ptr; ++ int ret = 0; ++ ++ if (queue->queue_type == IFACEQ_MSGQ_ID) ++ receive_request = 1; ++ ++ if (read_idx == write_idx) { ++ queue->rx_req = receive_request; ++ /* Ensure qhdr is updated in main memory */ ++ mb(); ++ return -ENODATA; ++ } ++ ++ read_ptr = qinfo->kernel_vaddr + read_idx; ++ if (read_ptr < (u32 *)qinfo->kernel_vaddr || ++ read_ptr > (u32 *)(qinfo->kernel_vaddr + ++ IFACEQ_QUEUE_SIZE - sizeof(*read_ptr))) ++ return -ENODATA; ++ ++ packet_size = *read_ptr; ++ if (!packet_size) ++ return -EINVAL; ++ ++ new_read_idx = read_idx + packet_size; ++ if (packet_size <= IFACEQ_CORE_PKT_SIZE) { ++ if (new_read_idx < IFACEQ_QUEUE_SIZE) { ++ memcpy(packet, read_ptr, packet_size); ++ } else { ++ residue = new_read_idx - IFACEQ_QUEUE_SIZE; ++ memcpy(packet, read_ptr, (packet_size - residue)); ++ memcpy((packet + (packet_size - residue)), ++ qinfo->kernel_vaddr, residue); ++ new_read_idx = residue; ++ } ++ } else { ++ new_read_idx = write_idx; ++ ret = -EBADMSG; ++ } ++ ++ queue->rx_req = receive_request; ++ ++ queue->read_idx = new_read_idx / sizeof(u32); ++ /* Ensure qhdr is updated in main memory */ ++ mb(); ++ ++ return ret; ++} ++ ++int iris_hfi_queue_cmd_write_locked(struct iris_core *core, void *pkt, u32 pkt_size) ++{ ++ struct iris_iface_q_info *q_info = &core->command_queue; ++ ++ if (core->state == IRIS_CORE_ERROR) ++ return -EINVAL; ++ ++ if (!iris_hfi_queue_write(q_info, pkt, pkt_size)) { ++ iris_vpu_raise_interrupt(core); ++ } else { ++ dev_err(core->dev, "queue full\n"); ++ return -ENODATA; ++ } ++ ++ return 0; ++} ++ ++int iris_hfi_queue_cmd_write(struct iris_core *core, void *pkt, u32 pkt_size) ++{ ++ int ret; ++ ++ mutex_lock(&core->lock); ++ ret = iris_hfi_queue_cmd_write_locked(core, pkt, pkt_size); ++ mutex_unlock(&core->lock); ++ ++ return ret; ++} ++ ++int iris_hfi_queue_msg_read(struct iris_core *core, void *pkt) ++{ ++ struct iris_iface_q_info *q_info = &core->message_queue; ++ int ret = 0; ++ ++ mutex_lock(&core->lock); ++ if (core->state != IRIS_CORE_INIT) { ++ ret = -EINVAL; ++ goto unlock; ++ } ++ ++ if (iris_hfi_queue_read(q_info, pkt)) { ++ ret = -ENODATA; ++ goto unlock; ++ } ++ ++unlock: ++ mutex_unlock(&core->lock); ++ ++ return ret; ++} ++ ++int iris_hfi_queue_dbg_read(struct iris_core *core, void *pkt) ++{ ++ struct iris_iface_q_info *q_info = &core->debug_queue; ++ int ret = 0; ++ ++ mutex_lock(&core->lock); ++ if (core->state != IRIS_CORE_INIT) { ++ ret = -EINVAL; ++ goto unlock; ++ } ++ ++ if (iris_hfi_queue_read(q_info, pkt)) { ++ ret = -ENODATA; ++ goto unlock; ++ } ++ ++unlock: ++ mutex_unlock(&core->lock); ++ ++ return ret; ++} + + static void iris_hfi_queue_set_header(struct iris_core *core, u32 queue_id, + struct iris_iface_q_info *iface_q) +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_queue.h b/drivers/media/platform/qcom/iris/iris_hfi_queue.h +index 99a3b83d063f..2174fc5ce618 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_queue.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_queue.h +@@ -174,4 +174,9 @@ struct iris_iface_q_info { + int iris_hfi_queues_init(struct iris_core *core); + void iris_hfi_queues_deinit(struct iris_core *core); + ++int iris_hfi_queue_cmd_write_locked(struct iris_core *core, void *pkt, u32 pkt_size); ++int iris_hfi_queue_cmd_write(struct iris_core *core, void *pkt, u32 pkt_size); ++int iris_hfi_queue_msg_read(struct iris_core *core, void *pkt); ++int iris_hfi_queue_dbg_read(struct iris_core *core, void *pkt); ++ + #endif +diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h +index 7e661e8928bd..adf639d1a109 100644 +--- a/drivers/media/platform/qcom/iris/iris_platform_common.h ++++ b/drivers/media/platform/qcom/iris/iris_platform_common.h +@@ -6,7 +6,10 @@ + #ifndef __IRIS_PLATFORM_COMMON_H__ + #define __IRIS_PLATFORM_COMMON_H__ + ++struct iris_core; ++ + #define IRIS_PAS_ID 9 ++#define HW_RESPONSE_TIMEOUT_VALUE (1000) /* milliseconds */ + + extern struct iris_platform_data sm8550_data; + +@@ -28,7 +31,19 @@ struct tz_cp_config { + u32 cp_nonpixel_size; + }; + ++struct ubwc_config_data { ++ u32 max_channels; ++ u32 mal_length; ++ u32 highest_bank_bit; ++ u32 bank_swzl_level; ++ u32 bank_swz2_level; ++ u32 bank_swz3_level; ++ u32 bank_spreading; ++}; ++ + struct iris_platform_data { ++ void (*init_hfi_command_ops)(struct iris_core *core); ++ void (*init_hfi_response_ops)(struct iris_core *core); + struct iris_inst *(*get_instance)(void); + const struct icc_info *icc_tbl; + unsigned int icc_tbl_size; +@@ -45,6 +60,8 @@ struct iris_platform_data { + u32 pas_id; + struct tz_cp_config *tz_cp_config_data; + u32 core_arch; ++ u32 hw_response_timeout; ++ struct ubwc_config_data *ubwc_config; + }; + + #endif +diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +index 237f932946d6..30d9664bd419 100644 +--- a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c ++++ b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +@@ -26,6 +26,16 @@ static const struct platform_clk_data sm8550_clk_table[] = { + {IRIS_HW_CLK, "vcodec0_core" }, + }; + ++static struct ubwc_config_data ubwc_config_sm8550 = { ++ .max_channels = 8, ++ .mal_length = 32, ++ .highest_bank_bit = 16, ++ .bank_swzl_level = 0, ++ .bank_swz2_level = 1, ++ .bank_swz3_level = 1, ++ .bank_spreading = 1, ++}; ++ + static struct tz_cp_config tz_cp_config_sm8550 = { + .cp_start = 0, + .cp_size = 0x25800000, +@@ -35,6 +45,8 @@ static struct tz_cp_config tz_cp_config_sm8550 = { + + struct iris_platform_data sm8550_data = { + .get_instance = iris_hfi_gen2_get_instance, ++ .init_hfi_command_ops = iris_hfi_gen2_command_ops_init, ++ .init_hfi_response_ops = iris_hfi_gen2_response_ops_init, + .icc_tbl = sm8550_icc_table, + .icc_tbl_size = ARRAY_SIZE(sm8550_icc_table), + .clk_rst_tbl = sm8550_clk_reset_table, +@@ -51,4 +63,6 @@ struct iris_platform_data sm8550_data = { + .pas_id = IRIS_PAS_ID, + .tz_cp_config_data = &tz_cp_config_sm8550, + .core_arch = VIDEO_ARCH_LX, ++ .hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE, ++ .ubwc_config = &ubwc_config_sm8550, + }; +diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c +index 3015e6cb347f..02887b3dbe0e 100644 +--- a/drivers/media/platform/qcom/iris/iris_probe.c ++++ b/drivers/media/platform/qcom/iris/iris_probe.c +@@ -177,6 +177,15 @@ static void iris_remove(struct platform_device *pdev) + mutex_destroy(&core->lock); + } + ++static void iris_sys_error_handler(struct work_struct *work) ++{ ++ struct iris_core *core = ++ container_of(work, struct iris_core, sys_error_handler.work); ++ ++ iris_core_deinit(core); ++ iris_core_init(core); ++} ++ + static int iris_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +@@ -191,6 +200,13 @@ static int iris_probe(struct platform_device *pdev) + + core->state = IRIS_CORE_DEINIT; + mutex_init(&core->lock); ++ init_completion(&core->core_init_done); ++ ++ core->response_packet = devm_kzalloc(core->dev, IFACEQ_CORE_PKT_SIZE, GFP_KERNEL); ++ if (!core->response_packet) ++ return -ENOMEM; ++ ++ INIT_DELAYED_WORK(&core->sys_error_handler, iris_sys_error_handler); + + core->reg_base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(core->reg_base)) +@@ -202,7 +218,17 @@ static int iris_probe(struct platform_device *pdev) + + core->iris_platform_data = of_device_get_match_data(core->dev); + ++ ret = devm_request_threaded_irq(core->dev, core->irq, iris_hfi_isr, ++ iris_hfi_isr_handler, IRQF_TRIGGER_HIGH, "iris", core); ++ if (ret) ++ return ret; ++ ++ disable_irq_nosync(core->irq); ++ + iris_init_ops(core); ++ core->iris_platform_data->init_hfi_command_ops(core); ++ core->iris_platform_data->init_hfi_response_ops(core); ++ + ret = iris_init_resources(core); + if (ret) + return ret; +diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.c b/drivers/media/platform/qcom/iris/iris_vpu_common.c +index 959ed46e8f47..34817573f61b 100644 +--- a/drivers/media/platform/qcom/iris/iris_vpu_common.c ++++ b/drivers/media/platform/qcom/iris/iris_vpu_common.c +@@ -11,10 +11,15 @@ + #define CPU_BASE_OFFS 0x000A0000 + + #define CPU_CS_BASE_OFFS (CPU_BASE_OFFS) ++#define CPU_IC_BASE_OFFS (CPU_BASE_OFFS) ++ ++#define CPU_CS_A2HSOFTINTCLR (CPU_CS_BASE_OFFS + 0x1C) ++#define CLEAR_XTENSA2HOST_INTR BIT(0) + + #define CTRL_INIT (CPU_CS_BASE_OFFS + 0x48) + #define CTRL_STATUS (CPU_CS_BASE_OFFS + 0x4C) + ++#define CTRL_INIT_IDLE_MSG_BMSK 0x40000000 + #define CTRL_ERROR_STATUS__M 0xfe + + #define QTBL_INFO (CPU_CS_BASE_OFFS + 0x50) +@@ -31,6 +36,14 @@ + + #define CPU_CS_X2RPMH (CPU_CS_BASE_OFFS + 0x168) + ++#define CPU_IC_SOFTINT (CPU_IC_BASE_OFFS + 0x150) ++#define CPU_IC_SOFTINT_H2A_SHFT 0x0 ++ ++#define WRAPPER_BASE_OFFS 0x000B0000 ++#define WRAPPER_INTR_STATUS (WRAPPER_BASE_OFFS + 0x0C) ++#define WRAPPER_INTR_STATUS_A2HWD_BMSK BIT(3) ++#define WRAPPER_INTR_STATUS_A2H_BMSK BIT(2) ++ + static void iris_vpu_setup_ucregion_memory_map(struct iris_core *core) + { + u32 queue_size, value; +@@ -87,3 +100,33 @@ int iris_vpu_boot_firmware(struct iris_core *core) + + return 0; + } ++ ++void iris_vpu_raise_interrupt(struct iris_core *core) ++{ ++ writel(1 << CPU_IC_SOFTINT_H2A_SHFT, core->reg_base + CPU_IC_SOFTINT); ++} ++ ++void iris_vpu_clear_interrupt(struct iris_core *core) ++{ ++ u32 intr_status, mask; ++ ++ intr_status = readl(core->reg_base + WRAPPER_INTR_STATUS); ++ mask = (WRAPPER_INTR_STATUS_A2H_BMSK | ++ WRAPPER_INTR_STATUS_A2HWD_BMSK | ++ CTRL_INIT_IDLE_MSG_BMSK); ++ ++ if (intr_status & mask) ++ core->intr_status |= intr_status; ++ ++ writel(CLEAR_XTENSA2HOST_INTR, core->reg_base + CPU_CS_A2HSOFTINTCLR); ++} ++ ++int iris_vpu_watchdog(struct iris_core *core, u32 intr_status) ++{ ++ if (intr_status & WRAPPER_INTR_STATUS_A2HWD_BMSK) { ++ dev_err(core->dev, "received watchdog interrupt\n"); ++ return -ETIME; ++ } ++ ++ return 0; ++} +diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.h b/drivers/media/platform/qcom/iris/iris_vpu_common.h +index bafcf46520fd..c38c055d3d14 100644 +--- a/drivers/media/platform/qcom/iris/iris_vpu_common.h ++++ b/drivers/media/platform/qcom/iris/iris_vpu_common.h +@@ -9,5 +9,8 @@ + struct iris_core; + + int iris_vpu_boot_firmware(struct iris_core *core); ++void iris_vpu_raise_interrupt(struct iris_core *core); ++void iris_vpu_clear_interrupt(struct iris_core *core); ++int iris_vpu_watchdog(struct iris_core *core, u32 intr_status); + + #endif +-- +2.34.1 + diff --git a/patch/kernel/archive/sm8550-6.12/0008_media--iris--implement-power-management.patch b/patch/kernel/archive/sm8550-6.12/0008_media--iris--implement-power-management.patch new file mode 100644 index 000000000..08f0e31d5 --- /dev/null +++ b/patch/kernel/archive/sm8550-6.12/0008_media--iris--implement-power-management.patch @@ -0,0 +1,1246 @@ +From 719a1fbd3dea369254d096d32ebdb3fbd9894bfa Mon Sep 17 00:00:00 2001 +From: Dikshita Agarwal +Date: Fri, 7 Feb 2025 13:24:48 +0530 +Subject: [PATCH] media: iris: implement power management + +Implement runtime power management for iris, including a platform +specific power on/off sequence. + +Tested-by: Stefan Schmidt # x1e80100 (Dell XPS 13 9345) +Reviewed-by: Stefan Schmidt +Tested-by: Neil Armstrong # on SM8550-QRD +Tested-by: Neil Armstrong # on SM8550-HDK +Signed-off-by: Dikshita Agarwal +Link: https://lore.kernel.org/r/20250207-qcom-video-iris-v10-8-ab66eeffbd20@quicinc.com +Signed-off-by: Neil Armstrong +--- + drivers/media/platform/qcom/iris/Makefile | 3 + + drivers/media/platform/qcom/iris/iris_core.c | 15 +- + drivers/media/platform/qcom/iris/iris_core.h | 4 + + .../media/platform/qcom/iris/iris_firmware.c | 5 + + .../media/platform/qcom/iris/iris_firmware.h | 1 + + .../platform/qcom/iris/iris_hfi_common.c | 62 +++++ + .../platform/qcom/iris/iris_hfi_common.h | 3 + + .../qcom/iris/iris_hfi_gen1_command.c | 11 + + .../qcom/iris/iris_hfi_gen1_defines.h | 5 + + .../qcom/iris/iris_hfi_gen2_command.c | 18 ++ + .../qcom/iris/iris_hfi_gen2_defines.h | 1 + + .../platform/qcom/iris/iris_hfi_gen2_packet.c | 13 + + .../platform/qcom/iris/iris_hfi_gen2_packet.h | 1 + + .../media/platform/qcom/iris/iris_hfi_queue.c | 18 ++ + .../platform/qcom/iris/iris_platform_common.h | 14 + + .../platform/qcom/iris/iris_platform_sm8550.c | 9 + + drivers/media/platform/qcom/iris/iris_probe.c | 53 ++++ + .../media/platform/qcom/iris/iris_resources.c | 131 ++++++++++ + .../media/platform/qcom/iris/iris_resources.h | 18 ++ + drivers/media/platform/qcom/iris/iris_vidc.c | 8 + + drivers/media/platform/qcom/iris/iris_vpu2.c | 11 + + drivers/media/platform/qcom/iris/iris_vpu3.c | 84 ++++++ + .../platform/qcom/iris/iris_vpu_common.c | 243 +++++++++++++++++- + .../platform/qcom/iris/iris_vpu_common.h | 11 + + .../qcom/iris/iris_vpu_register_defines.h | 17 ++ + 25 files changed, 755 insertions(+), 4 deletions(-) + create mode 100644 drivers/media/platform/qcom/iris/iris_resources.c + create mode 100644 drivers/media/platform/qcom/iris/iris_resources.h + create mode 100644 drivers/media/platform/qcom/iris/iris_vpu2.c + create mode 100644 drivers/media/platform/qcom/iris/iris_vpu3.c + create mode 100644 drivers/media/platform/qcom/iris/iris_vpu_register_defines.h + +diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile +index 76ca5287c49f..a5f290a8c4af 100644 +--- a/drivers/media/platform/qcom/iris/Makefile ++++ b/drivers/media/platform/qcom/iris/Makefile +@@ -9,7 +9,10 @@ iris-objs += iris_core.o \ + iris_hfi_queue.o \ + iris_platform_sm8550.o \ + iris_probe.o \ ++ iris_resources.o \ + iris_vidc.o \ ++ iris_vpu2.o \ ++ iris_vpu3.o \ + iris_vpu_common.o \ + + obj-$(CONFIG_VIDEO_QCOM_IRIS) += iris.o +diff --git a/drivers/media/platform/qcom/iris/iris_core.c b/drivers/media/platform/qcom/iris/iris_core.c +index 7e19bdd0a19b..0fa0a3b549a2 100644 +--- a/drivers/media/platform/qcom/iris/iris_core.c ++++ b/drivers/media/platform/qcom/iris/iris_core.c +@@ -3,6 +3,8 @@ + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + ++#include ++ + #include "iris_core.h" + #include "iris_firmware.h" + #include "iris_state.h" +@@ -10,11 +12,16 @@ + + void iris_core_deinit(struct iris_core *core) + { ++ pm_runtime_resume_and_get(core->dev); ++ + mutex_lock(&core->lock); + iris_fw_unload(core); ++ iris_vpu_power_off(core); + iris_hfi_queues_deinit(core); + core->state = IRIS_CORE_DEINIT; + mutex_unlock(&core->lock); ++ ++ pm_runtime_put_sync(core->dev); + } + + static int iris_wait_for_system_response(struct iris_core *core) +@@ -54,10 +61,14 @@ int iris_core_init(struct iris_core *core) + if (ret) + goto error; + +- ret = iris_fw_load(core); ++ ret = iris_vpu_power_on(core); + if (ret) + goto error_queue_deinit; + ++ ret = iris_fw_load(core); ++ if (ret) ++ goto error_power_off; ++ + ret = iris_vpu_boot_firmware(core); + if (ret) + goto error_unload_fw; +@@ -72,6 +83,8 @@ int iris_core_init(struct iris_core *core) + + error_unload_fw: + iris_fw_unload(core); ++error_power_off: ++ iris_vpu_power_off(core); + error_queue_deinit: + iris_hfi_queues_deinit(core); + error: +diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h +index c0f3c189d779..58aab78ab2c4 100644 +--- a/drivers/media/platform/qcom/iris/iris_core.h ++++ b/drivers/media/platform/qcom/iris/iris_core.h +@@ -7,11 +7,13 @@ + #define __IRIS_CORE_H__ + + #include ++#include + #include + + #include "iris_hfi_common.h" + #include "iris_hfi_queue.h" + #include "iris_platform_common.h" ++#include "iris_resources.h" + #include "iris_state.h" + + struct icc_info { +@@ -52,6 +54,7 @@ struct icc_info { + * @response_packet: a pointer to response packet from fw to driver + * @header_id: id of packet header + * @packet_id: id of packet ++ * @power: a structure for clock and bw information + * @hfi_ops: iris hfi command ops + * @hfi_response_ops: iris hfi response ops + * @core_init_done: structure of signal completion for system response +@@ -86,6 +89,7 @@ struct iris_core { + u8 *response_packet; + u32 header_id; + u32 packet_id; ++ struct iris_core_power power; + const struct iris_hfi_command_ops *hfi_ops; + const struct iris_hfi_response_ops *hfi_response_ops; + struct completion core_init_done; +diff --git a/drivers/media/platform/qcom/iris/iris_firmware.c b/drivers/media/platform/qcom/iris/iris_firmware.c +index 3d14e596a471..7c493b4a75db 100644 +--- a/drivers/media/platform/qcom/iris/iris_firmware.c ++++ b/drivers/media/platform/qcom/iris/iris_firmware.c +@@ -109,3 +109,8 @@ int iris_fw_unload(struct iris_core *core) + { + return qcom_scm_pas_shutdown(core->iris_platform_data->pas_id); + } ++ ++int iris_set_hw_state(struct iris_core *core, bool resume) ++{ ++ return qcom_scm_set_remote_state(resume, 0); ++} +diff --git a/drivers/media/platform/qcom/iris/iris_firmware.h b/drivers/media/platform/qcom/iris/iris_firmware.h +index 266bdd92a124..e833ecd34887 100644 +--- a/drivers/media/platform/qcom/iris/iris_firmware.h ++++ b/drivers/media/platform/qcom/iris/iris_firmware.h +@@ -10,5 +10,6 @@ struct iris_core; + + int iris_fw_load(struct iris_core *core); + int iris_fw_unload(struct iris_core *core); ++int iris_set_hw_state(struct iris_core *core, bool resume); + + #endif +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.c b/drivers/media/platform/qcom/iris/iris_hfi_common.c +index a19b988c9a88..29f56c2bf74c 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_common.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_common.c +@@ -3,6 +3,9 @@ + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + ++#include ++ ++#include "iris_firmware.h" + #include "iris_core.h" + #include "iris_hfi_common.h" + #include "iris_vpu_common.h" +@@ -38,6 +41,7 @@ irqreturn_t iris_hfi_isr_handler(int irq, void *data) + return IRQ_NONE; + + mutex_lock(&core->lock); ++ pm_runtime_mark_last_busy(core->dev); + iris_vpu_clear_interrupt(core); + mutex_unlock(&core->lock); + +@@ -48,3 +52,61 @@ irqreturn_t iris_hfi_isr_handler(int irq, void *data) + + return IRQ_HANDLED; + } ++ ++int iris_hfi_pm_suspend(struct iris_core *core) ++{ ++ int ret; ++ ++ ret = iris_vpu_prepare_pc(core); ++ if (ret) { ++ pm_runtime_mark_last_busy(core->dev); ++ ret = -EAGAIN; ++ goto error; ++ } ++ ++ ret = iris_set_hw_state(core, false); ++ if (ret) ++ goto error; ++ ++ iris_vpu_power_off(core); ++ ++ return 0; ++ ++error: ++ dev_err(core->dev, "failed to suspend\n"); ++ ++ return ret; ++} ++ ++int iris_hfi_pm_resume(struct iris_core *core) ++{ ++ const struct iris_hfi_command_ops *ops = core->hfi_ops; ++ int ret; ++ ++ ret = iris_vpu_power_on(core); ++ if (ret) ++ goto error; ++ ++ ret = iris_set_hw_state(core, true); ++ if (ret) ++ goto err_power_off; ++ ++ ret = iris_vpu_boot_firmware(core); ++ if (ret) ++ goto err_suspend_hw; ++ ++ ret = ops->sys_interframe_powercollapse(core); ++ if (ret) ++ goto err_suspend_hw; ++ ++ return 0; ++ ++err_suspend_hw: ++ iris_set_hw_state(core, false); ++err_power_off: ++ iris_vpu_power_off(core); ++error: ++ dev_err(core->dev, "failed to resume\n"); ++ ++ return -EBUSY; ++} +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.h b/drivers/media/platform/qcom/iris/iris_hfi_common.h +index b46a2f21102a..36673aafe1c9 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_common.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_common.h +@@ -46,6 +46,7 @@ struct iris_hfi_command_ops { + int (*sys_init)(struct iris_core *core); + int (*sys_image_version)(struct iris_core *core); + int (*sys_interframe_powercollapse)(struct iris_core *core); ++ int (*sys_pc_prep)(struct iris_core *core); + }; + + struct iris_hfi_response_ops { +@@ -53,6 +54,8 @@ struct iris_hfi_response_ops { + }; + + int iris_hfi_core_init(struct iris_core *core); ++int iris_hfi_pm_suspend(struct iris_core *core); ++int iris_hfi_pm_resume(struct iris_core *core); + + irqreturn_t iris_hfi_isr(int irq, void *data); + irqreturn_t iris_hfi_isr_handler(int irq, void *data); +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +index 07007d8812ba..b2e76d1dcbf7 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +@@ -56,10 +56,21 @@ static int iris_hfi_gen1_sys_interframe_powercollapse(struct iris_core *core) + return ret; + } + ++static int iris_hfi_gen1_sys_pc_prep(struct iris_core *core) ++{ ++ struct hfi_sys_pc_prep_pkt pkt; ++ ++ pkt.hdr.size = sizeof(struct hfi_sys_pc_prep_pkt); ++ pkt.hdr.pkt_type = HFI_CMD_SYS_PC_PREP; ++ ++ return iris_hfi_queue_cmd_write_locked(core, &pkt, pkt.hdr.size); ++} ++ + static const struct iris_hfi_command_ops iris_hfi_gen1_command_ops = { + .sys_init = iris_hfi_gen1_sys_init, + .sys_image_version = iris_hfi_gen1_sys_image_version, + .sys_interframe_powercollapse = iris_hfi_gen1_sys_interframe_powercollapse, ++ .sys_pc_prep = iris_hfi_gen1_sys_pc_prep, + }; + + void iris_hfi_gen1_command_ops_init(struct iris_core *core) +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +index 8af824a42bcf..81685a284f23 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +@@ -12,6 +12,7 @@ + #define HFI_ERR_NONE 0x0 + + #define HFI_CMD_SYS_INIT 0x10001 ++#define HFI_CMD_SYS_PC_PREP 0x10002 + #define HFI_CMD_SYS_SET_PROPERTY 0x10005 + #define HFI_CMD_SYS_GET_PROPERTY 0x10006 + +@@ -48,6 +49,10 @@ struct hfi_sys_get_property_pkt { + u32 data; + }; + ++struct hfi_sys_pc_prep_pkt { ++ struct hfi_pkt_hdr hdr; ++}; ++ + struct hfi_msg_event_notify_pkt { + struct hfi_pkt_hdr hdr; + u32 event_id; +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +index 5eaebe170214..f8cb1177ef54 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +@@ -68,10 +68,28 @@ static int iris_hfi_gen2_sys_interframe_powercollapse(struct iris_core *core) + return ret; + } + ++static int iris_hfi_gen2_sys_pc_prep(struct iris_core *core) ++{ ++ struct iris_hfi_header *hdr; ++ int ret; ++ ++ hdr = kzalloc(SYS_NO_PAYLOAD_PKT_SIZE, GFP_KERNEL); ++ if (!hdr) ++ return -ENOMEM; ++ ++ iris_hfi_gen2_packet_sys_pc_prep(core, hdr); ++ ret = iris_hfi_queue_cmd_write_locked(core, hdr, hdr->size); ++ ++ kfree(hdr); ++ ++ return ret; ++} ++ + static const struct iris_hfi_command_ops iris_hfi_gen2_command_ops = { + .sys_init = iris_hfi_gen2_sys_init, + .sys_image_version = iris_hfi_gen2_sys_image_version, + .sys_interframe_powercollapse = iris_hfi_gen2_sys_interframe_powercollapse, ++ .sys_pc_prep = iris_hfi_gen2_sys_pc_prep, + }; + + void iris_hfi_gen2_command_ops_init(struct iris_core *core) +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +index 2640caa7f9c0..e6a19ffc12fb 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +@@ -12,6 +12,7 @@ + + #define HFI_CMD_BEGIN 0x01000000 + #define HFI_CMD_INIT 0x01000001 ++#define HFI_CMD_POWER_COLLAPSE 0x01000002 + #define HFI_CMD_END 0x01FFFFFF + + #define HFI_PROP_BEGIN 0x03000000 +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c +index 986013aa62df..510d44408b41 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c +@@ -159,3 +159,16 @@ void iris_hfi_gen2_packet_sys_interframe_powercollapse(struct iris_core *core, + &payload, + sizeof(u32)); + } ++ ++void iris_hfi_gen2_packet_sys_pc_prep(struct iris_core *core, struct iris_hfi_header *hdr) ++{ ++ iris_hfi_gen2_create_header(hdr, 0 /*session_id*/, core->header_id++); ++ ++ iris_hfi_gen2_create_packet(hdr, ++ HFI_CMD_POWER_COLLAPSE, ++ HFI_HOST_FLAGS_NONE, ++ HFI_PAYLOAD_NONE, ++ HFI_PORT_NONE, ++ core->packet_id++, ++ NULL, 0); ++} +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h +index 10dcb6e4c3d9..3b771b7516de 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h +@@ -65,5 +65,6 @@ void iris_hfi_gen2_packet_sys_init(struct iris_core *core, struct iris_hfi_heade + void iris_hfi_gen2_packet_image_version(struct iris_core *core, struct iris_hfi_header *hdr); + void iris_hfi_gen2_packet_sys_interframe_powercollapse(struct iris_core *core, + struct iris_hfi_header *hdr); ++void iris_hfi_gen2_packet_sys_pc_prep(struct iris_core *core, struct iris_hfi_header *hdr); + + #endif +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_queue.c b/drivers/media/platform/qcom/iris/iris_hfi_queue.c +index ee245c540ce7..fac7df0c4d1a 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_queue.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_queue.c +@@ -3,6 +3,8 @@ + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + ++#include ++ + #include "iris_core.h" + #include "iris_hfi_queue.h" + #include "iris_vpu_common.h" +@@ -128,10 +130,26 @@ int iris_hfi_queue_cmd_write(struct iris_core *core, void *pkt, u32 pkt_size) + { + int ret; + ++ ret = pm_runtime_resume_and_get(core->dev); ++ if (ret < 0) ++ goto exit; ++ + mutex_lock(&core->lock); + ret = iris_hfi_queue_cmd_write_locked(core, pkt, pkt_size); ++ if (ret) { ++ mutex_unlock(&core->lock); ++ goto exit; ++ } + mutex_unlock(&core->lock); + ++ pm_runtime_mark_last_busy(core->dev); ++ pm_runtime_put_autosuspend(core->dev); ++ ++ return 0; ++ ++exit: ++ pm_runtime_put_sync(core->dev); ++ + return ret; + } + +diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h +index adf639d1a109..69c0a8b3d12d 100644 +--- a/drivers/media/platform/qcom/iris/iris_platform_common.h ++++ b/drivers/media/platform/qcom/iris/iris_platform_common.h +@@ -10,6 +10,7 @@ struct iris_core; + + #define IRIS_PAS_ID 9 + #define HW_RESPONSE_TIMEOUT_VALUE (1000) /* milliseconds */ ++#define AUTOSUSPEND_DELAY_VALUE (HW_RESPONSE_TIMEOUT_VALUE + 500) /* milliseconds */ + + extern struct iris_platform_data sm8550_data; + +@@ -41,10 +42,22 @@ struct ubwc_config_data { + u32 bank_spreading; + }; + ++struct iris_core_power { ++ u64 clk_freq; ++ u64 icc_bw; ++}; ++ ++enum platform_pm_domain_type { ++ IRIS_CTRL_POWER_DOMAIN, ++ IRIS_HW_POWER_DOMAIN, ++}; ++ + struct iris_platform_data { + void (*init_hfi_command_ops)(struct iris_core *core); + void (*init_hfi_response_ops)(struct iris_core *core); + struct iris_inst *(*get_instance)(void); ++ const struct vpu_ops *vpu_ops; ++ void (*set_preset_registers)(struct iris_core *core); + const struct icc_info *icc_tbl; + unsigned int icc_tbl_size; + const char * const *pmdomain_tbl; +@@ -62,6 +75,7 @@ struct iris_platform_data { + u32 core_arch; + u32 hw_response_timeout; + struct ubwc_config_data *ubwc_config; ++ u32 num_vpp_pipe; + }; + + #endif +diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +index 30d9664bd419..ed99cdb13d06 100644 +--- a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c ++++ b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +@@ -6,9 +6,15 @@ + #include "iris_core.h" + #include "iris_hfi_gen2.h" + #include "iris_platform_common.h" ++#include "iris_vpu_common.h" + + #define VIDEO_ARCH_LX 1 + ++static void iris_set_sm8550_preset_registers(struct iris_core *core) ++{ ++ writel(0x0, core->reg_base + 0xB0088); ++} ++ + static const struct icc_info sm8550_icc_table[] = { + { "cpu-cfg", 1000, 1000 }, + { "video-mem", 1000, 15000000 }, +@@ -47,6 +53,8 @@ struct iris_platform_data sm8550_data = { + .get_instance = iris_hfi_gen2_get_instance, + .init_hfi_command_ops = iris_hfi_gen2_command_ops_init, + .init_hfi_response_ops = iris_hfi_gen2_response_ops_init, ++ .vpu_ops = &iris_vpu3_ops, ++ .set_preset_registers = iris_set_sm8550_preset_registers, + .icc_tbl = sm8550_icc_table, + .icc_tbl_size = ARRAY_SIZE(sm8550_icc_table), + .clk_rst_tbl = sm8550_clk_reset_table, +@@ -65,4 +73,5 @@ struct iris_platform_data sm8550_data = { + .core_arch = VIDEO_ARCH_LX, + .hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE, + .ubwc_config = &ubwc_config_sm8550, ++ .num_vpp_pipe = 4, + }; +diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c +index 02887b3dbe0e..e8ef258b4f2e 100644 +--- a/drivers/media/platform/qcom/iris/iris_probe.c ++++ b/drivers/media/platform/qcom/iris/iris_probe.c +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + #include + + #include "iris_core.h" +@@ -252,6 +253,12 @@ static int iris_probe(struct platform_device *pdev) + dma_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32)); + dma_set_seg_boundary(&pdev->dev, DMA_BIT_MASK(32)); + ++ pm_runtime_set_autosuspend_delay(core->dev, AUTOSUSPEND_DELAY_VALUE); ++ pm_runtime_use_autosuspend(core->dev); ++ ret = devm_pm_runtime_enable(core->dev); ++ if (ret) ++ goto err_vdev_unreg; ++ + return 0; + + err_vdev_unreg: +@@ -262,6 +269,51 @@ static int iris_probe(struct platform_device *pdev) + return ret; + } + ++static int __maybe_unused iris_pm_suspend(struct device *dev) ++{ ++ struct iris_core *core; ++ int ret = 0; ++ ++ core = dev_get_drvdata(dev); ++ ++ mutex_lock(&core->lock); ++ if (core->state != IRIS_CORE_INIT) ++ goto exit; ++ ++ ret = iris_hfi_pm_suspend(core); ++ ++exit: ++ mutex_unlock(&core->lock); ++ ++ return ret; ++} ++ ++static int __maybe_unused iris_pm_resume(struct device *dev) ++{ ++ struct iris_core *core; ++ int ret = 0; ++ ++ core = dev_get_drvdata(dev); ++ ++ mutex_lock(&core->lock); ++ if (core->state != IRIS_CORE_INIT) ++ goto exit; ++ ++ ret = iris_hfi_pm_resume(core); ++ pm_runtime_mark_last_busy(core->dev); ++ ++exit: ++ mutex_unlock(&core->lock); ++ ++ return ret; ++} ++ ++static const struct dev_pm_ops iris_pm_ops = { ++ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, ++ pm_runtime_force_resume) ++ SET_RUNTIME_PM_OPS(iris_pm_suspend, iris_pm_resume, NULL) ++}; ++ + static const struct of_device_id iris_dt_match[] = { + { + .compatible = "qcom,sm8550-iris", +@@ -277,6 +329,7 @@ static struct platform_driver qcom_iris_driver = { + .driver = { + .name = "qcom-iris", + .of_match_table = iris_dt_match, ++ .pm = &iris_pm_ops, + }, + }; + +diff --git a/drivers/media/platform/qcom/iris/iris_resources.c b/drivers/media/platform/qcom/iris/iris_resources.c +new file mode 100644 +index 000000000000..cf32f268b703 +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_resources.c +@@ -0,0 +1,131 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "iris_core.h" ++#include "iris_resources.h" ++ ++#define BW_THRESHOLD 50000 ++ ++int iris_set_icc_bw(struct iris_core *core, unsigned long icc_bw) ++{ ++ unsigned long bw_kbps = 0, bw_prev = 0; ++ const struct icc_info *icc_tbl; ++ int ret = 0, i; ++ ++ icc_tbl = core->iris_platform_data->icc_tbl; ++ ++ for (i = 0; i < core->icc_count; i++) { ++ if (!strcmp(core->icc_tbl[i].name, "video-mem")) { ++ bw_kbps = icc_bw; ++ bw_prev = core->power.icc_bw; ++ ++ bw_kbps = clamp_t(typeof(bw_kbps), bw_kbps, ++ icc_tbl[i].bw_min_kbps, icc_tbl[i].bw_max_kbps); ++ ++ if (abs(bw_kbps - bw_prev) < BW_THRESHOLD && bw_prev) ++ return ret; ++ ++ core->icc_tbl[i].avg_bw = bw_kbps; ++ ++ core->power.icc_bw = bw_kbps; ++ break; ++ } ++ } ++ ++ return icc_bulk_set_bw(core->icc_count, core->icc_tbl); ++} ++ ++int iris_unset_icc_bw(struct iris_core *core) ++{ ++ u32 i; ++ ++ core->power.icc_bw = 0; ++ ++ for (i = 0; i < core->icc_count; i++) { ++ core->icc_tbl[i].avg_bw = 0; ++ core->icc_tbl[i].peak_bw = 0; ++ } ++ ++ return icc_bulk_set_bw(core->icc_count, core->icc_tbl); ++} ++ ++int iris_enable_power_domains(struct iris_core *core, struct device *pd_dev) ++{ ++ int ret; ++ ++ ret = dev_pm_opp_set_rate(core->dev, ULONG_MAX); ++ if (ret) ++ return ret; ++ ++ ret = pm_runtime_get_sync(pd_dev); ++ if (ret < 0) ++ return ret; ++ ++ return ret; ++} ++ ++int iris_disable_power_domains(struct iris_core *core, struct device *pd_dev) ++{ ++ int ret; ++ ++ ret = dev_pm_opp_set_rate(core->dev, 0); ++ if (ret) ++ return ret; ++ ++ pm_runtime_put_sync(pd_dev); ++ ++ return 0; ++} ++ ++static struct clk *iris_get_clk_by_type(struct iris_core *core, enum platform_clk_type clk_type) ++{ ++ const struct platform_clk_data *clk_tbl; ++ u32 clk_cnt, i, j; ++ ++ clk_tbl = core->iris_platform_data->clk_tbl; ++ clk_cnt = core->iris_platform_data->clk_tbl_size; ++ ++ for (i = 0; i < clk_cnt; i++) { ++ if (clk_tbl[i].clk_type == clk_type) { ++ for (j = 0; core->clock_tbl && j < core->clk_count; j++) { ++ if (!strcmp(core->clock_tbl[j].id, clk_tbl[i].clk_name)) ++ return core->clock_tbl[j].clk; ++ } ++ } ++ } ++ ++ return NULL; ++} ++ ++int iris_prepare_enable_clock(struct iris_core *core, enum platform_clk_type clk_type) ++{ ++ struct clk *clock; ++ ++ clock = iris_get_clk_by_type(core, clk_type); ++ if (!clock) ++ return -EINVAL; ++ ++ return clk_prepare_enable(clock); ++} ++ ++int iris_disable_unprepare_clock(struct iris_core *core, enum platform_clk_type clk_type) ++{ ++ struct clk *clock; ++ ++ clock = iris_get_clk_by_type(core, clk_type); ++ if (!clock) ++ return -EINVAL; ++ ++ clk_disable_unprepare(clock); ++ ++ return 0; ++} +diff --git a/drivers/media/platform/qcom/iris/iris_resources.h b/drivers/media/platform/qcom/iris/iris_resources.h +new file mode 100644 +index 000000000000..f723dfe5bd81 +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_resources.h +@@ -0,0 +1,18 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef __IRIS_RESOURCES_H__ ++#define __IRIS_RESOURCES_H__ ++ ++struct iris_core; ++ ++int iris_enable_power_domains(struct iris_core *core, struct device *pd_dev); ++int iris_disable_power_domains(struct iris_core *core, struct device *pd_dev); ++int iris_unset_icc_bw(struct iris_core *core); ++int iris_set_icc_bw(struct iris_core *core, unsigned long icc_bw); ++int iris_disable_unprepare_clock(struct iris_core *core, enum platform_clk_type clk_type); ++int iris_prepare_enable_clock(struct iris_core *core, enum platform_clk_type clk_type); ++ ++#endif +diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c +index 5dd0ccbaa2fb..b8654e73f516 100644 +--- a/drivers/media/platform/qcom/iris/iris_vidc.c ++++ b/drivers/media/platform/qcom/iris/iris_vidc.c +@@ -3,6 +3,7 @@ + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + ++#include + #include + #include + +@@ -81,12 +82,19 @@ int iris_open(struct file *filp) + struct iris_inst *inst; + int ret; + ++ ret = pm_runtime_resume_and_get(core->dev); ++ if (ret < 0) ++ return ret; ++ + ret = iris_core_init(core); + if (ret) { + dev_err(core->dev, "core init failed\n"); ++ pm_runtime_put_sync(core->dev); + return ret; + } + ++ pm_runtime_put_sync(core->dev); ++ + inst = core->iris_platform_data->get_instance(); + if (!inst) + return -ENOMEM; +diff --git a/drivers/media/platform/qcom/iris/iris_vpu2.c b/drivers/media/platform/qcom/iris/iris_vpu2.c +new file mode 100644 +index 000000000000..bd8427411576 +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_vpu2.c +@@ -0,0 +1,11 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include "iris_instance.h" ++#include "iris_vpu_common.h" ++ ++const struct vpu_ops iris_vpu2_ops = { ++ .power_off_hw = iris_vpu_power_off_hw, ++}; +diff --git a/drivers/media/platform/qcom/iris/iris_vpu3.c b/drivers/media/platform/qcom/iris/iris_vpu3.c +new file mode 100644 +index 000000000000..10599f1fa789 +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_vpu3.c +@@ -0,0 +1,84 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include ++ ++#include "iris_instance.h" ++#include "iris_vpu_common.h" ++#include "iris_vpu_register_defines.h" ++ ++#define AON_MVP_NOC_RESET 0x0001F000 ++ ++#define WRAPPER_CORE_CLOCK_CONFIG (WRAPPER_BASE_OFFS + 0x88) ++#define CORE_CLK_RUN 0x0 ++ ++#define CPU_CS_AHB_BRIDGE_SYNC_RESET (CPU_CS_BASE_OFFS + 0x160) ++#define CORE_BRIDGE_SW_RESET BIT(0) ++#define CORE_BRIDGE_HW_RESET_DISABLE BIT(1) ++ ++#define AON_WRAPPER_MVP_NOC_RESET_REQ (AON_MVP_NOC_RESET + 0x000) ++#define VIDEO_NOC_RESET_REQ (BIT(0) | BIT(1)) ++ ++#define AON_WRAPPER_MVP_NOC_RESET_ACK (AON_MVP_NOC_RESET + 0x004) ++ ++#define VCODEC_SS_IDLE_STATUSN (VCODEC_BASE_OFFS + 0x70) ++ ++static bool iris_vpu3_hw_power_collapsed(struct iris_core *core) ++{ ++ u32 value, pwr_status; ++ ++ value = readl(core->reg_base + WRAPPER_CORE_POWER_STATUS); ++ pwr_status = value & BIT(1); ++ ++ return pwr_status ? false : true; ++} ++ ++static void iris_vpu3_power_off_hardware(struct iris_core *core) ++{ ++ u32 reg_val = 0, value, i; ++ int ret; ++ ++ if (iris_vpu3_hw_power_collapsed(core)) ++ goto disable_power; ++ ++ dev_err(core->dev, "video hw is power on\n"); ++ ++ value = readl(core->reg_base + WRAPPER_CORE_CLOCK_CONFIG); ++ if (value) ++ writel(CORE_CLK_RUN, core->reg_base + WRAPPER_CORE_CLOCK_CONFIG); ++ ++ for (i = 0; i < core->iris_platform_data->num_vpp_pipe; i++) { ++ ret = readl_poll_timeout(core->reg_base + VCODEC_SS_IDLE_STATUSN + 4 * i, ++ reg_val, reg_val & 0x400000, 2000, 20000); ++ if (ret) ++ goto disable_power; ++ } ++ ++ writel(VIDEO_NOC_RESET_REQ, core->reg_base + AON_WRAPPER_MVP_NOC_RESET_REQ); ++ ++ ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_RESET_ACK, ++ reg_val, reg_val & 0x3, 200, 2000); ++ if (ret) ++ goto disable_power; ++ ++ writel(0x0, core->reg_base + AON_WRAPPER_MVP_NOC_RESET_REQ); ++ ++ ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_RESET_ACK, ++ reg_val, !(reg_val & 0x3), 200, 2000); ++ if (ret) ++ goto disable_power; ++ ++ writel(CORE_BRIDGE_SW_RESET | CORE_BRIDGE_HW_RESET_DISABLE, ++ core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); ++ writel(CORE_BRIDGE_HW_RESET_DISABLE, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); ++ writel(0x0, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); ++ ++disable_power: ++ iris_vpu_power_off_hw(core); ++} ++ ++const struct vpu_ops iris_vpu3_ops = { ++ .power_off_hw = iris_vpu3_power_off_hardware, ++}; +diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.c b/drivers/media/platform/qcom/iris/iris_vpu_common.c +index 34817573f61b..fe9896d66848 100644 +--- a/drivers/media/platform/qcom/iris/iris_vpu_common.c ++++ b/drivers/media/platform/qcom/iris/iris_vpu_common.c +@@ -4,13 +4,16 @@ + */ + + #include ++#include ++#include + + #include "iris_core.h" + #include "iris_vpu_common.h" ++#include "iris_vpu_register_defines.h" + +-#define CPU_BASE_OFFS 0x000A0000 ++#define WRAPPER_TZ_BASE_OFFS 0x000C0000 ++#define AON_BASE_OFFS 0x000E0000 + +-#define CPU_CS_BASE_OFFS (CPU_BASE_OFFS) + #define CPU_IC_BASE_OFFS (CPU_BASE_OFFS) + + #define CPU_CS_A2HSOFTINTCLR (CPU_CS_BASE_OFFS + 0x1C) +@@ -21,6 +24,7 @@ + + #define CTRL_INIT_IDLE_MSG_BMSK 0x40000000 + #define CTRL_ERROR_STATUS__M 0xfe ++#define CTRL_STATUS_PC_READY 0x100 + + #define QTBL_INFO (CPU_CS_BASE_OFFS + 0x50) + #define QTBL_ENABLE BIT(0) +@@ -35,15 +39,48 @@ + #define HOST2XTENSA_INTR_ENABLE BIT(0) + + #define CPU_CS_X2RPMH (CPU_CS_BASE_OFFS + 0x168) ++#define MSK_SIGNAL_FROM_TENSILICA BIT(0) ++#define MSK_CORE_POWER_ON BIT(1) + + #define CPU_IC_SOFTINT (CPU_IC_BASE_OFFS + 0x150) + #define CPU_IC_SOFTINT_H2A_SHFT 0x0 + +-#define WRAPPER_BASE_OFFS 0x000B0000 + #define WRAPPER_INTR_STATUS (WRAPPER_BASE_OFFS + 0x0C) + #define WRAPPER_INTR_STATUS_A2HWD_BMSK BIT(3) + #define WRAPPER_INTR_STATUS_A2H_BMSK BIT(2) + ++#define WRAPPER_INTR_MASK (WRAPPER_BASE_OFFS + 0x10) ++#define WRAPPER_INTR_MASK_A2HWD_BMSK BIT(3) ++#define WRAPPER_INTR_MASK_A2HCPU_BMSK BIT(2) ++ ++#define WRAPPER_DEBUG_BRIDGE_LPI_CONTROL (WRAPPER_BASE_OFFS + 0x54) ++#define WRAPPER_DEBUG_BRIDGE_LPI_STATUS (WRAPPER_BASE_OFFS + 0x58) ++#define WRAPPER_IRIS_CPU_NOC_LPI_CONTROL (WRAPPER_BASE_OFFS + 0x5C) ++#define WRAPPER_IRIS_CPU_NOC_LPI_STATUS (WRAPPER_BASE_OFFS + 0x60) ++ ++#define WRAPPER_TZ_CPU_STATUS (WRAPPER_TZ_BASE_OFFS + 0x10) ++#define WRAPPER_TZ_CTL_AXI_CLOCK_CONFIG (WRAPPER_TZ_BASE_OFFS + 0x14) ++#define CTL_AXI_CLK_HALT BIT(0) ++#define CTL_CLK_HALT BIT(1) ++ ++#define WRAPPER_TZ_QNS4PDXFIFO_RESET (WRAPPER_TZ_BASE_OFFS + 0x18) ++#define RESET_HIGH BIT(0) ++ ++#define AON_WRAPPER_MVP_NOC_LPI_CONTROL (AON_BASE_OFFS) ++#define REQ_POWER_DOWN_PREP BIT(0) ++ ++#define AON_WRAPPER_MVP_NOC_LPI_STATUS (AON_BASE_OFFS + 0x4) ++ ++static void iris_vpu_interrupt_init(struct iris_core *core) ++{ ++ u32 mask_val; ++ ++ mask_val = readl(core->reg_base + WRAPPER_INTR_MASK); ++ mask_val &= ~(WRAPPER_INTR_MASK_A2HWD_BMSK | ++ WRAPPER_INTR_MASK_A2HCPU_BMSK); ++ writel(mask_val, core->reg_base + WRAPPER_INTR_MASK); ++} ++ + static void iris_vpu_setup_ucregion_memory_map(struct iris_core *core) + { + u32 queue_size, value; +@@ -130,3 +167,203 @@ int iris_vpu_watchdog(struct iris_core *core, u32 intr_status) + + return 0; + } ++ ++int iris_vpu_prepare_pc(struct iris_core *core) ++{ ++ u32 wfi_status, idle_status, pc_ready; ++ u32 ctrl_status, val = 0; ++ int ret; ++ ++ ctrl_status = readl(core->reg_base + CTRL_STATUS); ++ pc_ready = ctrl_status & CTRL_STATUS_PC_READY; ++ idle_status = ctrl_status & BIT(30); ++ if (pc_ready) ++ return 0; ++ ++ wfi_status = readl(core->reg_base + WRAPPER_TZ_CPU_STATUS); ++ wfi_status &= BIT(0); ++ if (!wfi_status || !idle_status) ++ goto skip_power_off; ++ ++ ret = core->hfi_ops->sys_pc_prep(core); ++ if (ret) ++ goto skip_power_off; ++ ++ ret = readl_poll_timeout(core->reg_base + CTRL_STATUS, val, ++ val & CTRL_STATUS_PC_READY, 250, 2500); ++ if (ret) ++ goto skip_power_off; ++ ++ ret = readl_poll_timeout(core->reg_base + WRAPPER_TZ_CPU_STATUS, ++ val, val & BIT(0), 250, 2500); ++ if (ret) ++ goto skip_power_off; ++ ++ return 0; ++ ++skip_power_off: ++ ctrl_status = readl(core->reg_base + CTRL_STATUS); ++ wfi_status = readl(core->reg_base + WRAPPER_TZ_CPU_STATUS); ++ wfi_status &= BIT(0); ++ dev_err(core->dev, "skip power collapse, wfi=%#x, idle=%#x, pcr=%#x, ctrl=%#x)\n", ++ wfi_status, idle_status, pc_ready, ctrl_status); ++ ++ return -EAGAIN; ++} ++ ++static int iris_vpu_power_off_controller(struct iris_core *core) ++{ ++ u32 val = 0; ++ int ret; ++ ++ writel(MSK_SIGNAL_FROM_TENSILICA | MSK_CORE_POWER_ON, core->reg_base + CPU_CS_X2RPMH); ++ ++ writel(REQ_POWER_DOWN_PREP, core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL); ++ ++ ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_LPI_STATUS, ++ val, val & BIT(0), 200, 2000); ++ if (ret) ++ goto disable_power; ++ ++ writel(REQ_POWER_DOWN_PREP, core->reg_base + WRAPPER_IRIS_CPU_NOC_LPI_CONTROL); ++ ++ ret = readl_poll_timeout(core->reg_base + WRAPPER_IRIS_CPU_NOC_LPI_STATUS, ++ val, val & BIT(0), 200, 2000); ++ if (ret) ++ goto disable_power; ++ ++ writel(0x0, core->reg_base + WRAPPER_DEBUG_BRIDGE_LPI_CONTROL); ++ ++ ret = readl_poll_timeout(core->reg_base + WRAPPER_DEBUG_BRIDGE_LPI_STATUS, ++ val, val == 0, 200, 2000); ++ if (ret) ++ goto disable_power; ++ ++ writel(CTL_AXI_CLK_HALT | CTL_CLK_HALT, ++ core->reg_base + WRAPPER_TZ_CTL_AXI_CLOCK_CONFIG); ++ writel(RESET_HIGH, core->reg_base + WRAPPER_TZ_QNS4PDXFIFO_RESET); ++ writel(0x0, core->reg_base + WRAPPER_TZ_QNS4PDXFIFO_RESET); ++ writel(0x0, core->reg_base + WRAPPER_TZ_CTL_AXI_CLOCK_CONFIG); ++ ++disable_power: ++ iris_disable_unprepare_clock(core, IRIS_CTRL_CLK); ++ iris_disable_unprepare_clock(core, IRIS_AXI_CLK); ++ iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); ++ ++ return 0; ++} ++ ++void iris_vpu_power_off_hw(struct iris_core *core) ++{ ++ dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN], false); ++ iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); ++ iris_disable_unprepare_clock(core, IRIS_HW_CLK); ++} ++ ++void iris_vpu_power_off(struct iris_core *core) ++{ ++ dev_pm_opp_set_rate(core->dev, 0); ++ core->iris_platform_data->vpu_ops->power_off_hw(core); ++ iris_vpu_power_off_controller(core); ++ iris_unset_icc_bw(core); ++ ++ if (!iris_vpu_watchdog(core, core->intr_status)) ++ disable_irq_nosync(core->irq); ++} ++ ++static int iris_vpu_power_on_controller(struct iris_core *core) ++{ ++ u32 rst_tbl_size = core->iris_platform_data->clk_rst_tbl_size; ++ int ret; ++ ++ ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); ++ if (ret) ++ return ret; ++ ++ ret = reset_control_bulk_reset(rst_tbl_size, core->resets); ++ if (ret) ++ goto err_disable_power; ++ ++ ret = iris_prepare_enable_clock(core, IRIS_AXI_CLK); ++ if (ret) ++ goto err_disable_power; ++ ++ ret = iris_prepare_enable_clock(core, IRIS_CTRL_CLK); ++ if (ret) ++ goto err_disable_clock; ++ ++ return 0; ++ ++err_disable_clock: ++ iris_disable_unprepare_clock(core, IRIS_AXI_CLK); ++err_disable_power: ++ iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); ++ ++ return ret; ++} ++ ++static int iris_vpu_power_on_hw(struct iris_core *core) ++{ ++ int ret; ++ ++ ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); ++ if (ret) ++ return ret; ++ ++ ret = iris_prepare_enable_clock(core, IRIS_HW_CLK); ++ if (ret) ++ goto err_disable_power; ++ ++ ret = dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN], true); ++ if (ret) ++ goto err_disable_clock; ++ ++ return 0; ++ ++err_disable_clock: ++ iris_disable_unprepare_clock(core, IRIS_HW_CLK); ++err_disable_power: ++ iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); ++ ++ return ret; ++} ++ ++int iris_vpu_power_on(struct iris_core *core) ++{ ++ u32 freq; ++ int ret; ++ ++ ret = iris_set_icc_bw(core, INT_MAX); ++ if (ret) ++ goto err; ++ ++ ret = iris_vpu_power_on_controller(core); ++ if (ret) ++ goto err_unvote_icc; ++ ++ ret = iris_vpu_power_on_hw(core); ++ if (ret) ++ goto err_power_off_ctrl; ++ ++ freq = core->power.clk_freq ? core->power.clk_freq : ++ (u32)ULONG_MAX; ++ ++ dev_pm_opp_set_rate(core->dev, freq); ++ ++ core->iris_platform_data->set_preset_registers(core); ++ ++ iris_vpu_interrupt_init(core); ++ core->intr_status = 0; ++ enable_irq(core->irq); ++ ++ return 0; ++ ++err_power_off_ctrl: ++ iris_vpu_power_off_controller(core); ++err_unvote_icc: ++ iris_unset_icc_bw(core); ++err: ++ dev_err(core->dev, "power on failed\n"); ++ ++ return ret; ++} +diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.h b/drivers/media/platform/qcom/iris/iris_vpu_common.h +index c38c055d3d14..d3efa7c0ce9a 100644 +--- a/drivers/media/platform/qcom/iris/iris_vpu_common.h ++++ b/drivers/media/platform/qcom/iris/iris_vpu_common.h +@@ -8,9 +8,20 @@ + + struct iris_core; + ++extern const struct vpu_ops iris_vpu2_ops; ++extern const struct vpu_ops iris_vpu3_ops; ++ ++struct vpu_ops { ++ void (*power_off_hw)(struct iris_core *core); ++}; ++ + int iris_vpu_boot_firmware(struct iris_core *core); + void iris_vpu_raise_interrupt(struct iris_core *core); + void iris_vpu_clear_interrupt(struct iris_core *core); + int iris_vpu_watchdog(struct iris_core *core, u32 intr_status); ++int iris_vpu_prepare_pc(struct iris_core *core); ++int iris_vpu_power_on(struct iris_core *core); ++void iris_vpu_power_off_hw(struct iris_core *core); ++void iris_vpu_power_off(struct iris_core *core); + + #endif +diff --git a/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h b/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h +new file mode 100644 +index 000000000000..fe8a39e5e5a3 +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h +@@ -0,0 +1,17 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef __IRIS_VPU_REGISTER_DEFINES_H__ ++#define __IRIS_VPU_REGISTER_DEFINES_H__ ++ ++#define VCODEC_BASE_OFFS 0x00000000 ++#define CPU_BASE_OFFS 0x000A0000 ++#define WRAPPER_BASE_OFFS 0x000B0000 ++ ++#define CPU_CS_BASE_OFFS (CPU_BASE_OFFS) ++ ++#define WRAPPER_CORE_POWER_STATUS (WRAPPER_BASE_OFFS + 0x80) ++ ++#endif +-- +2.34.1 + diff --git a/patch/kernel/archive/sm8550-6.12/0009_media--iris--implement-reqbuf-ioctl-with-vb2_queue.patch b/patch/kernel/archive/sm8550-6.12/0009_media--iris--implement-reqbuf-ioctl-with-vb2_queue.patch new file mode 100644 index 000000000..2f9645c7c --- /dev/null +++ b/patch/kernel/archive/sm8550-6.12/0009_media--iris--implement-reqbuf-ioctl-with-vb2_queue.patch @@ -0,0 +1,1651 @@ +From c099666411578d2d1eea95bd644af25033f24af7 Mon Sep 17 00:00:00 2001 +From: Dikshita Agarwal +Date: Fri, 7 Feb 2025 13:24:49 +0530 +Subject: [PATCH] media: iris: implement reqbuf ioctl with vb2_queue_setup + +Implement the reqbuf IOCTL op and the vb2_queue_setup vb2 op in the +driver with necessary hooks. + +Reviewed-by: Hans Verkuil +Tested-by: Stefan Schmidt # x1e80100 (Dell XPS 13 9345) +Reviewed-by: Stefan Schmidt +Tested-by: Neil Armstrong # on SM8550-QRD +Tested-by: Neil Armstrong # on SM8550-HDK +Signed-off-by: Dikshita Agarwal +Link: https://lore.kernel.org/r/20250207-qcom-video-iris-v10-9-ab66eeffbd20@quicinc.com +Signed-off-by: Neil Armstrong +--- + drivers/media/platform/qcom/iris/Makefile | 7 +- + .../media/platform/qcom/iris/iris_buffer.c | 119 ++++++++++++++++++ + .../media/platform/qcom/iris/iris_buffer.h | 107 ++++++++++++++++ + drivers/media/platform/qcom/iris/iris_core.h | 6 + + .../platform/qcom/iris/iris_hfi_common.h | 3 + + .../qcom/iris/iris_hfi_gen1_command.c | 40 ++++++ + .../qcom/iris/iris_hfi_gen1_defines.h | 47 ++++++- + .../qcom/iris/iris_hfi_gen1_response.c | 79 +++++++++++- + .../media/platform/qcom/iris/iris_hfi_gen2.h | 5 + + .../qcom/iris/iris_hfi_gen2_command.c | 105 ++++++++++++++++ + .../qcom/iris/iris_hfi_gen2_defines.h | 35 ++++++ + .../platform/qcom/iris/iris_hfi_gen2_packet.c | 39 ++++++ + .../platform/qcom/iris/iris_hfi_gen2_packet.h | 7 ++ + .../qcom/iris/iris_hfi_gen2_response.c | 111 +++++++++++++++- + .../media/platform/qcom/iris/iris_instance.h | 22 ++++ + .../platform/qcom/iris/iris_platform_common.h | 5 + + .../platform/qcom/iris/iris_platform_sm8550.c | 6 + + drivers/media/platform/qcom/iris/iris_probe.c | 2 + + drivers/media/platform/qcom/iris/iris_utils.c | 52 ++++++++ + drivers/media/platform/qcom/iris/iris_utils.h | 34 +++++ + drivers/media/platform/qcom/iris/iris_vb2.c | 50 ++++++++ + drivers/media/platform/qcom/iris/iris_vb2.h | 12 ++ + drivers/media/platform/qcom/iris/iris_vdec.c | 56 +++++++++ + drivers/media/platform/qcom/iris/iris_vdec.h | 14 +++ + drivers/media/platform/qcom/iris/iris_vidc.c | 81 ++++++++++++ + .../platform/qcom/iris/iris_vpu_buffer.c | 19 +++ + .../platform/qcom/iris/iris_vpu_buffer.h | 15 +++ + 27 files changed, 1070 insertions(+), 8 deletions(-) + create mode 100644 drivers/media/platform/qcom/iris/iris_buffer.c + create mode 100644 drivers/media/platform/qcom/iris/iris_buffer.h + create mode 100644 drivers/media/platform/qcom/iris/iris_utils.c + create mode 100644 drivers/media/platform/qcom/iris/iris_utils.h + create mode 100644 drivers/media/platform/qcom/iris/iris_vb2.c + create mode 100644 drivers/media/platform/qcom/iris/iris_vb2.h + create mode 100644 drivers/media/platform/qcom/iris/iris_vdec.c + create mode 100644 drivers/media/platform/qcom/iris/iris_vdec.h + create mode 100644 drivers/media/platform/qcom/iris/iris_vpu_buffer.c + create mode 100644 drivers/media/platform/qcom/iris/iris_vpu_buffer.h + +diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile +index a5f290a8c4af..48ab264b7906 100644 +--- a/drivers/media/platform/qcom/iris/Makefile ++++ b/drivers/media/platform/qcom/iris/Makefile +@@ -1,4 +1,5 @@ +-iris-objs += iris_core.o \ ++iris-objs += iris_buffer.o \ ++ iris_core.o \ + iris_firmware.o \ + iris_hfi_common.o \ + iris_hfi_gen1_command.o \ +@@ -10,9 +11,13 @@ iris-objs += iris_core.o \ + iris_platform_sm8550.o \ + iris_probe.o \ + iris_resources.o \ ++ iris_utils.o \ + iris_vidc.o \ ++ iris_vb2.o \ ++ iris_vdec.o \ + iris_vpu2.o \ + iris_vpu3.o \ ++ iris_vpu_buffer.o \ + iris_vpu_common.o \ + + obj-$(CONFIG_VIDEO_QCOM_IRIS) += iris.o +diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c +new file mode 100644 +index 000000000000..037931ce6550 +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_buffer.c +@@ -0,0 +1,119 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include ++ ++#include "iris_buffer.h" ++#include "iris_instance.h" ++ ++#define PIXELS_4K 4096 ++#define MAX_WIDTH 4096 ++#define MAX_HEIGHT 2304 ++#define Y_STRIDE_ALIGN 128 ++#define UV_STRIDE_ALIGN 128 ++#define Y_SCANLINE_ALIGN 32 ++#define UV_SCANLINE_ALIGN 16 ++#define UV_SCANLINE_ALIGN_QC08C 32 ++#define META_STRIDE_ALIGNED 64 ++#define META_SCANLINE_ALIGNED 16 ++#define NUM_MBS_4K (DIV_ROUND_UP(MAX_WIDTH, 16) * DIV_ROUND_UP(MAX_HEIGHT, 16)) ++ ++/* ++ * NV12: ++ * YUV 4:2:0 image with a plane of 8 bit Y samples followed ++ * by an interleaved U/V plane containing 8 bit 2x2 subsampled ++ * colour difference samples. ++ * ++ * <-Y/UV_Stride (aligned to 128)-> ++ * <------- Width -------> ++ * Y Y Y Y Y Y Y Y Y Y Y Y . . . . ^ ^ ++ * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | | ++ * Y Y Y Y Y Y Y Y Y Y Y Y . . . . Height | ++ * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | y_scanlines (aligned to 32) ++ * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | | ++ * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | | ++ * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | | ++ * Y Y Y Y Y Y Y Y Y Y Y Y . . . . V | ++ * . . . . . . . . . . . . . . . . | ++ * . . . . . . . . . . . . . . . . | ++ * . . . . . . . . . . . . . . . . | ++ * . . . . . . . . . . . . . . . . V ++ * U V U V U V U V U V U V . . . . ^ ++ * U V U V U V U V U V U V . . . . | ++ * U V U V U V U V U V U V . . . . | ++ * U V U V U V U V U V U V . . . . uv_scanlines (aligned to 16) ++ * . . . . . . . . . . . . . . . . | ++ * . . . . . . . . . . . . . . . . V ++ * . . . . . . . . . . . . . . . . --> Buffer size aligned to 4K ++ * ++ * y_stride : Width aligned to 128 ++ * uv_stride : Width aligned to 128 ++ * y_scanlines: Height aligned to 32 ++ * uv_scanlines: Height/2 aligned to 16 ++ * Total size = align((y_stride * y_scanlines ++ * + uv_stride * uv_scanlines , 4096) ++ * ++ * Note: All the alignments are hardware requirements. ++ */ ++static u32 iris_yuv_buffer_size_nv12(struct iris_inst *inst) ++{ ++ u32 y_plane, uv_plane, y_stride, uv_stride, y_scanlines, uv_scanlines; ++ struct v4l2_format *f = inst->fmt_dst; ++ ++ y_stride = ALIGN(f->fmt.pix_mp.width, Y_STRIDE_ALIGN); ++ uv_stride = ALIGN(f->fmt.pix_mp.width, UV_STRIDE_ALIGN); ++ y_scanlines = ALIGN(f->fmt.pix_mp.height, Y_SCANLINE_ALIGN); ++ uv_scanlines = ALIGN((f->fmt.pix_mp.height + 1) >> 1, UV_SCANLINE_ALIGN); ++ y_plane = y_stride * y_scanlines; ++ uv_plane = uv_stride * uv_scanlines; ++ ++ return ALIGN(y_plane + uv_plane, PIXELS_4K); ++} ++ ++static u32 iris_bitstream_buffer_size(struct iris_inst *inst) ++{ ++ struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps; ++ u32 base_res_mbs = NUM_MBS_4K; ++ u32 frame_size, num_mbs; ++ u32 div_factor = 2; ++ ++ num_mbs = iris_get_mbpf(inst); ++ if (num_mbs > NUM_MBS_4K) { ++ div_factor = 4; ++ base_res_mbs = caps->max_mbpf; ++ } ++ ++ /* ++ * frame_size = YUVsize / div_factor ++ * where YUVsize = resolution_in_MBs * MBs_in_pixel * 3 / 2 ++ */ ++ frame_size = base_res_mbs * (16 * 16) * 3 / 2 / div_factor; ++ ++ return ALIGN(frame_size, PIXELS_4K); ++} ++ ++int iris_get_buffer_size(struct iris_inst *inst, ++ enum iris_buffer_type buffer_type) ++{ ++ switch (buffer_type) { ++ case BUF_INPUT: ++ return iris_bitstream_buffer_size(inst); ++ case BUF_OUTPUT: ++ return iris_yuv_buffer_size_nv12(inst); ++ default: ++ return 0; ++ } ++} ++ ++void iris_vb2_queue_error(struct iris_inst *inst) ++{ ++ struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; ++ struct vb2_queue *q; ++ ++ q = v4l2_m2m_get_src_vq(m2m_ctx); ++ vb2_queue_error(q); ++ q = v4l2_m2m_get_dst_vq(m2m_ctx); ++ vb2_queue_error(q); ++} +diff --git a/drivers/media/platform/qcom/iris/iris_buffer.h b/drivers/media/platform/qcom/iris/iris_buffer.h +new file mode 100644 +index 000000000000..ae2ec5637108 +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_buffer.h +@@ -0,0 +1,107 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef __IRIS_BUFFER_H__ ++#define __IRIS_BUFFER_H__ ++ ++#include ++ ++struct iris_inst; ++ ++#define to_iris_buffer(ptr) container_of(ptr, struct iris_buffer, vb2) ++ ++/** ++ * enum iris_buffer_type ++ * ++ * @BUF_INPUT: input buffer to the iris hardware ++ * @BUF_OUTPUT: output buffer from the iris hardware ++ * @BUF_BIN: buffer to store intermediate bin data ++ * @BUF_ARP: buffer for auto register programming ++ * @BUF_COMV: buffer to store colocated motion vectors ++ * @BUF_NON_COMV: buffer to hold config data for HW ++ * @BUF_LINE: buffer to store decoding/encoding context data for HW ++ * @BUF_DPB: buffer to store display picture buffers for reference ++ * @BUF_PERSIST: buffer to store session context data ++ * @BUF_SCRATCH_1: buffer to store decoding/encoding context data for HW ++ * @BUF_TYPE_MAX: max buffer types ++ */ ++enum iris_buffer_type { ++ BUF_INPUT = 1, ++ BUF_OUTPUT, ++ BUF_BIN, ++ BUF_ARP, ++ BUF_COMV, ++ BUF_NON_COMV, ++ BUF_LINE, ++ BUF_DPB, ++ BUF_PERSIST, ++ BUF_SCRATCH_1, ++ BUF_TYPE_MAX, ++}; ++ ++/* ++ * enum iris_buffer_attributes ++ * ++ * BUF_ATTR_DEFERRED: buffer queued by client but not submitted to firmware. ++ * BUF_ATTR_PENDING_RELEASE: buffers requested to be released from firmware. ++ * BUF_ATTR_QUEUED: buffers submitted to firmware. ++ * BUF_ATTR_DEQUEUED: buffers received from firmware. ++ * BUF_ATTR_BUFFER_DONE: buffers sent back to vb2. ++ */ ++enum iris_buffer_attributes { ++ BUF_ATTR_DEFERRED = BIT(0), ++ BUF_ATTR_PENDING_RELEASE = BIT(1), ++ BUF_ATTR_QUEUED = BIT(2), ++ BUF_ATTR_DEQUEUED = BIT(3), ++ BUF_ATTR_BUFFER_DONE = BIT(4), ++}; ++ ++/** ++ * struct iris_buffer ++ * ++ * @vb2: v4l2 vb2 buffer ++ * @list: list head for the iris_buffers structure ++ * @inst: iris instance structure ++ * @type: enum for type of iris buffer ++ * @index: identifier for the iris buffer ++ * @fd: file descriptor of the buffer ++ * @buffer_size: accessible buffer size in bytes starting from addr_offset ++ * @data_offset: accessible buffer offset from base address ++ * @data_size: data size in bytes ++ * @device_addr: device address of the buffer ++ * @kvaddr: kernel virtual address of the buffer ++ * @dma_attrs: dma attributes ++ * @flags: buffer flags. It is represented as bit masks. ++ * @timestamp: timestamp of the buffer in nano seconds (ns) ++ * @attr: enum for iris buffer attributes ++ */ ++struct iris_buffer { ++ struct vb2_v4l2_buffer vb2; ++ struct list_head list; ++ struct iris_inst *inst; ++ enum iris_buffer_type type; ++ u32 index; ++ int fd; ++ size_t buffer_size; ++ u32 data_offset; ++ size_t data_size; ++ dma_addr_t device_addr; ++ void *kvaddr; ++ unsigned long dma_attrs; ++ u32 flags; /* V4L2_BUF_FLAG_* */ ++ u64 timestamp; ++ enum iris_buffer_attributes attr; ++}; ++ ++struct iris_buffers { ++ struct list_head list; ++ u32 min_count; ++ u32 size; ++}; ++ ++int iris_get_buffer_size(struct iris_inst *inst, enum iris_buffer_type buffer_type); ++void iris_vb2_queue_error(struct iris_inst *inst); ++ ++#endif +diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h +index 58aab78ab2c4..1ddcb8793172 100644 +--- a/drivers/media/platform/qcom/iris/iris_core.h ++++ b/drivers/media/platform/qcom/iris/iris_core.h +@@ -34,6 +34,8 @@ struct icc_info { + * @v4l2_dev: a holder for v4l2 device structure + * @vdev_dec: iris video device structure for decoder + * @iris_v4l2_file_ops: iris v4l2 file ops ++ * @iris_v4l2_ioctl_ops: iris v4l2 ioctl ops ++ * @iris_vb2_ops: iris vb2 ops + * @icc_tbl: table of iris interconnects + * @icc_count: count of iris interconnects + * @pmdomain_tbl: table of iris power domains +@@ -60,6 +62,7 @@ struct icc_info { + * @core_init_done: structure of signal completion for system response + * @intr_status: interrupt status + * @sys_error_handler: a delayed work for handling system fatal error ++ * @instances: a list_head of all instances + */ + + struct iris_core { +@@ -69,6 +72,8 @@ struct iris_core { + struct v4l2_device v4l2_dev; + struct video_device *vdev_dec; + const struct v4l2_file_operations *iris_v4l2_file_ops; ++ const struct v4l2_ioctl_ops *iris_v4l2_ioctl_ops; ++ const struct vb2_ops *iris_vb2_ops; + struct icc_bulk_data *icc_tbl; + u32 icc_count; + struct dev_pm_domain_list *pmdomain_tbl; +@@ -95,6 +100,7 @@ struct iris_core { + struct completion core_init_done; + u32 intr_status; + struct delayed_work sys_error_handler; ++ struct list_head instances; + }; + + int iris_core_init(struct iris_core *core); +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.h b/drivers/media/platform/qcom/iris/iris_hfi_common.h +index 36673aafe1c9..eaa2db469c74 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_common.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_common.h +@@ -9,6 +9,7 @@ + #include + #include + ++struct iris_inst; + struct iris_core; + + enum hfi_packet_port_type { +@@ -47,6 +48,8 @@ struct iris_hfi_command_ops { + int (*sys_image_version)(struct iris_core *core); + int (*sys_interframe_powercollapse)(struct iris_core *core); + int (*sys_pc_prep)(struct iris_core *core); ++ int (*session_open)(struct iris_inst *inst); ++ int (*session_close)(struct iris_inst *inst); + }; + + struct iris_hfi_response_ops { +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +index b2e76d1dcbf7..7ee69c5223ce 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +@@ -66,11 +66,51 @@ static int iris_hfi_gen1_sys_pc_prep(struct iris_core *core) + return iris_hfi_queue_cmd_write_locked(core, &pkt, pkt.hdr.size); + } + ++static int iris_hfi_gen1_session_open(struct iris_inst *inst) ++{ ++ struct hfi_session_open_pkt packet; ++ int ret; ++ ++ packet.shdr.hdr.size = sizeof(struct hfi_session_open_pkt); ++ packet.shdr.hdr.pkt_type = HFI_CMD_SYS_SESSION_INIT; ++ packet.shdr.session_id = inst->session_id; ++ packet.session_domain = HFI_SESSION_TYPE_DEC; ++ packet.session_codec = HFI_VIDEO_CODEC_H264; ++ ++ reinit_completion(&inst->completion); ++ ++ ret = iris_hfi_queue_cmd_write(inst->core, &packet, packet.shdr.hdr.size); ++ if (ret) ++ return ret; ++ ++ return iris_wait_for_session_response(inst); ++} ++ ++static void iris_hfi_gen1_packet_session_cmd(struct iris_inst *inst, ++ struct hfi_session_pkt *packet, ++ u32 ptype) ++{ ++ packet->shdr.hdr.size = sizeof(*packet); ++ packet->shdr.hdr.pkt_type = ptype; ++ packet->shdr.session_id = inst->session_id; ++} ++ ++static int iris_hfi_gen1_session_close(struct iris_inst *inst) ++{ ++ struct hfi_session_pkt packet; ++ ++ iris_hfi_gen1_packet_session_cmd(inst, &packet, HFI_CMD_SYS_SESSION_END); ++ ++ return iris_hfi_queue_cmd_write(inst->core, &packet, packet.shdr.hdr.size); ++} ++ + static const struct iris_hfi_command_ops iris_hfi_gen1_command_ops = { + .sys_init = iris_hfi_gen1_sys_init, + .sys_image_version = iris_hfi_gen1_sys_image_version, + .sys_interframe_powercollapse = iris_hfi_gen1_sys_interframe_powercollapse, + .sys_pc_prep = iris_hfi_gen1_sys_pc_prep, ++ .session_open = iris_hfi_gen1_session_open, ++ .session_close = iris_hfi_gen1_session_close, + }; + + void iris_hfi_gen1_command_ops_init(struct iris_core *core) +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +index 81685a284f23..3640f8504db9 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +@@ -9,19 +9,34 @@ + #include + + #define HFI_VIDEO_ARCH_OX 0x1 ++ ++#define HFI_SESSION_TYPE_DEC 2 ++ ++#define HFI_VIDEO_CODEC_H264 0x00000002 ++ + #define HFI_ERR_NONE 0x0 + + #define HFI_CMD_SYS_INIT 0x10001 + #define HFI_CMD_SYS_PC_PREP 0x10002 + #define HFI_CMD_SYS_SET_PROPERTY 0x10005 + #define HFI_CMD_SYS_GET_PROPERTY 0x10006 ++#define HFI_CMD_SYS_SESSION_INIT 0x10007 ++#define HFI_CMD_SYS_SESSION_END 0x10008 + +-#define HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL 0x5 +-#define HFI_PROPERTY_SYS_IMAGE_VERSION 0x6 ++#define HFI_ERR_SESSION_UNSUPPORTED_SETTING 0x1008 ++#define HFI_ERR_SESSION_UNSUPPORT_BUFFERTYPE 0x1010 ++#define HFI_ERR_SESSION_INVALID_SCALE_FACTOR 0x1012 ++#define HFI_ERR_SESSION_UPSCALE_NOT_SUPPORTED 0x1013 + + #define HFI_EVENT_SYS_ERROR 0x1 ++#define HFI_EVENT_SESSION_ERROR 0x2 ++ ++#define HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL 0x5 ++#define HFI_PROPERTY_SYS_IMAGE_VERSION 0x6 + + #define HFI_MSG_SYS_INIT 0x20001 ++#define HFI_MSG_SYS_SESSION_INIT 0x20006 ++#define HFI_MSG_SYS_SESSION_END 0x20007 + #define HFI_MSG_SYS_COV 0x20009 + #define HFI_MSG_SYS_PROPERTY_INFO 0x2000a + +@@ -32,6 +47,21 @@ struct hfi_pkt_hdr { + u32 pkt_type; + }; + ++struct hfi_session_hdr_pkt { ++ struct hfi_pkt_hdr hdr; ++ u32 session_id; ++}; ++ ++struct hfi_session_open_pkt { ++ struct hfi_session_hdr_pkt shdr; ++ u32 session_domain; ++ u32 session_codec; ++}; ++ ++struct hfi_session_pkt { ++ struct hfi_session_hdr_pkt shdr; ++}; ++ + struct hfi_sys_init_pkt { + struct hfi_pkt_hdr hdr; + u32 arch_type; +@@ -54,7 +84,7 @@ struct hfi_sys_pc_prep_pkt { + }; + + struct hfi_msg_event_notify_pkt { +- struct hfi_pkt_hdr hdr; ++ struct hfi_session_hdr_pkt shdr; + u32 event_id; + u32 event_data1; + u32 event_data2; +@@ -68,6 +98,17 @@ struct hfi_msg_sys_init_done_pkt { + u32 data[]; + }; + ++struct hfi_msg_session_hdr_pkt { ++ struct hfi_session_hdr_pkt shdr; ++ u32 error_type; ++}; ++ ++struct hfi_msg_session_init_done_pkt { ++ struct hfi_msg_session_hdr_pkt shdr; ++ u32 num_properties; ++ u32 data[]; ++}; ++ + struct hfi_msg_sys_property_info_pkt { + struct hfi_pkt_hdr hdr; + u32 num_properties; +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c +index 78fefa4176f9..18ba5f67dd36 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c +@@ -13,13 +13,54 @@ iris_hfi_gen1_sys_event_notify(struct iris_core *core, void *packet) + struct hfi_msg_event_notify_pkt *pkt = packet; + + if (pkt->event_id == HFI_EVENT_SYS_ERROR) +- dev_err(core->dev, "sys error (type: %x, data1:%x, data2:%x)\n", +- pkt->event_id, pkt->event_data1, pkt->event_data2); ++ dev_err(core->dev, "sys error (type: %x, session id:%x, data1:%x, data2:%x)\n", ++ pkt->event_id, pkt->shdr.session_id, pkt->event_data1, ++ pkt->event_data2); + + core->state = IRIS_CORE_ERROR; + schedule_delayed_work(&core->sys_error_handler, msecs_to_jiffies(10)); + } + ++static void ++iris_hfi_gen1_event_session_error(struct iris_inst *inst, struct hfi_msg_event_notify_pkt *pkt) ++{ ++ switch (pkt->event_data1) { ++ /* non fatal session errors */ ++ case HFI_ERR_SESSION_INVALID_SCALE_FACTOR: ++ case HFI_ERR_SESSION_UNSUPPORT_BUFFERTYPE: ++ case HFI_ERR_SESSION_UNSUPPORTED_SETTING: ++ case HFI_ERR_SESSION_UPSCALE_NOT_SUPPORTED: ++ dev_dbg(inst->core->dev, "session error: event id:%x, session id:%x\n", ++ pkt->event_data1, pkt->shdr.session_id); ++ break; ++ /* fatal session errors */ ++ default: ++ /* ++ * firmware fills event_data2 as an additional information about the ++ * hfi command for which session error has ouccured. ++ */ ++ dev_err(inst->core->dev, ++ "session error for command: %x, event id:%x, session id:%x\n", ++ pkt->event_data2, pkt->event_data1, ++ pkt->shdr.session_id); ++ iris_vb2_queue_error(inst); ++ break; ++ } ++} ++ ++static void iris_hfi_gen1_session_event_notify(struct iris_inst *inst, void *packet) ++{ ++ struct hfi_msg_event_notify_pkt *pkt = packet; ++ ++ switch (pkt->event_id) { ++ case HFI_EVENT_SESSION_ERROR: ++ iris_hfi_gen1_event_session_error(inst, pkt); ++ break; ++ default: ++ break; ++ } ++} ++ + static void iris_hfi_gen1_sys_init_done(struct iris_core *core, void *packet) + { + struct hfi_msg_sys_init_done_pkt *pkt = packet; +@@ -99,6 +140,14 @@ static const struct iris_hfi_gen1_response_pkt_info pkt_infos[] = { + .pkt = HFI_MSG_SYS_PROPERTY_INFO, + .pkt_sz = sizeof(struct hfi_msg_sys_property_info_pkt), + }, ++ { ++ .pkt = HFI_MSG_SYS_SESSION_INIT, ++ .pkt_sz = sizeof(struct hfi_msg_session_init_done_pkt), ++ }, ++ { ++ .pkt = HFI_MSG_SYS_SESSION_END, ++ .pkt_sz = sizeof(struct hfi_msg_session_hdr_pkt), ++ }, + }; + + static void iris_hfi_gen1_handle_response(struct iris_core *core, void *response) +@@ -106,6 +155,8 @@ static void iris_hfi_gen1_handle_response(struct iris_core *core, void *response + struct hfi_pkt_hdr *hdr = (struct hfi_pkt_hdr *)response; + const struct iris_hfi_gen1_response_pkt_info *pkt_info; + struct device *dev = core->dev; ++ struct hfi_session_pkt *pkt; ++ struct iris_inst *inst; + bool found = false; + u32 i; + +@@ -132,9 +183,31 @@ static void iris_hfi_gen1_handle_response(struct iris_core *core, void *response + iris_hfi_gen1_sys_property_info(core, hdr); + break; + case HFI_MSG_EVENT_NOTIFY: +- iris_hfi_gen1_sys_event_notify(core, hdr); ++ pkt = (struct hfi_session_pkt *)hdr; ++ inst = iris_get_instance(core, pkt->shdr.session_id); ++ if (inst) { ++ mutex_lock(&inst->lock); ++ iris_hfi_gen1_session_event_notify(inst, hdr); ++ mutex_unlock(&inst->lock); ++ } else { ++ iris_hfi_gen1_sys_event_notify(core, hdr); ++ } ++ + break; + default: ++ pkt = (struct hfi_session_pkt *)hdr; ++ inst = iris_get_instance(core, pkt->shdr.session_id); ++ if (!inst) { ++ dev_warn(dev, "no valid instance(pkt session_id:%x, pkt:%x)\n", ++ pkt->shdr.session_id, ++ pkt_info ? pkt_info->pkt : 0); ++ return; ++ } ++ ++ mutex_lock(&inst->lock); ++ complete(&inst->completion); ++ mutex_unlock(&inst->lock); ++ + break; + } + } +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2.h +index c43b51774978..aaf6660bc1fe 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2.h +@@ -10,13 +10,18 @@ + + struct iris_core; + ++#define to_iris_inst_hfi_gen2(ptr) \ ++ container_of(ptr, struct iris_inst_hfi_gen2, inst) ++ + /** + * struct iris_inst_hfi_gen2 - holds per video instance parameters for hfi_gen2 + * + * @inst: pointer to iris_instance structure ++ * @packet: HFI packet + */ + struct iris_inst_hfi_gen2 { + struct iris_inst inst; ++ struct iris_hfi_header *packet; + }; + + void iris_hfi_gen2_command_ops_init(struct iris_core *core); +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +index f8cb1177ef54..a08e844bb4bb 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +@@ -85,11 +85,116 @@ static int iris_hfi_gen2_sys_pc_prep(struct iris_core *core) + return ret; + } + ++static int iris_hfi_gen2_session_set_codec(struct iris_inst *inst) ++{ ++ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); ++ u32 codec = HFI_CODEC_DECODE_AVC; ++ ++ iris_hfi_gen2_packet_session_property(inst, ++ HFI_PROP_CODEC, ++ HFI_HOST_FLAGS_NONE, ++ HFI_PORT_NONE, ++ HFI_PAYLOAD_U32_ENUM, ++ &codec, ++ sizeof(u32)); ++ ++ return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet, ++ inst_hfi_gen2->packet->size); ++} ++ ++static int iris_hfi_gen2_session_set_default_header(struct iris_inst *inst) ++{ ++ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); ++ u32 default_header = false; ++ ++ iris_hfi_gen2_packet_session_property(inst, ++ HFI_PROP_DEC_DEFAULT_HEADER, ++ HFI_HOST_FLAGS_NONE, ++ HFI_PORT_BITSTREAM, ++ HFI_PAYLOAD_U32, ++ &default_header, ++ sizeof(u32)); ++ ++ return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet, ++ inst_hfi_gen2->packet->size); ++} ++ ++static int iris_hfi_gen2_session_open(struct iris_inst *inst) ++{ ++ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); ++ int ret; ++ ++ inst_hfi_gen2->packet = kzalloc(4096, GFP_KERNEL); ++ if (!inst_hfi_gen2->packet) ++ return -ENOMEM; ++ ++ iris_hfi_gen2_packet_session_command(inst, ++ HFI_CMD_OPEN, ++ HFI_HOST_FLAGS_RESPONSE_REQUIRED | ++ HFI_HOST_FLAGS_INTR_REQUIRED, ++ HFI_PORT_NONE, ++ 0, ++ HFI_PAYLOAD_U32, ++ &inst->session_id, ++ sizeof(u32)); ++ ++ ret = iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet, ++ inst_hfi_gen2->packet->size); ++ if (ret) ++ goto fail_free_packet; ++ ++ ret = iris_hfi_gen2_session_set_codec(inst); ++ if (ret) ++ goto fail_free_packet; ++ ++ ret = iris_hfi_gen2_session_set_default_header(inst); ++ if (ret) ++ goto fail_free_packet; ++ ++ return 0; ++ ++fail_free_packet: ++ kfree(inst_hfi_gen2->packet); ++ inst_hfi_gen2->packet = NULL; ++ ++ return ret; ++} ++ ++static int iris_hfi_gen2_session_close(struct iris_inst *inst) ++{ ++ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); ++ int ret; ++ ++ if (!inst_hfi_gen2->packet) ++ return -EINVAL; ++ ++ iris_hfi_gen2_packet_session_command(inst, ++ HFI_CMD_CLOSE, ++ (HFI_HOST_FLAGS_RESPONSE_REQUIRED | ++ HFI_HOST_FLAGS_INTR_REQUIRED | ++ HFI_HOST_FLAGS_NON_DISCARDABLE), ++ HFI_PORT_NONE, ++ inst->session_id, ++ HFI_PAYLOAD_NONE, ++ NULL, ++ 0); ++ ++ ret = iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet, ++ inst_hfi_gen2->packet->size); ++ ++ kfree(inst_hfi_gen2->packet); ++ inst_hfi_gen2->packet = NULL; ++ ++ return ret; ++} ++ + static const struct iris_hfi_command_ops iris_hfi_gen2_command_ops = { + .sys_init = iris_hfi_gen2_sys_init, + .sys_image_version = iris_hfi_gen2_sys_image_version, + .sys_interframe_powercollapse = iris_hfi_gen2_sys_interframe_powercollapse, + .sys_pc_prep = iris_hfi_gen2_sys_pc_prep, ++ .session_open = iris_hfi_gen2_session_open, ++ .session_close = iris_hfi_gen2_session_close, + }; + + void iris_hfi_gen2_command_ops_init(struct iris_core *core) +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +index e6a19ffc12fb..ccf5fd0902d7 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +@@ -13,6 +13,8 @@ + #define HFI_CMD_BEGIN 0x01000000 + #define HFI_CMD_INIT 0x01000001 + #define HFI_CMD_POWER_COLLAPSE 0x01000002 ++#define HFI_CMD_OPEN 0x01000003 ++#define HFI_CMD_CLOSE 0x01000004 + #define HFI_CMD_END 0x01FFFFFF + + #define HFI_PROP_BEGIN 0x03000000 +@@ -25,12 +27,45 @@ + #define HFI_PROP_UBWC_BANK_SWZL_LEVEL2 0x03000007 + #define HFI_PROP_UBWC_BANK_SWZL_LEVEL3 0x03000008 + #define HFI_PROP_UBWC_BANK_SPREADING 0x03000009 ++#define HFI_PROP_CODEC 0x03000100 ++#define HFI_PROP_DEC_DEFAULT_HEADER 0x03000168 + #define HFI_PROP_END 0x03FFFFFF + ++#define HFI_SESSION_ERROR_BEGIN 0x04000000 ++#define HFI_ERROR_UNKNOWN_SESSION 0x04000001 ++#define HFI_ERROR_MAX_SESSIONS 0x04000002 ++#define HFI_ERROR_FATAL 0x04000003 ++#define HFI_ERROR_INVALID_STATE 0x04000004 ++#define HFI_ERROR_INSUFFICIENT_RESOURCES 0x04000005 ++#define HFI_ERROR_BUFFER_NOT_SET 0x04000006 ++#define HFI_ERROR_STREAM_UNSUPPORTED 0x04000008 ++#define HFI_SESSION_ERROR_END 0x04FFFFFF ++ + #define HFI_SYSTEM_ERROR_BEGIN 0x05000000 + #define HFI_SYS_ERROR_WD_TIMEOUT 0x05000001 + #define HFI_SYSTEM_ERROR_END 0x05FFFFFF + ++enum hfi_codec_type { ++ HFI_CODEC_DECODE_AVC = 1, ++ HFI_CODEC_ENCODE_AVC = 2, ++}; ++ ++enum hfi_buffer_type { ++ HFI_BUFFER_BITSTREAM = 0x00000001, ++ HFI_BUFFER_RAW = 0x00000002, ++ HFI_BUFFER_METADATA = 0x00000003, ++ HFI_BUFFER_SUBCACHE = 0x00000004, ++ HFI_BUFFER_PARTIAL_DATA = 0x00000005, ++ HFI_BUFFER_DPB = 0x00000006, ++ HFI_BUFFER_BIN = 0x00000007, ++ HFI_BUFFER_LINE = 0x00000008, ++ HFI_BUFFER_ARP = 0x00000009, ++ HFI_BUFFER_COMV = 0x0000000A, ++ HFI_BUFFER_NON_COMV = 0x0000000B, ++ HFI_BUFFER_PERSIST = 0x0000000C, ++ HFI_BUFFER_VPSS = 0x0000000D, ++}; ++ + enum hfi_packet_firmware_flags { + HFI_FW_FLAGS_SUCCESS = 0x00000001, + HFI_FW_FLAGS_INFORMATION = 0x00000002, +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c +index 510d44408b41..739b2ce5bfae 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c +@@ -143,6 +143,45 @@ void iris_hfi_gen2_packet_image_version(struct iris_core *core, struct iris_hfi_ + NULL, 0); + } + ++void iris_hfi_gen2_packet_session_command(struct iris_inst *inst, u32 pkt_type, ++ u32 flags, u32 port, u32 session_id, ++ u32 payload_type, void *payload, ++ u32 payload_size) ++{ ++ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); ++ struct iris_core *core = inst->core; ++ ++ iris_hfi_gen2_create_header(inst_hfi_gen2->packet, session_id, core->header_id++); ++ ++ iris_hfi_gen2_create_packet(inst_hfi_gen2->packet, ++ pkt_type, ++ flags, ++ payload_type, ++ port, ++ core->packet_id++, ++ payload, ++ payload_size); ++} ++ ++void iris_hfi_gen2_packet_session_property(struct iris_inst *inst, ++ u32 pkt_type, u32 flags, u32 port, ++ u32 payload_type, void *payload, u32 payload_size) ++{ ++ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); ++ struct iris_core *core = inst->core; ++ ++ iris_hfi_gen2_create_header(inst_hfi_gen2->packet, inst->session_id, core->header_id++); ++ ++ iris_hfi_gen2_create_packet(inst_hfi_gen2->packet, ++ pkt_type, ++ flags, ++ payload_type, ++ port, ++ core->packet_id++, ++ payload, ++ payload_size); ++} ++ + void iris_hfi_gen2_packet_sys_interframe_powercollapse(struct iris_core *core, + struct iris_hfi_header *hdr) + { +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h +index 3b771b7516de..4a9b88185b0d 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h +@@ -63,6 +63,13 @@ struct iris_hfi_packet { + + void iris_hfi_gen2_packet_sys_init(struct iris_core *core, struct iris_hfi_header *hdr); + void iris_hfi_gen2_packet_image_version(struct iris_core *core, struct iris_hfi_header *hdr); ++void iris_hfi_gen2_packet_session_command(struct iris_inst *inst, u32 pkt_type, ++ u32 flags, u32 port, u32 session_id, ++ u32 payload_type, void *payload, ++ u32 payload_size); ++void iris_hfi_gen2_packet_session_property(struct iris_inst *inst, ++ u32 pkt_type, u32 flags, u32 port, ++ u32 payload_type, void *payload, u32 payload_size); + void iris_hfi_gen2_packet_sys_interframe_powercollapse(struct iris_core *core, + struct iris_hfi_header *hdr); + void iris_hfi_gen2_packet_sys_pc_prep(struct iris_core *core, struct iris_hfi_header *hdr); +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c +index 007e4a7b6782..e1c43daea6c7 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c +@@ -14,6 +14,17 @@ struct iris_hfi_gen2_core_hfi_range { + int (*handle)(struct iris_core *core, struct iris_hfi_packet *pkt); + }; + ++struct iris_hfi_gen2_inst_hfi_range { ++ u32 begin; ++ u32 end; ++ int (*handle)(struct iris_inst *inst, struct iris_hfi_packet *pkt); ++}; ++ ++struct iris_hfi_gen2_packet_handle { ++ enum hfi_buffer_type type; ++ int (*handle)(struct iris_inst *inst, struct iris_hfi_packet *pkt); ++}; ++ + static int iris_hfi_gen2_validate_packet(u8 *response_pkt, u8 *core_resp_pkt) + { + u8 *response_limit = core_resp_pkt + IFACEQ_CORE_PKT_SIZE; +@@ -55,6 +66,45 @@ static int iris_hfi_gen2_validate_hdr_packet(struct iris_core *core, struct iris + return 0; + } + ++static int iris_hfi_gen2_handle_session_error(struct iris_inst *inst, ++ struct iris_hfi_packet *pkt) ++{ ++ struct iris_core *core = inst->core; ++ char *error; ++ ++ switch (pkt->type) { ++ case HFI_ERROR_MAX_SESSIONS: ++ error = "exceeded max sessions"; ++ break; ++ case HFI_ERROR_UNKNOWN_SESSION: ++ error = "unknown session id"; ++ break; ++ case HFI_ERROR_INVALID_STATE: ++ error = "invalid operation for current state"; ++ break; ++ case HFI_ERROR_INSUFFICIENT_RESOURCES: ++ error = "insufficient resources"; ++ break; ++ case HFI_ERROR_BUFFER_NOT_SET: ++ error = "internal buffers not set"; ++ break; ++ case HFI_ERROR_FATAL: ++ error = "fatal error"; ++ break; ++ case HFI_ERROR_STREAM_UNSUPPORTED: ++ error = "unsupported stream"; ++ break; ++ default: ++ error = "unknown"; ++ break; ++ } ++ ++ dev_err(core->dev, "session error received %#x: %s\n", pkt->type, error); ++ iris_vb2_queue_error(inst); ++ ++ return 0; ++} ++ + static int iris_hfi_gen2_handle_system_error(struct iris_core *core, + struct iris_hfi_packet *pkt) + { +@@ -79,6 +129,22 @@ static int iris_hfi_gen2_handle_system_init(struct iris_core *core, + return 0; + } + ++static int iris_hfi_gen2_handle_session_command(struct iris_inst *inst, ++ struct iris_hfi_packet *pkt) ++{ ++ int ret = 0; ++ ++ switch (pkt->type) { ++ case HFI_CMD_CLOSE: ++ complete(&inst->completion); ++ break; ++ default: ++ break; ++ } ++ ++ return ret; ++} ++ + static int iris_hfi_gen2_handle_image_version_property(struct iris_core *core, + struct iris_hfi_packet *pkt) + { +@@ -152,6 +218,46 @@ static int iris_hfi_gen2_handle_system_response(struct iris_core *core, + return 0; + } + ++static int iris_hfi_gen2_handle_session_response(struct iris_core *core, ++ struct iris_hfi_header *hdr) ++{ ++ struct iris_hfi_packet *packet; ++ struct iris_inst *inst; ++ int ret = 0; ++ u32 i, j; ++ u8 *pkt; ++ static const struct iris_hfi_gen2_inst_hfi_range range[] = { ++ {HFI_SESSION_ERROR_BEGIN, HFI_SESSION_ERROR_END, ++ iris_hfi_gen2_handle_session_error}, ++ {HFI_CMD_BEGIN, HFI_CMD_END, ++ iris_hfi_gen2_handle_session_command }, ++ }; ++ ++ inst = iris_get_instance(core, hdr->session_id); ++ if (!inst) ++ return -EINVAL; ++ ++ mutex_lock(&inst->lock); ++ ++ pkt = (u8 *)((u8 *)hdr + sizeof(*hdr)); ++ for (i = 0; i < ARRAY_SIZE(range); i++) { ++ pkt = (u8 *)((u8 *)hdr + sizeof(*hdr)); ++ for (j = 0; j < hdr->num_packets; j++) { ++ packet = (struct iris_hfi_packet *)pkt; ++ if (packet->flags & HFI_FW_FLAGS_SESSION_ERROR) ++ iris_hfi_gen2_handle_session_error(inst, packet); ++ ++ if (packet->type > range[i].begin && packet->type < range[i].end) ++ ret = range[i].handle(inst, packet); ++ pkt += packet->size; ++ } ++ } ++ ++ mutex_unlock(&inst->lock); ++ ++ return ret; ++} ++ + static int iris_hfi_gen2_handle_response(struct iris_core *core, void *response) + { + struct iris_hfi_header *hdr = (struct iris_hfi_header *)response; +@@ -161,7 +267,10 @@ static int iris_hfi_gen2_handle_response(struct iris_core *core, void *response) + if (ret) + return iris_hfi_gen2_handle_system_error(core, NULL); + +- return iris_hfi_gen2_handle_system_response(core, hdr); ++ if (!hdr->session_id) ++ return iris_hfi_gen2_handle_system_response(core, hdr); ++ else ++ return iris_hfi_gen2_handle_session_response(core, hdr); + } + + static void iris_hfi_gen2_flush_debug_queue(struct iris_core *core, u8 *packet) +diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/drivers/media/platform/qcom/iris/iris_instance.h +index 527a270f12d4..b9c7dcfb20f7 100644 +--- a/drivers/media/platform/qcom/iris/iris_instance.h ++++ b/drivers/media/platform/qcom/iris/iris_instance.h +@@ -6,24 +6,46 @@ + #ifndef __IRIS_INSTANCE_H__ + #define __IRIS_INSTANCE_H__ + ++#include ++ ++#include "iris_buffer.h" + #include "iris_core.h" ++#include "iris_utils.h" + + /** + * struct iris_inst - holds per video instance parameters + * ++ * @list: used for attach an instance to the core + * @core: pointer to core structure ++ * @session_id: id of current video session + * @ctx_q_lock: lock to serialize queues related ioctls + * @lock: lock to seralise forward and reverse threads + * @fh: reference of v4l2 file handler ++ * @fmt_src: structure of v4l2_format for source ++ * @fmt_dst: structure of v4l2_format for destination ++ * @crop: structure of crop info ++ * @completion: structure of signal completions ++ * @buffers: array of different iris buffers ++ * @fw_min_count: minimnum count of buffers needed by fw ++ * @once_per_session_set: boolean to set once per session property + * @m2m_dev: a reference to m2m device structure + * @m2m_ctx: a reference to m2m context structure + */ + + struct iris_inst { ++ struct list_head list; + struct iris_core *core; ++ u32 session_id; + struct mutex ctx_q_lock;/* lock to serialize queues related ioctls */ + struct mutex lock; /* lock to serialize forward and reverse threads */ + struct v4l2_fh fh; ++ struct v4l2_format *fmt_src; ++ struct v4l2_format *fmt_dst; ++ struct iris_hfi_rect_desc crop; ++ struct completion completion; ++ struct iris_buffers buffers[BUF_TYPE_MAX]; ++ u32 fw_min_count; ++ bool once_per_session_set; + struct v4l2_m2m_dev *m2m_dev; + struct v4l2_m2m_ctx *m2m_ctx; + }; +diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h +index 69c0a8b3d12d..d508477b066e 100644 +--- a/drivers/media/platform/qcom/iris/iris_platform_common.h ++++ b/drivers/media/platform/qcom/iris/iris_platform_common.h +@@ -42,6 +42,9 @@ struct ubwc_config_data { + u32 bank_spreading; + }; + ++struct platform_inst_caps { ++ u32 max_mbpf; ++}; + struct iris_core_power { + u64 clk_freq; + u64 icc_bw; +@@ -71,11 +74,13 @@ struct iris_platform_data { + u64 dma_mask; + const char *fwname; + u32 pas_id; ++ struct platform_inst_caps *inst_caps; + struct tz_cp_config *tz_cp_config_data; + u32 core_arch; + u32 hw_response_timeout; + struct ubwc_config_data *ubwc_config; + u32 num_vpp_pipe; ++ u32 max_session_count; + }; + + #endif +diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +index ed99cdb13d06..e4232c755074 100644 +--- a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c ++++ b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +@@ -10,6 +10,10 @@ + + #define VIDEO_ARCH_LX 1 + ++static struct platform_inst_caps platform_inst_cap_sm8550 = { ++ .max_mbpf = (8192 * 4352) / 256, ++}; ++ + static void iris_set_sm8550_preset_registers(struct iris_core *core) + { + writel(0x0, core->reg_base + 0xB0088); +@@ -69,9 +73,11 @@ struct iris_platform_data sm8550_data = { + .dma_mask = 0xe0000000 - 1, + .fwname = "qcom/vpu/vpu30_p4.mbn", + .pas_id = IRIS_PAS_ID, ++ .inst_caps = &platform_inst_cap_sm8550, + .tz_cp_config_data = &tz_cp_config_sm8550, + .core_arch = VIDEO_ARCH_LX, + .hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE, + .ubwc_config = &ubwc_config_sm8550, + .num_vpp_pipe = 4, ++ .max_session_count = 16, + }; +diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c +index e8ef258b4f2e..a9162be5f9f6 100644 +--- a/drivers/media/platform/qcom/iris/iris_probe.c ++++ b/drivers/media/platform/qcom/iris/iris_probe.c +@@ -142,6 +142,7 @@ static int iris_register_video_device(struct iris_core *core) + strscpy(vdev->name, "qcom-iris-decoder", sizeof(vdev->name)); + vdev->release = video_device_release; + vdev->fops = core->iris_v4l2_file_ops; ++ vdev->ioctl_ops = core->iris_v4l2_ioctl_ops; + vdev->vfl_dir = VFL_DIR_M2M; + vdev->v4l2_dev = &core->v4l2_dev; + vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; +@@ -207,6 +208,7 @@ static int iris_probe(struct platform_device *pdev) + if (!core->response_packet) + return -ENOMEM; + ++ INIT_LIST_HEAD(&core->instances); + INIT_DELAYED_WORK(&core->sys_error_handler, iris_sys_error_handler); + + core->reg_base = devm_platform_ioremap_resource(pdev, 0); +diff --git a/drivers/media/platform/qcom/iris/iris_utils.c b/drivers/media/platform/qcom/iris/iris_utils.c +new file mode 100644 +index 000000000000..d5c8e052922c +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_utils.c +@@ -0,0 +1,52 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include ++ ++#include "iris_instance.h" ++#include "iris_utils.h" ++ ++int iris_get_mbpf(struct iris_inst *inst) ++{ ++ struct v4l2_format *inp_f = inst->fmt_src; ++ u32 height = max(inp_f->fmt.pix_mp.height, inst->crop.height); ++ u32 width = max(inp_f->fmt.pix_mp.width, inst->crop.width); ++ ++ return NUM_MBS_PER_FRAME(height, width); ++} ++ ++int iris_wait_for_session_response(struct iris_inst *inst) ++{ ++ struct iris_core *core = inst->core; ++ u32 hw_response_timeout_val; ++ int ret; ++ ++ hw_response_timeout_val = core->iris_platform_data->hw_response_timeout; ++ ++ mutex_unlock(&inst->lock); ++ ret = wait_for_completion_timeout(&inst->completion, ++ msecs_to_jiffies(hw_response_timeout_val)); ++ mutex_lock(&inst->lock); ++ if (!ret) ++ return -ETIMEDOUT; ++ ++ return 0; ++} ++ ++struct iris_inst *iris_get_instance(struct iris_core *core, u32 session_id) ++{ ++ struct iris_inst *inst; ++ ++ mutex_lock(&core->lock); ++ list_for_each_entry(inst, &core->instances, list) { ++ if (inst->session_id == session_id) { ++ mutex_unlock(&core->lock); ++ return inst; ++ } ++ } ++ ++ mutex_unlock(&core->lock); ++ return NULL; ++} +diff --git a/drivers/media/platform/qcom/iris/iris_utils.h b/drivers/media/platform/qcom/iris/iris_utils.h +new file mode 100644 +index 000000000000..26649b66d978 +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_utils.h +@@ -0,0 +1,34 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef __IRIS_UTILS_H__ ++#define __IRIS_UTILS_H__ ++ ++struct iris_core; ++#include "iris_buffer.h" ++ ++struct iris_hfi_rect_desc { ++ u32 left; ++ u32 top; ++ u32 width; ++ u32 height; ++}; ++ ++#define NUM_MBS_PER_FRAME(height, width) \ ++ (DIV_ROUND_UP(height, 16) * DIV_ROUND_UP(width, 16)) ++ ++static inline enum iris_buffer_type iris_v4l2_type_to_driver(u32 type) ++{ ++ if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ++ return BUF_INPUT; ++ else ++ return BUF_OUTPUT; ++} ++ ++int iris_get_mbpf(struct iris_inst *inst); ++struct iris_inst *iris_get_instance(struct iris_core *core, u32 session_id); ++int iris_wait_for_session_response(struct iris_inst *inst); ++ ++#endif +diff --git a/drivers/media/platform/qcom/iris/iris_vb2.c b/drivers/media/platform/qcom/iris/iris_vb2.c +new file mode 100644 +index 000000000000..e9db44515d91 +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_vb2.c +@@ -0,0 +1,50 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include "iris_instance.h" ++#include "iris_vb2.h" ++ ++int iris_vb2_queue_setup(struct vb2_queue *q, ++ unsigned int *num_buffers, unsigned int *num_planes, ++ unsigned int sizes[], struct device *alloc_devs[]) ++{ ++ struct iris_inst *inst; ++ struct iris_core *core; ++ struct v4l2_format *f; ++ int ret = 0; ++ ++ inst = vb2_get_drv_priv(q); ++ ++ mutex_lock(&inst->lock); ++ ++ core = inst->core; ++ f = V4L2_TYPE_IS_OUTPUT(q->type) ? inst->fmt_src : inst->fmt_dst; ++ ++ if (*num_planes) { ++ if (*num_planes != f->fmt.pix_mp.num_planes || ++ sizes[0] < f->fmt.pix_mp.plane_fmt[0].sizeimage) ++ ret = -EINVAL; ++ goto unlock; ++ } ++ ++ if (!inst->once_per_session_set) { ++ inst->once_per_session_set = true; ++ ++ ret = core->hfi_ops->session_open(inst); ++ if (ret) { ++ ret = -EINVAL; ++ dev_err(core->dev, "session open failed\n"); ++ goto unlock; ++ } ++ } ++ ++ *num_planes = 1; ++ sizes[0] = f->fmt.pix_mp.plane_fmt[0].sizeimage; ++ ++unlock: ++ mutex_unlock(&inst->lock); ++ ++ return ret; ++} +diff --git a/drivers/media/platform/qcom/iris/iris_vb2.h b/drivers/media/platform/qcom/iris/iris_vb2.h +new file mode 100644 +index 000000000000..d2e71d0596cc +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_vb2.h +@@ -0,0 +1,12 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef __IRIS_VB2_H__ ++#define __IRIS_VB2_H__ ++ ++int iris_vb2_queue_setup(struct vb2_queue *q, ++ unsigned int *num_buffers, unsigned int *num_planes, ++ unsigned int sizes[], struct device *alloc_devs[]); ++#endif +diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c +new file mode 100644 +index 000000000000..2ed50ad5d58b +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_vdec.c +@@ -0,0 +1,56 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include "iris_buffer.h" ++#include "iris_instance.h" ++#include "iris_vdec.h" ++#include "iris_vpu_buffer.h" ++ ++#define DEFAULT_WIDTH 320 ++#define DEFAULT_HEIGHT 240 ++ ++void iris_vdec_inst_init(struct iris_inst *inst) ++{ ++ struct v4l2_format *f; ++ ++ inst->fmt_src = kzalloc(sizeof(*inst->fmt_src), GFP_KERNEL); ++ inst->fmt_dst = kzalloc(sizeof(*inst->fmt_dst), GFP_KERNEL); ++ ++ inst->fw_min_count = MIN_BUFFERS; ++ ++ f = inst->fmt_src; ++ f->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; ++ f->fmt.pix_mp.width = DEFAULT_WIDTH; ++ f->fmt.pix_mp.height = DEFAULT_HEIGHT; ++ f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264; ++ f->fmt.pix_mp.num_planes = 1; ++ f->fmt.pix_mp.plane_fmt[0].bytesperline = 0; ++ f->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_INPUT); ++ f->fmt.pix_mp.field = V4L2_FIELD_NONE; ++ inst->buffers[BUF_INPUT].min_count = iris_vpu_buf_count(inst, BUF_INPUT); ++ inst->buffers[BUF_INPUT].size = f->fmt.pix_mp.plane_fmt[0].sizeimage; ++ ++ f = inst->fmt_dst; ++ f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; ++ f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12; ++ f->fmt.pix_mp.width = ALIGN(DEFAULT_WIDTH, 128); ++ f->fmt.pix_mp.height = ALIGN(DEFAULT_HEIGHT, 32); ++ f->fmt.pix_mp.num_planes = 1; ++ f->fmt.pix_mp.plane_fmt[0].bytesperline = ALIGN(DEFAULT_WIDTH, 128); ++ f->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_OUTPUT); ++ f->fmt.pix_mp.field = V4L2_FIELD_NONE; ++ f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT; ++ f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT; ++ f->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; ++ f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT; ++ inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT); ++ inst->buffers[BUF_OUTPUT].size = f->fmt.pix_mp.plane_fmt[0].sizeimage; ++} ++ ++void iris_vdec_inst_deinit(struct iris_inst *inst) ++{ ++ kfree(inst->fmt_dst); ++ kfree(inst->fmt_src); ++} +diff --git a/drivers/media/platform/qcom/iris/iris_vdec.h b/drivers/media/platform/qcom/iris/iris_vdec.h +new file mode 100644 +index 000000000000..353b73b76230 +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_vdec.h +@@ -0,0 +1,14 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef __IRIS_VDEC_H__ ++#define __IRIS_VDEC_H__ ++ ++struct iris_inst; ++ ++void iris_vdec_inst_init(struct iris_inst *inst); ++void iris_vdec_inst_deinit(struct iris_inst *inst); ++ ++#endif +diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c +index b8654e73f516..ab3b63171c1d 100644 +--- a/drivers/media/platform/qcom/iris/iris_vidc.c ++++ b/drivers/media/platform/qcom/iris/iris_vidc.c +@@ -9,6 +9,9 @@ + + #include "iris_vidc.h" + #include "iris_instance.h" ++#include "iris_vdec.h" ++#include "iris_vb2.h" ++#include "iris_vpu_buffer.h" + #include "iris_platform_common.h" + + #define IRIS_DRV_NAME "iris_driver" +@@ -28,6 +31,38 @@ static void iris_v4l2_fh_deinit(struct iris_inst *inst) + v4l2_fh_exit(&inst->fh); + } + ++static void iris_add_session(struct iris_inst *inst) ++{ ++ struct iris_core *core = inst->core; ++ struct iris_inst *iter; ++ u32 count = 0; ++ ++ mutex_lock(&core->lock); ++ ++ list_for_each_entry(iter, &core->instances, list) ++ count++; ++ ++ if (count < core->iris_platform_data->max_session_count) ++ list_add_tail(&inst->list, &core->instances); ++ ++ mutex_unlock(&core->lock); ++} ++ ++static void iris_remove_session(struct iris_inst *inst) ++{ ++ struct iris_core *core = inst->core; ++ struct iris_inst *iter, *temp; ++ ++ mutex_lock(&core->lock); ++ list_for_each_entry_safe(iter, temp, &core->instances, list) { ++ if (iter->session_id == inst->session_id) { ++ list_del_init(&iter->list); ++ break; ++ } ++ } ++ mutex_unlock(&core->lock); ++} ++ + static inline struct iris_inst *iris_get_inst(struct file *filp, void *fh) + { + return container_of(filp->private_data, struct iris_inst, fh); +@@ -59,7 +94,10 @@ iris_m2m_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_ + src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + src_vq->io_modes = VB2_MMAP | VB2_DMABUF; + src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; ++ src_vq->ops = inst->core->iris_vb2_ops; + src_vq->drv_priv = inst; ++ src_vq->buf_struct_size = sizeof(struct iris_buffer); ++ src_vq->min_reqbufs_allocation = MIN_BUFFERS; + src_vq->dev = inst->core->dev; + src_vq->lock = &inst->ctx_q_lock; + ret = vb2_queue_init(src_vq); +@@ -69,7 +107,10 @@ iris_m2m_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_ + dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; + dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; ++ dst_vq->ops = inst->core->iris_vb2_ops; + dst_vq->drv_priv = inst; ++ dst_vq->buf_struct_size = sizeof(struct iris_buffer); ++ dst_vq->min_reqbufs_allocation = MIN_BUFFERS; + dst_vq->dev = inst->core->dev; + dst_vq->lock = &inst->ctx_q_lock; + +@@ -100,8 +141,11 @@ int iris_open(struct file *filp) + return -ENOMEM; + + inst->core = core; ++ inst->session_id = hash32_ptr(inst); + ++ mutex_init(&inst->lock); + mutex_init(&inst->ctx_q_lock); ++ init_completion(&inst->completion); + + iris_v4l2_fh_init(inst); + +@@ -117,6 +161,10 @@ int iris_open(struct file *filp) + goto fail_m2m_release; + } + ++ iris_vdec_inst_init(inst); ++ ++ iris_add_session(inst); ++ + inst->fh.m2m_ctx = inst->m2m_ctx; + filp->private_data = &inst->fh; + +@@ -127,19 +175,42 @@ int iris_open(struct file *filp) + fail_v4l2_fh_deinit: + iris_v4l2_fh_deinit(inst); + mutex_destroy(&inst->ctx_q_lock); ++ mutex_destroy(&inst->lock); + kfree(inst); + + return ret; + } + ++static void iris_session_close(struct iris_inst *inst) ++{ ++ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; ++ bool wait_for_response = true; ++ int ret; ++ ++ reinit_completion(&inst->completion); ++ ++ ret = hfi_ops->session_close(inst); ++ if (ret) ++ wait_for_response = false; ++ ++ if (wait_for_response) ++ iris_wait_for_session_response(inst); ++} ++ + int iris_close(struct file *filp) + { + struct iris_inst *inst = iris_get_inst(filp, NULL); + + v4l2_m2m_ctx_release(inst->m2m_ctx); + v4l2_m2m_release(inst->m2m_dev); ++ mutex_lock(&inst->lock); ++ iris_vdec_inst_deinit(inst); ++ iris_session_close(inst); + iris_v4l2_fh_deinit(inst); ++ iris_remove_session(inst); ++ mutex_unlock(&inst->lock); + mutex_destroy(&inst->ctx_q_lock); ++ mutex_destroy(&inst->lock); + kfree(inst); + filp->private_data = NULL; + +@@ -155,7 +226,17 @@ static struct v4l2_file_operations iris_v4l2_file_ops = { + .mmap = v4l2_m2m_fop_mmap, + }; + ++static const struct vb2_ops iris_vb2_ops = { ++ .queue_setup = iris_vb2_queue_setup, ++}; ++ ++static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops = { ++ .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, ++}; ++ + void iris_init_ops(struct iris_core *core) + { + core->iris_v4l2_file_ops = &iris_v4l2_file_ops; ++ core->iris_vb2_ops = &iris_vb2_ops; ++ core->iris_v4l2_ioctl_ops = &iris_v4l2_ioctl_ops; + } +diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c +new file mode 100644 +index 000000000000..2402a33723ab +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c +@@ -0,0 +1,19 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include "iris_instance.h" ++#include "iris_vpu_buffer.h" ++ ++int iris_vpu_buf_count(struct iris_inst *inst, enum iris_buffer_type buffer_type) ++{ ++ switch (buffer_type) { ++ case BUF_INPUT: ++ return MIN_BUFFERS; ++ case BUF_OUTPUT: ++ return inst->fw_min_count; ++ default: ++ return 0; ++ } ++} +diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h +new file mode 100644 +index 000000000000..06e6e958dcac +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h +@@ -0,0 +1,15 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef __IRIS_VPU_BUFFER_H__ ++#define __IRIS_VPU_BUFFER_H__ ++ ++struct iris_inst; ++ ++#define MIN_BUFFERS 4 ++ ++int iris_vpu_buf_count(struct iris_inst *inst, enum iris_buffer_type buffer_type); ++ ++#endif +-- +2.34.1 + diff --git a/patch/kernel/archive/sm8550-6.12/0010_media--iris--implement-s_fmt,-g_fmt-and-try_fmt-io.patch b/patch/kernel/archive/sm8550-6.12/0010_media--iris--implement-s_fmt,-g_fmt-and-try_fmt-io.patch new file mode 100644 index 000000000..31a3f4e78 --- /dev/null +++ b/patch/kernel/archive/sm8550-6.12/0010_media--iris--implement-s_fmt,-g_fmt-and-try_fmt-io.patch @@ -0,0 +1,248 @@ +From 8f9fd0b682dbead270bc0cb83e0511af1f5f4e6d Mon Sep 17 00:00:00 2001 +From: Vedang Nagar +Date: Fri, 7 Feb 2025 13:24:50 +0530 +Subject: [PATCH] media: iris: implement s_fmt, g_fmt and try_fmt ioctls + +Implement the s_fmt, g_fmt and try_fmt ioctl ops with the necessary +hooks. + +Signed-off-by: Vedang Nagar +Reviewed-by: Hans Verkuil +Tested-by: Stefan Schmidt # x1e80100 (Dell XPS 13 9345) +Reviewed-by: Stefan Schmidt +Tested-by: Neil Armstrong # on SM8550-QRD +Tested-by: Neil Armstrong # on SM8550-HDK +Signed-off-by: Dikshita Agarwal +Link: https://lore.kernel.org/r/20250207-qcom-video-iris-v10-10-ab66eeffbd20@quicinc.com +Signed-off-by: Neil Armstrong +--- + drivers/media/platform/qcom/iris/iris_vdec.c | 122 +++++++++++++++++++ + drivers/media/platform/qcom/iris/iris_vdec.h | 2 + + drivers/media/platform/qcom/iris/iris_vidc.c | 48 ++++++++ + 3 files changed, 172 insertions(+) + +diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c +index 2ed50ad5d58b..38a5df8191cc 100644 +--- a/drivers/media/platform/qcom/iris/iris_vdec.c ++++ b/drivers/media/platform/qcom/iris/iris_vdec.c +@@ -3,6 +3,8 @@ + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + ++#include ++ + #include "iris_buffer.h" + #include "iris_instance.h" + #include "iris_vdec.h" +@@ -10,6 +12,7 @@ + + #define DEFAULT_WIDTH 320 + #define DEFAULT_HEIGHT 240 ++#define DEFAULT_CODEC_ALIGNMENT 16 + + void iris_vdec_inst_init(struct iris_inst *inst) + { +@@ -54,3 +57,122 @@ void iris_vdec_inst_deinit(struct iris_inst *inst) + kfree(inst->fmt_dst); + kfree(inst->fmt_src); + } ++ ++int iris_vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f) ++{ ++ struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; ++ struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; ++ struct v4l2_format *f_inst; ++ struct vb2_queue *src_q; ++ ++ memset(pixmp->reserved, 0, sizeof(pixmp->reserved)); ++ switch (f->type) { ++ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: ++ if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_H264) { ++ f_inst = inst->fmt_src; ++ f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width; ++ f->fmt.pix_mp.height = f_inst->fmt.pix_mp.height; ++ f->fmt.pix_mp.pixelformat = f_inst->fmt.pix_mp.pixelformat; ++ } ++ break; ++ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: ++ if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_NV12) { ++ f_inst = inst->fmt_dst; ++ f->fmt.pix_mp.pixelformat = f_inst->fmt.pix_mp.pixelformat; ++ f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width; ++ f->fmt.pix_mp.height = f_inst->fmt.pix_mp.height; ++ } ++ ++ src_q = v4l2_m2m_get_src_vq(m2m_ctx); ++ if (vb2_is_streaming(src_q)) { ++ f_inst = inst->fmt_src; ++ f->fmt.pix_mp.height = f_inst->fmt.pix_mp.height; ++ f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width; ++ } ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ if (pixmp->field == V4L2_FIELD_ANY) ++ pixmp->field = V4L2_FIELD_NONE; ++ ++ pixmp->num_planes = 1; ++ ++ return 0; ++} ++ ++int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f) ++{ ++ struct v4l2_format *fmt, *output_fmt; ++ struct vb2_queue *q; ++ u32 codec_align; ++ ++ q = v4l2_m2m_get_vq(inst->m2m_ctx, f->type); ++ if (!q) ++ return -EINVAL; ++ ++ if (vb2_is_busy(q)) ++ return -EBUSY; ++ ++ iris_vdec_try_fmt(inst, f); ++ ++ switch (f->type) { ++ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: ++ if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_H264) ++ return -EINVAL; ++ ++ fmt = inst->fmt_src; ++ fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; ++ ++ codec_align = DEFAULT_CODEC_ALIGNMENT; ++ fmt->fmt.pix_mp.width = ALIGN(f->fmt.pix_mp.width, codec_align); ++ fmt->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, codec_align); ++ fmt->fmt.pix_mp.num_planes = 1; ++ fmt->fmt.pix_mp.plane_fmt[0].bytesperline = 0; ++ fmt->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_INPUT); ++ inst->buffers[BUF_INPUT].min_count = iris_vpu_buf_count(inst, BUF_INPUT); ++ inst->buffers[BUF_INPUT].size = fmt->fmt.pix_mp.plane_fmt[0].sizeimage; ++ ++ fmt->fmt.pix_mp.colorspace = f->fmt.pix_mp.colorspace; ++ fmt->fmt.pix_mp.xfer_func = f->fmt.pix_mp.xfer_func; ++ fmt->fmt.pix_mp.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc; ++ fmt->fmt.pix_mp.quantization = f->fmt.pix_mp.quantization; ++ ++ output_fmt = inst->fmt_dst; ++ output_fmt->fmt.pix_mp.colorspace = f->fmt.pix_mp.colorspace; ++ output_fmt->fmt.pix_mp.xfer_func = f->fmt.pix_mp.xfer_func; ++ output_fmt->fmt.pix_mp.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc; ++ output_fmt->fmt.pix_mp.quantization = f->fmt.pix_mp.quantization; ++ ++ inst->crop.left = 0; ++ inst->crop.top = 0; ++ inst->crop.width = f->fmt.pix_mp.width; ++ inst->crop.height = f->fmt.pix_mp.height; ++ break; ++ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: ++ fmt = inst->fmt_dst; ++ fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; ++ if (fmt->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_NV12) ++ return -EINVAL; ++ fmt->fmt.pix_mp.pixelformat = f->fmt.pix_mp.pixelformat; ++ fmt->fmt.pix_mp.width = ALIGN(f->fmt.pix_mp.width, 128); ++ fmt->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, 32); ++ fmt->fmt.pix_mp.num_planes = 1; ++ fmt->fmt.pix_mp.plane_fmt[0].bytesperline = ALIGN(f->fmt.pix_mp.width, 128); ++ fmt->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_OUTPUT); ++ inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT); ++ inst->buffers[BUF_OUTPUT].size = fmt->fmt.pix_mp.plane_fmt[0].sizeimage; ++ ++ inst->crop.top = 0; ++ inst->crop.left = 0; ++ inst->crop.width = f->fmt.pix_mp.width; ++ inst->crop.height = f->fmt.pix_mp.height; ++ break; ++ default: ++ return -EINVAL; ++ } ++ memcpy(f, fmt, sizeof(*fmt)); ++ ++ return 0; ++} +diff --git a/drivers/media/platform/qcom/iris/iris_vdec.h b/drivers/media/platform/qcom/iris/iris_vdec.h +index 353b73b76230..85e93f33e9e7 100644 +--- a/drivers/media/platform/qcom/iris/iris_vdec.h ++++ b/drivers/media/platform/qcom/iris/iris_vdec.h +@@ -10,5 +10,7 @@ struct iris_inst; + + void iris_vdec_inst_init(struct iris_inst *inst); + void iris_vdec_inst_deinit(struct iris_inst *inst); ++int iris_vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f); ++int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f); + + #endif +diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c +index ab3b63171c1d..bec965284b6e 100644 +--- a/drivers/media/platform/qcom/iris/iris_vidc.c ++++ b/drivers/media/platform/qcom/iris/iris_vidc.c +@@ -217,6 +217,48 @@ int iris_close(struct file *filp) + return 0; + } + ++static int iris_try_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_format *f) ++{ ++ struct iris_inst *inst = iris_get_inst(filp, NULL); ++ int ret; ++ ++ mutex_lock(&inst->lock); ++ ret = iris_vdec_try_fmt(inst, f); ++ mutex_unlock(&inst->lock); ++ ++ return ret; ++} ++ ++static int iris_s_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_format *f) ++{ ++ struct iris_inst *inst = iris_get_inst(filp, NULL); ++ int ret; ++ ++ mutex_lock(&inst->lock); ++ ret = iris_vdec_s_fmt(inst, f); ++ mutex_unlock(&inst->lock); ++ ++ return ret; ++} ++ ++static int iris_g_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_format *f) ++{ ++ struct iris_inst *inst = iris_get_inst(filp, NULL); ++ int ret = 0; ++ ++ mutex_lock(&inst->lock); ++ if (V4L2_TYPE_IS_OUTPUT(f->type)) ++ *f = *inst->fmt_src; ++ else if (V4L2_TYPE_IS_CAPTURE(f->type)) ++ *f = *inst->fmt_dst; ++ else ++ ret = -EINVAL; ++ ++ mutex_unlock(&inst->lock); ++ ++ return ret; ++} ++ + static struct v4l2_file_operations iris_v4l2_file_ops = { + .owner = THIS_MODULE, + .open = iris_open, +@@ -231,6 +273,12 @@ static const struct vb2_ops iris_vb2_ops = { + }; + + static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops = { ++ .vidioc_try_fmt_vid_cap_mplane = iris_try_fmt_vid_mplane, ++ .vidioc_try_fmt_vid_out_mplane = iris_try_fmt_vid_mplane, ++ .vidioc_s_fmt_vid_cap_mplane = iris_s_fmt_vid_mplane, ++ .vidioc_s_fmt_vid_out_mplane = iris_s_fmt_vid_mplane, ++ .vidioc_g_fmt_vid_cap_mplane = iris_g_fmt_vid_mplane, ++ .vidioc_g_fmt_vid_out_mplane = iris_g_fmt_vid_mplane, + .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, + }; + +-- +2.34.1 + diff --git a/patch/kernel/archive/sm8550-6.12/0011_media--iris--implement-g_selection-ioctl.patch b/patch/kernel/archive/sm8550-6.12/0011_media--iris--implement-g_selection-ioctl.patch new file mode 100644 index 000000000..df3a199db --- /dev/null +++ b/patch/kernel/archive/sm8550-6.12/0011_media--iris--implement-g_selection-ioctl.patch @@ -0,0 +1,70 @@ +From 304c180d9f6f9cadc42a3ed40b5f82629dd3aeda Mon Sep 17 00:00:00 2001 +From: Vedang Nagar +Date: Fri, 7 Feb 2025 13:24:51 +0530 +Subject: [PATCH] media: iris: implement g_selection ioctl + +Implement the g_selection ioctl op in the driver with the necessary +hooks. + +Signed-off-by: Vedang Nagar +Reviewed-by: Hans Verkuil +Tested-by: Stefan Schmidt # x1e80100 (Dell XPS 13 9345) +Reviewed-by: Stefan Schmidt +Tested-by: Neil Armstrong # on SM8550-QRD +Tested-by: Neil Armstrong # on SM8550-HDK +Signed-off-by: Dikshita Agarwal +Link: https://lore.kernel.org/r/20250207-qcom-video-iris-v10-11-ab66eeffbd20@quicinc.com +Signed-off-by: Neil Armstrong +--- + drivers/media/platform/qcom/iris/iris_vidc.c | 28 ++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c +index bec965284b6e..92eb793cbeb7 100644 +--- a/drivers/media/platform/qcom/iris/iris_vidc.c ++++ b/drivers/media/platform/qcom/iris/iris_vidc.c +@@ -259,6 +259,33 @@ static int iris_g_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_format + return ret; + } + ++static int iris_g_selection(struct file *filp, void *fh, struct v4l2_selection *s) ++{ ++ struct iris_inst *inst = iris_get_inst(filp, NULL); ++ ++ if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ ++ switch (s->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ case V4L2_SEL_TGT_CROP: ++ case V4L2_SEL_TGT_COMPOSE_BOUNDS: ++ case V4L2_SEL_TGT_COMPOSE_PADDED: ++ case V4L2_SEL_TGT_COMPOSE_DEFAULT: ++ case V4L2_SEL_TGT_COMPOSE: ++ s->r.left = inst->crop.left; ++ s->r.top = inst->crop.top; ++ s->r.width = inst->crop.width; ++ s->r.height = inst->crop.height; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ + static struct v4l2_file_operations iris_v4l2_file_ops = { + .owner = THIS_MODULE, + .open = iris_open, +@@ -280,6 +307,7 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops = { + .vidioc_g_fmt_vid_cap_mplane = iris_g_fmt_vid_mplane, + .vidioc_g_fmt_vid_out_mplane = iris_g_fmt_vid_mplane, + .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, ++ .vidioc_g_selection = iris_g_selection, + }; + + void iris_init_ops(struct iris_core *core) +-- +2.34.1 + diff --git a/patch/kernel/archive/sm8550-6.12/0012_media--iris--implement-enum_fmt-and-enum_framesize.patch b/patch/kernel/archive/sm8550-6.12/0012_media--iris--implement-enum_fmt-and-enum_framesize.patch new file mode 100644 index 000000000..f941a7e54 --- /dev/null +++ b/patch/kernel/archive/sm8550-6.12/0012_media--iris--implement-enum_fmt-and-enum_framesize.patch @@ -0,0 +1,168 @@ +From 7c0295c068f6d1c1ecb76e0ca4e144d197ee974b Mon Sep 17 00:00:00 2001 +From: Vedang Nagar +Date: Fri, 7 Feb 2025 13:24:52 +0530 +Subject: [PATCH] media: iris: implement enum_fmt and enum_framesizes ioctls + +Implement the enum_fmt and enum_framesizes ioctls with the necessary +hooks. + +Signed-off-by: Vedang Nagar +Reviewed-by: Hans Verkuil +Tested-by: Stefan Schmidt # x1e80100 (Dell XPS 13 9345) +Reviewed-by: Stefan Schmidt +Tested-by: Neil Armstrong # on SM8550-QRD +Tested-by: Neil Armstrong # on SM8550-HDK +Signed-off-by: Dikshita Agarwal +Link: https://lore.kernel.org/r/20250207-qcom-video-iris-v10-12-ab66eeffbd20@quicinc.com +Signed-off-by: Neil Armstrong +--- + .../platform/qcom/iris/iris_platform_common.h | 4 ++ + .../platform/qcom/iris/iris_platform_sm8550.c | 4 ++ + drivers/media/platform/qcom/iris/iris_vdec.c | 17 ++++++++ + drivers/media/platform/qcom/iris/iris_vdec.h | 1 + + drivers/media/platform/qcom/iris/iris_vidc.c | 39 +++++++++++++++++++ + 5 files changed, 65 insertions(+) + +diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h +index d508477b066e..75d4932df910 100644 +--- a/drivers/media/platform/qcom/iris/iris_platform_common.h ++++ b/drivers/media/platform/qcom/iris/iris_platform_common.h +@@ -43,6 +43,10 @@ struct ubwc_config_data { + }; + + struct platform_inst_caps { ++ u32 min_frame_width; ++ u32 max_frame_width; ++ u32 min_frame_height; ++ u32 max_frame_height; + u32 max_mbpf; + }; + struct iris_core_power { +diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +index e4232c755074..3972b64dbda6 100644 +--- a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c ++++ b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +@@ -11,6 +11,10 @@ + #define VIDEO_ARCH_LX 1 + + static struct platform_inst_caps platform_inst_cap_sm8550 = { ++ .min_frame_width = 96, ++ .max_frame_width = 8192, ++ .min_frame_height = 96, ++ .max_frame_height = 8192, + .max_mbpf = (8192 * 4352) / 256, + }; + +diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c +index 38a5df8191cc..081a9eda5c49 100644 +--- a/drivers/media/platform/qcom/iris/iris_vdec.c ++++ b/drivers/media/platform/qcom/iris/iris_vdec.c +@@ -58,6 +58,23 @@ void iris_vdec_inst_deinit(struct iris_inst *inst) + kfree(inst->fmt_src); + } + ++int iris_vdec_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f) ++{ ++ switch (f->type) { ++ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: ++ f->pixelformat = V4L2_PIX_FMT_H264; ++ f->flags = V4L2_FMT_FLAG_COMPRESSED | V4L2_FMT_FLAG_DYN_RESOLUTION; ++ break; ++ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: ++ f->pixelformat = V4L2_PIX_FMT_NV12; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ + int iris_vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f) + { + struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; +diff --git a/drivers/media/platform/qcom/iris/iris_vdec.h b/drivers/media/platform/qcom/iris/iris_vdec.h +index 85e93f33e9e7..ae456676e578 100644 +--- a/drivers/media/platform/qcom/iris/iris_vdec.h ++++ b/drivers/media/platform/qcom/iris/iris_vdec.h +@@ -10,6 +10,7 @@ struct iris_inst; + + void iris_vdec_inst_init(struct iris_inst *inst); + void iris_vdec_inst_deinit(struct iris_inst *inst); ++int iris_vdec_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f); + int iris_vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f); + int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f); + +diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c +index 92eb793cbeb7..82bd0be8e5da 100644 +--- a/drivers/media/platform/qcom/iris/iris_vidc.c ++++ b/drivers/media/platform/qcom/iris/iris_vidc.c +@@ -217,6 +217,16 @@ int iris_close(struct file *filp) + return 0; + } + ++static int iris_enum_fmt(struct file *filp, void *fh, struct v4l2_fmtdesc *f) ++{ ++ struct iris_inst *inst = iris_get_inst(filp, NULL); ++ ++ if (f->index) ++ return -EINVAL; ++ ++ return iris_vdec_enum_fmt(inst, f); ++} ++ + static int iris_try_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_format *f) + { + struct iris_inst *inst = iris_get_inst(filp, NULL); +@@ -259,6 +269,32 @@ static int iris_g_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_format + return ret; + } + ++static int iris_enum_framesizes(struct file *filp, void *fh, ++ struct v4l2_frmsizeenum *fsize) ++{ ++ struct iris_inst *inst = iris_get_inst(filp, NULL); ++ struct platform_inst_caps *caps; ++ ++ if (fsize->index) ++ return -EINVAL; ++ ++ if (fsize->pixel_format != V4L2_PIX_FMT_H264 && ++ fsize->pixel_format != V4L2_PIX_FMT_NV12) ++ return -EINVAL; ++ ++ caps = inst->core->iris_platform_data->inst_caps; ++ ++ fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; ++ fsize->stepwise.min_width = caps->min_frame_width; ++ fsize->stepwise.max_width = caps->max_frame_width; ++ fsize->stepwise.step_width = STEP_WIDTH; ++ fsize->stepwise.min_height = caps->min_frame_height; ++ fsize->stepwise.max_height = caps->max_frame_height; ++ fsize->stepwise.step_height = STEP_HEIGHT; ++ ++ return 0; ++} ++ + static int iris_g_selection(struct file *filp, void *fh, struct v4l2_selection *s) + { + struct iris_inst *inst = iris_get_inst(filp, NULL); +@@ -300,12 +336,15 @@ static const struct vb2_ops iris_vb2_ops = { + }; + + static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops = { ++ .vidioc_enum_fmt_vid_cap = iris_enum_fmt, ++ .vidioc_enum_fmt_vid_out = iris_enum_fmt, + .vidioc_try_fmt_vid_cap_mplane = iris_try_fmt_vid_mplane, + .vidioc_try_fmt_vid_out_mplane = iris_try_fmt_vid_mplane, + .vidioc_s_fmt_vid_cap_mplane = iris_s_fmt_vid_mplane, + .vidioc_s_fmt_vid_out_mplane = iris_s_fmt_vid_mplane, + .vidioc_g_fmt_vid_cap_mplane = iris_g_fmt_vid_mplane, + .vidioc_g_fmt_vid_out_mplane = iris_g_fmt_vid_mplane, ++ .vidioc_enum_framesizes = iris_enum_framesizes, + .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, + .vidioc_g_selection = iris_g_selection, + }; +-- +2.34.1 + diff --git a/patch/kernel/archive/sm8550-6.12/0013_media--iris--implement-subscribe_event-and-unsubsc.patch b/patch/kernel/archive/sm8550-6.12/0013_media--iris--implement-subscribe_event-and-unsubsc.patch new file mode 100644 index 000000000..8759061bd --- /dev/null +++ b/patch/kernel/archive/sm8550-6.12/0013_media--iris--implement-subscribe_event-and-unsubsc.patch @@ -0,0 +1,110 @@ +From cbcd78524e95d5d2581ebcafdab2ff4d13ac64c1 Mon Sep 17 00:00:00 2001 +From: Vedang Nagar +Date: Fri, 7 Feb 2025 13:24:53 +0530 +Subject: [PATCH] media: iris: implement subscribe_event and unsubscribe_event + ioctls + +Implement the subscribe_event and unsubscribe_event iocts with the +necessary hooks. + +Signed-off-by: Vedang Nagar +Reviewed-by: Hans Verkuil +Tested-by: Stefan Schmidt # x1e80100 (Dell XPS 13 9345) +Reviewed-by: Stefan Schmidt +Tested-by: Neil Armstrong # on SM8550-QRD +Tested-by: Neil Armstrong # on SM8550-HDK +Signed-off-by: Dikshita Agarwal +Link: https://lore.kernel.org/r/20250207-qcom-video-iris-v10-13-ab66eeffbd20@quicinc.com +Signed-off-by: Neil Armstrong +--- + drivers/media/platform/qcom/iris/iris_vdec.c | 22 ++++++++++++++++++++ + drivers/media/platform/qcom/iris/iris_vdec.h | 1 + + drivers/media/platform/qcom/iris/iris_vidc.c | 10 +++++++++ + 3 files changed, 33 insertions(+) + +diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c +index 081a9eda5c49..0ba60bcb9fa9 100644 +--- a/drivers/media/platform/qcom/iris/iris_vdec.c ++++ b/drivers/media/platform/qcom/iris/iris_vdec.c +@@ -3,6 +3,7 @@ + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + ++#include + #include + + #include "iris_buffer.h" +@@ -193,3 +194,24 @@ int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f) + + return 0; + } ++ ++int iris_vdec_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub) ++{ ++ int ret = 0; ++ ++ switch (sub->type) { ++ case V4L2_EVENT_EOS: ++ ret = v4l2_event_subscribe(&inst->fh, sub, 0, NULL); ++ break; ++ case V4L2_EVENT_SOURCE_CHANGE: ++ ret = v4l2_src_change_event_subscribe(&inst->fh, sub); ++ break; ++ case V4L2_EVENT_CTRL: ++ ret = v4l2_ctrl_subscribe_event(&inst->fh, sub); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return ret; ++} +diff --git a/drivers/media/platform/qcom/iris/iris_vdec.h b/drivers/media/platform/qcom/iris/iris_vdec.h +index ae456676e578..f64ce3234e6a 100644 +--- a/drivers/media/platform/qcom/iris/iris_vdec.h ++++ b/drivers/media/platform/qcom/iris/iris_vdec.h +@@ -13,5 +13,6 @@ void iris_vdec_inst_deinit(struct iris_inst *inst); + int iris_vdec_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f); + int iris_vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f); + int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f); ++int iris_vdec_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub); + + #endif +diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c +index 82bd0be8e5da..511cd13ac471 100644 +--- a/drivers/media/platform/qcom/iris/iris_vidc.c ++++ b/drivers/media/platform/qcom/iris/iris_vidc.c +@@ -4,6 +4,7 @@ + */ + + #include ++#include + #include + #include + +@@ -322,6 +323,13 @@ static int iris_g_selection(struct file *filp, void *fh, struct v4l2_selection * + return 0; + } + ++static int iris_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub) ++{ ++ struct iris_inst *inst = container_of(fh, struct iris_inst, fh); ++ ++ return iris_vdec_subscribe_event(inst, sub); ++} ++ + static struct v4l2_file_operations iris_v4l2_file_ops = { + .owner = THIS_MODULE, + .open = iris_open, +@@ -347,6 +355,8 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops = { + .vidioc_enum_framesizes = iris_enum_framesizes, + .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, + .vidioc_g_selection = iris_g_selection, ++ .vidioc_subscribe_event = iris_subscribe_event, ++ .vidioc_unsubscribe_event = v4l2_event_unsubscribe, + }; + + void iris_init_ops(struct iris_core *core) +-- +2.34.1 + diff --git a/patch/kernel/archive/sm8550-6.12/0014_media--iris--implement-iris-v4l2_ctrl_ops.patch b/patch/kernel/archive/sm8550-6.12/0014_media--iris--implement-iris-v4l2_ctrl_ops.patch new file mode 100644 index 000000000..a74c9f9c7 --- /dev/null +++ b/patch/kernel/archive/sm8550-6.12/0014_media--iris--implement-iris-v4l2_ctrl_ops.patch @@ -0,0 +1,539 @@ +From e94d3d551e3feedc7299f884c3b9b57452fa82c2 Mon Sep 17 00:00:00 2001 +From: Dikshita Agarwal +Date: Fri, 7 Feb 2025 13:24:54 +0530 +Subject: [PATCH] media: iris: implement iris v4l2_ctrl_ops + +Initialize the control handler by reading the platform specific firmware +capabilities. Capabilities are features, which are supported by a +specific platform (SOC). Each capability is defined with a min, max, +range and default value and a corresponding HFI. Implement s_ctrl and +g_volatile_ctrl ctrl ops. + +Co-developed-by: Vedang Nagar +Signed-off-by: Vedang Nagar +Reviewed-by: Hans Verkuil +Tested-by: Stefan Schmidt # x1e80100 (Dell XPS 13 9345) +Reviewed-by: Stefan Schmidt +Tested-by: Neil Armstrong # on SM8550-QRD +Tested-by: Neil Armstrong # on SM8550-HDK +Signed-off-by: Dikshita Agarwal +Link: https://lore.kernel.org/r/20250207-qcom-video-iris-v10-14-ab66eeffbd20@quicinc.com +Signed-off-by: Neil Armstrong +--- + drivers/media/platform/qcom/iris/Makefile | 1 + + drivers/media/platform/qcom/iris/iris_core.h | 2 + + drivers/media/platform/qcom/iris/iris_ctrls.c | 165 ++++++++++++++++++ + drivers/media/platform/qcom/iris/iris_ctrls.h | 17 ++ + .../qcom/iris/iris_hfi_gen2_defines.h | 2 + + .../media/platform/qcom/iris/iris_instance.h | 4 + + .../platform/qcom/iris/iris_platform_common.h | 30 ++++ + .../platform/qcom/iris/iris_platform_sm8550.c | 47 +++++ + drivers/media/platform/qcom/iris/iris_probe.c | 3 + + drivers/media/platform/qcom/iris/iris_vdec.c | 9 +- + drivers/media/platform/qcom/iris/iris_vdec.h | 2 +- + drivers/media/platform/qcom/iris/iris_vidc.c | 9 +- + 12 files changed, 288 insertions(+), 3 deletions(-) + create mode 100644 drivers/media/platform/qcom/iris/iris_ctrls.c + create mode 100644 drivers/media/platform/qcom/iris/iris_ctrls.h + +diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile +index 48ab264b7906..f685d76c2f79 100644 +--- a/drivers/media/platform/qcom/iris/Makefile ++++ b/drivers/media/platform/qcom/iris/Makefile +@@ -1,5 +1,6 @@ + iris-objs += iris_buffer.o \ + iris_core.o \ ++ iris_ctrls.o \ + iris_firmware.o \ + iris_hfi_common.o \ + iris_hfi_gen1_command.o \ +diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h +index 1ddcb8793172..37fb4919fecc 100644 +--- a/drivers/media/platform/qcom/iris/iris_core.h ++++ b/drivers/media/platform/qcom/iris/iris_core.h +@@ -63,6 +63,7 @@ struct icc_info { + * @intr_status: interrupt status + * @sys_error_handler: a delayed work for handling system fatal error + * @instances: a list_head of all instances ++ * @inst_fw_caps: an array of supported instance capabilities + */ + + struct iris_core { +@@ -101,6 +102,7 @@ struct iris_core { + u32 intr_status; + struct delayed_work sys_error_handler; + struct list_head instances; ++ struct platform_inst_fw_cap inst_fw_caps[INST_FW_CAP_MAX]; + }; + + int iris_core_init(struct iris_core *core); +diff --git a/drivers/media/platform/qcom/iris/iris_ctrls.c b/drivers/media/platform/qcom/iris/iris_ctrls.c +new file mode 100644 +index 000000000000..3652fa535bf3 +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_ctrls.c +@@ -0,0 +1,165 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include ++#include "iris_ctrls.h" ++#include "iris_instance.h" ++ ++static inline bool iris_valid_cap_id(enum platform_inst_fw_cap_type cap_id) ++{ ++ return cap_id >= 1 && cap_id < INST_FW_CAP_MAX; ++} ++ ++static enum platform_inst_fw_cap_type iris_get_cap_id(u32 id) ++{ ++ switch (id) { ++ case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER: ++ return DEBLOCK; ++ case V4L2_CID_MPEG_VIDEO_H264_PROFILE: ++ return PROFILE; ++ case V4L2_CID_MPEG_VIDEO_H264_LEVEL: ++ return LEVEL; ++ default: ++ return INST_FW_CAP_MAX; ++ } ++} ++ ++static u32 iris_get_v4l2_id(enum platform_inst_fw_cap_type cap_id) ++{ ++ if (!iris_valid_cap_id(cap_id)) ++ return 0; ++ ++ switch (cap_id) { ++ case DEBLOCK: ++ return V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER; ++ case PROFILE: ++ return V4L2_CID_MPEG_VIDEO_H264_PROFILE; ++ case LEVEL: ++ return V4L2_CID_MPEG_VIDEO_H264_LEVEL; ++ default: ++ return 0; ++ } ++} ++ ++static int iris_vdec_op_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct iris_inst *inst = container_of(ctrl->handler, struct iris_inst, ctrl_handler); ++ enum platform_inst_fw_cap_type cap_id; ++ struct platform_inst_fw_cap *cap; ++ struct vb2_queue *q; ++ ++ cap = &inst->fw_caps[0]; ++ cap_id = iris_get_cap_id(ctrl->id); ++ if (!iris_valid_cap_id(cap_id)) ++ return -EINVAL; ++ ++ q = v4l2_m2m_get_src_vq(inst->m2m_ctx); ++ if (vb2_is_streaming(q) && ++ (!(inst->fw_caps[cap_id].flags & CAP_FLAG_DYNAMIC_ALLOWED))) ++ return -EINVAL; ++ ++ cap[cap_id].flags |= CAP_FLAG_CLIENT_SET; ++ ++ inst->fw_caps[cap_id].value = ctrl->val; ++ ++ return 0; ++} ++ ++static const struct v4l2_ctrl_ops iris_ctrl_ops = { ++ .s_ctrl = iris_vdec_op_s_ctrl, ++}; ++ ++int iris_ctrls_init(struct iris_inst *inst) ++{ ++ struct platform_inst_fw_cap *cap = &inst->fw_caps[0]; ++ u32 num_ctrls = 0, ctrl_idx = 0, idx = 0; ++ u32 v4l2_id; ++ int ret; ++ ++ for (idx = 1; idx < INST_FW_CAP_MAX; idx++) { ++ if (iris_get_v4l2_id(cap[idx].cap_id)) ++ num_ctrls++; ++ } ++ if (!num_ctrls) ++ return -EINVAL; ++ ++ /* Adding 1 to num_ctrls to include V4L2_CID_MIN_BUFFERS_FOR_CAPTURE */ ++ ++ ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, num_ctrls + 1); ++ if (ret) ++ return ret; ++ ++ for (idx = 1; idx < INST_FW_CAP_MAX; idx++) { ++ struct v4l2_ctrl *ctrl; ++ ++ v4l2_id = iris_get_v4l2_id(cap[idx].cap_id); ++ if (!v4l2_id) ++ continue; ++ ++ if (ctrl_idx >= num_ctrls) { ++ ret = -EINVAL; ++ goto error; ++ } ++ ++ if (cap[idx].flags & CAP_FLAG_MENU) { ++ ctrl = v4l2_ctrl_new_std_menu(&inst->ctrl_handler, ++ &iris_ctrl_ops, ++ v4l2_id, ++ cap[idx].max, ++ ~(cap[idx].step_or_mask), ++ cap[idx].value); ++ } else { ++ ctrl = v4l2_ctrl_new_std(&inst->ctrl_handler, ++ &iris_ctrl_ops, ++ v4l2_id, ++ cap[idx].min, ++ cap[idx].max, ++ cap[idx].step_or_mask, ++ cap[idx].value); ++ } ++ if (!ctrl) { ++ ret = -EINVAL; ++ goto error; ++ } ++ ++ ctrl_idx++; ++ } ++ ++ v4l2_ctrl_new_std(&inst->ctrl_handler, NULL, ++ V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 4); ++ ++ ret = inst->ctrl_handler.error; ++ if (ret) ++ goto error; ++ ++ return 0; ++error: ++ v4l2_ctrl_handler_free(&inst->ctrl_handler); ++ ++ return ret; ++} ++ ++void iris_session_init_caps(struct iris_core *core) ++{ ++ struct platform_inst_fw_cap *caps; ++ u32 i, num_cap, cap_id; ++ ++ caps = core->iris_platform_data->inst_fw_caps; ++ num_cap = core->iris_platform_data->inst_fw_caps_size; ++ ++ for (i = 0; i < num_cap; i++) { ++ cap_id = caps[i].cap_id; ++ if (!iris_valid_cap_id(cap_id)) ++ continue; ++ ++ core->inst_fw_caps[cap_id].cap_id = caps[i].cap_id; ++ core->inst_fw_caps[cap_id].min = caps[i].min; ++ core->inst_fw_caps[cap_id].max = caps[i].max; ++ core->inst_fw_caps[cap_id].step_or_mask = caps[i].step_or_mask; ++ core->inst_fw_caps[cap_id].value = caps[i].value; ++ core->inst_fw_caps[cap_id].flags = caps[i].flags; ++ core->inst_fw_caps[cap_id].hfi_id = caps[i].hfi_id; ++ } ++} +diff --git a/drivers/media/platform/qcom/iris/iris_ctrls.h b/drivers/media/platform/qcom/iris/iris_ctrls.h +new file mode 100644 +index 000000000000..fe65a772e6dd +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_ctrls.h +@@ -0,0 +1,17 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef __IRIS_CTRLS_H__ ++#define __IRIS_CTRLS_H__ ++ ++#include "iris_platform_common.h" ++ ++struct iris_core; ++struct iris_inst; ++ ++int iris_ctrls_init(struct iris_inst *inst); ++void iris_session_init_caps(struct iris_core *core); ++ ++#endif +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +index ccf5fd0902d7..173a554a0d44 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +@@ -28,6 +28,8 @@ + #define HFI_PROP_UBWC_BANK_SWZL_LEVEL3 0x03000008 + #define HFI_PROP_UBWC_BANK_SPREADING 0x03000009 + #define HFI_PROP_CODEC 0x03000100 ++#define HFI_PROP_PROFILE 0x03000107 ++#define HFI_PROP_LEVEL 0x03000108 + #define HFI_PROP_DEC_DEFAULT_HEADER 0x03000168 + #define HFI_PROP_END 0x03FFFFFF + +diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/drivers/media/platform/qcom/iris/iris_instance.h +index b9c7dcfb20f7..9f1a1e5ba7c7 100644 +--- a/drivers/media/platform/qcom/iris/iris_instance.h ++++ b/drivers/media/platform/qcom/iris/iris_instance.h +@@ -23,8 +23,10 @@ + * @fh: reference of v4l2 file handler + * @fmt_src: structure of v4l2_format for source + * @fmt_dst: structure of v4l2_format for destination ++ * @ctrl_handler: reference of v4l2 ctrl handler + * @crop: structure of crop info + * @completion: structure of signal completions ++ * @fw_caps: array of supported instance firmware capabilities + * @buffers: array of different iris buffers + * @fw_min_count: minimnum count of buffers needed by fw + * @once_per_session_set: boolean to set once per session property +@@ -41,8 +43,10 @@ struct iris_inst { + struct v4l2_fh fh; + struct v4l2_format *fmt_src; + struct v4l2_format *fmt_dst; ++ struct v4l2_ctrl_handler ctrl_handler; + struct iris_hfi_rect_desc crop; + struct completion completion; ++ struct platform_inst_fw_cap fw_caps[INST_FW_CAP_MAX]; + struct iris_buffers buffers[BUF_TYPE_MAX]; + u32 fw_min_count; + bool once_per_session_set; +diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h +index 75d4932df910..23170cd37c04 100644 +--- a/drivers/media/platform/qcom/iris/iris_platform_common.h ++++ b/drivers/media/platform/qcom/iris/iris_platform_common.h +@@ -49,6 +49,34 @@ struct platform_inst_caps { + u32 max_frame_height; + u32 max_mbpf; + }; ++ ++enum platform_inst_fw_cap_type { ++ PROFILE = 1, ++ LEVEL, ++ DEBLOCK, ++ INST_FW_CAP_MAX, ++}; ++ ++enum platform_inst_fw_cap_flags { ++ CAP_FLAG_DYNAMIC_ALLOWED = BIT(0), ++ CAP_FLAG_MENU = BIT(1), ++ CAP_FLAG_INPUT_PORT = BIT(2), ++ CAP_FLAG_OUTPUT_PORT = BIT(3), ++ CAP_FLAG_CLIENT_SET = BIT(4), ++ CAP_FLAG_BITMASK = BIT(5), ++ CAP_FLAG_VOLATILE = BIT(6), ++}; ++ ++struct platform_inst_fw_cap { ++ enum platform_inst_fw_cap_type cap_id; ++ s64 min; ++ s64 max; ++ s64 step_or_mask; ++ s64 value; ++ u32 hfi_id; ++ enum platform_inst_fw_cap_flags flags; ++}; ++ + struct iris_core_power { + u64 clk_freq; + u64 icc_bw; +@@ -79,6 +107,8 @@ struct iris_platform_data { + const char *fwname; + u32 pas_id; + struct platform_inst_caps *inst_caps; ++ struct platform_inst_fw_cap *inst_fw_caps; ++ u32 inst_fw_caps_size; + struct tz_cp_config *tz_cp_config_data; + u32 core_arch; + u32 hw_response_timeout; +diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +index 3972b64dbda6..58b1d1d43731 100644 +--- a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c ++++ b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +@@ -5,11 +5,56 @@ + + #include "iris_core.h" + #include "iris_hfi_gen2.h" ++#include "iris_hfi_gen2_defines.h" + #include "iris_platform_common.h" + #include "iris_vpu_common.h" + + #define VIDEO_ARCH_LX 1 + ++static struct platform_inst_fw_cap inst_fw_cap_sm8550[] = { ++ { ++ .cap_id = PROFILE, ++ .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE, ++ .max = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH, ++ .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) | ++ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) | ++ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) | ++ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH) | ++ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH), ++ .value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, ++ .hfi_id = HFI_PROP_PROFILE, ++ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, ++ }, ++ { ++ .cap_id = LEVEL, ++ .min = V4L2_MPEG_VIDEO_H264_LEVEL_1_0, ++ .max = V4L2_MPEG_VIDEO_H264_LEVEL_6_2, ++ .step_or_mask = 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), ++ .value = V4L2_MPEG_VIDEO_H264_LEVEL_6_1, ++ .hfi_id = HFI_PROP_LEVEL, ++ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, ++ }, ++}; ++ + static struct platform_inst_caps platform_inst_cap_sm8550 = { + .min_frame_width = 96, + .max_frame_width = 8192, +@@ -78,6 +123,8 @@ struct iris_platform_data sm8550_data = { + .fwname = "qcom/vpu/vpu30_p4.mbn", + .pas_id = IRIS_PAS_ID, + .inst_caps = &platform_inst_cap_sm8550, ++ .inst_fw_caps = inst_fw_cap_sm8550, ++ .inst_fw_caps_size = ARRAY_SIZE(inst_fw_cap_sm8550), + .tz_cp_config_data = &tz_cp_config_sm8550, + .core_arch = VIDEO_ARCH_LX, + .hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE, +diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c +index a9162be5f9f6..954cc7c0cc97 100644 +--- a/drivers/media/platform/qcom/iris/iris_probe.c ++++ b/drivers/media/platform/qcom/iris/iris_probe.c +@@ -12,6 +12,7 @@ + #include + + #include "iris_core.h" ++#include "iris_ctrls.h" + #include "iris_vidc.h" + + static int iris_init_icc(struct iris_core *core) +@@ -236,6 +237,8 @@ static int iris_probe(struct platform_device *pdev) + if (ret) + return ret; + ++ iris_session_init_caps(core); ++ + ret = v4l2_device_register(dev, &core->v4l2_dev); + if (ret) + return ret; +diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c +index 0ba60bcb9fa9..132b578b34dc 100644 +--- a/drivers/media/platform/qcom/iris/iris_vdec.c ++++ b/drivers/media/platform/qcom/iris/iris_vdec.c +@@ -7,6 +7,7 @@ + #include + + #include "iris_buffer.h" ++#include "iris_ctrls.h" + #include "iris_instance.h" + #include "iris_vdec.h" + #include "iris_vpu_buffer.h" +@@ -15,8 +16,9 @@ + #define DEFAULT_HEIGHT 240 + #define DEFAULT_CODEC_ALIGNMENT 16 + +-void iris_vdec_inst_init(struct iris_inst *inst) ++int iris_vdec_inst_init(struct iris_inst *inst) + { ++ struct iris_core *core = inst->core; + struct v4l2_format *f; + + inst->fmt_src = kzalloc(sizeof(*inst->fmt_src), GFP_KERNEL); +@@ -51,6 +53,11 @@ void iris_vdec_inst_init(struct iris_inst *inst) + f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT; + inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT); + inst->buffers[BUF_OUTPUT].size = f->fmt.pix_mp.plane_fmt[0].sizeimage; ++ ++ memcpy(&inst->fw_caps[0], &core->inst_fw_caps[0], ++ INST_FW_CAP_MAX * sizeof(struct platform_inst_fw_cap)); ++ ++ return iris_ctrls_init(inst); + } + + void iris_vdec_inst_deinit(struct iris_inst *inst) +diff --git a/drivers/media/platform/qcom/iris/iris_vdec.h b/drivers/media/platform/qcom/iris/iris_vdec.h +index f64ce3234e6a..9f08a13cb6bb 100644 +--- a/drivers/media/platform/qcom/iris/iris_vdec.h ++++ b/drivers/media/platform/qcom/iris/iris_vdec.h +@@ -8,7 +8,7 @@ + + struct iris_inst; + +-void iris_vdec_inst_init(struct iris_inst *inst); ++int iris_vdec_inst_init(struct iris_inst *inst); + void iris_vdec_inst_deinit(struct iris_inst *inst); + int iris_vdec_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f); + int iris_vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f); +diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c +index 511cd13ac471..90e70aa8eedf 100644 +--- a/drivers/media/platform/qcom/iris/iris_vidc.c ++++ b/drivers/media/platform/qcom/iris/iris_vidc.c +@@ -23,12 +23,14 @@ + static void iris_v4l2_fh_init(struct iris_inst *inst) + { + v4l2_fh_init(&inst->fh, inst->core->vdev_dec); ++ inst->fh.ctrl_handler = &inst->ctrl_handler; + v4l2_fh_add(&inst->fh); + } + + static void iris_v4l2_fh_deinit(struct iris_inst *inst) + { + v4l2_fh_del(&inst->fh); ++ inst->fh.ctrl_handler = NULL; + v4l2_fh_exit(&inst->fh); + } + +@@ -162,7 +164,9 @@ int iris_open(struct file *filp) + goto fail_m2m_release; + } + +- iris_vdec_inst_init(inst); ++ ret = iris_vdec_inst_init(inst); ++ if (ret) ++ goto fail_m2m_ctx_release; + + iris_add_session(inst); + +@@ -171,6 +175,8 @@ int iris_open(struct file *filp) + + return 0; + ++fail_m2m_ctx_release: ++ v4l2_m2m_ctx_release(inst->m2m_ctx); + fail_m2m_release: + v4l2_m2m_release(inst->m2m_dev); + fail_v4l2_fh_deinit: +@@ -202,6 +208,7 @@ int iris_close(struct file *filp) + { + struct iris_inst *inst = iris_get_inst(filp, NULL); + ++ v4l2_ctrl_handler_free(&inst->ctrl_handler); + v4l2_m2m_ctx_release(inst->m2m_ctx); + v4l2_m2m_release(inst->m2m_dev); + mutex_lock(&inst->lock); +-- +2.34.1 + diff --git a/patch/kernel/archive/sm8550-6.12/0015_media--iris--implement-query_cap-ioctl.patch b/patch/kernel/archive/sm8550-6.12/0015_media--iris--implement-query_cap-ioctl.patch new file mode 100644 index 000000000..4cb4a8a4d --- /dev/null +++ b/patch/kernel/archive/sm8550-6.12/0015_media--iris--implement-query_cap-ioctl.patch @@ -0,0 +1,50 @@ +From 33f111b8320ac637150755b607b781f3562d86e3 Mon Sep 17 00:00:00 2001 +From: Vedang Nagar +Date: Fri, 7 Feb 2025 13:24:55 +0530 +Subject: [PATCH] media: iris: implement query_cap ioctl + +Implement the query_cap ioctl with the necessary hooks. + +Signed-off-by: Vedang Nagar +Reviewed-by: Hans Verkuil +Tested-by: Stefan Schmidt # x1e80100 (Dell XPS 13 9345) +Reviewed-by: Stefan Schmidt +Tested-by: Neil Armstrong # on SM8550-QRD +Tested-by: Neil Armstrong # on SM8550-HDK +Signed-off-by: Dikshita Agarwal +Link: https://lore.kernel.org/r/20250207-qcom-video-iris-v10-15-ab66eeffbd20@quicinc.com +Signed-off-by: Neil Armstrong +--- + drivers/media/platform/qcom/iris/iris_vidc.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c +index 90e70aa8eedf..5b54231f2def 100644 +--- a/drivers/media/platform/qcom/iris/iris_vidc.c ++++ b/drivers/media/platform/qcom/iris/iris_vidc.c +@@ -303,6 +303,14 @@ static int iris_enum_framesizes(struct file *filp, void *fh, + return 0; + } + ++static int iris_querycap(struct file *filp, void *fh, struct v4l2_capability *cap) ++{ ++ strscpy(cap->driver, IRIS_DRV_NAME, sizeof(cap->driver)); ++ strscpy(cap->card, "Iris Decoder", sizeof(cap->card)); ++ ++ return 0; ++} ++ + static int iris_g_selection(struct file *filp, void *fh, struct v4l2_selection *s) + { + struct iris_inst *inst = iris_get_inst(filp, NULL); +@@ -361,6 +369,7 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops = { + .vidioc_g_fmt_vid_out_mplane = iris_g_fmt_vid_mplane, + .vidioc_enum_framesizes = iris_enum_framesizes, + .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, ++ .vidioc_querycap = iris_querycap, + .vidioc_g_selection = iris_g_selection, + .vidioc_subscribe_event = iris_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, +-- +2.34.1 + diff --git a/patch/kernel/archive/sm8550-6.12/0016_media--iris--implement-vb2-streaming-ops.patch b/patch/kernel/archive/sm8550-6.12/0016_media--iris--implement-vb2-streaming-ops.patch new file mode 100644 index 000000000..3875375cb --- /dev/null +++ b/patch/kernel/archive/sm8550-6.12/0016_media--iris--implement-vb2-streaming-ops.patch @@ -0,0 +1,1083 @@ +From 5d1672570ca7a2f494c5d0b280242a992fd3eac4 Mon Sep 17 00:00:00 2001 +From: Dikshita Agarwal +Date: Fri, 7 Feb 2025 13:24:56 +0530 +Subject: [PATCH] media: iris: implement vb2 streaming ops + +During the stream on operation, send HFI_CMD_START on the capture and +output planes to start processing on the respective planes. + +During the stream off operation, send HFI_CMD_STOP to the firmware, +which is a synchronous command. After the response is received by the +firmware, the session is closed on the firmware. + +Introduce different states for the instance and state transitions. + +IRIS_INST_INIT - video instance is opened. +IRIS_INST_INPUT_STREAMING - stream on is completed on output plane. +IRIS_INST_OUTPUT_STREAMING - stream on is completed on capture plane. +IRIS_INST_STREAMING - stream on is completed on both output and capture +planes. +IRIS_INST_DEINIT - video instance is closed. +IRIS_INST_ERROR - error state. + + | + v + ------------- + +---------| INIT |--------- + + | ------------- | + | ^ ^ | + | / \ | + | / \ | + | v v | + | ----------- ----------- | + | | INPUT OUTPUT | | + |---| STREAMING STREAMING |---| + | ----------- ----------- | + | ^ ^ | + | \ / | + | \ / | + | v v | + | ------------- | + |--------| STREAMING |-----------| + | ------------- | + | | | + | | | + | v | + | ----------- | + +-------->| DEINIT |<----------+ + | ----------- | + | | | + | | | + | v | + | ---------- | + +-------->| ERROR |<-----------+ + ----------. + +Reviewed-by: Hans Verkuil +Tested-by: Stefan Schmidt # x1e80100 (Dell XPS 13 9345) +Reviewed-by: Stefan Schmidt +Tested-by: Neil Armstrong # on SM8550-QRD +Tested-by: Neil Armstrong # on SM8550-HDK +Signed-off-by: Dikshita Agarwal +Link: https://lore.kernel.org/r/20250207-qcom-video-iris-v10-16-ab66eeffbd20@quicinc.com +Signed-off-by: Neil Armstrong +--- + drivers/media/platform/qcom/iris/Makefile | 1 + + .../platform/qcom/iris/iris_hfi_common.h | 2 + + .../qcom/iris/iris_hfi_gen1_command.c | 82 +++++++++++++- + .../qcom/iris/iris_hfi_gen1_defines.h | 24 ++++ + .../qcom/iris/iris_hfi_gen1_response.c | 39 ++++++- + .../qcom/iris/iris_hfi_gen2_command.c | 61 ++++++++++ + .../qcom/iris/iris_hfi_gen2_defines.h | 2 + + .../qcom/iris/iris_hfi_gen2_response.c | 32 +++++- + .../media/platform/qcom/iris/iris_instance.h | 4 + + drivers/media/platform/qcom/iris/iris_state.c | 104 ++++++++++++++++++ + drivers/media/platform/qcom/iris/iris_state.h | 58 ++++++++++ + drivers/media/platform/qcom/iris/iris_utils.c | 11 +- + drivers/media/platform/qcom/iris/iris_utils.h | 2 +- + drivers/media/platform/qcom/iris/iris_vb2.c | 70 ++++++++++++ + drivers/media/platform/qcom/iris/iris_vb2.h | 3 + + drivers/media/platform/qcom/iris/iris_vdec.c | 75 +++++++++++++ + drivers/media/platform/qcom/iris/iris_vdec.h | 3 + + drivers/media/platform/qcom/iris/iris_vidc.c | 12 +- + 18 files changed, 573 insertions(+), 12 deletions(-) + create mode 100644 drivers/media/platform/qcom/iris/iris_state.c + +diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile +index f685d76c2f79..ab16189aa9e6 100644 +--- a/drivers/media/platform/qcom/iris/Makefile ++++ b/drivers/media/platform/qcom/iris/Makefile +@@ -12,6 +12,7 @@ iris-objs += iris_buffer.o \ + iris_platform_sm8550.o \ + iris_probe.o \ + iris_resources.o \ ++ iris_state.o \ + iris_utils.o \ + iris_vidc.o \ + iris_vb2.o \ +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.h b/drivers/media/platform/qcom/iris/iris_hfi_common.h +index eaa2db469c74..8b1c4d156cf2 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_common.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_common.h +@@ -49,6 +49,8 @@ struct iris_hfi_command_ops { + int (*sys_interframe_powercollapse)(struct iris_core *core); + int (*sys_pc_prep)(struct iris_core *core); + int (*session_open)(struct iris_inst *inst); ++ int (*session_start)(struct iris_inst *inst, u32 plane); ++ int (*session_stop)(struct iris_inst *inst, u32 plane); + int (*session_close)(struct iris_inst *inst); + }; + +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +index 7ee69c5223ce..a3b09e8d1f49 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +@@ -71,6 +71,9 @@ static int iris_hfi_gen1_session_open(struct iris_inst *inst) + struct hfi_session_open_pkt packet; + int ret; + ++ if (inst->state != IRIS_INST_DEINIT) ++ return -EALREADY; ++ + packet.shdr.hdr.size = sizeof(struct hfi_session_open_pkt); + packet.shdr.hdr.pkt_type = HFI_CMD_SYS_SESSION_INIT; + packet.shdr.session_id = inst->session_id; +@@ -83,7 +86,7 @@ static int iris_hfi_gen1_session_open(struct iris_inst *inst) + if (ret) + return ret; + +- return iris_wait_for_session_response(inst); ++ return iris_wait_for_session_response(inst, false); + } + + static void iris_hfi_gen1_packet_session_cmd(struct iris_inst *inst, +@@ -104,12 +107,89 @@ static int iris_hfi_gen1_session_close(struct iris_inst *inst) + return iris_hfi_queue_cmd_write(inst->core, &packet, packet.shdr.hdr.size); + } + ++static int iris_hfi_gen1_session_start(struct iris_inst *inst, u32 plane) ++{ ++ struct iris_core *core = inst->core; ++ struct hfi_session_pkt packet; ++ int ret; ++ ++ if (!V4L2_TYPE_IS_OUTPUT(plane)) ++ return 0; ++ ++ reinit_completion(&inst->completion); ++ iris_hfi_gen1_packet_session_cmd(inst, &packet, HFI_CMD_SESSION_LOAD_RESOURCES); ++ ++ ret = iris_hfi_queue_cmd_write(core, &packet, packet.shdr.hdr.size); ++ if (ret) ++ return ret; ++ ++ ret = iris_wait_for_session_response(inst, false); ++ if (ret) ++ return ret; ++ ++ reinit_completion(&inst->completion); ++ iris_hfi_gen1_packet_session_cmd(inst, &packet, HFI_CMD_SESSION_START); ++ ++ ret = iris_hfi_queue_cmd_write(core, &packet, packet.shdr.hdr.size); ++ if (ret) ++ return ret; ++ ++ return iris_wait_for_session_response(inst, false); ++} ++ ++static int iris_hfi_gen1_session_stop(struct iris_inst *inst, u32 plane) ++{ ++ struct hfi_session_flush_pkt flush_pkt; ++ struct iris_core *core = inst->core; ++ struct hfi_session_pkt pkt; ++ u32 flush_type = 0; ++ int ret = 0; ++ ++ if ((V4L2_TYPE_IS_OUTPUT(plane) && ++ inst->state == IRIS_INST_INPUT_STREAMING) || ++ (V4L2_TYPE_IS_CAPTURE(plane) && ++ inst->state == IRIS_INST_OUTPUT_STREAMING) || ++ inst->state == IRIS_INST_ERROR) { ++ reinit_completion(&inst->completion); ++ iris_hfi_gen1_packet_session_cmd(inst, &pkt, HFI_CMD_SESSION_STOP); ++ ret = iris_hfi_queue_cmd_write(core, &pkt, pkt.shdr.hdr.size); ++ if (!ret) ++ ret = iris_wait_for_session_response(inst, false); ++ ++ reinit_completion(&inst->completion); ++ iris_hfi_gen1_packet_session_cmd(inst, &pkt, HFI_CMD_SESSION_RELEASE_RESOURCES); ++ ret = iris_hfi_queue_cmd_write(core, &pkt, pkt.shdr.hdr.size); ++ if (!ret) ++ ret = iris_wait_for_session_response(inst, false); ++ } else if (inst->state == IRIS_INST_STREAMING) { ++ if (V4L2_TYPE_IS_OUTPUT(plane)) ++ flush_type = HFI_FLUSH_ALL; ++ else if (V4L2_TYPE_IS_CAPTURE(plane)) ++ flush_type = HFI_FLUSH_OUTPUT; ++ ++ reinit_completion(&inst->flush_completion); ++ ++ flush_pkt.shdr.hdr.size = sizeof(struct hfi_session_flush_pkt); ++ flush_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_FLUSH; ++ flush_pkt.shdr.session_id = inst->session_id; ++ flush_pkt.flush_type = flush_type; ++ ++ ret = iris_hfi_queue_cmd_write(core, &flush_pkt, flush_pkt.shdr.hdr.size); ++ if (!ret) ++ ret = iris_wait_for_session_response(inst, true); ++ } ++ ++ return ret; ++} ++ + static const struct iris_hfi_command_ops iris_hfi_gen1_command_ops = { + .sys_init = iris_hfi_gen1_sys_init, + .sys_image_version = iris_hfi_gen1_sys_image_version, + .sys_interframe_powercollapse = iris_hfi_gen1_sys_interframe_powercollapse, + .sys_pc_prep = iris_hfi_gen1_sys_pc_prep, + .session_open = iris_hfi_gen1_session_open, ++ .session_start = iris_hfi_gen1_session_start, ++ .session_stop = iris_hfi_gen1_session_stop, + .session_close = iris_hfi_gen1_session_close, + }; + +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +index 3640f8504db9..1b2bf6afc6ce 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +@@ -23,6 +23,12 @@ + #define HFI_CMD_SYS_SESSION_INIT 0x10007 + #define HFI_CMD_SYS_SESSION_END 0x10008 + ++#define HFI_CMD_SESSION_LOAD_RESOURCES 0x211001 ++#define HFI_CMD_SESSION_START 0x211002 ++#define HFI_CMD_SESSION_STOP 0x211003 ++#define HFI_CMD_SESSION_FLUSH 0x211008 ++#define HFI_CMD_SESSION_RELEASE_RESOURCES 0x21100c ++ + #define HFI_ERR_SESSION_UNSUPPORTED_SETTING 0x1008 + #define HFI_ERR_SESSION_UNSUPPORT_BUFFERTYPE 0x1010 + #define HFI_ERR_SESSION_INVALID_SCALE_FACTOR 0x1012 +@@ -31,6 +37,9 @@ + #define HFI_EVENT_SYS_ERROR 0x1 + #define HFI_EVENT_SESSION_ERROR 0x2 + ++#define HFI_FLUSH_OUTPUT 0x1000002 ++#define HFI_FLUSH_OUTPUT2 0x1000003 ++#define HFI_FLUSH_ALL 0x1000004 + #define HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL 0x5 + #define HFI_PROPERTY_SYS_IMAGE_VERSION 0x6 + +@@ -41,6 +50,11 @@ + #define HFI_MSG_SYS_PROPERTY_INFO 0x2000a + + #define HFI_MSG_EVENT_NOTIFY 0x21001 ++#define HFI_MSG_SESSION_LOAD_RESOURCES 0x221001 ++#define HFI_MSG_SESSION_START 0x221002 ++#define HFI_MSG_SESSION_STOP 0x221003 ++#define HFI_MSG_SESSION_FLUSH 0x221006 ++#define HFI_MSG_SESSION_RELEASE_RESOURCES 0x22100a + + struct hfi_pkt_hdr { + u32 size; +@@ -83,6 +97,11 @@ struct hfi_sys_pc_prep_pkt { + struct hfi_pkt_hdr hdr; + }; + ++struct hfi_session_flush_pkt { ++ struct hfi_session_hdr_pkt shdr; ++ u32 flush_type; ++}; ++ + struct hfi_msg_event_notify_pkt { + struct hfi_session_hdr_pkt shdr; + u32 event_id; +@@ -116,6 +135,11 @@ struct hfi_msg_sys_property_info_pkt { + u8 data[]; + }; + ++struct hfi_msg_session_flush_done_pkt { ++ struct hfi_msg_session_hdr_pkt shdr; ++ u32 flush_type; ++}; ++ + struct hfi_enable { + u32 enable; + }; +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c +index 18ba5f67dd36..db5858ec04ea 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c +@@ -11,6 +11,7 @@ static void + iris_hfi_gen1_sys_event_notify(struct iris_core *core, void *packet) + { + struct hfi_msg_event_notify_pkt *pkt = packet; ++ struct iris_inst *instance; + + if (pkt->event_id == HFI_EVENT_SYS_ERROR) + dev_err(core->dev, "sys error (type: %x, session id:%x, data1:%x, data2:%x)\n", +@@ -18,6 +19,12 @@ iris_hfi_gen1_sys_event_notify(struct iris_core *core, void *packet) + pkt->event_data2); + + core->state = IRIS_CORE_ERROR; ++ ++ mutex_lock(&core->lock); ++ list_for_each_entry(instance, &core->instances, list) ++ iris_inst_change_state(instance, IRIS_INST_ERROR); ++ mutex_unlock(&core->lock); ++ + schedule_delayed_work(&core->sys_error_handler, msecs_to_jiffies(10)); + } + +@@ -44,6 +51,7 @@ iris_hfi_gen1_event_session_error(struct iris_inst *inst, struct hfi_msg_event_n + pkt->event_data2, pkt->event_data1, + pkt->shdr.session_id); + iris_vb2_queue_error(inst); ++ iris_inst_change_state(inst, IRIS_INST_ERROR); + break; + } + } +@@ -148,6 +156,26 @@ static const struct iris_hfi_gen1_response_pkt_info pkt_infos[] = { + .pkt = HFI_MSG_SYS_SESSION_END, + .pkt_sz = sizeof(struct hfi_msg_session_hdr_pkt), + }, ++ { ++ .pkt = HFI_MSG_SESSION_LOAD_RESOURCES, ++ .pkt_sz = sizeof(struct hfi_msg_session_hdr_pkt), ++ }, ++ { ++ .pkt = HFI_MSG_SESSION_START, ++ .pkt_sz = sizeof(struct hfi_msg_session_hdr_pkt), ++ }, ++ { ++ .pkt = HFI_MSG_SESSION_STOP, ++ .pkt_sz = sizeof(struct hfi_msg_session_hdr_pkt), ++ }, ++ { ++ .pkt = HFI_MSG_SESSION_FLUSH, ++ .pkt_sz = sizeof(struct hfi_msg_session_flush_done_pkt), ++ }, ++ { ++ .pkt = HFI_MSG_SESSION_RELEASE_RESOURCES, ++ .pkt_sz = sizeof(struct hfi_msg_session_hdr_pkt), ++ }, + }; + + static void iris_hfi_gen1_handle_response(struct iris_core *core, void *response) +@@ -156,6 +184,7 @@ static void iris_hfi_gen1_handle_response(struct iris_core *core, void *response + const struct iris_hfi_gen1_response_pkt_info *pkt_info; + struct device *dev = core->dev; + struct hfi_session_pkt *pkt; ++ struct completion *done; + struct iris_inst *inst; + bool found = false; + u32 i; +@@ -205,7 +234,15 @@ static void iris_hfi_gen1_handle_response(struct iris_core *core, void *response + } + + mutex_lock(&inst->lock); +- complete(&inst->completion); ++ struct hfi_msg_session_hdr_pkt *shdr; ++ ++ shdr = (struct hfi_msg_session_hdr_pkt *)hdr; ++ if (shdr->error_type != HFI_ERR_NONE) ++ iris_inst_change_state(inst, IRIS_INST_ERROR); ++ ++ done = pkt_info->pkt == HFI_MSG_SESSION_FLUSH ? ++ &inst->flush_completion : &inst->completion; ++ complete(done); + mutex_unlock(&inst->lock); + + break; +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +index a08e844bb4bb..b0557917fc52 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +@@ -85,6 +85,18 @@ static int iris_hfi_gen2_sys_pc_prep(struct iris_core *core) + return ret; + } + ++static u32 iris_hfi_gen2_get_port(u32 plane) ++{ ++ switch (plane) { ++ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: ++ return HFI_PORT_BITSTREAM; ++ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: ++ return HFI_PORT_RAW; ++ default: ++ return HFI_PORT_NONE; ++ } ++} ++ + static int iris_hfi_gen2_session_set_codec(struct iris_inst *inst) + { + struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); +@@ -124,6 +136,9 @@ static int iris_hfi_gen2_session_open(struct iris_inst *inst) + struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); + int ret; + ++ if (inst->state != IRIS_INST_DEINIT) ++ return -EALREADY; ++ + inst_hfi_gen2->packet = kzalloc(4096, GFP_KERNEL); + if (!inst_hfi_gen2->packet) + return -ENOMEM; +@@ -188,12 +203,58 @@ static int iris_hfi_gen2_session_close(struct iris_inst *inst) + return ret; + } + ++static int iris_hfi_gen2_session_start(struct iris_inst *inst, u32 plane) ++{ ++ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); ++ ++ iris_hfi_gen2_packet_session_command(inst, ++ HFI_CMD_START, ++ (HFI_HOST_FLAGS_RESPONSE_REQUIRED | ++ HFI_HOST_FLAGS_INTR_REQUIRED), ++ iris_hfi_gen2_get_port(plane), ++ inst->session_id, ++ HFI_PAYLOAD_NONE, ++ NULL, ++ 0); ++ ++ return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet, ++ inst_hfi_gen2->packet->size); ++} ++ ++static int iris_hfi_gen2_session_stop(struct iris_inst *inst, u32 plane) ++{ ++ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); ++ int ret = 0; ++ ++ reinit_completion(&inst->completion); ++ ++ iris_hfi_gen2_packet_session_command(inst, ++ HFI_CMD_STOP, ++ (HFI_HOST_FLAGS_RESPONSE_REQUIRED | ++ HFI_HOST_FLAGS_INTR_REQUIRED | ++ HFI_HOST_FLAGS_NON_DISCARDABLE), ++ iris_hfi_gen2_get_port(plane), ++ inst->session_id, ++ HFI_PAYLOAD_NONE, ++ NULL, ++ 0); ++ ++ ret = iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet, ++ inst_hfi_gen2->packet->size); ++ if (ret) ++ return ret; ++ ++ return iris_wait_for_session_response(inst, false); ++} ++ + static const struct iris_hfi_command_ops iris_hfi_gen2_command_ops = { + .sys_init = iris_hfi_gen2_sys_init, + .sys_image_version = iris_hfi_gen2_sys_image_version, + .sys_interframe_powercollapse = iris_hfi_gen2_sys_interframe_powercollapse, + .sys_pc_prep = iris_hfi_gen2_sys_pc_prep, + .session_open = iris_hfi_gen2_session_open, ++ .session_start = iris_hfi_gen2_session_start, ++ .session_stop = iris_hfi_gen2_session_stop, + .session_close = iris_hfi_gen2_session_close, + }; + +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +index 173a554a0d44..930dbae49dfa 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +@@ -15,6 +15,8 @@ + #define HFI_CMD_POWER_COLLAPSE 0x01000002 + #define HFI_CMD_OPEN 0x01000003 + #define HFI_CMD_CLOSE 0x01000004 ++#define HFI_CMD_START 0x01000005 ++#define HFI_CMD_STOP 0x01000006 + #define HFI_CMD_END 0x01FFFFFF + + #define HFI_PROP_BEGIN 0x03000000 +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c +index e1c43daea6c7..53b700ef852e 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c +@@ -101,6 +101,7 @@ static int iris_hfi_gen2_handle_session_error(struct iris_inst *inst, + + dev_err(core->dev, "session error received %#x: %s\n", pkt->type, error); + iris_vb2_queue_error(inst); ++ iris_inst_change_state(inst, IRIS_INST_ERROR); + + return 0; + } +@@ -108,9 +109,17 @@ static int iris_hfi_gen2_handle_session_error(struct iris_inst *inst, + static int iris_hfi_gen2_handle_system_error(struct iris_core *core, + struct iris_hfi_packet *pkt) + { ++ struct iris_inst *instance; ++ + dev_err(core->dev, "received system error of type %#x\n", pkt->type); + + core->state = IRIS_CORE_ERROR; ++ ++ mutex_lock(&core->lock); ++ list_for_each_entry(instance, &core->instances, list) ++ iris_inst_change_state(instance, IRIS_INST_ERROR); ++ mutex_unlock(&core->lock); ++ + schedule_delayed_work(&core->sys_error_handler, msecs_to_jiffies(10)); + + return 0; +@@ -129,20 +138,32 @@ static int iris_hfi_gen2_handle_system_init(struct iris_core *core, + return 0; + } + ++static void iris_hfi_gen2_handle_session_close(struct iris_inst *inst, ++ struct iris_hfi_packet *pkt) ++{ ++ if (!(pkt->flags & HFI_FW_FLAGS_SUCCESS)) { ++ iris_inst_change_state(inst, IRIS_INST_ERROR); ++ return; ++ } ++ ++ complete(&inst->completion); ++} ++ + static int iris_hfi_gen2_handle_session_command(struct iris_inst *inst, + struct iris_hfi_packet *pkt) + { +- int ret = 0; +- + switch (pkt->type) { + case HFI_CMD_CLOSE: ++ iris_hfi_gen2_handle_session_close(inst, pkt); ++ break; ++ case HFI_CMD_STOP: + complete(&inst->completion); + break; + default: + break; + } + +- return ret; ++ return 0; + } + + static int iris_hfi_gen2_handle_image_version_property(struct iris_core *core, +@@ -247,8 +268,11 @@ static int iris_hfi_gen2_handle_session_response(struct iris_core *core, + if (packet->flags & HFI_FW_FLAGS_SESSION_ERROR) + iris_hfi_gen2_handle_session_error(inst, packet); + +- if (packet->type > range[i].begin && packet->type < range[i].end) ++ if (packet->type > range[i].begin && packet->type < range[i].end) { + ret = range[i].handle(inst, packet); ++ if (ret) ++ iris_inst_change_state(inst, IRIS_INST_ERROR); ++ } + pkt += packet->size; + } + } +diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/drivers/media/platform/qcom/iris/iris_instance.h +index 9f1a1e5ba7c7..6b88daf31011 100644 +--- a/drivers/media/platform/qcom/iris/iris_instance.h ++++ b/drivers/media/platform/qcom/iris/iris_instance.h +@@ -26,9 +26,11 @@ + * @ctrl_handler: reference of v4l2 ctrl handler + * @crop: structure of crop info + * @completion: structure of signal completions ++ * @flush_completion: structure of signal completions for flush cmd + * @fw_caps: array of supported instance firmware capabilities + * @buffers: array of different iris buffers + * @fw_min_count: minimnum count of buffers needed by fw ++ * @state: instance state + * @once_per_session_set: boolean to set once per session property + * @m2m_dev: a reference to m2m device structure + * @m2m_ctx: a reference to m2m context structure +@@ -46,9 +48,11 @@ struct iris_inst { + struct v4l2_ctrl_handler ctrl_handler; + struct iris_hfi_rect_desc crop; + struct completion completion; ++ struct completion flush_completion; + struct platform_inst_fw_cap fw_caps[INST_FW_CAP_MAX]; + struct iris_buffers buffers[BUF_TYPE_MAX]; + u32 fw_min_count; ++ enum iris_inst_state state; + bool once_per_session_set; + struct v4l2_m2m_dev *m2m_dev; + struct v4l2_m2m_ctx *m2m_ctx; +diff --git a/drivers/media/platform/qcom/iris/iris_state.c b/drivers/media/platform/qcom/iris/iris_state.c +new file mode 100644 +index 000000000000..44362e8fe18f +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_state.c +@@ -0,0 +1,104 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include "iris_instance.h" ++ ++static bool iris_allow_inst_state_change(struct iris_inst *inst, ++ enum iris_inst_state req_state) ++{ ++ switch (inst->state) { ++ case IRIS_INST_INIT: ++ if (req_state == IRIS_INST_INPUT_STREAMING || ++ req_state == IRIS_INST_OUTPUT_STREAMING || ++ req_state == IRIS_INST_DEINIT) ++ return true; ++ return false; ++ case IRIS_INST_INPUT_STREAMING: ++ if (req_state == IRIS_INST_INIT || ++ req_state == IRIS_INST_STREAMING || ++ req_state == IRIS_INST_DEINIT) ++ return true; ++ return false; ++ case IRIS_INST_OUTPUT_STREAMING: ++ if (req_state == IRIS_INST_INIT || ++ req_state == IRIS_INST_STREAMING || ++ req_state == IRIS_INST_DEINIT) ++ return true; ++ return false; ++ case IRIS_INST_STREAMING: ++ if (req_state == IRIS_INST_INPUT_STREAMING || ++ req_state == IRIS_INST_OUTPUT_STREAMING || ++ req_state == IRIS_INST_DEINIT) ++ return true; ++ return false; ++ case IRIS_INST_DEINIT: ++ if (req_state == IRIS_INST_INIT) ++ return true; ++ return false; ++ default: ++ return false; ++ } ++} ++ ++int iris_inst_change_state(struct iris_inst *inst, ++ enum iris_inst_state request_state) ++{ ++ if (inst->state == IRIS_INST_ERROR) ++ return 0; ++ ++ if (inst->state == request_state) ++ return 0; ++ ++ if (request_state == IRIS_INST_ERROR) ++ goto change_state; ++ ++ if (!iris_allow_inst_state_change(inst, request_state)) ++ return -EINVAL; ++ ++change_state: ++ inst->state = request_state; ++ dev_dbg(inst->core->dev, "state changed from %x to %x\n", ++ inst->state, request_state); ++ ++ return 0; ++} ++ ++int iris_inst_state_change_streamon(struct iris_inst *inst, u32 plane) ++{ ++ enum iris_inst_state new_state = IRIS_INST_ERROR; ++ ++ if (V4L2_TYPE_IS_OUTPUT(plane)) { ++ if (inst->state == IRIS_INST_INIT) ++ new_state = IRIS_INST_INPUT_STREAMING; ++ else if (inst->state == IRIS_INST_OUTPUT_STREAMING) ++ new_state = IRIS_INST_STREAMING; ++ } else if (V4L2_TYPE_IS_CAPTURE(plane)) { ++ if (inst->state == IRIS_INST_INIT) ++ new_state = IRIS_INST_OUTPUT_STREAMING; ++ else if (inst->state == IRIS_INST_INPUT_STREAMING) ++ new_state = IRIS_INST_STREAMING; ++ } ++ ++ return iris_inst_change_state(inst, new_state); ++} ++ ++int iris_inst_state_change_streamoff(struct iris_inst *inst, u32 plane) ++{ ++ enum iris_inst_state new_state = IRIS_INST_ERROR; ++ ++ if (V4L2_TYPE_IS_OUTPUT(plane)) { ++ if (inst->state == IRIS_INST_INPUT_STREAMING) ++ new_state = IRIS_INST_INIT; ++ else if (inst->state == IRIS_INST_STREAMING) ++ new_state = IRIS_INST_OUTPUT_STREAMING; ++ } else if (V4L2_TYPE_IS_CAPTURE(plane)) { ++ if (inst->state == IRIS_INST_OUTPUT_STREAMING) ++ new_state = IRIS_INST_INIT; ++ else if (inst->state == IRIS_INST_STREAMING) ++ new_state = IRIS_INST_INPUT_STREAMING; ++ } ++ ++ return iris_inst_change_state(inst, new_state); ++} +diff --git a/drivers/media/platform/qcom/iris/iris_state.h b/drivers/media/platform/qcom/iris/iris_state.h +index 1ffe6fe706bd..0bf9d0e063ac 100644 +--- a/drivers/media/platform/qcom/iris/iris_state.h ++++ b/drivers/media/platform/qcom/iris/iris_state.h +@@ -6,6 +6,8 @@ + #ifndef __IRIS_STATE_H__ + #define __IRIS_STATE_H__ + ++struct iris_inst; ++ + /** + * enum iris_core_state + * +@@ -38,4 +40,60 @@ enum iris_core_state { + IRIS_CORE_ERROR, + }; + ++/** ++ * enum iris_inst_state ++ * ++ * @IRIS_INST_INIT: video instance is opened. ++ * @IRIS_INST_INPUT_STREAMING: stream on is completed on output plane. ++ * @IRIS_INST_OUTPUT_STREAMING: stream on is completed on capture plane. ++ * @IRIS_INST_STREAMING: stream on is completed on both output and capture planes. ++ * @IRIS_INST_DEINIT: video instance is closed. ++ * @IRIS_INST_ERROR: error state. ++ * | ++ * V ++ * ------------- ++ * +--------| INIT |----------+ ++ * | ------------- | ++ * | ^ ^ | ++ * | / \ | ++ * | / \ | ++ * | v v | ++ * | ----------- ----------- | ++ * | | INPUT OUTPUT | | ++ * |---| STREAMING STREAMING |---| ++ * | ----------- ----------- | ++ * | ^ ^ | ++ * | \ / | ++ * | \ / | ++ * | v v | ++ * | ------------- | ++ * |--------| STREAMING |-----------| ++ * | ------------- | ++ * | | | ++ * | | | ++ * | v | ++ * | ----------- | ++ * +-------->| DEINIT |<----------+ ++ * | ----------- | ++ * | | | ++ * | | | ++ * | v | ++ * | ---------- | ++ * +-------->| ERROR |<------------+ ++ * ---------- ++ */ ++enum iris_inst_state { ++ IRIS_INST_DEINIT, ++ IRIS_INST_INIT, ++ IRIS_INST_INPUT_STREAMING, ++ IRIS_INST_OUTPUT_STREAMING, ++ IRIS_INST_STREAMING, ++ IRIS_INST_ERROR, ++}; ++ ++int iris_inst_change_state(struct iris_inst *inst, ++ enum iris_inst_state request_state); ++int iris_inst_state_change_streamon(struct iris_inst *inst, u32 plane); ++int iris_inst_state_change_streamoff(struct iris_inst *inst, u32 plane); ++ + #endif +diff --git a/drivers/media/platform/qcom/iris/iris_utils.c b/drivers/media/platform/qcom/iris/iris_utils.c +index d5c8e052922c..4833830f30d5 100644 +--- a/drivers/media/platform/qcom/iris/iris_utils.c ++++ b/drivers/media/platform/qcom/iris/iris_utils.c +@@ -17,20 +17,23 @@ int iris_get_mbpf(struct iris_inst *inst) + return NUM_MBS_PER_FRAME(height, width); + } + +-int iris_wait_for_session_response(struct iris_inst *inst) ++int iris_wait_for_session_response(struct iris_inst *inst, bool is_flush) + { + struct iris_core *core = inst->core; + u32 hw_response_timeout_val; ++ struct completion *done; + int ret; + + hw_response_timeout_val = core->iris_platform_data->hw_response_timeout; ++ done = is_flush ? &inst->flush_completion : &inst->completion; + + mutex_unlock(&inst->lock); +- ret = wait_for_completion_timeout(&inst->completion, +- msecs_to_jiffies(hw_response_timeout_val)); ++ ret = wait_for_completion_timeout(done, msecs_to_jiffies(hw_response_timeout_val)); + mutex_lock(&inst->lock); +- if (!ret) ++ if (!ret) { ++ iris_inst_change_state(inst, IRIS_INST_ERROR); + return -ETIMEDOUT; ++ } + + return 0; + } +diff --git a/drivers/media/platform/qcom/iris/iris_utils.h b/drivers/media/platform/qcom/iris/iris_utils.h +index 26649b66d978..40658a6643cf 100644 +--- a/drivers/media/platform/qcom/iris/iris_utils.h ++++ b/drivers/media/platform/qcom/iris/iris_utils.h +@@ -29,6 +29,6 @@ static inline enum iris_buffer_type iris_v4l2_type_to_driver(u32 type) + + int iris_get_mbpf(struct iris_inst *inst); + struct iris_inst *iris_get_instance(struct iris_core *core, u32 session_id); +-int iris_wait_for_session_response(struct iris_inst *inst); ++int iris_wait_for_session_response(struct iris_inst *inst, bool is_flush); + + #endif +diff --git a/drivers/media/platform/qcom/iris/iris_vb2.c b/drivers/media/platform/qcom/iris/iris_vb2.c +index e9db44515d91..b93da860d336 100644 +--- a/drivers/media/platform/qcom/iris/iris_vb2.c ++++ b/drivers/media/platform/qcom/iris/iris_vb2.c +@@ -5,6 +5,7 @@ + + #include "iris_instance.h" + #include "iris_vb2.h" ++#include "iris_vdec.h" + + int iris_vb2_queue_setup(struct vb2_queue *q, + unsigned int *num_buffers, unsigned int *num_planes, +@@ -18,6 +19,10 @@ int iris_vb2_queue_setup(struct vb2_queue *q, + inst = vb2_get_drv_priv(q); + + mutex_lock(&inst->lock); ++ if (inst->state == IRIS_INST_ERROR) { ++ ret = -EBUSY; ++ goto unlock; ++ } + + core = inst->core; + f = V4L2_TYPE_IS_OUTPUT(q->type) ? inst->fmt_src : inst->fmt_dst; +@@ -38,6 +43,10 @@ int iris_vb2_queue_setup(struct vb2_queue *q, + dev_err(core->dev, "session open failed\n"); + goto unlock; + } ++ ++ ret = iris_inst_change_state(inst, IRIS_INST_INIT); ++ if (ret) ++ goto unlock; + } + + *num_planes = 1; +@@ -48,3 +57,64 @@ int iris_vb2_queue_setup(struct vb2_queue *q, + + return ret; + } ++ ++int iris_vb2_start_streaming(struct vb2_queue *q, unsigned int count) ++{ ++ struct iris_inst *inst; ++ int ret = 0; ++ ++ inst = vb2_get_drv_priv(q); ++ ++ if (V4L2_TYPE_IS_CAPTURE(q->type) && inst->state == IRIS_INST_INIT) ++ return 0; ++ ++ mutex_lock(&inst->lock); ++ if (inst->state == IRIS_INST_ERROR) { ++ ret = -EBUSY; ++ goto error; ++ } ++ ++ if (!V4L2_TYPE_IS_OUTPUT(q->type) && ++ !V4L2_TYPE_IS_CAPTURE(q->type)) { ++ ret = -EINVAL; ++ goto error; ++ } ++ ++ if (V4L2_TYPE_IS_OUTPUT(q->type)) ++ ret = iris_vdec_streamon_input(inst); ++ else if (V4L2_TYPE_IS_CAPTURE(q->type)) ++ ret = iris_vdec_streamon_output(inst); ++ if (ret) ++ goto error; ++ ++ mutex_unlock(&inst->lock); ++ ++ return ret; ++ ++error: ++ iris_inst_change_state(inst, IRIS_INST_ERROR); ++ mutex_unlock(&inst->lock); ++ ++ return ret; ++} ++ ++void iris_vb2_stop_streaming(struct vb2_queue *q) ++{ ++ struct iris_inst *inst; ++ ++ inst = vb2_get_drv_priv(q); ++ ++ if (V4L2_TYPE_IS_CAPTURE(q->type) && inst->state == IRIS_INST_INIT) ++ return; ++ ++ mutex_lock(&inst->lock); ++ ++ if (!V4L2_TYPE_IS_OUTPUT(q->type) && ++ !V4L2_TYPE_IS_CAPTURE(q->type)) ++ goto exit; ++ ++ iris_vdec_session_streamoff(inst, q->type); ++ ++exit: ++ mutex_unlock(&inst->lock); ++} +diff --git a/drivers/media/platform/qcom/iris/iris_vb2.h b/drivers/media/platform/qcom/iris/iris_vb2.h +index d2e71d0596cc..3906510fa71f 100644 +--- a/drivers/media/platform/qcom/iris/iris_vb2.h ++++ b/drivers/media/platform/qcom/iris/iris_vb2.h +@@ -9,4 +9,7 @@ + int iris_vb2_queue_setup(struct vb2_queue *q, + unsigned int *num_buffers, unsigned int *num_planes, + unsigned int sizes[], struct device *alloc_devs[]); ++int iris_vb2_start_streaming(struct vb2_queue *q, unsigned int count); ++void iris_vb2_stop_streaming(struct vb2_queue *q); ++ + #endif +diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c +index 132b578b34dc..92651d86376d 100644 +--- a/drivers/media/platform/qcom/iris/iris_vdec.c ++++ b/drivers/media/platform/qcom/iris/iris_vdec.c +@@ -222,3 +222,78 @@ int iris_vdec_subscribe_event(struct iris_inst *inst, const struct v4l2_event_su + + return ret; + } ++ ++static void iris_vdec_kill_session(struct iris_inst *inst) ++{ ++ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; ++ ++ if (!inst->session_id) ++ return; ++ ++ hfi_ops->session_close(inst); ++ iris_inst_change_state(inst, IRIS_INST_ERROR); ++} ++ ++void iris_vdec_session_streamoff(struct iris_inst *inst, u32 plane) ++{ ++ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; ++ int ret; ++ ++ ret = hfi_ops->session_stop(inst, plane); ++ if (ret) ++ goto error; ++ ++ ret = iris_inst_state_change_streamoff(inst, plane); ++ if (ret) ++ goto error; ++ ++ return; ++ ++error: ++ iris_vdec_kill_session(inst); ++} ++ ++static int iris_vdec_process_streamon_input(struct iris_inst *inst) ++{ ++ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; ++ int ret; ++ ++ ret = hfi_ops->session_start(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); ++ if (ret) ++ return ret; ++ ++ return iris_inst_state_change_streamon(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); ++} ++ ++int iris_vdec_streamon_input(struct iris_inst *inst) ++{ ++ return iris_vdec_process_streamon_input(inst); ++} ++ ++static int iris_vdec_process_streamon_output(struct iris_inst *inst) ++{ ++ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; ++ int ret; ++ ++ ret = hfi_ops->session_start(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); ++ if (ret) ++ return ret; ++ ++ return iris_inst_state_change_streamon(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); ++} ++ ++int iris_vdec_streamon_output(struct iris_inst *inst) ++{ ++ int ret; ++ ++ ret = iris_vdec_process_streamon_output(inst); ++ if (ret) ++ goto error; ++ ++ return ret; ++ ++error: ++ iris_vdec_session_streamoff(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); ++ ++ return ret; ++} +diff --git a/drivers/media/platform/qcom/iris/iris_vdec.h b/drivers/media/platform/qcom/iris/iris_vdec.h +index 9f08a13cb6bb..a17bb817b6e5 100644 +--- a/drivers/media/platform/qcom/iris/iris_vdec.h ++++ b/drivers/media/platform/qcom/iris/iris_vdec.h +@@ -14,5 +14,8 @@ int iris_vdec_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f); + int iris_vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f); + int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f); + int iris_vdec_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub); ++int iris_vdec_streamon_input(struct iris_inst *inst); ++int iris_vdec_streamon_output(struct iris_inst *inst); ++void iris_vdec_session_streamoff(struct iris_inst *inst, u32 plane); + + #endif +diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c +index 5b54231f2def..1d10c430c795 100644 +--- a/drivers/media/platform/qcom/iris/iris_vidc.c ++++ b/drivers/media/platform/qcom/iris/iris_vidc.c +@@ -145,10 +145,12 @@ int iris_open(struct file *filp) + + inst->core = core; + inst->session_id = hash32_ptr(inst); ++ inst->state = IRIS_INST_DEINIT; + + mutex_init(&inst->lock); + mutex_init(&inst->ctx_q_lock); + init_completion(&inst->completion); ++ init_completion(&inst->flush_completion); + + iris_v4l2_fh_init(inst); + +@@ -194,6 +196,9 @@ static void iris_session_close(struct iris_inst *inst) + bool wait_for_response = true; + int ret; + ++ if (inst->state == IRIS_INST_DEINIT) ++ return; ++ + reinit_completion(&inst->completion); + + ret = hfi_ops->session_close(inst); +@@ -201,7 +206,7 @@ static void iris_session_close(struct iris_inst *inst) + wait_for_response = false; + + if (wait_for_response) +- iris_wait_for_session_response(inst); ++ iris_wait_for_session_response(inst, false); + } + + int iris_close(struct file *filp) +@@ -214,6 +219,7 @@ int iris_close(struct file *filp) + mutex_lock(&inst->lock); + iris_vdec_inst_deinit(inst); + iris_session_close(inst); ++ iris_inst_change_state(inst, IRIS_INST_DEINIT); + iris_v4l2_fh_deinit(inst); + iris_remove_session(inst); + mutex_unlock(&inst->lock); +@@ -356,6 +362,8 @@ static struct v4l2_file_operations iris_v4l2_file_ops = { + + static const struct vb2_ops iris_vb2_ops = { + .queue_setup = iris_vb2_queue_setup, ++ .start_streaming = iris_vb2_start_streaming, ++ .stop_streaming = iris_vb2_stop_streaming, + }; + + static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops = { +@@ -373,6 +381,8 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops = { + .vidioc_g_selection = iris_g_selection, + .vidioc_subscribe_event = iris_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, ++ .vidioc_streamon = v4l2_m2m_ioctl_streamon, ++ .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, + }; + + void iris_init_ops(struct iris_core *core) +-- +2.34.1 + diff --git a/patch/kernel/archive/sm8550-6.12/0017_media--iris--implement-set-properties-to-firmware-.patch b/patch/kernel/archive/sm8550-6.12/0017_media--iris--implement-set-properties-to-firmware-.patch new file mode 100644 index 000000000..f086ab64e --- /dev/null +++ b/patch/kernel/archive/sm8550-6.12/0017_media--iris--implement-set-properties-to-firmware-.patch @@ -0,0 +1,1863 @@ +From f2eb2b24a358631afbe6f8d0909e1d64ddb1eb48 Mon Sep 17 00:00:00 2001 +From: Vedang Nagar +Date: Fri, 7 Feb 2025 13:24:57 +0530 +Subject: [PATCH] media: iris: implement set properties to firmware during + streamon + +During the stream on operation, set some mandatory properties on the +firmware to start a session. Set all v4l2 properties, which are set by +the client, on to firmware, which is prepared with the dependency graph. + +Signed-off-by: Vedang Nagar +Tested-by: Stefan Schmidt # x1e80100 (Dell XPS 13 9345) +Reviewed-by: Stefan Schmidt +Tested-by: Neil Armstrong # on SM8550-QRD +Tested-by: Neil Armstrong # on SM8550-HDK +Signed-off-by: Dikshita Agarwal +Link: https://lore.kernel.org/r/20250207-qcom-video-iris-v10-17-ab66eeffbd20@quicinc.com +Signed-off-by: Neil Armstrong +--- + .../media/platform/qcom/iris/iris_buffer.c | 121 ++++++ + drivers/media/platform/qcom/iris/iris_ctrls.c | 94 ++++ + drivers/media/platform/qcom/iris/iris_ctrls.h | 5 + + .../platform/qcom/iris/iris_hfi_common.h | 76 ++++ + .../qcom/iris/iris_hfi_gen1_command.c | 411 ++++++++++++++++++ + .../qcom/iris/iris_hfi_gen1_defines.h | 83 ++++ + .../media/platform/qcom/iris/iris_hfi_gen2.h | 2 + + .../qcom/iris/iris_hfi_gen2_command.c | 300 +++++++++++++ + .../qcom/iris/iris_hfi_gen2_defines.h | 27 ++ + .../platform/qcom/iris/iris_hfi_gen2_packet.c | 79 ++++ + .../platform/qcom/iris/iris_hfi_gen2_packet.h | 7 + + .../qcom/iris/iris_hfi_gen2_response.c | 49 +++ + .../platform/qcom/iris/iris_platform_common.h | 32 ++ + .../platform/qcom/iris/iris_platform_sm8550.c | 89 ++++ + drivers/media/platform/qcom/iris/iris_utils.c | 19 + + drivers/media/platform/qcom/iris/iris_utils.h | 3 + + drivers/media/platform/qcom/iris/iris_vdec.c | 11 + + .../platform/qcom/iris/iris_vpu_buffer.c | 20 + + .../platform/qcom/iris/iris_vpu_buffer.h | 1 + + 19 files changed, 1429 insertions(+) + +diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c +index 037931ce6550..58d45d23393b 100644 +--- a/drivers/media/platform/qcom/iris/iris_buffer.c ++++ b/drivers/media/platform/qcom/iris/iris_buffer.c +@@ -72,6 +72,125 @@ static u32 iris_yuv_buffer_size_nv12(struct iris_inst *inst) + return ALIGN(y_plane + uv_plane, PIXELS_4K); + } + ++/* ++ * QC08C: ++ * Compressed Macro-tile format for NV12. ++ * Contains 4 planes in the following order - ++ * (A) Y_Meta_Plane ++ * (B) Y_UBWC_Plane ++ * (C) UV_Meta_Plane ++ * (D) UV_UBWC_Plane ++ * ++ * Y_Meta_Plane consists of meta information to decode compressed ++ * tile data in Y_UBWC_Plane. ++ * Y_UBWC_Plane consists of Y data in compressed macro-tile format. ++ * UBWC decoder block will use the Y_Meta_Plane data together with ++ * Y_UBWC_Plane data to produce loss-less uncompressed 8 bit Y samples. ++ * ++ * UV_Meta_Plane consists of meta information to decode compressed ++ * tile data in UV_UBWC_Plane. ++ * UV_UBWC_Plane consists of UV data in compressed macro-tile format. ++ * UBWC decoder block will use UV_Meta_Plane data together with ++ * UV_UBWC_Plane data to produce loss-less uncompressed 8 bit 2x2 ++ * subsampled color difference samples. ++ * ++ * Each tile in Y_UBWC_Plane/UV_UBWC_Plane is independently decodable ++ * and randomly accessible. There is no dependency between tiles. ++ * ++ * <----- y_meta_stride ----> (aligned to 64) ++ * <-------- Width ------> ++ * M M M M M M M M M M M M . . ^ ^ ++ * M M M M M M M M M M M M . . | | ++ * M M M M M M M M M M M M . . Height | ++ * M M M M M M M M M M M M . . | y_meta_scanlines (aligned to 16) ++ * M M M M M M M M M M M M . . | | ++ * M M M M M M M M M M M M . . | | ++ * M M M M M M M M M M M M . . | | ++ * M M M M M M M M M M M M . . V | ++ * . . . . . . . . . . . . . . | ++ * . . . . . . . . . . . . . . | ++ * . . . . . . . . . . . . . . -------> Buffer size aligned to 4k ++ * . . . . . . . . . . . . . . V ++ * <--Compressed tile y_stride---> (aligned to 128) ++ * <------- Width -------> ++ * Y* Y* Y* Y* Y* Y* Y* Y* . . . . ^ ^ ++ * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | | ++ * Y* Y* Y* Y* Y* Y* Y* Y* . . . . Height | ++ * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | Macro_tile y_scanlines (aligned to 32) ++ * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | | ++ * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | | ++ * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | | ++ * Y* Y* Y* Y* Y* Y* Y* Y* . . . . V | ++ * . . . . . . . . . . . . . . . . | ++ * . . . . . . . . . . . . . . . . | ++ * . . . . . . . . . . . . . . . . -------> Buffer size aligned to 4k ++ * . . . . . . . . . . . . . . . . V ++ * <----- uv_meta_stride ----> (aligned to 64) ++ * M M M M M M M M M M M M . . ^ ++ * M M M M M M M M M M M M . . | ++ * M M M M M M M M M M M M . . | ++ * M M M M M M M M M M M M . . uv_meta_scanlines (aligned to 16) ++ * . . . . . . . . . . . . . . | ++ * . . . . . . . . . . . . . . V ++ * . . . . . . . . . . . . . . -------> Buffer size aligned to 4k ++ * <--Compressed tile uv_stride---> (aligned to 128) ++ * U* V* U* V* U* V* U* V* . . . . ^ ++ * U* V* U* V* U* V* U* V* . . . . | ++ * U* V* U* V* U* V* U* V* . . . . | ++ * U* V* U* V* U* V* U* V* . . . . uv_scanlines (aligned to 32) ++ * . . . . . . . . . . . . . . . . | ++ * . . . . . . . . . . . . . . . . V ++ * . . . . . . . . . . . . . . . . -------> Buffer size aligned to 4k ++ * ++ * y_stride: width aligned to 128 ++ * uv_stride: width aligned to 128 ++ * y_scanlines: height aligned to 32 ++ * uv_scanlines: height aligned to 32 ++ * y_plane: buffer size aligned to 4096 ++ * uv_plane: buffer size aligned to 4096 ++ * y_meta_stride: width aligned to 64 ++ * y_meta_scanlines: height aligned to 16 ++ * y_meta_plane: buffer size aligned to 4096 ++ * uv_meta_stride: width aligned to 64 ++ * uv_meta_scanlines: height aligned to 16 ++ * uv_meta_plane: buffer size aligned to 4096 ++ * ++ * Total size = align( y_plane + uv_plane + ++ * y_meta_plane + uv_meta_plane, 4096) ++ * ++ * Note: All the alignments are hardware requirements. ++ */ ++static u32 iris_yuv_buffer_size_qc08c(struct iris_inst *inst) ++{ ++ u32 y_plane, uv_plane, y_stride, uv_stride; ++ struct v4l2_format *f = inst->fmt_dst; ++ u32 uv_meta_stride, uv_meta_plane; ++ u32 y_meta_stride, y_meta_plane; ++ ++ y_meta_stride = ALIGN(DIV_ROUND_UP(f->fmt.pix_mp.width, META_STRIDE_ALIGNED >> 1), ++ META_STRIDE_ALIGNED); ++ y_meta_plane = y_meta_stride * ALIGN(DIV_ROUND_UP(f->fmt.pix_mp.height, ++ META_SCANLINE_ALIGNED >> 1), ++ META_SCANLINE_ALIGNED); ++ y_meta_plane = ALIGN(y_meta_plane, PIXELS_4K); ++ ++ y_stride = ALIGN(f->fmt.pix_mp.width, Y_STRIDE_ALIGN); ++ y_plane = ALIGN(y_stride * ALIGN(f->fmt.pix_mp.height, Y_SCANLINE_ALIGN), PIXELS_4K); ++ ++ uv_meta_stride = ALIGN(DIV_ROUND_UP(f->fmt.pix_mp.width / 2, META_STRIDE_ALIGNED >> 2), ++ META_STRIDE_ALIGNED); ++ uv_meta_plane = uv_meta_stride * ALIGN(DIV_ROUND_UP(f->fmt.pix_mp.height / 2, ++ META_SCANLINE_ALIGNED >> 1), ++ META_SCANLINE_ALIGNED); ++ uv_meta_plane = ALIGN(uv_meta_plane, PIXELS_4K); ++ ++ uv_stride = ALIGN(f->fmt.pix_mp.width, UV_STRIDE_ALIGN); ++ uv_plane = ALIGN(uv_stride * ALIGN(f->fmt.pix_mp.height / 2, UV_SCANLINE_ALIGN_QC08C), ++ PIXELS_4K); ++ ++ return ALIGN(y_meta_plane + y_plane + uv_meta_plane + uv_plane, PIXELS_4K); ++} ++ + static u32 iris_bitstream_buffer_size(struct iris_inst *inst) + { + struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps; +@@ -102,6 +221,8 @@ int iris_get_buffer_size(struct iris_inst *inst, + return iris_bitstream_buffer_size(inst); + case BUF_OUTPUT: + return iris_yuv_buffer_size_nv12(inst); ++ case BUF_DPB: ++ return iris_yuv_buffer_size_qc08c(inst); + default: + return 0; + } +diff --git a/drivers/media/platform/qcom/iris/iris_ctrls.c b/drivers/media/platform/qcom/iris/iris_ctrls.c +index 3652fa535bf3..b690578256d5 100644 +--- a/drivers/media/platform/qcom/iris/iris_ctrls.c ++++ b/drivers/media/platform/qcom/iris/iris_ctrls.c +@@ -3,7 +3,9 @@ + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + ++#include + #include ++ + #include "iris_ctrls.h" + #include "iris_instance.h" + +@@ -163,3 +165,95 @@ void iris_session_init_caps(struct iris_core *core) + core->inst_fw_caps[cap_id].hfi_id = caps[i].hfi_id; + } + } ++ ++static u32 iris_get_port_info(struct iris_inst *inst, ++ enum platform_inst_fw_cap_type cap_id) ++{ ++ if (inst->fw_caps[cap_id].flags & CAP_FLAG_INPUT_PORT) ++ return HFI_PORT_BITSTREAM; ++ else if (inst->fw_caps[cap_id].flags & CAP_FLAG_OUTPUT_PORT) ++ return HFI_PORT_RAW; ++ ++ return HFI_PORT_NONE; ++} ++ ++int iris_set_u32_enum(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) ++{ ++ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; ++ u32 hfi_value = inst->fw_caps[cap_id].value; ++ u32 hfi_id = inst->fw_caps[cap_id].hfi_id; ++ ++ return hfi_ops->session_set_property(inst, hfi_id, ++ HFI_HOST_FLAGS_NONE, ++ iris_get_port_info(inst, cap_id), ++ HFI_PAYLOAD_U32_ENUM, ++ &hfi_value, sizeof(u32)); ++} ++ ++int iris_set_u32(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) ++{ ++ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; ++ u32 hfi_value = inst->fw_caps[cap_id].value; ++ u32 hfi_id = inst->fw_caps[cap_id].hfi_id; ++ ++ return hfi_ops->session_set_property(inst, hfi_id, ++ HFI_HOST_FLAGS_NONE, ++ iris_get_port_info(inst, cap_id), ++ HFI_PAYLOAD_U32, ++ &hfi_value, sizeof(u32)); ++} ++ ++int iris_set_stage(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) ++{ ++ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; ++ struct v4l2_format *inp_f = inst->fmt_src; ++ u32 hfi_id = inst->fw_caps[cap_id].hfi_id; ++ u32 height = inp_f->fmt.pix_mp.height; ++ u32 width = inp_f->fmt.pix_mp.width; ++ u32 work_mode = STAGE_2; ++ ++ if (iris_res_is_less_than(width, height, 1280, 720)) ++ work_mode = STAGE_1; ++ ++ return hfi_ops->session_set_property(inst, hfi_id, ++ HFI_HOST_FLAGS_NONE, ++ iris_get_port_info(inst, cap_id), ++ HFI_PAYLOAD_U32, ++ &work_mode, sizeof(u32)); ++} ++ ++int iris_set_pipe(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) ++{ ++ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; ++ u32 work_route = inst->fw_caps[PIPE].value; ++ u32 hfi_id = inst->fw_caps[cap_id].hfi_id; ++ ++ return hfi_ops->session_set_property(inst, hfi_id, ++ HFI_HOST_FLAGS_NONE, ++ iris_get_port_info(inst, cap_id), ++ HFI_PAYLOAD_U32, ++ &work_route, sizeof(u32)); ++} ++ ++int iris_set_properties(struct iris_inst *inst, u32 plane) ++{ ++ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; ++ struct platform_inst_fw_cap *cap; ++ int ret; ++ u32 i; ++ ++ ret = hfi_ops->session_set_config_params(inst, plane); ++ if (ret) ++ return ret; ++ ++ for (i = 1; i < INST_FW_CAP_MAX; i++) { ++ cap = &inst->fw_caps[i]; ++ if (!iris_valid_cap_id(cap->cap_id)) ++ continue; ++ ++ if (cap->cap_id && cap->set) ++ cap->set(inst, i); ++ } ++ ++ return 0; ++} +diff --git a/drivers/media/platform/qcom/iris/iris_ctrls.h b/drivers/media/platform/qcom/iris/iris_ctrls.h +index fe65a772e6dd..9b5741868933 100644 +--- a/drivers/media/platform/qcom/iris/iris_ctrls.h ++++ b/drivers/media/platform/qcom/iris/iris_ctrls.h +@@ -13,5 +13,10 @@ struct iris_inst; + + int iris_ctrls_init(struct iris_inst *inst); + void iris_session_init_caps(struct iris_core *core); ++int iris_set_u32_enum(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); ++int iris_set_stage(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); ++int iris_set_pipe(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); ++int iris_set_u32(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); ++int iris_set_properties(struct iris_inst *inst, u32 plane); + + #endif +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.h b/drivers/media/platform/qcom/iris/iris_hfi_common.h +index 8b1c4d156cf2..1fba5a9292af 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_common.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_common.h +@@ -43,11 +43,75 @@ enum hfi_packet_host_flags { + HFI_HOST_FLAGS_GET_PROPERTY = 0x00000008, + }; + ++enum hfi_color_primaries { ++ HFI_PRIMARIES_RESERVED = 0, ++ HFI_PRIMARIES_BT709 = 1, ++ HFI_PRIMARIES_UNSPECIFIED = 2, ++ HFI_PRIMARIES_BT470_SYSTEM_M = 4, ++ HFI_PRIMARIES_BT470_SYSTEM_BG = 5, ++ HFI_PRIMARIES_BT601_525 = 6, ++ HFI_PRIMARIES_SMPTE_ST240M = 7, ++ HFI_PRIMARIES_GENERIC_FILM = 8, ++ HFI_PRIMARIES_BT2020 = 9, ++ HFI_PRIMARIES_SMPTE_ST428_1 = 10, ++ HFI_PRIMARIES_SMPTE_RP431_2 = 11, ++ HFI_PRIMARIES_SMPTE_EG431_1 = 12, ++ HFI_PRIMARIES_SMPTE_EBU_TECH = 22, ++}; ++ ++enum hfi_transfer_characteristics { ++ HFI_TRANSFER_RESERVED = 0, ++ HFI_TRANSFER_BT709 = 1, ++ HFI_TRANSFER_UNSPECIFIED = 2, ++ HFI_TRANSFER_BT470_SYSTEM_M = 4, ++ HFI_TRANSFER_BT470_SYSTEM_BG = 5, ++ HFI_TRANSFER_BT601_525_OR_625 = 6, ++ HFI_TRANSFER_SMPTE_ST240M = 7, ++ HFI_TRANSFER_LINEAR = 8, ++ HFI_TRANSFER_LOG_100_1 = 9, ++ HFI_TRANSFER_LOG_SQRT = 10, ++ HFI_TRANSFER_XVYCC = 11, ++ HFI_TRANSFER_BT1361_0 = 12, ++ HFI_TRANSFER_SRGB_SYCC = 13, ++ HFI_TRANSFER_BT2020_14 = 14, ++ HFI_TRANSFER_BT2020_15 = 15, ++ HFI_TRANSFER_SMPTE_ST2084_PQ = 16, ++ HFI_TRANSFER_SMPTE_ST428_1 = 17, ++ HFI_TRANSFER_BT2100_2_HLG = 18, ++}; ++ ++enum hfi_matrix_coefficients { ++ HFI_MATRIX_COEFF_SRGB_SMPTE_ST428_1 = 0, ++ HFI_MATRIX_COEFF_BT709 = 1, ++ HFI_MATRIX_COEFF_UNSPECIFIED = 2, ++ HFI_MATRIX_COEFF_RESERVED = 3, ++ HFI_MATRIX_COEFF_FCC_TITLE_47 = 4, ++ HFI_MATRIX_COEFF_BT470_SYS_BG_OR_BT601_625 = 5, ++ HFI_MATRIX_COEFF_BT601_525_BT1358_525_OR_625 = 6, ++ HFI_MATRIX_COEFF_SMPTE_ST240 = 7, ++ HFI_MATRIX_COEFF_YCGCO = 8, ++ HFI_MATRIX_COEFF_BT2020_NON_CONSTANT = 9, ++ HFI_MATRIX_COEFF_BT2020_CONSTANT = 10, ++ HFI_MATRIX_COEFF_SMPTE_ST2085 = 11, ++ HFI_MATRIX_COEFF_SMPTE_CHROM_DERV_NON_CONSTANT = 12, ++ HFI_MATRIX_COEFF_SMPTE_CHROM_DERV_CONSTANT = 13, ++ HFI_MATRIX_COEFF_BT2100 = 14, ++}; ++ ++struct iris_hfi_prop_type_handle { ++ u32 type; ++ int (*handle)(struct iris_inst *inst); ++}; ++ + struct iris_hfi_command_ops { + int (*sys_init)(struct iris_core *core); + int (*sys_image_version)(struct iris_core *core); + int (*sys_interframe_powercollapse)(struct iris_core *core); + int (*sys_pc_prep)(struct iris_core *core); ++ int (*session_set_config_params)(struct iris_inst *inst, u32 plane); ++ int (*session_set_property)(struct iris_inst *inst, ++ u32 packet_type, u32 flag, u32 plane, u32 payload_type, ++ void *payload, u32 payload_size); + int (*session_open)(struct iris_inst *inst); + int (*session_start)(struct iris_inst *inst, u32 plane); + int (*session_stop)(struct iris_inst *inst, u32 plane); +@@ -58,6 +122,18 @@ struct iris_hfi_response_ops { + void (*hfi_response_handler)(struct iris_core *core); + }; + ++struct hfi_subscription_params { ++ u32 bitstream_resolution; ++ u32 crop_offsets[2]; ++ u32 bit_depth; ++ u32 coded_frames; ++ u32 fw_min_count; ++ u32 pic_order_cnt; ++ u32 color_info; ++ u32 profile; ++ u32 level; ++}; ++ + int iris_hfi_core_init(struct iris_core *core); + int iris_hfi_pm_suspend(struct iris_core *core); + int iris_hfi_pm_resume(struct iris_core *core); +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +index a3b09e8d1f49..26fe65ddba8a 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +@@ -6,6 +6,7 @@ + #include "iris_hfi_gen1.h" + #include "iris_hfi_gen1_defines.h" + #include "iris_instance.h" ++#include "iris_vpu_buffer.h" + + static int iris_hfi_gen1_sys_init(struct iris_core *core) + { +@@ -182,12 +183,422 @@ static int iris_hfi_gen1_session_stop(struct iris_inst *inst, u32 plane) + return ret; + } + ++static int ++iris_hfi_gen1_packet_session_set_property(struct hfi_session_set_property_pkt *packet, ++ struct iris_inst *inst, u32 ptype, void *pdata) ++{ ++ void *prop_data = &packet->data[1]; ++ ++ packet->shdr.hdr.size = sizeof(*packet); ++ packet->shdr.hdr.pkt_type = HFI_CMD_SESSION_SET_PROPERTY; ++ packet->shdr.session_id = inst->session_id; ++ packet->num_properties = 1; ++ packet->data[0] = ptype; ++ ++ switch (ptype) { ++ case HFI_PROPERTY_PARAM_FRAME_SIZE: { ++ struct hfi_framesize *in = pdata, *fsize = prop_data; ++ ++ fsize->buffer_type = in->buffer_type; ++ fsize->height = in->height; ++ fsize->width = in->width; ++ packet->shdr.hdr.size += sizeof(u32) + sizeof(*fsize); ++ break; ++ } ++ case HFI_PROPERTY_CONFIG_VIDEOCORES_USAGE: { ++ struct hfi_videocores_usage_type *in = pdata, *cu = prop_data; ++ ++ cu->video_core_enable_mask = in->video_core_enable_mask; ++ packet->shdr.hdr.size += sizeof(u32) + sizeof(*cu); ++ break; ++ } ++ case HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT: { ++ struct hfi_uncompressed_format_select *in = pdata; ++ struct hfi_uncompressed_format_select *hfi = prop_data; ++ ++ hfi->buffer_type = in->buffer_type; ++ hfi->format = in->format; ++ packet->shdr.hdr.size += sizeof(u32) + sizeof(*hfi); ++ break; ++ } ++ case HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO: { ++ struct hfi_uncompressed_plane_actual_constraints_info *info = prop_data; ++ ++ info->buffer_type = HFI_BUFFER_OUTPUT2; ++ info->num_planes = 2; ++ info->plane_format[0].stride_multiples = 128; ++ info->plane_format[0].max_stride = 8192; ++ info->plane_format[0].min_plane_buffer_height_multiple = 32; ++ info->plane_format[0].buffer_alignment = 256; ++ if (info->num_planes > 1) { ++ info->plane_format[1].stride_multiples = 128; ++ info->plane_format[1].max_stride = 8192; ++ info->plane_format[1].min_plane_buffer_height_multiple = 16; ++ info->plane_format[1].buffer_alignment = 256; ++ } ++ ++ packet->shdr.hdr.size += sizeof(u32) + sizeof(*info); ++ break; ++ } ++ case HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL: { ++ struct hfi_buffer_count_actual *in = pdata; ++ struct hfi_buffer_count_actual *count = prop_data; ++ ++ count->type = in->type; ++ count->count_actual = in->count_actual; ++ count->count_min_host = in->count_min_host; ++ packet->shdr.hdr.size += sizeof(u32) + sizeof(*count); ++ break; ++ } ++ case HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM: { ++ struct hfi_multi_stream *in = pdata; ++ struct hfi_multi_stream *multi = prop_data; ++ ++ multi->buffer_type = in->buffer_type; ++ multi->enable = in->enable; ++ packet->shdr.hdr.size += sizeof(u32) + sizeof(*multi); ++ break; ++ } ++ case HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL: { ++ struct hfi_buffer_size_actual *in = pdata, *sz = prop_data; ++ ++ sz->size = in->size; ++ sz->type = in->type; ++ packet->shdr.hdr.size += sizeof(u32) + sizeof(*sz); ++ break; ++ } ++ case HFI_PROPERTY_PARAM_WORK_ROUTE: { ++ struct hfi_video_work_route *wr = prop_data; ++ u32 *in = pdata; ++ ++ wr->video_work_route = *in; ++ packet->shdr.hdr.size += sizeof(u32) + sizeof(*wr); ++ break; ++ } ++ case HFI_PROPERTY_PARAM_WORK_MODE: { ++ struct hfi_video_work_mode *wm = prop_data; ++ u32 *in = pdata; ++ ++ wm->video_work_mode = *in; ++ packet->shdr.hdr.size += sizeof(u32) + sizeof(*wm); ++ break; ++ } ++ case HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER: { ++ struct hfi_enable *en = prop_data; ++ u32 *in = pdata; ++ ++ en->enable = *in; ++ packet->shdr.hdr.size += sizeof(u32) + sizeof(*en); ++ break; ++ } ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int hfi_gen1_set_property(struct iris_inst *inst, u32 packet_type, ++ void *payload, u32 payload_size) ++{ ++ struct hfi_session_set_property_pkt *pkt; ++ u32 packet_size; ++ int ret; ++ ++ packet_size = sizeof(*pkt) + sizeof(u32) + payload_size; ++ pkt = kzalloc(packet_size, GFP_KERNEL); ++ if (!pkt) ++ return -ENOMEM; ++ ++ ret = iris_hfi_gen1_packet_session_set_property(pkt, inst, packet_type, payload); ++ if (ret == -EOPNOTSUPP) { ++ ret = 0; ++ goto exit; ++ } ++ if (ret) ++ goto exit; ++ ++ ret = iris_hfi_queue_cmd_write(inst->core, pkt, pkt->shdr.hdr.size); ++ ++exit: ++ kfree(pkt); ++ ++ return ret; ++} ++ ++static int iris_hfi_gen1_session_set_property(struct iris_inst *inst, u32 packet_type, ++ u32 flag, u32 plane, u32 payload_type, ++ void *payload, u32 payload_size) ++{ ++ return hfi_gen1_set_property(inst, packet_type, payload, payload_size); ++} ++ ++static int iris_hfi_gen1_set_resolution(struct iris_inst *inst) ++{ ++ u32 ptype = HFI_PROPERTY_PARAM_FRAME_SIZE; ++ struct hfi_framesize fs; ++ int ret; ++ ++ fs.buffer_type = HFI_BUFFER_INPUT; ++ fs.width = inst->fmt_src->fmt.pix_mp.width; ++ fs.height = inst->fmt_src->fmt.pix_mp.height; ++ ++ ret = hfi_gen1_set_property(inst, ptype, &fs, sizeof(fs)); ++ if (ret) ++ return ret; ++ ++ fs.buffer_type = HFI_BUFFER_OUTPUT2; ++ fs.width = inst->fmt_dst->fmt.pix_mp.width; ++ fs.height = inst->fmt_dst->fmt.pix_mp.height; ++ ++ return hfi_gen1_set_property(inst, ptype, &fs, sizeof(fs)); ++} ++ ++static int iris_hfi_gen1_decide_core(struct iris_inst *inst) ++{ ++ const u32 ptype = HFI_PROPERTY_CONFIG_VIDEOCORES_USAGE; ++ struct hfi_videocores_usage_type cu; ++ ++ cu.video_core_enable_mask = HFI_CORE_ID_1; ++ ++ return hfi_gen1_set_property(inst, ptype, &cu, sizeof(cu)); ++} ++ ++static int iris_hfi_gen1_set_raw_format(struct iris_inst *inst) ++{ ++ const u32 ptype = HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT; ++ u32 pixelformat = inst->fmt_dst->fmt.pix_mp.pixelformat; ++ struct hfi_uncompressed_format_select fmt; ++ int ret; ++ ++ if (iris_split_mode_enabled(inst)) { ++ fmt.buffer_type = HFI_BUFFER_OUTPUT; ++ fmt.format = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FORMAT_NV12_UBWC : 0; ++ ++ ret = hfi_gen1_set_property(inst, ptype, &fmt, sizeof(fmt)); ++ if (ret) ++ return ret; ++ ++ fmt.buffer_type = HFI_BUFFER_OUTPUT2; ++ fmt.format = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FORMAT_NV12 : 0; ++ ++ ret = hfi_gen1_set_property(inst, ptype, &fmt, sizeof(fmt)); ++ } else { ++ fmt.buffer_type = HFI_BUFFER_OUTPUT; ++ fmt.format = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FORMAT_NV12 : 0; ++ ++ ret = hfi_gen1_set_property(inst, ptype, &fmt, sizeof(fmt)); ++ } ++ ++ return ret; ++} ++ ++static int iris_hfi_gen1_set_format_constraints(struct iris_inst *inst) ++{ ++ const u32 ptype = HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO; ++ struct hfi_uncompressed_plane_actual_constraints_info pconstraint; ++ ++ pconstraint.buffer_type = HFI_BUFFER_OUTPUT2; ++ pconstraint.num_planes = 2; ++ pconstraint.plane_format[0].stride_multiples = 128; ++ pconstraint.plane_format[0].max_stride = 8192; ++ pconstraint.plane_format[0].min_plane_buffer_height_multiple = 32; ++ pconstraint.plane_format[0].buffer_alignment = 256; ++ ++ pconstraint.plane_format[1].stride_multiples = 128; ++ pconstraint.plane_format[1].max_stride = 8192; ++ pconstraint.plane_format[1].min_plane_buffer_height_multiple = 16; ++ pconstraint.plane_format[1].buffer_alignment = 256; ++ ++ return hfi_gen1_set_property(inst, ptype, &pconstraint, sizeof(pconstraint)); ++} ++ ++static int iris_hfi_gen1_set_num_bufs(struct iris_inst *inst) ++{ ++ u32 ptype = HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL; ++ struct hfi_buffer_count_actual buf_count; ++ int ret; ++ ++ buf_count.type = HFI_BUFFER_INPUT; ++ buf_count.count_actual = VIDEO_MAX_FRAME; ++ buf_count.count_min_host = VIDEO_MAX_FRAME; ++ ++ ret = hfi_gen1_set_property(inst, ptype, &buf_count, sizeof(buf_count)); ++ if (ret) ++ return ret; ++ ++ if (iris_split_mode_enabled(inst)) { ++ buf_count.type = HFI_BUFFER_OUTPUT; ++ buf_count.count_actual = VIDEO_MAX_FRAME; ++ buf_count.count_min_host = VIDEO_MAX_FRAME; ++ ++ ret = hfi_gen1_set_property(inst, ptype, &buf_count, sizeof(buf_count)); ++ if (ret) ++ return ret; ++ ++ buf_count.type = HFI_BUFFER_OUTPUT2; ++ buf_count.count_actual = iris_vpu_buf_count(inst, BUF_DPB); ++ buf_count.count_min_host = iris_vpu_buf_count(inst, BUF_DPB); ++ ++ ret = hfi_gen1_set_property(inst, ptype, &buf_count, sizeof(buf_count)); ++ } else { ++ buf_count.type = HFI_BUFFER_OUTPUT; ++ buf_count.count_actual = VIDEO_MAX_FRAME; ++ buf_count.count_min_host = VIDEO_MAX_FRAME; ++ ++ ret = hfi_gen1_set_property(inst, ptype, &buf_count, sizeof(buf_count)); ++ } ++ ++ return ret; ++} ++ ++static int iris_hfi_gen1_set_multistream(struct iris_inst *inst) ++{ ++ u32 ptype = HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM; ++ struct hfi_multi_stream multi = {0}; ++ int ret; ++ ++ if (iris_split_mode_enabled(inst)) { ++ multi.buffer_type = HFI_BUFFER_OUTPUT; ++ multi.enable = 0; ++ ++ ret = hfi_gen1_set_property(inst, ptype, &multi, sizeof(multi)); ++ if (ret) ++ return ret; ++ ++ multi.buffer_type = HFI_BUFFER_OUTPUT2; ++ multi.enable = 1; ++ ++ ret = hfi_gen1_set_property(inst, ptype, &multi, sizeof(multi)); ++ } else { ++ multi.buffer_type = HFI_BUFFER_OUTPUT; ++ multi.enable = 1; ++ ++ ret = hfi_gen1_set_property(inst, ptype, &multi, sizeof(multi)); ++ if (ret) ++ return ret; ++ ++ multi.buffer_type = HFI_BUFFER_OUTPUT2; ++ multi.enable = 0; ++ ++ ret = hfi_gen1_set_property(inst, ptype, &multi, sizeof(multi)); ++ } ++ ++ return ret; ++} ++ ++static int iris_hfi_gen1_set_bufsize(struct iris_inst *inst) ++{ ++ const u32 ptype = HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL; ++ struct hfi_buffer_size_actual bufsz; ++ int ret; ++ ++ if (iris_split_mode_enabled(inst)) { ++ bufsz.type = HFI_BUFFER_OUTPUT; ++ bufsz.size = iris_vpu_dec_dpb_size(inst); ++ ++ ret = hfi_gen1_set_property(inst, ptype, &bufsz, sizeof(bufsz)); ++ if (ret) ++ return ret; ++ ++ bufsz.type = HFI_BUFFER_OUTPUT2; ++ bufsz.size = inst->buffers[BUF_OUTPUT].size; ++ ++ ret = hfi_gen1_set_property(inst, ptype, &bufsz, sizeof(bufsz)); ++ } else { ++ bufsz.type = HFI_BUFFER_OUTPUT; ++ bufsz.size = inst->buffers[BUF_OUTPUT].size; ++ ++ ret = hfi_gen1_set_property(inst, ptype, &bufsz, sizeof(bufsz)); ++ if (ret) ++ return ret; ++ ++ bufsz.type = HFI_BUFFER_OUTPUT2; ++ bufsz.size = 0; ++ ++ ret = hfi_gen1_set_property(inst, ptype, &bufsz, sizeof(bufsz)); ++ } ++ ++ return ret; ++} ++ ++static int iris_hfi_gen1_session_set_config_params(struct iris_inst *inst, u32 plane) ++{ ++ struct iris_core *core = inst->core; ++ u32 config_params_size, i, j; ++ const u32 *config_params; ++ int ret; ++ ++ static const struct iris_hfi_prop_type_handle prop_type_handle_inp_arr[] = { ++ {HFI_PROPERTY_PARAM_FRAME_SIZE, ++ iris_hfi_gen1_set_resolution}, ++ {HFI_PROPERTY_CONFIG_VIDEOCORES_USAGE, ++ iris_hfi_gen1_decide_core}, ++ {HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT, ++ iris_hfi_gen1_set_raw_format}, ++ {HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO, ++ iris_hfi_gen1_set_format_constraints}, ++ {HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL, ++ iris_hfi_gen1_set_num_bufs}, ++ {HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM, ++ iris_hfi_gen1_set_multistream}, ++ {HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL, ++ iris_hfi_gen1_set_bufsize}, ++ }; ++ ++ static const struct iris_hfi_prop_type_handle prop_type_handle_out_arr[] = { ++ {HFI_PROPERTY_PARAM_FRAME_SIZE, ++ iris_hfi_gen1_set_resolution}, ++ {HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT, ++ iris_hfi_gen1_set_raw_format}, ++ {HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO, ++ iris_hfi_gen1_set_format_constraints}, ++ {HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL, ++ iris_hfi_gen1_set_num_bufs}, ++ {HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM, ++ iris_hfi_gen1_set_multistream}, ++ {HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL, ++ iris_hfi_gen1_set_bufsize}, ++ }; ++ ++ config_params = core->iris_platform_data->input_config_params; ++ config_params_size = core->iris_platform_data->input_config_params_size; ++ ++ if (V4L2_TYPE_IS_OUTPUT(plane)) { ++ for (i = 0; i < config_params_size; i++) { ++ for (j = 0; j < ARRAY_SIZE(prop_type_handle_inp_arr); j++) { ++ if (prop_type_handle_inp_arr[j].type == config_params[i]) { ++ ret = prop_type_handle_inp_arr[j].handle(inst); ++ if (ret) ++ return ret; ++ break; ++ } ++ } ++ } ++ } else if (V4L2_TYPE_IS_CAPTURE(plane)) { ++ for (i = 0; i < config_params_size; i++) { ++ for (j = 0; j < ARRAY_SIZE(prop_type_handle_out_arr); j++) { ++ if (prop_type_handle_out_arr[j].type == config_params[i]) { ++ ret = prop_type_handle_out_arr[j].handle(inst); ++ if (ret) ++ return ret; ++ break; ++ } ++ } ++ } ++ } ++ ++ return 0; ++} ++ + static const struct iris_hfi_command_ops iris_hfi_gen1_command_ops = { + .sys_init = iris_hfi_gen1_sys_init, + .sys_image_version = iris_hfi_gen1_sys_image_version, + .sys_interframe_powercollapse = iris_hfi_gen1_sys_interframe_powercollapse, + .sys_pc_prep = iris_hfi_gen1_sys_pc_prep, + .session_open = iris_hfi_gen1_session_open, ++ .session_set_config_params = iris_hfi_gen1_session_set_config_params, ++ .session_set_property = iris_hfi_gen1_session_set_property, + .session_start = iris_hfi_gen1_session_start, + .session_stop = iris_hfi_gen1_session_stop, + .session_close = iris_hfi_gen1_session_close, +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +index 1b2bf6afc6ce..67e7575351d4 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +@@ -23,6 +23,8 @@ + #define HFI_CMD_SYS_SESSION_INIT 0x10007 + #define HFI_CMD_SYS_SESSION_END 0x10008 + ++#define HFI_CMD_SESSION_SET_PROPERTY 0x11001 ++ + #define HFI_CMD_SESSION_LOAD_RESOURCES 0x211001 + #define HFI_CMD_SESSION_START 0x211002 + #define HFI_CMD_SESSION_STOP 0x211003 +@@ -40,9 +42,32 @@ + #define HFI_FLUSH_OUTPUT 0x1000002 + #define HFI_FLUSH_OUTPUT2 0x1000003 + #define HFI_FLUSH_ALL 0x1000004 ++ ++#define HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL 0x201001 ++#define HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO 0x201002 ++#define HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE 0x201008 ++#define HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL 0x20100c ++ ++#define HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER 0x1200001 ++ ++#define HFI_BUFFER_INPUT 0x1 ++#define HFI_BUFFER_OUTPUT 0x2 ++#define HFI_BUFFER_OUTPUT2 0x3 ++ + #define HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL 0x5 + #define HFI_PROPERTY_SYS_IMAGE_VERSION 0x6 + ++#define HFI_PROPERTY_PARAM_FRAME_SIZE 0x1001 ++#define HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT 0x1003 ++#define HFI_PROPERTY_PARAM_WORK_MODE 0x1015 ++#define HFI_PROPERTY_PARAM_WORK_ROUTE 0x1017 ++#define HFI_PROPERTY_CONFIG_VIDEOCORES_USAGE 0x2002 ++ ++#define HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM 0x1003001 ++#define HFI_CORE_ID_1 1 ++#define HFI_COLOR_FORMAT_NV12 0x02 ++#define HFI_COLOR_FORMAT_NV12_UBWC 0x8002 ++ + #define HFI_MSG_SYS_INIT 0x20001 + #define HFI_MSG_SYS_SESSION_INIT 0x20006 + #define HFI_MSG_SYS_SESSION_END 0x20007 +@@ -93,6 +118,12 @@ struct hfi_sys_get_property_pkt { + u32 data; + }; + ++struct hfi_session_set_property_pkt { ++ struct hfi_session_hdr_pkt shdr; ++ u32 num_properties; ++ u32 data[]; ++}; ++ + struct hfi_sys_pc_prep_pkt { + struct hfi_pkt_hdr hdr; + }; +@@ -144,6 +175,58 @@ struct hfi_enable { + u32 enable; + }; + ++struct hfi_framesize { ++ u32 buffer_type; ++ u32 width; ++ u32 height; ++}; ++ ++struct hfi_videocores_usage_type { ++ u32 video_core_enable_mask; ++}; ++ ++struct hfi_video_work_mode { ++ u32 video_work_mode; ++}; ++ ++struct hfi_video_work_route { ++ u32 video_work_route; ++}; ++ ++struct hfi_uncompressed_format_select { ++ u32 buffer_type; ++ u32 format; ++}; ++ ++struct hfi_uncompressed_plane_constraints { ++ u32 stride_multiples; ++ u32 max_stride; ++ u32 min_plane_buffer_height_multiple; ++ u32 buffer_alignment; ++}; ++ ++struct hfi_uncompressed_plane_actual_constraints_info { ++ u32 buffer_type; ++ u32 num_planes; ++ struct hfi_uncompressed_plane_constraints plane_format[2]; ++}; ++ ++struct hfi_buffer_count_actual { ++ u32 type; ++ u32 count_actual; ++ u32 count_min_host; ++}; ++ ++struct hfi_buffer_size_actual { ++ u32 type; ++ u32 size; ++}; ++ ++struct hfi_multi_stream { ++ u32 buffer_type; ++ u32 enable; ++}; ++ + struct hfi_msg_sys_debug_pkt { + struct hfi_pkt_hdr hdr; + u32 msg_type; +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2.h +index aaf6660bc1fe..676bcb3dc81f 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2.h +@@ -18,10 +18,12 @@ struct iris_core; + * + * @inst: pointer to iris_instance structure + * @packet: HFI packet ++ * @src_subcr_params: subscription params to fw on input port + */ + struct iris_inst_hfi_gen2 { + struct iris_inst inst; + struct iris_hfi_header *packet; ++ struct hfi_subscription_params src_subcr_params; + }; + + void iris_hfi_gen2_command_ops_init(struct iris_core *core); +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +index b0557917fc52..0845b75aafe9 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +@@ -3,9 +3,12 @@ + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + ++#include ++ + #include "iris_hfi_gen2.h" + #include "iris_hfi_gen2_packet.h" + ++#define UNSPECIFIED_COLOR_FORMAT 5 + #define NUM_SYS_INIT_PACKETS 8 + + #define SYS_INIT_PKT_SIZE (sizeof(struct iris_hfi_header) + \ +@@ -97,6 +100,301 @@ static u32 iris_hfi_gen2_get_port(u32 plane) + } + } + ++static int iris_hfi_gen2_session_set_property(struct iris_inst *inst, u32 packet_type, u32 flag, ++ u32 plane, u32 payload_type, void *payload, ++ u32 payload_size) ++{ ++ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); ++ ++ iris_hfi_gen2_packet_session_property(inst, ++ packet_type, ++ flag, ++ plane, ++ payload_type, ++ payload, ++ payload_size); ++ ++ return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet, ++ inst_hfi_gen2->packet->size); ++} ++ ++static int iris_hfi_gen2_set_bitstream_resolution(struct iris_inst *inst) ++{ ++ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); ++ u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); ++ u32 resolution = inst->fmt_src->fmt.pix_mp.width << 16 | ++ inst->fmt_src->fmt.pix_mp.height; ++ ++ inst_hfi_gen2->src_subcr_params.bitstream_resolution = resolution; ++ ++ return iris_hfi_gen2_session_set_property(inst, ++ HFI_PROP_BITSTREAM_RESOLUTION, ++ HFI_HOST_FLAGS_NONE, ++ port, ++ HFI_PAYLOAD_U32, ++ &resolution, ++ sizeof(u32)); ++} ++ ++static int iris_hfi_gen2_set_crop_offsets(struct iris_inst *inst) ++{ ++ u32 bottom_offset = (inst->fmt_src->fmt.pix_mp.height - inst->crop.height); ++ u32 right_offset = (inst->fmt_src->fmt.pix_mp.width - inst->crop.width); ++ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); ++ u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); ++ u32 left_offset = inst->crop.left; ++ u32 top_offset = inst->crop.top; ++ u32 payload[2]; ++ ++ payload[0] = FIELD_PREP(GENMASK(31, 16), left_offset) | top_offset; ++ payload[1] = FIELD_PREP(GENMASK(31, 16), right_offset) | bottom_offset; ++ inst_hfi_gen2->src_subcr_params.crop_offsets[0] = payload[0]; ++ inst_hfi_gen2->src_subcr_params.crop_offsets[1] = payload[1]; ++ ++ return iris_hfi_gen2_session_set_property(inst, ++ HFI_PROP_CROP_OFFSETS, ++ HFI_HOST_FLAGS_NONE, ++ port, ++ HFI_PAYLOAD_64_PACKED, ++ &payload, ++ sizeof(u64)); ++} ++ ++static int iris_hfi_gen2_set_bit_dpeth(struct iris_inst *inst) ++{ ++ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); ++ u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); ++ u32 bitdepth = BIT_DEPTH_8; ++ ++ inst_hfi_gen2->src_subcr_params.bit_depth = bitdepth; ++ ++ return iris_hfi_gen2_session_set_property(inst, ++ HFI_PROP_LUMA_CHROMA_BIT_DEPTH, ++ HFI_HOST_FLAGS_NONE, ++ port, ++ HFI_PAYLOAD_U32, ++ &bitdepth, ++ sizeof(u32)); ++} ++ ++static int iris_hfi_gen2_set_coded_frames(struct iris_inst *inst) ++{ ++ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); ++ u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); ++ u32 coded_frames = 0; ++ ++ if (inst->fw_caps[CODED_FRAMES].value == CODED_FRAMES_PROGRESSIVE) ++ coded_frames = HFI_BITMASK_FRAME_MBS_ONLY_FLAG; ++ inst_hfi_gen2->src_subcr_params.coded_frames = coded_frames; ++ ++ return iris_hfi_gen2_session_set_property(inst, ++ HFI_PROP_CODED_FRAMES, ++ HFI_HOST_FLAGS_NONE, ++ port, ++ HFI_PAYLOAD_U32, ++ &coded_frames, ++ sizeof(u32)); ++} ++ ++static int iris_hfi_gen2_set_min_output_count(struct iris_inst *inst) ++{ ++ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); ++ u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); ++ u32 min_output = inst->buffers[BUF_OUTPUT].min_count; ++ ++ inst_hfi_gen2->src_subcr_params.fw_min_count = min_output; ++ ++ return iris_hfi_gen2_session_set_property(inst, ++ HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT, ++ HFI_HOST_FLAGS_NONE, ++ port, ++ HFI_PAYLOAD_U32, ++ &min_output, ++ sizeof(u32)); ++} ++ ++static int iris_hfi_gen2_set_picture_order_count(struct iris_inst *inst) ++{ ++ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); ++ u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); ++ u32 poc = 0; ++ ++ inst_hfi_gen2->src_subcr_params.pic_order_cnt = poc; ++ ++ return iris_hfi_gen2_session_set_property(inst, ++ HFI_PROP_PIC_ORDER_CNT_TYPE, ++ HFI_HOST_FLAGS_NONE, ++ port, ++ HFI_PAYLOAD_U32, ++ &poc, ++ sizeof(u32)); ++} ++ ++static int iris_hfi_gen2_set_colorspace(struct iris_inst *inst) ++{ ++ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); ++ u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); ++ struct v4l2_pix_format_mplane *pixmp = &inst->fmt_src->fmt.pix_mp; ++ u32 video_signal_type_present_flag = 0, color_info; ++ u32 matrix_coeff = HFI_MATRIX_COEFF_RESERVED; ++ u32 video_format = UNSPECIFIED_COLOR_FORMAT; ++ u32 full_range = V4L2_QUANTIZATION_DEFAULT; ++ u32 transfer_char = HFI_TRANSFER_RESERVED; ++ u32 colour_description_present_flag = 0; ++ u32 primaries = HFI_PRIMARIES_RESERVED; ++ ++ if (pixmp->colorspace != V4L2_COLORSPACE_DEFAULT || ++ pixmp->ycbcr_enc != V4L2_YCBCR_ENC_DEFAULT || ++ pixmp->xfer_func != V4L2_XFER_FUNC_DEFAULT) { ++ colour_description_present_flag = 1; ++ video_signal_type_present_flag = 1; ++ primaries = iris_hfi_gen2_get_color_primaries(pixmp->colorspace); ++ matrix_coeff = iris_hfi_gen2_get_matrix_coefficients(pixmp->ycbcr_enc); ++ transfer_char = iris_hfi_gen2_get_transfer_char(pixmp->xfer_func); ++ } ++ ++ if (pixmp->quantization != V4L2_QUANTIZATION_DEFAULT) { ++ video_signal_type_present_flag = 1; ++ full_range = pixmp->quantization == V4L2_QUANTIZATION_FULL_RANGE ? 1 : 0; ++ } ++ ++ color_info = iris_hfi_gen2_get_color_info(matrix_coeff, transfer_char, primaries, ++ colour_description_present_flag, full_range, ++ video_format, video_signal_type_present_flag); ++ ++ inst_hfi_gen2->src_subcr_params.color_info = color_info; ++ ++ return iris_hfi_gen2_session_set_property(inst, ++ HFI_PROP_SIGNAL_COLOR_INFO, ++ HFI_HOST_FLAGS_NONE, ++ port, ++ HFI_PAYLOAD_32_PACKED, ++ &color_info, ++ sizeof(u32)); ++} ++ ++static int iris_hfi_gen2_set_profile(struct iris_inst *inst) ++{ ++ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); ++ u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); ++ u32 profile = inst->fw_caps[PROFILE].value; ++ ++ inst_hfi_gen2->src_subcr_params.profile = profile; ++ ++ return iris_hfi_gen2_session_set_property(inst, ++ HFI_PROP_PROFILE, ++ HFI_HOST_FLAGS_NONE, ++ port, ++ HFI_PAYLOAD_U32_ENUM, ++ &profile, ++ sizeof(u32)); ++} ++ ++static int iris_hfi_gen2_set_level(struct iris_inst *inst) ++{ ++ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); ++ u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); ++ u32 level = inst->fw_caps[LEVEL].value; ++ ++ inst_hfi_gen2->src_subcr_params.level = level; ++ ++ return iris_hfi_gen2_session_set_property(inst, ++ HFI_PROP_LEVEL, ++ HFI_HOST_FLAGS_NONE, ++ port, ++ HFI_PAYLOAD_U32_ENUM, ++ &level, ++ sizeof(u32)); ++} ++ ++static int iris_hfi_gen2_set_colorformat(struct iris_inst *inst) ++{ ++ u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); ++ u32 hfi_colorformat, pixelformat; ++ ++ pixelformat = inst->fmt_dst->fmt.pix_mp.pixelformat; ++ hfi_colorformat = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FMT_NV12 : 0; ++ ++ return iris_hfi_gen2_session_set_property(inst, ++ HFI_PROP_COLOR_FORMAT, ++ HFI_HOST_FLAGS_NONE, ++ port, ++ HFI_PAYLOAD_U32, ++ &hfi_colorformat, ++ sizeof(u32)); ++} ++ ++static int iris_hfi_gen2_set_linear_stride_scanline(struct iris_inst *inst) ++{ ++ u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); ++ u32 pixelformat = inst->fmt_dst->fmt.pix_mp.pixelformat; ++ u32 scanline_y = inst->fmt_dst->fmt.pix_mp.height; ++ u32 stride_y = inst->fmt_dst->fmt.pix_mp.width; ++ u32 scanline_uv = scanline_y / 2; ++ u32 stride_uv = stride_y; ++ u32 payload[2]; ++ ++ if (pixelformat != V4L2_PIX_FMT_NV12) ++ return 0; ++ ++ payload[0] = stride_y << 16 | scanline_y; ++ payload[1] = stride_uv << 16 | scanline_uv; ++ ++ return iris_hfi_gen2_session_set_property(inst, ++ HFI_PROP_LINEAR_STRIDE_SCANLINE, ++ HFI_HOST_FLAGS_NONE, ++ port, ++ HFI_PAYLOAD_U64, ++ &payload, ++ sizeof(u64)); ++} ++ ++static int iris_hfi_gen2_session_set_config_params(struct iris_inst *inst, u32 plane) ++{ ++ struct iris_core *core = inst->core; ++ u32 config_params_size, i, j; ++ const u32 *config_params; ++ int ret; ++ ++ static const struct iris_hfi_prop_type_handle prop_type_handle_arr[] = { ++ {HFI_PROP_BITSTREAM_RESOLUTION, iris_hfi_gen2_set_bitstream_resolution }, ++ {HFI_PROP_CROP_OFFSETS, iris_hfi_gen2_set_crop_offsets }, ++ {HFI_PROP_CODED_FRAMES, iris_hfi_gen2_set_coded_frames }, ++ {HFI_PROP_LUMA_CHROMA_BIT_DEPTH, iris_hfi_gen2_set_bit_dpeth }, ++ {HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT, iris_hfi_gen2_set_min_output_count }, ++ {HFI_PROP_PIC_ORDER_CNT_TYPE, iris_hfi_gen2_set_picture_order_count }, ++ {HFI_PROP_SIGNAL_COLOR_INFO, iris_hfi_gen2_set_colorspace }, ++ {HFI_PROP_PROFILE, iris_hfi_gen2_set_profile }, ++ {HFI_PROP_LEVEL, iris_hfi_gen2_set_level }, ++ {HFI_PROP_COLOR_FORMAT, iris_hfi_gen2_set_colorformat }, ++ {HFI_PROP_LINEAR_STRIDE_SCANLINE, iris_hfi_gen2_set_linear_stride_scanline }, ++ }; ++ ++ if (V4L2_TYPE_IS_OUTPUT(plane)) { ++ config_params = core->iris_platform_data->input_config_params; ++ config_params_size = core->iris_platform_data->input_config_params_size; ++ } else { ++ config_params = core->iris_platform_data->output_config_params; ++ config_params_size = core->iris_platform_data->output_config_params_size; ++ } ++ ++ if (!config_params || !config_params_size) ++ return -EINVAL; ++ ++ for (i = 0; i < config_params_size; i++) { ++ for (j = 0; j < ARRAY_SIZE(prop_type_handle_arr); j++) { ++ if (prop_type_handle_arr[j].type == config_params[i]) { ++ ret = prop_type_handle_arr[j].handle(inst); ++ if (ret) ++ return ret; ++ break; ++ } ++ } ++ } ++ ++ return 0; ++} ++ + static int iris_hfi_gen2_session_set_codec(struct iris_inst *inst) + { + struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); +@@ -253,6 +551,8 @@ static const struct iris_hfi_command_ops iris_hfi_gen2_command_ops = { + .sys_interframe_powercollapse = iris_hfi_gen2_sys_interframe_powercollapse, + .sys_pc_prep = iris_hfi_gen2_sys_pc_prep, + .session_open = iris_hfi_gen2_session_open, ++ .session_set_config_params = iris_hfi_gen2_session_set_config_params, ++ .session_set_property = iris_hfi_gen2_session_set_property, + .session_start = iris_hfi_gen2_session_start, + .session_stop = iris_hfi_gen2_session_stop, + .session_close = iris_hfi_gen2_session_close, +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +index 930dbae49dfa..4c9604b05034 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +@@ -19,6 +19,8 @@ + #define HFI_CMD_STOP 0x01000006 + #define HFI_CMD_END 0x01FFFFFF + ++#define HFI_BITMASK_FRAME_MBS_ONLY_FLAG 0x00000001 ++ + #define HFI_PROP_BEGIN 0x03000000 + #define HFI_PROP_IMAGE_VERSION 0x03000001 + #define HFI_PROP_INTRA_FRAME_POWER_COLLAPSE 0x03000002 +@@ -30,9 +32,23 @@ + #define HFI_PROP_UBWC_BANK_SWZL_LEVEL3 0x03000008 + #define HFI_PROP_UBWC_BANK_SPREADING 0x03000009 + #define HFI_PROP_CODEC 0x03000100 ++#define HFI_PROP_COLOR_FORMAT 0x03000101 ++#define HFI_PROP_BITSTREAM_RESOLUTION 0x03000103 ++#define HFI_PROP_LINEAR_STRIDE_SCANLINE 0x03000104 ++#define HFI_PROP_CROP_OFFSETS 0x03000105 + #define HFI_PROP_PROFILE 0x03000107 + #define HFI_PROP_LEVEL 0x03000108 ++#define HFI_PROP_STAGE 0x0300010a ++#define HFI_PROP_PIPE 0x0300010b ++#define HFI_PROP_LUMA_CHROMA_BIT_DEPTH 0x0300010f ++#define HFI_PROP_CODED_FRAMES 0x03000120 ++#define HFI_PROP_BUFFER_HOST_MAX_COUNT 0x03000123 ++#define HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT 0x03000124 ++#define HFI_PROP_PIC_ORDER_CNT_TYPE 0x03000128 ++#define HFI_PROP_QUALITY_MODE 0x03000148 ++#define HFI_PROP_SIGNAL_COLOR_INFO 0x03000155 + #define HFI_PROP_DEC_DEFAULT_HEADER 0x03000168 ++#define HFI_PROP_DEC_START_FROM_RAP_FRAME 0x03000169 + #define HFI_PROP_END 0x03FFFFFF + + #define HFI_SESSION_ERROR_BEGIN 0x04000000 +@@ -49,6 +65,17 @@ + #define HFI_SYS_ERROR_WD_TIMEOUT 0x05000001 + #define HFI_SYSTEM_ERROR_END 0x05FFFFFF + ++enum hfi_color_format { ++ HFI_COLOR_FMT_OPAQUE = 0, ++ HFI_COLOR_FMT_NV12 = 1, ++ HFI_COLOR_FMT_NV12_UBWC = 2, ++ HFI_COLOR_FMT_P010 = 3, ++ HFI_COLOR_FMT_TP10_UBWC = 4, ++ HFI_COLOR_FMT_RGBA8888 = 5, ++ HFI_COLOR_FMT_RGBA8888_UBWC = 6, ++ HFI_COLOR_FMT_NV21 = 7, ++}; ++ + enum hfi_codec_type { + HFI_CODEC_DECODE_AVC = 1, + HFI_CODEC_ENCODE_AVC = 2, +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c +index 739b2ce5bfae..d77fa29f44fc 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c +@@ -7,6 +7,85 @@ + #include "iris_hfi_gen2.h" + #include "iris_hfi_gen2_packet.h" + ++u32 iris_hfi_gen2_get_color_primaries(u32 primaries) ++{ ++ switch (primaries) { ++ case V4L2_COLORSPACE_DEFAULT: ++ return HFI_PRIMARIES_RESERVED; ++ case V4L2_COLORSPACE_REC709: ++ return HFI_PRIMARIES_BT709; ++ case V4L2_COLORSPACE_470_SYSTEM_M: ++ return HFI_PRIMARIES_BT470_SYSTEM_M; ++ case V4L2_COLORSPACE_470_SYSTEM_BG: ++ return HFI_PRIMARIES_BT470_SYSTEM_BG; ++ case V4L2_COLORSPACE_SMPTE170M: ++ return HFI_PRIMARIES_BT601_525; ++ case V4L2_COLORSPACE_SMPTE240M: ++ return HFI_PRIMARIES_SMPTE_ST240M; ++ case V4L2_COLORSPACE_BT2020: ++ return HFI_PRIMARIES_BT2020; ++ case V4L2_COLORSPACE_DCI_P3: ++ return HFI_PRIMARIES_SMPTE_RP431_2; ++ default: ++ return HFI_PRIMARIES_RESERVED; ++ } ++} ++ ++u32 iris_hfi_gen2_get_transfer_char(u32 characterstics) ++{ ++ switch (characterstics) { ++ case V4L2_XFER_FUNC_DEFAULT: ++ return HFI_TRANSFER_RESERVED; ++ case V4L2_XFER_FUNC_709: ++ return HFI_TRANSFER_BT709; ++ case V4L2_XFER_FUNC_SMPTE240M: ++ return HFI_TRANSFER_SMPTE_ST240M; ++ case V4L2_XFER_FUNC_SRGB: ++ return HFI_TRANSFER_SRGB_SYCC; ++ case V4L2_XFER_FUNC_SMPTE2084: ++ return HFI_TRANSFER_SMPTE_ST2084_PQ; ++ default: ++ return HFI_TRANSFER_RESERVED; ++ } ++} ++ ++u32 iris_hfi_gen2_get_matrix_coefficients(u32 coefficients) ++{ ++ switch (coefficients) { ++ case V4L2_YCBCR_ENC_DEFAULT: ++ return HFI_MATRIX_COEFF_RESERVED; ++ case V4L2_YCBCR_ENC_709: ++ return HFI_MATRIX_COEFF_BT709; ++ case V4L2_YCBCR_ENC_XV709: ++ return HFI_MATRIX_COEFF_BT709; ++ case V4L2_YCBCR_ENC_XV601: ++ return HFI_MATRIX_COEFF_BT470_SYS_BG_OR_BT601_625; ++ case V4L2_YCBCR_ENC_601: ++ return HFI_MATRIX_COEFF_BT601_525_BT1358_525_OR_625; ++ case V4L2_YCBCR_ENC_SMPTE240M: ++ return HFI_MATRIX_COEFF_SMPTE_ST240; ++ case V4L2_YCBCR_ENC_BT2020: ++ return HFI_MATRIX_COEFF_BT2020_NON_CONSTANT; ++ case V4L2_YCBCR_ENC_BT2020_CONST_LUM: ++ return HFI_MATRIX_COEFF_BT2020_CONSTANT; ++ default: ++ return HFI_MATRIX_COEFF_RESERVED; ++ } ++} ++ ++u32 iris_hfi_gen2_get_color_info(u32 matrix_coeff, u32 transfer_char, u32 primaries, ++ u32 colour_description_present_flag, u32 full_range, ++ u32 video_format, u32 video_signal_type_present_flag) ++{ ++ return (matrix_coeff & 0xFF) | ++ ((transfer_char << 8) & 0xFF00) | ++ ((primaries << 16) & 0xFF0000) | ++ ((colour_description_present_flag << 24) & 0x1000000) | ++ ((full_range << 25) & 0x2000000) | ++ ((video_format << 26) & 0x1C000000) | ++ ((video_signal_type_present_flag << 29) & 0x20000000); ++} ++ + static void iris_hfi_gen2_create_header(struct iris_hfi_header *hdr, + u32 session_id, u32 header_id) + { +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h +index 4a9b88185b0d..0333e37572f6 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h +@@ -61,6 +61,13 @@ struct iris_hfi_packet { + u32 payload[]; + }; + ++u32 iris_hfi_gen2_get_color_primaries(u32 primaries); ++u32 iris_hfi_gen2_get_transfer_char(u32 characterstics); ++u32 iris_hfi_gen2_get_matrix_coefficients(u32 coefficients); ++u32 iris_hfi_gen2_get_color_info(u32 matrix_coeff, u32 transfer_char, u32 primaries, ++ u32 colour_description_present_flag, u32 full_range, ++ u32 video_format, u32 video_signal_type_present_flag); ++ + void iris_hfi_gen2_packet_sys_init(struct iris_core *core, struct iris_hfi_header *hdr); + void iris_hfi_gen2_packet_image_version(struct iris_core *core, struct iris_hfi_header *hdr); + void iris_hfi_gen2_packet_session_command(struct iris_inst *inst, u32 pkt_type, +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c +index 53b700ef852e..336b43740b72 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c +@@ -166,6 +166,53 @@ static int iris_hfi_gen2_handle_session_command(struct iris_inst *inst, + return 0; + } + ++static int iris_hfi_gen2_handle_session_property(struct iris_inst *inst, ++ struct iris_hfi_packet *pkt) ++{ ++ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); ++ ++ if (pkt->port != HFI_PORT_BITSTREAM) ++ return 0; ++ ++ if (pkt->flags & HFI_FW_FLAGS_INFORMATION) ++ return 0; ++ ++ switch (pkt->type) { ++ case HFI_PROP_BITSTREAM_RESOLUTION: ++ inst_hfi_gen2->src_subcr_params.bitstream_resolution = pkt->payload[0]; ++ break; ++ case HFI_PROP_CROP_OFFSETS: ++ inst_hfi_gen2->src_subcr_params.crop_offsets[0] = pkt->payload[0]; ++ inst_hfi_gen2->src_subcr_params.crop_offsets[1] = pkt->payload[1]; ++ break; ++ case HFI_PROP_CODED_FRAMES: ++ inst_hfi_gen2->src_subcr_params.coded_frames = pkt->payload[0]; ++ break; ++ case HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT: ++ inst_hfi_gen2->src_subcr_params.fw_min_count = pkt->payload[0]; ++ break; ++ case HFI_PROP_PIC_ORDER_CNT_TYPE: ++ inst_hfi_gen2->src_subcr_params.pic_order_cnt = pkt->payload[0]; ++ break; ++ case HFI_PROP_SIGNAL_COLOR_INFO: ++ inst_hfi_gen2->src_subcr_params.color_info = pkt->payload[0]; ++ break; ++ case HFI_PROP_PROFILE: ++ inst_hfi_gen2->src_subcr_params.profile = pkt->payload[0]; ++ break; ++ case HFI_PROP_LEVEL: ++ inst_hfi_gen2->src_subcr_params.level = pkt->payload[0]; ++ break; ++ case HFI_PROP_QUALITY_MODE: ++ case HFI_PROP_STAGE: ++ case HFI_PROP_PIPE: ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ + static int iris_hfi_gen2_handle_image_version_property(struct iris_core *core, + struct iris_hfi_packet *pkt) + { +@@ -250,6 +297,8 @@ static int iris_hfi_gen2_handle_session_response(struct iris_core *core, + static const struct iris_hfi_gen2_inst_hfi_range range[] = { + {HFI_SESSION_ERROR_BEGIN, HFI_SESSION_ERROR_END, + iris_hfi_gen2_handle_session_error}, ++ {HFI_PROP_BEGIN, HFI_PROP_END, ++ iris_hfi_gen2_handle_session_property}, + {HFI_CMD_BEGIN, HFI_CMD_END, + iris_hfi_gen2_handle_session_command }, + }; +diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h +index 23170cd37c04..5643fb55b09e 100644 +--- a/drivers/media/platform/qcom/iris/iris_platform_common.h ++++ b/drivers/media/platform/qcom/iris/iris_platform_common.h +@@ -6,12 +6,31 @@ + #ifndef __IRIS_PLATFORM_COMMON_H__ + #define __IRIS_PLATFORM_COMMON_H__ + ++#include ++ + struct iris_core; ++struct iris_inst; + + #define IRIS_PAS_ID 9 + #define HW_RESPONSE_TIMEOUT_VALUE (1000) /* milliseconds */ + #define AUTOSUSPEND_DELAY_VALUE (HW_RESPONSE_TIMEOUT_VALUE + 500) /* milliseconds */ + ++#define REGISTER_BIT_DEPTH(luma, chroma) ((luma) << 16 | (chroma)) ++#define BIT_DEPTH_8 REGISTER_BIT_DEPTH(8, 8) ++#define CODED_FRAMES_PROGRESSIVE 0x0 ++#define DEFAULT_MAX_HOST_BUF_COUNT 64 ++#define DEFAULT_MAX_HOST_BURST_BUF_COUNT 256 ++enum stage_type { ++ STAGE_1 = 1, ++ STAGE_2 = 2, ++}; ++ ++enum pipe_type { ++ PIPE_1 = 1, ++ PIPE_2 = 2, ++ PIPE_4 = 4, ++}; ++ + extern struct iris_platform_data sm8550_data; + + enum platform_clk_type { +@@ -53,6 +72,13 @@ struct platform_inst_caps { + enum platform_inst_fw_cap_type { + PROFILE = 1, + LEVEL, ++ INPUT_BUF_HOST_MAX_COUNT, ++ STAGE, ++ PIPE, ++ POC, ++ CODED_FRAMES, ++ BIT_DEPTH, ++ RAP_FRAME, + DEBLOCK, + INST_FW_CAP_MAX, + }; +@@ -75,6 +101,8 @@ struct platform_inst_fw_cap { + s64 value; + u32 hfi_id; + enum platform_inst_fw_cap_flags flags; ++ int (*set)(struct iris_inst *inst, ++ enum platform_inst_fw_cap_type cap_id); + }; + + struct iris_core_power { +@@ -115,6 +143,10 @@ struct iris_platform_data { + struct ubwc_config_data *ubwc_config; + u32 num_vpp_pipe; + u32 max_session_count; ++ const u32 *input_config_params; ++ unsigned int input_config_params_size; ++ const u32 *output_config_params; ++ unsigned int output_config_params_size; + }; + + #endif +diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +index 58b1d1d43731..8a55c1f731c0 100644 +--- a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c ++++ b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +@@ -4,6 +4,7 @@ + */ + + #include "iris_core.h" ++#include "iris_ctrls.h" + #include "iris_hfi_gen2.h" + #include "iris_hfi_gen2_defines.h" + #include "iris_platform_common.h" +@@ -24,6 +25,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8550[] = { + .value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, + .hfi_id = HFI_PROP_PROFILE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, ++ .set = iris_set_u32_enum, + }, + { + .cap_id = LEVEL, +@@ -52,6 +54,69 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8550[] = { + .value = V4L2_MPEG_VIDEO_H264_LEVEL_6_1, + .hfi_id = HFI_PROP_LEVEL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, ++ .set = iris_set_u32_enum, ++ }, ++ { ++ .cap_id = INPUT_BUF_HOST_MAX_COUNT, ++ .min = DEFAULT_MAX_HOST_BUF_COUNT, ++ .max = DEFAULT_MAX_HOST_BURST_BUF_COUNT, ++ .step_or_mask = 1, ++ .value = DEFAULT_MAX_HOST_BUF_COUNT, ++ .hfi_id = HFI_PROP_BUFFER_HOST_MAX_COUNT, ++ .flags = CAP_FLAG_INPUT_PORT, ++ .set = iris_set_u32, ++ }, ++ { ++ .cap_id = STAGE, ++ .min = STAGE_1, ++ .max = STAGE_2, ++ .step_or_mask = 1, ++ .value = STAGE_2, ++ .hfi_id = HFI_PROP_STAGE, ++ .set = iris_set_stage, ++ }, ++ { ++ .cap_id = PIPE, ++ .min = PIPE_1, ++ .max = PIPE_4, ++ .step_or_mask = 1, ++ .value = PIPE_4, ++ .hfi_id = HFI_PROP_PIPE, ++ .set = iris_set_pipe, ++ }, ++ { ++ .cap_id = POC, ++ .min = 0, ++ .max = 2, ++ .step_or_mask = 1, ++ .value = 1, ++ .hfi_id = HFI_PROP_PIC_ORDER_CNT_TYPE, ++ }, ++ { ++ .cap_id = CODED_FRAMES, ++ .min = CODED_FRAMES_PROGRESSIVE, ++ .max = CODED_FRAMES_PROGRESSIVE, ++ .step_or_mask = 0, ++ .value = CODED_FRAMES_PROGRESSIVE, ++ .hfi_id = HFI_PROP_CODED_FRAMES, ++ }, ++ { ++ .cap_id = BIT_DEPTH, ++ .min = BIT_DEPTH_8, ++ .max = BIT_DEPTH_8, ++ .step_or_mask = 1, ++ .value = BIT_DEPTH_8, ++ .hfi_id = HFI_PROP_LUMA_CHROMA_BIT_DEPTH, ++ }, ++ { ++ .cap_id = RAP_FRAME, ++ .min = 0, ++ .max = 1, ++ .step_or_mask = 1, ++ .value = 1, ++ .hfi_id = HFI_PROP_DEC_START_FROM_RAP_FRAME, ++ .flags = CAP_FLAG_INPUT_PORT, ++ .set = iris_set_u32, + }, + }; + +@@ -102,6 +167,22 @@ static struct tz_cp_config tz_cp_config_sm8550 = { + .cp_nonpixel_size = 0x24800000, + }; + ++static const u32 sm8550_vdec_input_config_params[] = { ++ 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_output_config_params[] = { ++ HFI_PROP_COLOR_FORMAT, ++ HFI_PROP_LINEAR_STRIDE_SCANLINE, ++}; ++ + struct iris_platform_data sm8550_data = { + .get_instance = iris_hfi_gen2_get_instance, + .init_hfi_command_ops = iris_hfi_gen2_command_ops_init, +@@ -131,4 +212,12 @@ struct iris_platform_data sm8550_data = { + .ubwc_config = &ubwc_config_sm8550, + .num_vpp_pipe = 4, + .max_session_count = 16, ++ .input_config_params = ++ sm8550_vdec_input_config_params, ++ .input_config_params_size = ++ ARRAY_SIZE(sm8550_vdec_input_config_params), ++ .output_config_params = ++ sm8550_vdec_output_config_params, ++ .output_config_params_size = ++ ARRAY_SIZE(sm8550_vdec_output_config_params), + }; +diff --git a/drivers/media/platform/qcom/iris/iris_utils.c b/drivers/media/platform/qcom/iris/iris_utils.c +index 4833830f30d5..8bcfa97db97d 100644 +--- a/drivers/media/platform/qcom/iris/iris_utils.c ++++ b/drivers/media/platform/qcom/iris/iris_utils.c +@@ -8,6 +8,20 @@ + #include "iris_instance.h" + #include "iris_utils.h" + ++bool iris_res_is_less_than(u32 width, u32 height, ++ u32 ref_width, u32 ref_height) ++{ ++ u32 num_mbs = NUM_MBS_PER_FRAME(height, width); ++ u32 max_side = max(ref_width, ref_height); ++ ++ if (num_mbs < NUM_MBS_PER_FRAME(ref_height, ref_width) && ++ width < max_side && ++ height < max_side) ++ return true; ++ ++ return false; ++} ++ + int iris_get_mbpf(struct iris_inst *inst) + { + struct v4l2_format *inp_f = inst->fmt_src; +@@ -17,6 +31,11 @@ int iris_get_mbpf(struct iris_inst *inst) + return NUM_MBS_PER_FRAME(height, width); + } + ++bool iris_split_mode_enabled(struct iris_inst *inst) ++{ ++ return inst->fmt_dst->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_NV12; ++} ++ + int iris_wait_for_session_response(struct iris_inst *inst, bool is_flush) + { + struct iris_core *core = inst->core; +diff --git a/drivers/media/platform/qcom/iris/iris_utils.h b/drivers/media/platform/qcom/iris/iris_utils.h +index 40658a6643cf..3400847f5e72 100644 +--- a/drivers/media/platform/qcom/iris/iris_utils.h ++++ b/drivers/media/platform/qcom/iris/iris_utils.h +@@ -27,7 +27,10 @@ static inline enum iris_buffer_type iris_v4l2_type_to_driver(u32 type) + return BUF_OUTPUT; + } + ++bool iris_res_is_less_than(u32 width, u32 height, ++ u32 ref_width, u32 ref_height); + int iris_get_mbpf(struct iris_inst *inst); ++bool iris_split_mode_enabled(struct iris_inst *inst); + struct iris_inst *iris_get_instance(struct iris_core *core, u32 session_id); + int iris_wait_for_session_response(struct iris_inst *inst, bool is_flush); + +diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c +index 92651d86376d..13902f4e9724 100644 +--- a/drivers/media/platform/qcom/iris/iris_vdec.c ++++ b/drivers/media/platform/qcom/iris/iris_vdec.c +@@ -267,6 +267,12 @@ static int iris_vdec_process_streamon_input(struct iris_inst *inst) + + int iris_vdec_streamon_input(struct iris_inst *inst) + { ++ int ret; ++ ++ ret = iris_set_properties(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); ++ if (ret) ++ return ret; ++ + return iris_vdec_process_streamon_input(inst); + } + +@@ -284,8 +290,13 @@ static int iris_vdec_process_streamon_output(struct iris_inst *inst) + + int iris_vdec_streamon_output(struct iris_inst *inst) + { ++ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + int ret; + ++ ret = hfi_ops->session_set_config_params(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); ++ if (ret) ++ return ret; ++ + ret = iris_vdec_process_streamon_output(inst); + if (ret) + goto error; +diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c +index 2402a33723ab..0a65a17f13d2 100644 +--- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c ++++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c +@@ -6,6 +6,24 @@ + #include "iris_instance.h" + #include "iris_vpu_buffer.h" + ++u32 iris_vpu_dec_dpb_size(struct iris_inst *inst) ++{ ++ if (iris_split_mode_enabled(inst)) ++ return iris_get_buffer_size(inst, BUF_DPB); ++ else ++ return 0; ++} ++ ++static inline int iris_vpu_dpb_count(struct iris_inst *inst) ++{ ++ if (iris_split_mode_enabled(inst)) { ++ return inst->fw_min_count ? ++ inst->fw_min_count : inst->buffers[BUF_OUTPUT].min_count; ++ } ++ ++ return 0; ++} ++ + int iris_vpu_buf_count(struct iris_inst *inst, enum iris_buffer_type buffer_type) + { + switch (buffer_type) { +@@ -13,6 +31,8 @@ int iris_vpu_buf_count(struct iris_inst *inst, enum iris_buffer_type buffer_type + return MIN_BUFFERS; + case BUF_OUTPUT: + return inst->fw_min_count; ++ case BUF_DPB: ++ return iris_vpu_dpb_count(inst); + default: + return 0; + } +diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h +index 06e6e958dcac..865539d626b7 100644 +--- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h ++++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h +@@ -10,6 +10,7 @@ struct iris_inst; + + #define MIN_BUFFERS 4 + ++u32 iris_vpu_dec_dpb_size(struct iris_inst *inst); + int iris_vpu_buf_count(struct iris_inst *inst, enum iris_buffer_type buffer_type); + + #endif +-- +2.34.1 + diff --git a/patch/kernel/archive/sm8550-6.12/0018_media--iris--subscribe-parameters-and-properties-t.patch b/patch/kernel/archive/sm8550-6.12/0018_media--iris--subscribe-parameters-and-properties-t.patch new file mode 100644 index 000000000..2708a3515 --- /dev/null +++ b/patch/kernel/archive/sm8550-6.12/0018_media--iris--subscribe-parameters-and-properties-t.patch @@ -0,0 +1,331 @@ +From fdf8534d663da51ca7377eaea621c2470d7f6e01 Mon Sep 17 00:00:00 2001 +From: Vedang Nagar +Date: Fri, 7 Feb 2025 13:24:58 +0530 +Subject: [PATCH] media: iris: subscribe parameters and properties to firmware + for hfi_gen2 + +For hfi_gen2, subscribe different bitstream parameters on to firmware, +to get notified of a change in any of the subscribed parameters. + +Signed-off-by: Vedang Nagar +Tested-by: Stefan Schmidt # x1e80100 (Dell XPS 13 9345) +Reviewed-by: Stefan Schmidt +Tested-by: Neil Armstrong # on SM8550-QRD +Tested-by: Neil Armstrong # on SM8550-HDK +Signed-off-by: Dikshita Agarwal +Link: https://lore.kernel.org/r/20250207-qcom-video-iris-v10-18-ab66eeffbd20@quicinc.com +Signed-off-by: Neil Armstrong +--- + .../media/platform/qcom/iris/iris_hfi_gen2.h | 6 + + .../qcom/iris/iris_hfi_gen2_command.c | 174 ++++++++++++++++++ + .../qcom/iris/iris_hfi_gen2_defines.h | 9 + + .../platform/qcom/iris/iris_platform_common.h | 4 + + .../platform/qcom/iris/iris_platform_sm8550.c | 13 ++ + 5 files changed, 206 insertions(+) + +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2.h +index 676bcb3dc81f..0a946c1e3a4c 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2.h +@@ -18,12 +18,18 @@ struct iris_core; + * + * @inst: pointer to iris_instance structure + * @packet: HFI packet ++ * @ipsc_properties_set: boolean to set ipsc properties to fw ++ * @opsc_properties_set: boolean to set opsc properties to fw + * @src_subcr_params: subscription params to fw on input port ++ * @dst_subcr_params: subscription params to fw on output port + */ + struct iris_inst_hfi_gen2 { + struct iris_inst inst; + struct iris_hfi_header *packet; ++ bool ipsc_properties_set; ++ bool opsc_properties_set; + struct hfi_subscription_params src_subcr_params; ++ struct hfi_subscription_params dst_subcr_params; + }; + + void iris_hfi_gen2_command_ops_init(struct iris_core *core); +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +index 0845b75aafe9..dddaa074cae1 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +@@ -437,6 +437,9 @@ static int iris_hfi_gen2_session_open(struct iris_inst *inst) + if (inst->state != IRIS_INST_DEINIT) + return -EALREADY; + ++ inst_hfi_gen2->ipsc_properties_set = false; ++ inst_hfi_gen2->opsc_properties_set = false; ++ + inst_hfi_gen2->packet = kzalloc(4096, GFP_KERNEL); + if (!inst_hfi_gen2->packet) + return -ENOMEM; +@@ -501,9 +504,180 @@ static int iris_hfi_gen2_session_close(struct iris_inst *inst) + return ret; + } + ++static int iris_hfi_gen2_session_subscribe_mode(struct iris_inst *inst, ++ u32 cmd, u32 plane, u32 payload_type, ++ void *payload, u32 payload_size) ++{ ++ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); ++ ++ iris_hfi_gen2_packet_session_command(inst, ++ cmd, ++ (HFI_HOST_FLAGS_RESPONSE_REQUIRED | ++ HFI_HOST_FLAGS_INTR_REQUIRED), ++ iris_hfi_gen2_get_port(plane), ++ inst->session_id, ++ payload_type, ++ payload, ++ payload_size); ++ ++ return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet, ++ inst_hfi_gen2->packet->size); ++} ++ ++static int iris_hfi_gen2_subscribe_change_param(struct iris_inst *inst, u32 plane) ++{ ++ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); ++ struct hfi_subscription_params subsc_params; ++ u32 prop_type, payload_size, payload_type; ++ struct iris_core *core = inst->core; ++ const u32 *change_param; ++ u32 change_param_size; ++ u32 payload[32] = {0}; ++ u32 hfi_port = 0, i; ++ int ret; ++ ++ if ((V4L2_TYPE_IS_OUTPUT(plane) && inst_hfi_gen2->ipsc_properties_set) || ++ (V4L2_TYPE_IS_CAPTURE(plane) && inst_hfi_gen2->opsc_properties_set)) { ++ dev_err(core->dev, "invalid plane\n"); ++ return 0; ++ } ++ ++ change_param = core->iris_platform_data->input_config_params; ++ change_param_size = core->iris_platform_data->input_config_params_size; ++ ++ payload[0] = HFI_MODE_PORT_SETTINGS_CHANGE; ++ ++ for (i = 0; i < change_param_size; i++) ++ payload[i + 1] = change_param[i]; ++ ++ ret = iris_hfi_gen2_session_subscribe_mode(inst, ++ HFI_CMD_SUBSCRIBE_MODE, ++ plane, ++ HFI_PAYLOAD_U32_ARRAY, ++ &payload[0], ++ ((change_param_size + 1) * sizeof(u32))); ++ if (ret) ++ return ret; ++ ++ if (V4L2_TYPE_IS_OUTPUT(plane)) { ++ inst_hfi_gen2->ipsc_properties_set = true; ++ } else { ++ hfi_port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); ++ memcpy(&inst_hfi_gen2->dst_subcr_params, ++ &inst_hfi_gen2->src_subcr_params, ++ sizeof(inst_hfi_gen2->src_subcr_params)); ++ subsc_params = inst_hfi_gen2->dst_subcr_params; ++ for (i = 0; i < change_param_size; i++) { ++ payload[0] = 0; ++ payload[1] = 0; ++ payload_size = 0; ++ payload_type = 0; ++ prop_type = change_param[i]; ++ switch (prop_type) { ++ case HFI_PROP_BITSTREAM_RESOLUTION: ++ payload[0] = subsc_params.bitstream_resolution; ++ payload_size = sizeof(u32); ++ payload_type = HFI_PAYLOAD_U32; ++ break; ++ case HFI_PROP_CROP_OFFSETS: ++ payload[0] = subsc_params.crop_offsets[0]; ++ payload[1] = subsc_params.crop_offsets[1]; ++ payload_size = sizeof(u64); ++ payload_type = HFI_PAYLOAD_64_PACKED; ++ break; ++ case HFI_PROP_CODED_FRAMES: ++ payload[0] = subsc_params.coded_frames; ++ payload_size = sizeof(u32); ++ payload_type = HFI_PAYLOAD_U32; ++ break; ++ case HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT: ++ payload[0] = subsc_params.fw_min_count; ++ payload_size = sizeof(u32); ++ payload_type = HFI_PAYLOAD_U32; ++ break; ++ case HFI_PROP_PIC_ORDER_CNT_TYPE: ++ payload[0] = subsc_params.pic_order_cnt; ++ payload_size = sizeof(u32); ++ payload_type = HFI_PAYLOAD_U32; ++ break; ++ case HFI_PROP_SIGNAL_COLOR_INFO: ++ payload[0] = subsc_params.color_info; ++ payload_size = sizeof(u32); ++ payload_type = HFI_PAYLOAD_U32; ++ break; ++ case HFI_PROP_PROFILE: ++ payload[0] = subsc_params.profile; ++ payload_size = sizeof(u32); ++ payload_type = HFI_PAYLOAD_U32; ++ break; ++ case HFI_PROP_LEVEL: ++ payload[0] = subsc_params.level; ++ payload_size = sizeof(u32); ++ payload_type = HFI_PAYLOAD_U32; ++ break; ++ default: ++ prop_type = 0; ++ ret = -EINVAL; ++ break; ++ } ++ if (prop_type) { ++ ret = iris_hfi_gen2_session_set_property(inst, ++ prop_type, ++ HFI_HOST_FLAGS_NONE, ++ hfi_port, ++ payload_type, ++ &payload, ++ payload_size); ++ if (ret) ++ return ret; ++ } ++ } ++ inst_hfi_gen2->opsc_properties_set = true; ++ } ++ ++ return 0; ++} ++ ++static int iris_hfi_gen2_subscribe_property(struct iris_inst *inst, u32 plane) ++{ ++ struct iris_core *core = inst->core; ++ u32 subscribe_prop_size, i; ++ const u32 *subcribe_prop; ++ u32 payload[32] = {0}; ++ ++ payload[0] = HFI_MODE_PROPERTY; ++ ++ if (V4L2_TYPE_IS_OUTPUT(plane)) { ++ subscribe_prop_size = core->iris_platform_data->dec_input_prop_size; ++ subcribe_prop = core->iris_platform_data->dec_input_prop; ++ } else { ++ subscribe_prop_size = core->iris_platform_data->dec_output_prop_size; ++ subcribe_prop = core->iris_platform_data->dec_output_prop; ++ } ++ ++ for (i = 0; i < subscribe_prop_size; i++) ++ payload[i + 1] = subcribe_prop[i]; ++ ++ return iris_hfi_gen2_session_subscribe_mode(inst, ++ HFI_CMD_SUBSCRIBE_MODE, ++ plane, ++ HFI_PAYLOAD_U32_ARRAY, ++ &payload[0], ++ (subscribe_prop_size + 1) * sizeof(u32)); ++} ++ + static int iris_hfi_gen2_session_start(struct iris_inst *inst, u32 plane) + { + struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); ++ int ret = 0; ++ ++ ret = iris_hfi_gen2_subscribe_change_param(inst, plane); ++ if (ret) ++ return ret; ++ ++ ret = iris_hfi_gen2_subscribe_property(inst, plane); ++ if (ret) ++ return ret; + + iris_hfi_gen2_packet_session_command(inst, + HFI_CMD_START, +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +index 4c9604b05034..4fb7a4e4604d 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +@@ -17,6 +17,7 @@ + #define HFI_CMD_CLOSE 0x01000004 + #define HFI_CMD_START 0x01000005 + #define HFI_CMD_STOP 0x01000006 ++#define HFI_CMD_SUBSCRIBE_MODE 0x0100000B + #define HFI_CMD_END 0x01FFFFFF + + #define HFI_BITMASK_FRAME_MBS_ONLY_FLAG 0x00000001 +@@ -42,13 +43,16 @@ + #define HFI_PROP_PIPE 0x0300010b + #define HFI_PROP_LUMA_CHROMA_BIT_DEPTH 0x0300010f + #define HFI_PROP_CODED_FRAMES 0x03000120 ++#define HFI_PROP_CABAC_SESSION 0x03000121 + #define HFI_PROP_BUFFER_HOST_MAX_COUNT 0x03000123 + #define HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT 0x03000124 + #define HFI_PROP_PIC_ORDER_CNT_TYPE 0x03000128 + #define HFI_PROP_QUALITY_MODE 0x03000148 + #define HFI_PROP_SIGNAL_COLOR_INFO 0x03000155 ++#define HFI_PROP_PICTURE_TYPE 0x03000162 + #define HFI_PROP_DEC_DEFAULT_HEADER 0x03000168 + #define HFI_PROP_DEC_START_FROM_RAP_FRAME 0x03000169 ++#define HFI_PROP_NO_OUTPUT 0x0300016a + #define HFI_PROP_END 0x03FFFFFF + + #define HFI_SESSION_ERROR_BEGIN 0x04000000 +@@ -65,6 +69,11 @@ + #define HFI_SYS_ERROR_WD_TIMEOUT 0x05000001 + #define HFI_SYSTEM_ERROR_END 0x05FFFFFF + ++enum hfi_property_mode_type { ++ HFI_MODE_PORT_SETTINGS_CHANGE = 0x00000001, ++ HFI_MODE_PROPERTY = 0x00000002, ++}; ++ + enum hfi_color_format { + HFI_COLOR_FMT_OPAQUE = 0, + HFI_COLOR_FMT_NV12 = 1, +diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h +index 5643fb55b09e..50965450cbb9 100644 +--- a/drivers/media/platform/qcom/iris/iris_platform_common.h ++++ b/drivers/media/platform/qcom/iris/iris_platform_common.h +@@ -147,6 +147,10 @@ struct iris_platform_data { + unsigned int input_config_params_size; + const u32 *output_config_params; + unsigned int output_config_params_size; ++ const u32 *dec_input_prop; ++ unsigned int dec_input_prop_size; ++ const u32 *dec_output_prop; ++ unsigned int dec_output_prop_size; + }; + + #endif +diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +index 8a55c1f731c0..703e48802795 100644 +--- a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c ++++ b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +@@ -183,6 +183,15 @@ static const u32 sm8550_vdec_output_config_params[] = { + HFI_PROP_LINEAR_STRIDE_SCANLINE, + }; + ++static const u32 sm8550_vdec_subscribe_input_properties[] = { ++ HFI_PROP_NO_OUTPUT, ++}; ++ ++static const u32 sm8550_vdec_subscribe_output_properties[] = { ++ HFI_PROP_PICTURE_TYPE, ++ HFI_PROP_CABAC_SESSION, ++}; ++ + struct iris_platform_data sm8550_data = { + .get_instance = iris_hfi_gen2_get_instance, + .init_hfi_command_ops = iris_hfi_gen2_command_ops_init, +@@ -220,4 +229,8 @@ struct iris_platform_data sm8550_data = { + sm8550_vdec_output_config_params, + .output_config_params_size = + ARRAY_SIZE(sm8550_vdec_output_config_params), ++ .dec_input_prop = sm8550_vdec_subscribe_input_properties, ++ .dec_input_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_input_properties), ++ .dec_output_prop = sm8550_vdec_subscribe_output_properties, ++ .dec_output_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_output_properties), + }; +-- +2.34.1 + diff --git a/patch/kernel/archive/sm8550-6.12/0019_media--iris--allocate,-initialize-and-queue-intern.patch b/patch/kernel/archive/sm8550-6.12/0019_media--iris--allocate,-initialize-and-queue-intern.patch new file mode 100644 index 000000000..78a0353d7 --- /dev/null +++ b/patch/kernel/archive/sm8550-6.12/0019_media--iris--allocate,-initialize-and-queue-intern.patch @@ -0,0 +1,1477 @@ +From 1d0c9406d6b3174c928b1bd745912e63dfa4106e Mon Sep 17 00:00:00 2001 +From: Dikshita Agarwal +Date: Fri, 7 Feb 2025 13:24:59 +0530 +Subject: [PATCH] media: iris: allocate, initialize and queue internal buffers + +Implement the functions for creating, queueing, releasing and destroying +the buffers for internal usage. + +Tested-by: Stefan Schmidt # x1e80100 (Dell XPS 13 9345) +Reviewed-by: Stefan Schmidt +Tested-by: Neil Armstrong # on SM8550-QRD +Tested-by: Neil Armstrong # on SM8550-HDK +Signed-off-by: Dikshita Agarwal +Link: https://lore.kernel.org/r/20250207-qcom-video-iris-v10-19-ab66eeffbd20@quicinc.com +Signed-off-by: Neil Armstrong +--- + .../media/platform/qcom/iris/iris_buffer.c | 206 ++++++++++++++++ + .../media/platform/qcom/iris/iris_buffer.h | 7 + + .../platform/qcom/iris/iris_hfi_common.h | 4 + + .../qcom/iris/iris_hfi_gen1_command.c | 127 +++++++++- + .../qcom/iris/iris_hfi_gen1_defines.h | 37 +++ + .../qcom/iris/iris_hfi_gen1_response.c | 4 + + .../qcom/iris/iris_hfi_gen2_command.c | 132 ++++++++++ + .../qcom/iris/iris_hfi_gen2_defines.h | 9 + + .../platform/qcom/iris/iris_hfi_gen2_packet.h | 41 +++ + .../qcom/iris/iris_hfi_gen2_response.c | 149 ++++++++++- + .../platform/qcom/iris/iris_platform_common.h | 5 + + .../platform/qcom/iris/iris_platform_sm8550.c | 17 ++ + drivers/media/platform/qcom/iris/iris_vdec.c | 32 +++ + drivers/media/platform/qcom/iris/iris_vidc.c | 11 + + .../platform/qcom/iris/iris_vpu_buffer.c | 233 +++++++++++++++++- + .../platform/qcom/iris/iris_vpu_buffer.h | 77 +++++- + 16 files changed, 1087 insertions(+), 4 deletions(-) + +diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c +index 58d45d23393b..e9d372580b5f 100644 +--- a/drivers/media/platform/qcom/iris/iris_buffer.c ++++ b/drivers/media/platform/qcom/iris/iris_buffer.c +@@ -7,6 +7,7 @@ + + #include "iris_buffer.h" + #include "iris_instance.h" ++#include "iris_vpu_buffer.h" + + #define PIXELS_4K 4096 + #define MAX_WIDTH 4096 +@@ -228,6 +229,211 @@ int iris_get_buffer_size(struct iris_inst *inst, + } + } + ++static void iris_fill_internal_buf_info(struct iris_inst *inst, ++ enum iris_buffer_type buffer_type) ++{ ++ struct iris_buffers *buffers = &inst->buffers[buffer_type]; ++ ++ buffers->size = iris_vpu_buf_size(inst, buffer_type); ++ buffers->min_count = iris_vpu_buf_count(inst, buffer_type); ++} ++ ++void iris_get_internal_buffers(struct iris_inst *inst, u32 plane) ++{ ++ const struct iris_platform_data *platform_data = inst->core->iris_platform_data; ++ const u32 *internal_buf_type; ++ u32 internal_buffer_count, i; ++ ++ if (V4L2_TYPE_IS_OUTPUT(plane)) { ++ internal_buf_type = platform_data->dec_ip_int_buf_tbl; ++ internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size; ++ for (i = 0; i < internal_buffer_count; i++) ++ iris_fill_internal_buf_info(inst, internal_buf_type[i]); ++ } else { ++ internal_buf_type = platform_data->dec_op_int_buf_tbl; ++ internal_buffer_count = platform_data->dec_op_int_buf_tbl_size; ++ for (i = 0; i < internal_buffer_count; i++) ++ iris_fill_internal_buf_info(inst, internal_buf_type[i]); ++ } ++} ++ ++static int iris_create_internal_buffer(struct iris_inst *inst, ++ enum iris_buffer_type buffer_type, u32 index) ++{ ++ struct iris_buffers *buffers = &inst->buffers[buffer_type]; ++ struct iris_core *core = inst->core; ++ struct iris_buffer *buffer; ++ ++ if (!buffers->size) ++ return 0; ++ ++ buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); ++ if (!buffer) ++ return -ENOMEM; ++ ++ INIT_LIST_HEAD(&buffer->list); ++ buffer->type = buffer_type; ++ buffer->index = index; ++ buffer->buffer_size = buffers->size; ++ buffer->dma_attrs = DMA_ATTR_WRITE_COMBINE | DMA_ATTR_NO_KERNEL_MAPPING; ++ list_add_tail(&buffer->list, &buffers->list); ++ ++ buffer->kvaddr = dma_alloc_attrs(core->dev, buffer->buffer_size, ++ &buffer->device_addr, GFP_KERNEL, buffer->dma_attrs); ++ if (!buffer->kvaddr) ++ return -ENOMEM; ++ ++ return 0; ++} ++ ++int iris_create_internal_buffers(struct iris_inst *inst, u32 plane) ++{ ++ const struct iris_platform_data *platform_data = inst->core->iris_platform_data; ++ u32 internal_buffer_count, i, j; ++ struct iris_buffers *buffers; ++ const u32 *internal_buf_type; ++ int ret; ++ ++ if (V4L2_TYPE_IS_OUTPUT(plane)) { ++ internal_buf_type = platform_data->dec_ip_int_buf_tbl; ++ internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size; ++ } else { ++ internal_buf_type = platform_data->dec_op_int_buf_tbl; ++ internal_buffer_count = platform_data->dec_op_int_buf_tbl_size; ++ } ++ ++ for (i = 0; i < internal_buffer_count; i++) { ++ buffers = &inst->buffers[internal_buf_type[i]]; ++ for (j = 0; j < buffers->min_count; j++) { ++ ret = iris_create_internal_buffer(inst, internal_buf_type[i], j); ++ if (ret) ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++int iris_queue_buffer(struct iris_inst *inst, struct iris_buffer *buf) ++{ ++ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; ++ int ret; ++ ++ ret = hfi_ops->session_queue_buf(inst, buf); ++ if (ret) ++ return ret; ++ ++ buf->attr &= ~BUF_ATTR_DEFERRED; ++ buf->attr |= BUF_ATTR_QUEUED; ++ ++ return 0; ++} ++ ++int iris_queue_internal_buffers(struct iris_inst *inst, u32 plane) ++{ ++ const struct iris_platform_data *platform_data = inst->core->iris_platform_data; ++ struct iris_buffer *buffer, *next; ++ struct iris_buffers *buffers; ++ const u32 *internal_buf_type; ++ u32 internal_buffer_count, i; ++ int ret; ++ ++ if (V4L2_TYPE_IS_OUTPUT(plane)) { ++ internal_buf_type = platform_data->dec_ip_int_buf_tbl; ++ internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size; ++ } else { ++ internal_buf_type = platform_data->dec_op_int_buf_tbl; ++ internal_buffer_count = platform_data->dec_op_int_buf_tbl_size; ++ } ++ ++ for (i = 0; i < internal_buffer_count; i++) { ++ buffers = &inst->buffers[internal_buf_type[i]]; ++ list_for_each_entry_safe(buffer, next, &buffers->list, list) { ++ if (buffer->attr & BUF_ATTR_PENDING_RELEASE) ++ continue; ++ if (buffer->attr & BUF_ATTR_QUEUED) ++ continue; ++ ret = iris_queue_buffer(inst, buffer); ++ if (ret) ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++int iris_destroy_internal_buffer(struct iris_inst *inst, struct iris_buffer *buffer) ++{ ++ struct iris_core *core = inst->core; ++ ++ list_del(&buffer->list); ++ dma_free_attrs(core->dev, buffer->buffer_size, buffer->kvaddr, ++ buffer->device_addr, buffer->dma_attrs); ++ kfree(buffer); ++ ++ return 0; ++} ++ ++int iris_destroy_internal_buffers(struct iris_inst *inst, u32 plane) ++{ ++ const struct iris_platform_data *platform_data = inst->core->iris_platform_data; ++ struct iris_buffer *buf, *next; ++ struct iris_buffers *buffers; ++ const u32 *internal_buf_type; ++ u32 i, len; ++ int ret; ++ ++ if (V4L2_TYPE_IS_OUTPUT(plane)) { ++ internal_buf_type = platform_data->dec_ip_int_buf_tbl; ++ len = platform_data->dec_ip_int_buf_tbl_size; ++ } else { ++ internal_buf_type = platform_data->dec_op_int_buf_tbl; ++ len = platform_data->dec_op_int_buf_tbl_size; ++ } ++ ++ for (i = 0; i < len; i++) { ++ buffers = &inst->buffers[internal_buf_type[i]]; ++ list_for_each_entry_safe(buf, next, &buffers->list, list) { ++ ret = iris_destroy_internal_buffer(inst, buf); ++ if (ret) ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst) ++{ ++ struct iris_buffers *buffers = &inst->buffers[BUF_PERSIST]; ++ struct iris_buffer *buffer, *next; ++ int ret; ++ u32 i; ++ ++ if (!list_empty(&buffers->list)) ++ return 0; ++ ++ iris_fill_internal_buf_info(inst, BUF_PERSIST); ++ ++ for (i = 0; i < buffers->min_count; i++) { ++ ret = iris_create_internal_buffer(inst, BUF_PERSIST, i); ++ if (ret) ++ return ret; ++ } ++ ++ list_for_each_entry_safe(buffer, next, &buffers->list, list) { ++ if (buffer->attr & BUF_ATTR_PENDING_RELEASE) ++ continue; ++ if (buffer->attr & BUF_ATTR_QUEUED) ++ continue; ++ ret = iris_queue_buffer(inst, buffer); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ + void iris_vb2_queue_error(struct iris_inst *inst) + { + struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; +diff --git a/drivers/media/platform/qcom/iris/iris_buffer.h b/drivers/media/platform/qcom/iris/iris_buffer.h +index ae2ec5637108..73f3a16ff7a2 100644 +--- a/drivers/media/platform/qcom/iris/iris_buffer.h ++++ b/drivers/media/platform/qcom/iris/iris_buffer.h +@@ -102,6 +102,13 @@ struct iris_buffers { + }; + + int iris_get_buffer_size(struct iris_inst *inst, enum iris_buffer_type buffer_type); ++void iris_get_internal_buffers(struct iris_inst *inst, u32 plane); ++int iris_create_internal_buffers(struct iris_inst *inst, u32 plane); ++int iris_queue_internal_buffers(struct iris_inst *inst, u32 plane); ++int iris_destroy_internal_buffer(struct iris_inst *inst, struct iris_buffer *buffer); ++int iris_destroy_internal_buffers(struct iris_inst *inst, u32 plane); ++int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst); ++int iris_queue_buffer(struct iris_inst *inst, struct iris_buffer *buf); + void iris_vb2_queue_error(struct iris_inst *inst); + + #endif +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.h b/drivers/media/platform/qcom/iris/iris_hfi_common.h +index 1fba5a9292af..c54c88658633 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_common.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_common.h +@@ -9,6 +9,8 @@ + #include + #include + ++#include "iris_buffer.h" ++ + struct iris_inst; + struct iris_core; + +@@ -114,6 +116,8 @@ struct iris_hfi_command_ops { + void *payload, u32 payload_size); + int (*session_open)(struct iris_inst *inst); + int (*session_start)(struct iris_inst *inst, u32 plane); ++ int (*session_queue_buf)(struct iris_inst *inst, struct iris_buffer *buffer); ++ int (*session_release_buf)(struct iris_inst *inst, struct iris_buffer *buffer); + int (*session_stop)(struct iris_inst *inst, u32 plane); + int (*session_close)(struct iris_inst *inst); + }; +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +index 26fe65ddba8a..603ca485992d 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +@@ -8,6 +8,24 @@ + #include "iris_instance.h" + #include "iris_vpu_buffer.h" + ++static u32 iris_hfi_gen1_buf_type_from_driver(enum iris_buffer_type buffer_type) ++{ ++ switch (buffer_type) { ++ case BUF_INPUT: ++ return HFI_BUFFER_INPUT; ++ case BUF_OUTPUT: ++ return HFI_BUFFER_OUTPUT; ++ case BUF_PERSIST: ++ return HFI_BUFFER_INTERNAL_PERSIST_1; ++ case BUF_BIN: ++ return HFI_BUFFER_INTERNAL_SCRATCH; ++ case BUF_SCRATCH_1: ++ return HFI_BUFFER_INTERNAL_SCRATCH_1; ++ default: ++ return -EINVAL; ++ } ++} ++ + static int iris_hfi_gen1_sys_init(struct iris_core *core) + { + struct hfi_sys_init_pkt sys_init_pkt; +@@ -183,6 +201,111 @@ static int iris_hfi_gen1_session_stop(struct iris_inst *inst, u32 plane) + return ret; + } + ++static int iris_hfi_gen1_queue_internal_buffer(struct iris_inst *inst, struct iris_buffer *buf) ++{ ++ struct hfi_session_set_buffers_pkt *int_pkt; ++ u32 buffer_type, i; ++ u32 packet_size; ++ int ret; ++ ++ packet_size = struct_size(int_pkt, buffer_info, 1); ++ int_pkt = kzalloc(packet_size, GFP_KERNEL); ++ if (!int_pkt) ++ return -ENOMEM; ++ ++ int_pkt->shdr.hdr.pkt_type = HFI_CMD_SESSION_SET_BUFFERS; ++ int_pkt->shdr.session_id = inst->session_id; ++ int_pkt->buffer_size = buf->buffer_size; ++ int_pkt->min_buffer_size = buf->buffer_size; ++ int_pkt->num_buffers = 1; ++ int_pkt->extradata_size = 0; ++ int_pkt->shdr.hdr.size = packet_size; ++ for (i = 0; i < int_pkt->num_buffers; i++) ++ int_pkt->buffer_info[i] = buf->device_addr; ++ buffer_type = iris_hfi_gen1_buf_type_from_driver(buf->type); ++ if (buffer_type == -EINVAL) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ int_pkt->buffer_type = buffer_type; ++ ret = iris_hfi_queue_cmd_write(inst->core, int_pkt, int_pkt->shdr.hdr.size); ++ ++exit: ++ kfree(int_pkt); ++ ++ return ret; ++} ++ ++static int iris_hfi_gen1_session_queue_buffer(struct iris_inst *inst, struct iris_buffer *buf) ++{ ++ switch (buf->type) { ++ case BUF_PERSIST: ++ case BUF_BIN: ++ case BUF_SCRATCH_1: ++ return iris_hfi_gen1_queue_internal_buffer(inst, buf); ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int iris_hfi_gen1_session_unset_buffers(struct iris_inst *inst, struct iris_buffer *buf) ++{ ++ struct hfi_session_release_buffer_pkt *pkt; ++ u32 packet_size, buffer_type, i; ++ int ret; ++ ++ buffer_type = iris_hfi_gen1_buf_type_from_driver(buf->type); ++ if (buffer_type == -EINVAL) ++ return -EINVAL; ++ ++ if (buffer_type == HFI_BUFFER_INPUT) ++ return 0; ++ ++ packet_size = sizeof(*pkt) + sizeof(struct hfi_buffer_info); ++ pkt = kzalloc(packet_size, GFP_KERNEL); ++ if (!pkt) ++ return -ENOMEM; ++ ++ pkt->shdr.hdr.pkt_type = HFI_CMD_SESSION_RELEASE_BUFFERS; ++ pkt->shdr.session_id = inst->session_id; ++ pkt->buffer_size = buf->buffer_size; ++ pkt->num_buffers = 1; ++ ++ if (buffer_type == HFI_BUFFER_OUTPUT || ++ buffer_type == HFI_BUFFER_OUTPUT2) { ++ struct hfi_buffer_info *bi; ++ ++ bi = (struct hfi_buffer_info *)pkt->buffer_info; ++ for (i = 0; i < pkt->num_buffers; i++) { ++ bi->buffer_addr = buf->device_addr; ++ bi->extradata_addr = 0; ++ } ++ pkt->shdr.hdr.size = packet_size; ++ } else { ++ for (i = 0; i < pkt->num_buffers; i++) ++ pkt->buffer_info[i] = buf->device_addr; ++ pkt->extradata_size = 0; ++ pkt->shdr.hdr.size = ++ sizeof(struct hfi_session_set_buffers_pkt) + ++ ((pkt->num_buffers) * sizeof(u32)); ++ } ++ ++ pkt->response_req = true; ++ pkt->buffer_type = buffer_type; ++ ++ ret = iris_hfi_queue_cmd_write(inst->core, pkt, pkt->shdr.hdr.size); ++ if (ret) ++ goto exit; ++ ++ ret = iris_wait_for_session_response(inst, false); ++ ++exit: ++ kfree(pkt); ++ ++ return ret; ++} ++ + static int + iris_hfi_gen1_packet_session_set_property(struct hfi_session_set_property_pkt *packet, + struct iris_inst *inst, u32 ptype, void *pdata) +@@ -495,7 +618,7 @@ static int iris_hfi_gen1_set_bufsize(struct iris_inst *inst) + + if (iris_split_mode_enabled(inst)) { + bufsz.type = HFI_BUFFER_OUTPUT; +- bufsz.size = iris_vpu_dec_dpb_size(inst); ++ bufsz.size = iris_vpu_buf_size(inst, BUF_DPB); + + ret = hfi_gen1_set_property(inst, ptype, &bufsz, sizeof(bufsz)); + if (ret) +@@ -600,6 +723,8 @@ static const struct iris_hfi_command_ops iris_hfi_gen1_command_ops = { + .session_set_config_params = iris_hfi_gen1_session_set_config_params, + .session_set_property = iris_hfi_gen1_session_set_property, + .session_start = iris_hfi_gen1_session_start, ++ .session_queue_buf = iris_hfi_gen1_session_queue_buffer, ++ .session_release_buf = iris_hfi_gen1_session_unset_buffers, + .session_stop = iris_hfi_gen1_session_stop, + .session_close = iris_hfi_gen1_session_close, + }; +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +index 67e7575351d4..cabd91eafc92 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +@@ -24,11 +24,13 @@ + #define HFI_CMD_SYS_SESSION_END 0x10008 + + #define HFI_CMD_SESSION_SET_PROPERTY 0x11001 ++#define HFI_CMD_SESSION_SET_BUFFERS 0x11002 + + #define HFI_CMD_SESSION_LOAD_RESOURCES 0x211001 + #define HFI_CMD_SESSION_START 0x211002 + #define HFI_CMD_SESSION_STOP 0x211003 + #define HFI_CMD_SESSION_FLUSH 0x211008 ++#define HFI_CMD_SESSION_RELEASE_BUFFERS 0x21100b + #define HFI_CMD_SESSION_RELEASE_RESOURCES 0x21100c + + #define HFI_ERR_SESSION_UNSUPPORTED_SETTING 0x1008 +@@ -53,6 +55,9 @@ + #define HFI_BUFFER_INPUT 0x1 + #define HFI_BUFFER_OUTPUT 0x2 + #define HFI_BUFFER_OUTPUT2 0x3 ++#define HFI_BUFFER_INTERNAL_PERSIST_1 0x5 ++#define HFI_BUFFER_INTERNAL_SCRATCH 0x6 ++#define HFI_BUFFER_INTERNAL_SCRATCH_1 0x7 + + #define HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL 0x5 + #define HFI_PROPERTY_SYS_IMAGE_VERSION 0x6 +@@ -80,6 +85,7 @@ + #define HFI_MSG_SESSION_STOP 0x221003 + #define HFI_MSG_SESSION_FLUSH 0x221006 + #define HFI_MSG_SESSION_RELEASE_RESOURCES 0x22100a ++#define HFI_MSG_SESSION_RELEASE_BUFFERS 0x22100c + + struct hfi_pkt_hdr { + u32 size; +@@ -128,11 +134,36 @@ struct hfi_sys_pc_prep_pkt { + struct hfi_pkt_hdr hdr; + }; + ++struct hfi_session_set_buffers_pkt { ++ struct hfi_session_hdr_pkt shdr; ++ u32 buffer_type; ++ u32 buffer_size; ++ u32 extradata_size; ++ u32 min_buffer_size; ++ u32 num_buffers; ++ u32 buffer_info[]; ++}; ++ + struct hfi_session_flush_pkt { + struct hfi_session_hdr_pkt shdr; + u32 flush_type; + }; + ++struct hfi_session_release_buffer_pkt { ++ struct hfi_session_hdr_pkt shdr; ++ u32 buffer_type; ++ u32 buffer_size; ++ u32 extradata_size; ++ u32 response_req; ++ u32 num_buffers; ++ u32 buffer_info[]; ++}; ++ ++struct hfi_buffer_info { ++ u32 buffer_addr; ++ u32 extradata_addr; ++}; ++ + struct hfi_msg_event_notify_pkt { + struct hfi_session_hdr_pkt shdr; + u32 event_id; +@@ -227,6 +258,12 @@ struct hfi_multi_stream { + u32 enable; + }; + ++struct hfi_msg_session_release_buffers_done_pkt { ++ struct hfi_msg_session_hdr_pkt shdr; ++ u32 num_buffers; ++ u32 buffer_info[]; ++}; ++ + struct hfi_msg_sys_debug_pkt { + struct hfi_pkt_hdr hdr; + u32 msg_type; +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c +index db5858ec04ea..a84bb00388d9 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c +@@ -176,6 +176,10 @@ static const struct iris_hfi_gen1_response_pkt_info pkt_infos[] = { + .pkt = HFI_MSG_SESSION_RELEASE_RESOURCES, + .pkt_sz = sizeof(struct hfi_msg_session_hdr_pkt), + }, ++ { ++ .pkt = HFI_MSG_SESSION_RELEASE_BUFFERS, ++ .pkt_sz = sizeof(struct hfi_msg_session_release_buffers_done_pkt), ++ }, + }; + + static void iris_hfi_gen1_handle_response(struct iris_core *core, void *response) +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +index dddaa074cae1..cc75231f07f1 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +@@ -100,6 +100,24 @@ static u32 iris_hfi_gen2_get_port(u32 plane) + } + } + ++static u32 iris_hfi_gen2_get_port_from_buf_type(enum iris_buffer_type buffer_type) ++{ ++ switch (buffer_type) { ++ case BUF_INPUT: ++ case BUF_BIN: ++ case BUF_COMV: ++ case BUF_NON_COMV: ++ case BUF_LINE: ++ return HFI_PORT_BITSTREAM; ++ case BUF_OUTPUT: ++ case BUF_DPB: ++ return HFI_PORT_RAW; ++ case BUF_PERSIST: ++ default: ++ return HFI_PORT_NONE; ++ } ++} ++ + static int iris_hfi_gen2_session_set_property(struct iris_inst *inst, u32 packet_type, u32 flag, + u32 plane, u32 payload_type, void *payload, + u32 payload_size) +@@ -719,6 +737,118 @@ static int iris_hfi_gen2_session_stop(struct iris_inst *inst, u32 plane) + return iris_wait_for_session_response(inst, false); + } + ++static u32 iris_hfi_gen2_buf_type_from_driver(enum iris_buffer_type buffer_type) ++{ ++ switch (buffer_type) { ++ case BUF_INPUT: ++ return HFI_BUFFER_BITSTREAM; ++ case BUF_OUTPUT: ++ return HFI_BUFFER_RAW; ++ case BUF_BIN: ++ return HFI_BUFFER_BIN; ++ case BUF_COMV: ++ return HFI_BUFFER_COMV; ++ case BUF_NON_COMV: ++ return HFI_BUFFER_NON_COMV; ++ case BUF_LINE: ++ return HFI_BUFFER_LINE; ++ case BUF_DPB: ++ return HFI_BUFFER_DPB; ++ case BUF_PERSIST: ++ return HFI_BUFFER_PERSIST; ++ default: ++ return 0; ++ } ++} ++ ++static int iris_set_num_comv(struct iris_inst *inst) ++{ ++ struct platform_inst_caps *caps; ++ struct iris_core *core = inst->core; ++ u32 num_comv; ++ ++ caps = core->iris_platform_data->inst_caps; ++ num_comv = caps->num_comv; ++ ++ return core->hfi_ops->session_set_property(inst, ++ HFI_PROP_COMV_BUFFER_COUNT, ++ HFI_HOST_FLAGS_NONE, ++ HFI_PORT_BITSTREAM, ++ HFI_PAYLOAD_U32, ++ &num_comv, sizeof(u32)); ++} ++ ++static void iris_hfi_gen2_get_buffer(struct iris_buffer *buffer, struct iris_hfi_buffer *buf) ++{ ++ memset(buf, 0, sizeof(*buf)); ++ buf->type = iris_hfi_gen2_buf_type_from_driver(buffer->type); ++ buf->index = buffer->index; ++ buf->base_address = buffer->device_addr; ++ buf->addr_offset = 0; ++ buf->buffer_size = buffer->buffer_size; ++ ++ if (buffer->type == BUF_INPUT) ++ buf->buffer_size = ALIGN(buffer->buffer_size, 256); ++ buf->data_offset = buffer->data_offset; ++ buf->data_size = buffer->data_size; ++ if (buffer->attr & BUF_ATTR_PENDING_RELEASE) ++ buf->flags |= HFI_BUF_HOST_FLAG_RELEASE; ++ buf->flags |= HFI_BUF_HOST_FLAGS_CB_NON_SECURE; ++ buf->timestamp = buffer->timestamp; ++} ++ ++static int iris_hfi_gen2_session_queue_buffer(struct iris_inst *inst, struct iris_buffer *buffer) ++{ ++ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); ++ struct iris_hfi_buffer hfi_buffer; ++ u32 port; ++ int ret; ++ ++ iris_hfi_gen2_get_buffer(buffer, &hfi_buffer); ++ if (buffer->type == BUF_COMV) { ++ ret = iris_set_num_comv(inst); ++ if (ret) ++ return ret; ++ } ++ ++ port = iris_hfi_gen2_get_port_from_buf_type(buffer->type); ++ iris_hfi_gen2_packet_session_command(inst, ++ HFI_CMD_BUFFER, ++ HFI_HOST_FLAGS_INTR_REQUIRED, ++ port, ++ inst->session_id, ++ HFI_PAYLOAD_STRUCTURE, ++ &hfi_buffer, ++ sizeof(hfi_buffer)); ++ ++ return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet, ++ inst_hfi_gen2->packet->size); ++} ++ ++static int iris_hfi_gen2_session_release_buffer(struct iris_inst *inst, struct iris_buffer *buffer) ++{ ++ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); ++ struct iris_hfi_buffer hfi_buffer; ++ u32 port; ++ ++ iris_hfi_gen2_get_buffer(buffer, &hfi_buffer); ++ hfi_buffer.flags |= HFI_BUF_HOST_FLAG_RELEASE; ++ port = iris_hfi_gen2_get_port_from_buf_type(buffer->type); ++ ++ iris_hfi_gen2_packet_session_command(inst, ++ HFI_CMD_BUFFER, ++ (HFI_HOST_FLAGS_RESPONSE_REQUIRED | ++ HFI_HOST_FLAGS_INTR_REQUIRED), ++ port, ++ inst->session_id, ++ HFI_PAYLOAD_STRUCTURE, ++ &hfi_buffer, ++ sizeof(hfi_buffer)); ++ ++ return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet, ++ inst_hfi_gen2->packet->size); ++} ++ + static const struct iris_hfi_command_ops iris_hfi_gen2_command_ops = { + .sys_init = iris_hfi_gen2_sys_init, + .sys_image_version = iris_hfi_gen2_sys_image_version, +@@ -728,6 +858,8 @@ static const struct iris_hfi_command_ops iris_hfi_gen2_command_ops = { + .session_set_config_params = iris_hfi_gen2_session_set_config_params, + .session_set_property = iris_hfi_gen2_session_set_property, + .session_start = iris_hfi_gen2_session_start, ++ .session_queue_buf = iris_hfi_gen2_session_queue_buffer, ++ .session_release_buf = iris_hfi_gen2_session_release_buffer, + .session_stop = iris_hfi_gen2_session_stop, + .session_close = iris_hfi_gen2_session_close, + }; +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +index 4fb7a4e4604d..afbdf1f1e68a 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +@@ -17,6 +17,7 @@ + #define HFI_CMD_CLOSE 0x01000004 + #define HFI_CMD_START 0x01000005 + #define HFI_CMD_STOP 0x01000006 ++#define HFI_CMD_BUFFER 0x01000009 + #define HFI_CMD_SUBSCRIBE_MODE 0x0100000B + #define HFI_CMD_END 0x01FFFFFF + +@@ -53,6 +54,7 @@ + #define HFI_PROP_DEC_DEFAULT_HEADER 0x03000168 + #define HFI_PROP_DEC_START_FROM_RAP_FRAME 0x03000169 + #define HFI_PROP_NO_OUTPUT 0x0300016a ++#define HFI_PROP_COMV_BUFFER_COUNT 0x03000193 + #define HFI_PROP_END 0x03FFFFFF + + #define HFI_SESSION_ERROR_BEGIN 0x04000000 +@@ -106,6 +108,13 @@ enum hfi_buffer_type { + HFI_BUFFER_VPSS = 0x0000000D, + }; + ++enum hfi_buffer_host_flags { ++ HFI_BUF_HOST_FLAG_RELEASE = 0x00000001, ++ HFI_BUF_HOST_FLAG_READONLY = 0x00000010, ++ HFI_BUF_HOST_FLAG_CODEC_CONFIG = 0x00000100, ++ HFI_BUF_HOST_FLAGS_CB_NON_SECURE = 0x00000200, ++}; ++ + enum hfi_packet_firmware_flags { + HFI_FW_FLAGS_SUCCESS = 0x00000001, + HFI_FW_FLAGS_INFORMATION = 0x00000002, +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h +index 0333e37572f6..25b9582349ca 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h +@@ -61,6 +61,47 @@ struct iris_hfi_packet { + u32 payload[]; + }; + ++/** ++ * struct iris_hfi_buffer ++ * ++ * @type: buffer type indicated by "enum hfi_buffer_type" ++ * FW needs to return proper type for any buffer command. ++ * @index: index of the buffer ++ * @base_address: base address of the buffer. ++ * This buffer address is always 4KBytes aligned. ++ * @addr_offset: accessible buffer offset from base address ++ * Decoder bitstream buffer: 256 Bytes aligned ++ * Firmware can uniquely identify a buffer based on ++ * base_address & addr_offset. ++ * HW can read memory only from base_address+addr_offset. ++ * @buffer_size: accessible buffer size in bytes starting from addr_offset ++ * @data_offset: data starts from "base_address + addr_offset + data_offset" ++ * RAW buffer: data_offset is 0. Restriction: 4KBytes aligned ++ * decoder bitstream buffer: no restriction (can be any value) ++ * @data_size: data size in bytes ++ * @flags: buffer flags. It is represented as bit masks. ++ * host buffer flags are "enum hfi_buffer_host_flags" ++ * firmware buffer flags are "enum hfi_buffer_firmware_flags" ++ * @timestamp: timestamp of the buffer in nano seconds (ns) ++ * It is Presentation timestamp (PTS) for encoder & decoder. ++ * Decoder: it is pass through from bitstream to raw buffer. ++ * firmware does not need to return as part of input buffer done. ++ * For any internal buffers: there is no timestamp. Host sets as 0. ++ * @reserved: reserved for future use ++ */ ++struct iris_hfi_buffer { ++ u32 type; ++ u32 index; ++ u64 base_address; ++ u32 addr_offset; ++ u32 buffer_size; ++ u32 data_offset; ++ u32 data_size; ++ u64 timestamp; ++ u32 flags; ++ u32 reserved[5]; ++}; ++ + u32 iris_hfi_gen2_get_color_primaries(u32 primaries); + u32 iris_hfi_gen2_get_transfer_char(u32 characterstics); + u32 iris_hfi_gen2_get_matrix_coefficients(u32 coefficients); +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c +index 336b43740b72..9f3764f1903b 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c +@@ -25,6 +25,94 @@ struct iris_hfi_gen2_packet_handle { + int (*handle)(struct iris_inst *inst, struct iris_hfi_packet *pkt); + }; + ++static u32 iris_hfi_gen2_buf_type_to_driver(enum hfi_buffer_type buf_type) ++{ ++ switch (buf_type) { ++ case HFI_BUFFER_BITSTREAM: ++ return BUF_INPUT; ++ case HFI_BUFFER_RAW: ++ return BUF_OUTPUT; ++ case HFI_BUFFER_BIN: ++ return BUF_BIN; ++ case HFI_BUFFER_ARP: ++ return BUF_ARP; ++ case HFI_BUFFER_COMV: ++ return BUF_COMV; ++ case HFI_BUFFER_NON_COMV: ++ return BUF_NON_COMV; ++ case HFI_BUFFER_LINE: ++ return BUF_LINE; ++ case HFI_BUFFER_DPB: ++ return BUF_DPB; ++ case HFI_BUFFER_PERSIST: ++ return BUF_PERSIST; ++ default: ++ return 0; ++ } ++} ++ ++static bool iris_hfi_gen2_is_valid_hfi_buffer_type(u32 buffer_type) ++{ ++ switch (buffer_type) { ++ case HFI_BUFFER_BITSTREAM: ++ case HFI_BUFFER_RAW: ++ case HFI_BUFFER_BIN: ++ case HFI_BUFFER_ARP: ++ case HFI_BUFFER_COMV: ++ case HFI_BUFFER_NON_COMV: ++ case HFI_BUFFER_LINE: ++ case HFI_BUFFER_DPB: ++ case HFI_BUFFER_PERSIST: ++ case HFI_BUFFER_VPSS: ++ return true; ++ default: ++ return false; ++ } ++} ++ ++static bool iris_hfi_gen2_is_valid_hfi_port(u32 port, u32 buffer_type) ++{ ++ if (port == HFI_PORT_NONE && buffer_type != HFI_BUFFER_PERSIST) ++ return false; ++ ++ if (port != HFI_PORT_BITSTREAM && port != HFI_PORT_RAW) ++ return false; ++ ++ return true; ++} ++ ++static bool iris_hfi_gen2_validate_packet_payload(struct iris_hfi_packet *pkt) ++{ ++ u32 payload_size = 0; ++ ++ switch (pkt->payload_info) { ++ case HFI_PAYLOAD_U32: ++ case HFI_PAYLOAD_S32: ++ case HFI_PAYLOAD_Q16: ++ case HFI_PAYLOAD_U32_ENUM: ++ case HFI_PAYLOAD_32_PACKED: ++ payload_size = 4; ++ break; ++ case HFI_PAYLOAD_U64: ++ case HFI_PAYLOAD_S64: ++ case HFI_PAYLOAD_64_PACKED: ++ payload_size = 8; ++ break; ++ case HFI_PAYLOAD_STRUCTURE: ++ if (pkt->type == HFI_CMD_BUFFER) ++ payload_size = sizeof(struct iris_hfi_buffer); ++ break; ++ default: ++ payload_size = 0; ++ break; ++ } ++ ++ if (pkt->size < sizeof(struct iris_hfi_packet) + payload_size) ++ return false; ++ ++ return true; ++} ++ + static int iris_hfi_gen2_validate_packet(u8 *response_pkt, u8 *core_resp_pkt) + { + u8 *response_limit = core_resp_pkt + IFACEQ_CORE_PKT_SIZE; +@@ -149,9 +237,65 @@ static void iris_hfi_gen2_handle_session_close(struct iris_inst *inst, + complete(&inst->completion); + } + ++static int iris_hfi_gen2_handle_release_internal_buffer(struct iris_inst *inst, ++ struct iris_hfi_buffer *buffer) ++{ ++ struct iris_buffer *buf, *iter; ++ struct iris_buffers *buffers; ++ u32 buf_type; ++ int ret = 0; ++ bool found; ++ ++ buf_type = iris_hfi_gen2_buf_type_to_driver(buffer->type); ++ buffers = &inst->buffers[buf_type]; ++ ++ found = false; ++ list_for_each_entry(iter, &buffers->list, list) { ++ if (iter->device_addr == buffer->base_address) { ++ found = true; ++ buf = iter; ++ break; ++ } ++ } ++ if (!found) ++ return -EINVAL; ++ ++ buf->attr &= ~BUF_ATTR_QUEUED; ++ ++ if (buf->attr & BUF_ATTR_PENDING_RELEASE) ++ ret = iris_destroy_internal_buffer(inst, buf); ++ ++ return ret; ++} ++ ++static int iris_hfi_gen2_handle_session_buffer(struct iris_inst *inst, ++ struct iris_hfi_packet *pkt) ++{ ++ struct iris_hfi_buffer *buffer; ++ ++ if (pkt->payload_info == HFI_PAYLOAD_NONE) ++ return 0; ++ ++ if (!iris_hfi_gen2_validate_packet_payload(pkt)) { ++ iris_inst_change_state(inst, IRIS_INST_ERROR); ++ return 0; ++ } ++ ++ buffer = (struct iris_hfi_buffer *)((u8 *)pkt + sizeof(*pkt)); ++ if (!iris_hfi_gen2_is_valid_hfi_buffer_type(buffer->type)) ++ return 0; ++ ++ if (!iris_hfi_gen2_is_valid_hfi_port(pkt->port, buffer->type)) ++ return 0; ++ ++ return iris_hfi_gen2_handle_release_internal_buffer(inst, buffer); ++} ++ + static int iris_hfi_gen2_handle_session_command(struct iris_inst *inst, + struct iris_hfi_packet *pkt) + { ++ int ret = 0; ++ + switch (pkt->type) { + case HFI_CMD_CLOSE: + iris_hfi_gen2_handle_session_close(inst, pkt); +@@ -159,11 +303,14 @@ static int iris_hfi_gen2_handle_session_command(struct iris_inst *inst, + case HFI_CMD_STOP: + complete(&inst->completion); + break; ++ case HFI_CMD_BUFFER: ++ ret = iris_hfi_gen2_handle_session_buffer(inst, pkt); ++ break; + default: + break; + } + +- return 0; ++ return ret; + } + + static int iris_hfi_gen2_handle_session_property(struct iris_inst *inst, +diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h +index 50965450cbb9..de0388a100c3 100644 +--- a/drivers/media/platform/qcom/iris/iris_platform_common.h ++++ b/drivers/media/platform/qcom/iris/iris_platform_common.h +@@ -67,6 +67,7 @@ struct platform_inst_caps { + u32 min_frame_height; + u32 max_frame_height; + u32 max_mbpf; ++ u32 num_comv; + }; + + enum platform_inst_fw_cap_type { +@@ -151,6 +152,10 @@ struct iris_platform_data { + unsigned int dec_input_prop_size; + const u32 *dec_output_prop; + unsigned int dec_output_prop_size; ++ const u32 *dec_ip_int_buf_tbl; ++ unsigned int dec_ip_int_buf_tbl_size; ++ const u32 *dec_op_int_buf_tbl; ++ unsigned int dec_op_int_buf_tbl_size; + }; + + #endif +diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +index 703e48802795..dc51df71c377 100644 +--- a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c ++++ b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +@@ -126,6 +126,7 @@ static struct platform_inst_caps platform_inst_cap_sm8550 = { + .min_frame_height = 96, + .max_frame_height = 8192, + .max_mbpf = (8192 * 4352) / 256, ++ .num_comv = 0, + }; + + static void iris_set_sm8550_preset_registers(struct iris_core *core) +@@ -192,6 +193,17 @@ static const u32 sm8550_vdec_subscribe_output_properties[] = { + HFI_PROP_CABAC_SESSION, + }; + ++static const u32 sm8550_dec_ip_int_buf_tbl[] = { ++ BUF_BIN, ++ BUF_COMV, ++ BUF_NON_COMV, ++ BUF_LINE, ++}; ++ ++static const u32 sm8550_dec_op_int_buf_tbl[] = { ++ BUF_DPB, ++}; ++ + struct iris_platform_data sm8550_data = { + .get_instance = iris_hfi_gen2_get_instance, + .init_hfi_command_ops = iris_hfi_gen2_command_ops_init, +@@ -233,4 +245,9 @@ struct iris_platform_data sm8550_data = { + .dec_input_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_input_properties), + .dec_output_prop = sm8550_vdec_subscribe_output_properties, + .dec_output_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_output_properties), ++ ++ .dec_ip_int_buf_tbl = sm8550_dec_ip_int_buf_tbl, ++ .dec_ip_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_ip_int_buf_tbl), ++ .dec_op_int_buf_tbl = sm8550_dec_op_int_buf_tbl, ++ .dec_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_op_int_buf_tbl), + }; +diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c +index 13902f4e9724..8d489530da31 100644 +--- a/drivers/media/platform/qcom/iris/iris_vdec.c ++++ b/drivers/media/platform/qcom/iris/iris_vdec.c +@@ -273,6 +273,24 @@ int iris_vdec_streamon_input(struct iris_inst *inst) + if (ret) + return ret; + ++ ret = iris_alloc_and_queue_persist_bufs(inst); ++ if (ret) ++ return ret; ++ ++ iris_get_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); ++ ++ ret = iris_destroy_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); ++ if (ret) ++ return ret; ++ ++ ret = iris_create_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); ++ if (ret) ++ return ret; ++ ++ ret = iris_queue_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); ++ if (ret) ++ return ret; ++ + return iris_vdec_process_streamon_input(inst); + } + +@@ -297,10 +315,24 @@ int iris_vdec_streamon_output(struct iris_inst *inst) + if (ret) + return ret; + ++ iris_get_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); ++ ++ ret = iris_destroy_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); ++ if (ret) ++ return ret; ++ ++ ret = iris_create_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); ++ if (ret) ++ return ret; ++ + ret = iris_vdec_process_streamon_output(inst); + if (ret) + goto error; + ++ ret = iris_queue_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); ++ if (ret) ++ goto error; ++ + return ret; + + error: +diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c +index 1d10c430c795..ec5694c1c8de 100644 +--- a/drivers/media/platform/qcom/iris/iris_vidc.c ++++ b/drivers/media/platform/qcom/iris/iris_vidc.c +@@ -149,6 +149,15 @@ int iris_open(struct file *filp) + + mutex_init(&inst->lock); + mutex_init(&inst->ctx_q_lock); ++ ++ INIT_LIST_HEAD(&inst->buffers[BUF_BIN].list); ++ INIT_LIST_HEAD(&inst->buffers[BUF_ARP].list); ++ INIT_LIST_HEAD(&inst->buffers[BUF_COMV].list); ++ INIT_LIST_HEAD(&inst->buffers[BUF_NON_COMV].list); ++ INIT_LIST_HEAD(&inst->buffers[BUF_LINE].list); ++ INIT_LIST_HEAD(&inst->buffers[BUF_DPB].list); ++ INIT_LIST_HEAD(&inst->buffers[BUF_PERSIST].list); ++ INIT_LIST_HEAD(&inst->buffers[BUF_SCRATCH_1].list); + init_completion(&inst->completion); + init_completion(&inst->flush_completion); + +@@ -221,6 +230,8 @@ int iris_close(struct file *filp) + iris_session_close(inst); + iris_inst_change_state(inst, IRIS_INST_DEINIT); + iris_v4l2_fh_deinit(inst); ++ iris_destroy_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); ++ iris_destroy_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + iris_remove_session(inst); + mutex_unlock(&inst->lock); + mutex_destroy(&inst->ctx_q_lock); +diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c +index 0a65a17f13d2..dce25e410d80 100644 +--- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c ++++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c +@@ -6,7 +6,167 @@ + #include "iris_instance.h" + #include "iris_vpu_buffer.h" + +-u32 iris_vpu_dec_dpb_size(struct iris_inst *inst) ++static u32 size_h264d_hw_bin_buffer(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) ++{ ++ u32 size_yuv, size_bin_hdr, size_bin_res; ++ ++ size_yuv = ((frame_width * frame_height) <= BIN_BUFFER_THRESHOLD) ? ++ ((BIN_BUFFER_THRESHOLD * 3) >> 1) : ++ ((frame_width * frame_height * 3) >> 1); ++ size_bin_hdr = size_yuv * H264_CABAC_HDR_RATIO_HD_TOT; ++ size_bin_res = size_yuv * H264_CABAC_RES_RATIO_HD_TOT; ++ size_bin_hdr = ALIGN(size_bin_hdr / num_vpp_pipes, ++ DMA_ALIGNMENT) * num_vpp_pipes; ++ size_bin_res = ALIGN(size_bin_res / num_vpp_pipes, ++ DMA_ALIGNMENT) * num_vpp_pipes; ++ ++ return size_bin_hdr + size_bin_res; ++} ++ ++static u32 hfi_buffer_bin_h264d(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) ++{ ++ u32 n_aligned_h = ALIGN(frame_height, 16); ++ u32 n_aligned_w = ALIGN(frame_width, 16); ++ ++ return size_h264d_hw_bin_buffer(n_aligned_w, n_aligned_h, num_vpp_pipes); ++} ++ ++static u32 hfi_buffer_comv_h264d(u32 frame_width, u32 frame_height, u32 _comv_bufcount) ++{ ++ u32 frame_height_in_mbs = DIV_ROUND_UP(frame_height, 16); ++ u32 frame_width_in_mbs = DIV_ROUND_UP(frame_width, 16); ++ u32 col_zero_aligned_width = (frame_width_in_mbs << 2); ++ u32 col_mv_aligned_width = (frame_width_in_mbs << 7); ++ u32 col_zero_size, size_colloc; ++ ++ col_mv_aligned_width = ALIGN(col_mv_aligned_width, 16); ++ col_zero_aligned_width = ALIGN(col_zero_aligned_width, 16); ++ col_zero_size = col_zero_aligned_width * ++ ((frame_height_in_mbs + 1) >> 1); ++ col_zero_size = ALIGN(col_zero_size, 64); ++ col_zero_size <<= 1; ++ col_zero_size = ALIGN(col_zero_size, 512); ++ size_colloc = col_mv_aligned_width * ((frame_height_in_mbs + 1) >> 1); ++ size_colloc = ALIGN(size_colloc, 64); ++ size_colloc <<= 1; ++ size_colloc = ALIGN(size_colloc, 512); ++ size_colloc += (col_zero_size + SIZE_H264D_BUFTAB_T * 2); ++ ++ return (size_colloc * (_comv_bufcount)) + 512; ++} ++ ++static u32 size_h264d_bse_cmd_buf(u32 frame_height) ++{ ++ u32 height = ALIGN(frame_height, 32); ++ ++ return min_t(u32, (DIV_ROUND_UP(height, 16) * 48), H264D_MAX_SLICE) * ++ SIZE_H264D_BSE_CMD_PER_BUF; ++} ++ ++static u32 size_h264d_vpp_cmd_buf(u32 frame_height) ++{ ++ u32 size, height = ALIGN(frame_height, 32); ++ ++ size = min_t(u32, (DIV_ROUND_UP(height, 16) * 48), H264D_MAX_SLICE) * ++ SIZE_H264D_VPP_CMD_PER_BUF; ++ ++ return size > VPP_CMD_MAX_SIZE ? VPP_CMD_MAX_SIZE : size; ++} ++ ++static u32 hfi_buffer_persist_h264d(void) ++{ ++ return ALIGN(SIZE_SLIST_BUF_H264 * NUM_SLIST_BUF_H264 + ++ H264_DISPLAY_BUF_SIZE * H264_NUM_FRM_INFO + ++ NUM_HW_PIC_BUF * SIZE_SEI_USERDATA, ++ DMA_ALIGNMENT); ++} ++ ++static u32 hfi_buffer_non_comv_h264d(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) ++{ ++ u32 size_bse, size_vpp, size; ++ ++ size_bse = size_h264d_bse_cmd_buf(frame_height); ++ size_vpp = size_h264d_vpp_cmd_buf(frame_height); ++ size = ALIGN(size_bse, DMA_ALIGNMENT) + ++ ALIGN(size_vpp, DMA_ALIGNMENT) + ++ ALIGN(SIZE_HW_PIC(SIZE_H264D_HW_PIC_T), DMA_ALIGNMENT); ++ ++ return ALIGN(size, DMA_ALIGNMENT); ++} ++ ++static u32 size_vpss_lb(u32 frame_width, u32 frame_height) ++{ ++ u32 opb_lb_wr_llb_y_buffer_size, opb_lb_wr_llb_uv_buffer_size; ++ u32 opb_wr_top_line_chroma_buffer_size; ++ u32 opb_wr_top_line_luma_buffer_size; ++ u32 macrotiling_size = 32; ++ ++ opb_wr_top_line_luma_buffer_size = ++ ALIGN(frame_width, macrotiling_size) / macrotiling_size * 256; ++ opb_wr_top_line_luma_buffer_size = ++ ALIGN(opb_wr_top_line_luma_buffer_size, DMA_ALIGNMENT) + ++ (MAX_TILE_COLUMNS - 1) * 256; ++ opb_wr_top_line_luma_buffer_size = ++ max_t(u32, opb_wr_top_line_luma_buffer_size, (32 * ALIGN(frame_height, 8))); ++ opb_wr_top_line_chroma_buffer_size = opb_wr_top_line_luma_buffer_size; ++ opb_lb_wr_llb_uv_buffer_size = ++ ALIGN((ALIGN(frame_height, 8) / (4 / 2)) * 64, 32); ++ opb_lb_wr_llb_y_buffer_size = ++ ALIGN((ALIGN(frame_height, 8) / (4 / 2)) * 64, 32); ++ return opb_wr_top_line_luma_buffer_size + ++ opb_wr_top_line_chroma_buffer_size + ++ opb_lb_wr_llb_uv_buffer_size + ++ opb_lb_wr_llb_y_buffer_size; ++} ++ ++static u32 hfi_buffer_line_h264d(u32 frame_width, u32 frame_height, ++ bool is_opb, u32 num_vpp_pipes) ++{ ++ u32 vpss_lb_size = 0; ++ u32 size; ++ ++ size = ALIGN(size_h264d_lb_fe_top_data(frame_width), DMA_ALIGNMENT) + ++ ALIGN(size_h264d_lb_fe_top_ctrl(frame_width), DMA_ALIGNMENT) + ++ ALIGN(size_h264d_lb_fe_left_ctrl(frame_height), DMA_ALIGNMENT) * num_vpp_pipes + ++ ALIGN(size_h264d_lb_se_top_ctrl(frame_width), DMA_ALIGNMENT) + ++ ALIGN(size_h264d_lb_se_left_ctrl(frame_height), DMA_ALIGNMENT) * num_vpp_pipes + ++ ALIGN(size_h264d_lb_pe_top_data(frame_width), DMA_ALIGNMENT) + ++ ALIGN(size_h264d_lb_vsp_top(frame_width), DMA_ALIGNMENT) + ++ ALIGN(size_h264d_lb_recon_dma_metadata_wr(frame_height), DMA_ALIGNMENT) * 2 + ++ ALIGN(size_h264d_qp(frame_width, frame_height), DMA_ALIGNMENT); ++ size = ALIGN(size, DMA_ALIGNMENT); ++ if (is_opb) ++ vpss_lb_size = size_vpss_lb(frame_width, frame_height); ++ ++ return ALIGN((size + vpss_lb_size), DMA_ALIGNMENT); ++} ++ ++static u32 iris_vpu_dec_bin_size(struct iris_inst *inst) ++{ ++ u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe; ++ struct v4l2_format *f = inst->fmt_src; ++ u32 height = f->fmt.pix_mp.height; ++ u32 width = f->fmt.pix_mp.width; ++ ++ return hfi_buffer_bin_h264d(width, height, num_vpp_pipes); ++} ++ ++static u32 iris_vpu_dec_comv_size(struct iris_inst *inst) ++{ ++ u32 num_comv = VIDEO_MAX_FRAME; ++ struct v4l2_format *f = inst->fmt_src; ++ u32 height = f->fmt.pix_mp.height; ++ u32 width = f->fmt.pix_mp.width; ++ ++ return hfi_buffer_comv_h264d(width, height, num_comv); ++} ++ ++static u32 iris_vpu_dec_persist_size(struct iris_inst *inst) ++{ ++ return hfi_buffer_persist_h264d(); ++} ++ ++static u32 iris_vpu_dec_dpb_size(struct iris_inst *inst) + { + if (iris_split_mode_enabled(inst)) + return iris_get_buffer_size(inst, BUF_DPB); +@@ -14,6 +174,70 @@ u32 iris_vpu_dec_dpb_size(struct iris_inst *inst) + return 0; + } + ++static u32 iris_vpu_dec_non_comv_size(struct iris_inst *inst) ++{ ++ u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe; ++ struct v4l2_format *f = inst->fmt_src; ++ u32 height = f->fmt.pix_mp.height; ++ u32 width = f->fmt.pix_mp.width; ++ ++ return hfi_buffer_non_comv_h264d(width, height, num_vpp_pipes); ++} ++ ++static u32 iris_vpu_dec_line_size(struct iris_inst *inst) ++{ ++ u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe; ++ struct v4l2_format *f = inst->fmt_src; ++ u32 height = f->fmt.pix_mp.height; ++ u32 width = f->fmt.pix_mp.width; ++ bool is_opb = false; ++ ++ if (iris_split_mode_enabled(inst)) ++ is_opb = true; ++ ++ return hfi_buffer_line_h264d(width, height, is_opb, num_vpp_pipes); ++} ++ ++static u32 iris_vpu_dec_scratch1_size(struct iris_inst *inst) ++{ ++ return iris_vpu_dec_comv_size(inst) + ++ iris_vpu_dec_non_comv_size(inst) + ++ iris_vpu_dec_line_size(inst); ++} ++ ++struct iris_vpu_buf_type_handle { ++ enum iris_buffer_type type; ++ u32 (*handle)(struct iris_inst *inst); ++}; ++ ++int iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type) ++{ ++ const struct iris_vpu_buf_type_handle *buf_type_handle_arr; ++ u32 size = 0, buf_type_handle_size, i; ++ ++ static const struct iris_vpu_buf_type_handle dec_internal_buf_type_handle[] = { ++ {BUF_BIN, iris_vpu_dec_bin_size }, ++ {BUF_COMV, iris_vpu_dec_comv_size }, ++ {BUF_NON_COMV, iris_vpu_dec_non_comv_size }, ++ {BUF_LINE, iris_vpu_dec_line_size }, ++ {BUF_PERSIST, iris_vpu_dec_persist_size }, ++ {BUF_DPB, iris_vpu_dec_dpb_size }, ++ {BUF_SCRATCH_1, iris_vpu_dec_scratch1_size }, ++ }; ++ ++ buf_type_handle_size = ARRAY_SIZE(dec_internal_buf_type_handle); ++ buf_type_handle_arr = dec_internal_buf_type_handle; ++ ++ for (i = 0; i < buf_type_handle_size; i++) { ++ if (buf_type_handle_arr[i].type == buffer_type) { ++ size = buf_type_handle_arr[i].handle(inst); ++ break; ++ } ++ } ++ ++ return size; ++} ++ + static inline int iris_vpu_dpb_count(struct iris_inst *inst) + { + if (iris_split_mode_enabled(inst)) { +@@ -31,6 +255,13 @@ int iris_vpu_buf_count(struct iris_inst *inst, enum iris_buffer_type buffer_type + return MIN_BUFFERS; + case BUF_OUTPUT: + return inst->fw_min_count; ++ case BUF_BIN: ++ case BUF_COMV: ++ case BUF_NON_COMV: ++ case BUF_LINE: ++ case BUF_PERSIST: ++ case BUF_SCRATCH_1: ++ return 1; /* internal buffer count needed by firmware is 1 */ + case BUF_DPB: + return iris_vpu_dpb_count(inst); + default: +diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h +index 865539d626b7..62af6ea6ba1f 100644 +--- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h ++++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h +@@ -10,7 +10,82 @@ struct iris_inst; + + #define MIN_BUFFERS 4 + +-u32 iris_vpu_dec_dpb_size(struct iris_inst *inst); ++#define DMA_ALIGNMENT 256 ++ ++#define NUM_HW_PIC_BUF 32 ++#define SIZE_HW_PIC(size_per_buf) (NUM_HW_PIC_BUF * (size_per_buf)) ++ ++#define MAX_TILE_COLUMNS 32 ++#define BIN_BUFFER_THRESHOLD (1280 * 736) ++#define VPP_CMD_MAX_SIZE (BIT(20)) ++#define H264D_MAX_SLICE 1800 ++ ++#define SIZE_H264D_BUFTAB_T 256 ++#define SIZE_H264D_BSE_CMD_PER_BUF (32 * 4) ++#define SIZE_H264D_VPP_CMD_PER_BUF 512 ++ ++#define NUM_SLIST_BUF_H264 (256 + 32) ++#define SIZE_SLIST_BUF_H264 512 ++#define H264_DISPLAY_BUF_SIZE 3328 ++#define H264_NUM_FRM_INFO 66 ++ ++#define SIZE_SEI_USERDATA 4096 ++ ++#define H264_CABAC_HDR_RATIO_HD_TOT 1 ++#define H264_CABAC_RES_RATIO_HD_TOT 3 ++#define SIZE_H264D_HW_PIC_T (BIT(11)) ++ ++#define MAX_FE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE 64 ++#define MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE 16 ++#define MAX_PE_NBR_DATA_LCU64_LINE_BUFFER_SIZE 384 ++#define MAX_FE_NBR_DATA_LUMA_LINE_BUFFER_SIZE 640 ++ ++static inline u32 size_h264d_lb_fe_top_data(u32 frame_width) ++{ ++ return MAX_FE_NBR_DATA_LUMA_LINE_BUFFER_SIZE * ALIGN(frame_width, 16) * 3; ++} ++ ++static inline u32 size_h264d_lb_fe_top_ctrl(u32 frame_width) ++{ ++ return MAX_FE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE * DIV_ROUND_UP(frame_width, 16); ++} ++ ++static inline u32 size_h264d_lb_fe_left_ctrl(u32 frame_height) ++{ ++ return MAX_FE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE * DIV_ROUND_UP(frame_height, 16); ++} ++ ++static inline u32 size_h264d_lb_se_top_ctrl(u32 frame_width) ++{ ++ return MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE * DIV_ROUND_UP(frame_width, 16); ++} ++ ++static inline u32 size_h264d_lb_se_left_ctrl(u32 frame_height) ++{ ++ return MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE * DIV_ROUND_UP(frame_height, 16); ++} ++ ++static inline u32 size_h264d_lb_pe_top_data(u32 frame_width) ++{ ++ return MAX_PE_NBR_DATA_LCU64_LINE_BUFFER_SIZE * DIV_ROUND_UP(frame_width, 16); ++} ++ ++static inline u32 size_h264d_lb_vsp_top(u32 frame_width) ++{ ++ return (DIV_ROUND_UP(frame_width, 16) << 7); ++} ++ ++static inline u32 size_h264d_lb_recon_dma_metadata_wr(u32 frame_height) ++{ ++ return ALIGN(frame_height, 16) * 32; ++} ++ ++static inline u32 size_h264d_qp(u32 frame_width, u32 frame_height) ++{ ++ return DIV_ROUND_UP(frame_width, 64) * DIV_ROUND_UP(frame_height, 64) * 128; ++} ++ ++int iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type); + int iris_vpu_buf_count(struct iris_inst *inst, enum iris_buffer_type buffer_type); + + #endif +-- +2.34.1 + diff --git a/patch/kernel/archive/sm8550-6.12/0020_media--iris--implement-vb2-ops-for-buf_queue-and-f.patch b/patch/kernel/archive/sm8550-6.12/0020_media--iris--implement-vb2-ops-for-buf_queue-and-f.patch new file mode 100644 index 000000000..aa37cfade --- /dev/null +++ b/patch/kernel/archive/sm8550-6.12/0020_media--iris--implement-vb2-ops-for-buf_queue-and-f.patch @@ -0,0 +1,1478 @@ +From 0d452286222b3592f297af958172da80dc574d5c Mon Sep 17 00:00:00 2001 +From: Dikshita Agarwal +Date: Fri, 7 Feb 2025 13:25:00 +0530 +Subject: [PATCH] media: iris: implement vb2 ops for buf_queue and firmware + response + +Implement the vb2 ops for the buf queue. These are the different buffer +attributes: +BUF_ATTR_DEFERRED - buffer queued by the client but not submitted to + firmware. +BUF_ATTR_PENDING_RELEASE - buffers requested to be released from + the firmware. +BUF_ATTR_QUEUED - buffers submitted to the firmware. +BUF_ATTR_DEQUEUED - buffers received from the firmware. +BUF_ATTR_BUFFER_DONE - buffers sent back to vb2. + +Reviewed-by: Hans Verkuil +Tested-by: Stefan Schmidt # x1e80100 (Dell XPS 13 9345) +Reviewed-by: Stefan Schmidt +Tested-by: Neil Armstrong # on SM8550-QRD +Tested-by: Neil Armstrong # on SM8550-HDK +Signed-off-by: Dikshita Agarwal +Link: https://lore.kernel.org/r/20250207-qcom-video-iris-v10-20-ab66eeffbd20@quicinc.com +Signed-off-by: Neil Armstrong +--- + drivers/media/platform/qcom/iris/Kconfig | 1 + + .../media/platform/qcom/iris/iris_buffer.c | 116 +++++++++++ + .../media/platform/qcom/iris/iris_buffer.h | 2 + + .../qcom/iris/iris_hfi_gen1_command.c | 53 +++++ + .../qcom/iris/iris_hfi_gen1_defines.h | 80 ++++++++ + .../qcom/iris/iris_hfi_gen1_response.c | 167 +++++++++++++++- + .../media/platform/qcom/iris/iris_hfi_gen2.h | 2 + + .../qcom/iris/iris_hfi_gen2_defines.h | 22 +++ + .../qcom/iris/iris_hfi_gen2_response.c | 183 +++++++++++++++++- + .../media/platform/qcom/iris/iris_instance.h | 8 + + drivers/media/platform/qcom/iris/iris_utils.c | 16 ++ + drivers/media/platform/qcom/iris/iris_utils.h | 16 ++ + drivers/media/platform/qcom/iris/iris_vb2.c | 98 +++++++++- + drivers/media/platform/qcom/iris/iris_vb2.h | 4 + + drivers/media/platform/qcom/iris/iris_vdec.c | 151 ++++++++++++++- + drivers/media/platform/qcom/iris/iris_vdec.h | 3 +- + drivers/media/platform/qcom/iris/iris_vidc.c | 14 ++ + 17 files changed, 916 insertions(+), 20 deletions(-) + +diff --git a/drivers/media/platform/qcom/iris/Kconfig b/drivers/media/platform/qcom/iris/Kconfig +index f92cc7fe9378..3c803a05305a 100644 +--- a/drivers/media/platform/qcom/iris/Kconfig ++++ b/drivers/media/platform/qcom/iris/Kconfig +@@ -5,6 +5,7 @@ config VIDEO_QCOM_IRIS + select V4L2_MEM2MEM_DEV + select QCOM_MDT_LOADER if ARCH_QCOM + select QCOM_SCM ++ select VIDEOBUF2_DMA_CONTIG + help + This is a V4L2 driver for Qualcomm iris video accelerator + hardware. It accelerates decoding operations on various +diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c +index e9d372580b5f..de1267c387f1 100644 +--- a/drivers/media/platform/qcom/iris/iris_buffer.c ++++ b/drivers/media/platform/qcom/iris/iris_buffer.c +@@ -3,6 +3,7 @@ + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + ++#include + #include + + #include "iris_buffer.h" +@@ -434,6 +435,36 @@ int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst) + return 0; + } + ++int iris_queue_deferred_buffers(struct iris_inst *inst, enum iris_buffer_type buf_type) ++{ ++ struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; ++ struct v4l2_m2m_buffer *buffer, *n; ++ struct iris_buffer *buf; ++ int ret; ++ ++ if (buf_type == BUF_INPUT) { ++ v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buffer, n) { ++ buf = to_iris_buffer(&buffer->vb); ++ if (!(buf->attr & BUF_ATTR_DEFERRED)) ++ continue; ++ ret = iris_queue_buffer(inst, buf); ++ if (ret) ++ return ret; ++ } ++ } else { ++ v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, buffer, n) { ++ buf = to_iris_buffer(&buffer->vb); ++ if (!(buf->attr & BUF_ATTR_DEFERRED)) ++ continue; ++ ret = iris_queue_buffer(inst, buf); ++ if (ret) ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ + void iris_vb2_queue_error(struct iris_inst *inst) + { + struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; +@@ -444,3 +475,88 @@ void iris_vb2_queue_error(struct iris_inst *inst) + q = v4l2_m2m_get_dst_vq(m2m_ctx); + vb2_queue_error(q); + } ++ ++static struct vb2_v4l2_buffer * ++iris_helper_find_buf(struct iris_inst *inst, u32 type, u32 idx) ++{ ++ struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; ++ ++ if (V4L2_TYPE_IS_OUTPUT(type)) ++ return v4l2_m2m_src_buf_remove_by_idx(m2m_ctx, idx); ++ else ++ return v4l2_m2m_dst_buf_remove_by_idx(m2m_ctx, idx); ++} ++ ++static void iris_get_ts_metadata(struct iris_inst *inst, u64 timestamp_ns, ++ struct vb2_v4l2_buffer *vbuf) ++{ ++ u32 mask = V4L2_BUF_FLAG_TIMECODE | V4L2_BUF_FLAG_TSTAMP_SRC_MASK; ++ u32 i; ++ ++ for (i = 0; i < ARRAY_SIZE(inst->tss); ++i) { ++ if (inst->tss[i].ts_ns != timestamp_ns) ++ continue; ++ ++ vbuf->flags &= ~mask; ++ vbuf->flags |= inst->tss[i].flags; ++ vbuf->timecode = inst->tss[i].tc; ++ return; ++ } ++ ++ vbuf->flags &= ~mask; ++ vbuf->flags |= inst->tss[inst->metadata_idx].flags; ++ vbuf->timecode = inst->tss[inst->metadata_idx].tc; ++} ++ ++int iris_vb2_buffer_done(struct iris_inst *inst, struct iris_buffer *buf) ++{ ++ struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; ++ struct vb2_v4l2_buffer *vbuf; ++ struct vb2_buffer *vb2; ++ u32 type, state; ++ ++ switch (buf->type) { ++ case BUF_INPUT: ++ type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; ++ break; ++ case BUF_OUTPUT: ++ type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; ++ break; ++ default: ++ return 0; /* Internal DPB Buffers */ ++ } ++ ++ vbuf = iris_helper_find_buf(inst, type, buf->index); ++ if (!vbuf) ++ return -EINVAL; ++ ++ vb2 = &vbuf->vb2_buf; ++ ++ if (buf->flags & V4L2_BUF_FLAG_ERROR) ++ state = VB2_BUF_STATE_ERROR; ++ else ++ state = VB2_BUF_STATE_DONE; ++ ++ vbuf->flags |= buf->flags; ++ ++ if (V4L2_TYPE_IS_CAPTURE(type)) { ++ vb2_set_plane_payload(vb2, 0, buf->data_size); ++ vbuf->sequence = inst->sequence_cap++; ++ iris_get_ts_metadata(inst, buf->timestamp, vbuf); ++ } else { ++ vbuf->sequence = inst->sequence_out++; ++ } ++ ++ if (vbuf->flags & V4L2_BUF_FLAG_LAST) { ++ if (!v4l2_m2m_has_stopped(m2m_ctx)) { ++ const struct v4l2_event ev = { .type = V4L2_EVENT_EOS }; ++ ++ v4l2_event_queue_fh(&inst->fh, &ev); ++ v4l2_m2m_mark_stopped(m2m_ctx); ++ } ++ } ++ vb2->timestamp = buf->timestamp; ++ v4l2_m2m_buf_done(vbuf, state); ++ ++ return 0; ++} +diff --git a/drivers/media/platform/qcom/iris/iris_buffer.h b/drivers/media/platform/qcom/iris/iris_buffer.h +index 73f3a16ff7a2..2c7432a59906 100644 +--- a/drivers/media/platform/qcom/iris/iris_buffer.h ++++ b/drivers/media/platform/qcom/iris/iris_buffer.h +@@ -109,6 +109,8 @@ int iris_destroy_internal_buffer(struct iris_inst *inst, struct iris_buffer *buf + int iris_destroy_internal_buffers(struct iris_inst *inst, u32 plane); + int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst); + int iris_queue_buffer(struct iris_inst *inst, struct iris_buffer *buf); ++int iris_queue_deferred_buffers(struct iris_inst *inst, enum iris_buffer_type buf_type); ++int iris_vb2_buffer_done(struct iris_inst *inst, struct iris_buffer *buf); + void iris_vb2_queue_error(struct iris_inst *inst); + + #endif +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +index 603ca485992d..03f7e6ea4bf3 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +@@ -180,6 +180,10 @@ static int iris_hfi_gen1_session_stop(struct iris_inst *inst, u32 plane) + ret = iris_hfi_queue_cmd_write(core, &pkt, pkt.shdr.hdr.size); + if (!ret) + ret = iris_wait_for_session_response(inst, false); ++ iris_helper_buffers_done(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, ++ VB2_BUF_STATE_ERROR); ++ iris_helper_buffers_done(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, ++ VB2_BUF_STATE_ERROR); + } else if (inst->state == IRIS_INST_STREAMING) { + if (V4L2_TYPE_IS_OUTPUT(plane)) + flush_type = HFI_FLUSH_ALL; +@@ -201,6 +205,50 @@ static int iris_hfi_gen1_session_stop(struct iris_inst *inst, u32 plane) + return ret; + } + ++static int iris_hfi_gen1_queue_input_buffer(struct iris_inst *inst, struct iris_buffer *buf) ++{ ++ struct hfi_session_empty_buffer_compressed_pkt ip_pkt; ++ ++ ip_pkt.shdr.hdr.size = sizeof(struct hfi_session_empty_buffer_compressed_pkt); ++ ip_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_EMPTY_BUFFER; ++ ip_pkt.shdr.session_id = inst->session_id; ++ ip_pkt.time_stamp_hi = upper_32_bits(buf->timestamp); ++ ip_pkt.time_stamp_lo = lower_32_bits(buf->timestamp); ++ ip_pkt.flags = buf->flags; ++ ip_pkt.mark_target = 0; ++ ip_pkt.mark_data = 0; ++ ip_pkt.offset = buf->data_offset; ++ ip_pkt.alloc_len = buf->buffer_size; ++ ip_pkt.filled_len = buf->data_size; ++ ip_pkt.input_tag = buf->index; ++ ip_pkt.packet_buffer = buf->device_addr; ++ ++ return iris_hfi_queue_cmd_write(inst->core, &ip_pkt, ip_pkt.shdr.hdr.size); ++} ++ ++static int iris_hfi_gen1_queue_output_buffer(struct iris_inst *inst, struct iris_buffer *buf) ++{ ++ struct hfi_session_fill_buffer_pkt op_pkt; ++ ++ op_pkt.shdr.hdr.size = sizeof(struct hfi_session_fill_buffer_pkt); ++ op_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_FILL_BUFFER; ++ op_pkt.shdr.session_id = inst->session_id; ++ op_pkt.output_tag = buf->index; ++ op_pkt.packet_buffer = buf->device_addr; ++ op_pkt.extradata_buffer = 0; ++ op_pkt.alloc_len = buf->buffer_size; ++ op_pkt.filled_len = buf->data_size; ++ op_pkt.offset = buf->data_offset; ++ op_pkt.data = 0; ++ ++ if (buf->type == BUF_OUTPUT && iris_split_mode_enabled(inst)) ++ op_pkt.stream_id = 1; ++ else ++ op_pkt.stream_id = 0; ++ ++ return iris_hfi_queue_cmd_write(inst->core, &op_pkt, op_pkt.shdr.hdr.size); ++} ++ + static int iris_hfi_gen1_queue_internal_buffer(struct iris_inst *inst, struct iris_buffer *buf) + { + struct hfi_session_set_buffers_pkt *int_pkt; +@@ -240,6 +288,11 @@ static int iris_hfi_gen1_queue_internal_buffer(struct iris_inst *inst, struct ir + static int iris_hfi_gen1_session_queue_buffer(struct iris_inst *inst, struct iris_buffer *buf) + { + switch (buf->type) { ++ case BUF_INPUT: ++ return iris_hfi_gen1_queue_input_buffer(inst, buf); ++ case BUF_OUTPUT: ++ case BUF_DPB: ++ return iris_hfi_gen1_queue_output_buffer(inst, buf); + case BUF_PERSIST: + case BUF_BIN: + case BUF_SCRATCH_1: +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +index cabd91eafc92..108449d703e1 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +@@ -29,11 +29,14 @@ + #define HFI_CMD_SESSION_LOAD_RESOURCES 0x211001 + #define HFI_CMD_SESSION_START 0x211002 + #define HFI_CMD_SESSION_STOP 0x211003 ++#define HFI_CMD_SESSION_EMPTY_BUFFER 0x211004 ++#define HFI_CMD_SESSION_FILL_BUFFER 0x211005 + #define HFI_CMD_SESSION_FLUSH 0x211008 + #define HFI_CMD_SESSION_RELEASE_BUFFERS 0x21100b + #define HFI_CMD_SESSION_RELEASE_RESOURCES 0x21100c + + #define HFI_ERR_SESSION_UNSUPPORTED_SETTING 0x1008 ++#define HFI_ERR_SESSION_UNSUPPORTED_STREAM 0x100d + #define HFI_ERR_SESSION_UNSUPPORT_BUFFERTYPE 0x1010 + #define HFI_ERR_SESSION_INVALID_SCALE_FACTOR 0x1012 + #define HFI_ERR_SESSION_UPSCALE_NOT_SUPPORTED 0x1013 +@@ -41,6 +44,8 @@ + #define HFI_EVENT_SYS_ERROR 0x1 + #define HFI_EVENT_SESSION_ERROR 0x2 + ++#define HFI_BUFFERFLAG_TIMESTAMPINVALID 0x00000100 ++ + #define HFI_FLUSH_OUTPUT 0x1000002 + #define HFI_FLUSH_OUTPUT2 0x1000003 + #define HFI_FLUSH_ALL 0x1000004 +@@ -84,9 +89,19 @@ + #define HFI_MSG_SESSION_START 0x221002 + #define HFI_MSG_SESSION_STOP 0x221003 + #define HFI_MSG_SESSION_FLUSH 0x221006 ++#define HFI_MSG_SESSION_EMPTY_BUFFER 0x221007 ++#define HFI_MSG_SESSION_FILL_BUFFER 0x221008 + #define HFI_MSG_SESSION_RELEASE_RESOURCES 0x22100a + #define HFI_MSG_SESSION_RELEASE_BUFFERS 0x22100c + ++#define HFI_PICTURE_I 0x00000001 ++#define HFI_PICTURE_P 0x00000002 ++#define HFI_PICTURE_B 0x00000004 ++#define HFI_PICTURE_IDR 0x00000008 ++#define HFI_FRAME_NOTCODED 0x7f002000 ++#define HFI_FRAME_YUV 0x7f004000 ++#define HFI_UNUSED_PICT 0x10000000 ++ + struct hfi_pkt_hdr { + u32 size; + u32 pkt_type; +@@ -144,6 +159,34 @@ struct hfi_session_set_buffers_pkt { + u32 buffer_info[]; + }; + ++struct hfi_session_empty_buffer_compressed_pkt { ++ struct hfi_session_hdr_pkt shdr; ++ u32 time_stamp_hi; ++ u32 time_stamp_lo; ++ u32 flags; ++ u32 mark_target; ++ u32 mark_data; ++ u32 offset; ++ u32 alloc_len; ++ u32 filled_len; ++ u32 input_tag; ++ u32 packet_buffer; ++ u32 extradata_buffer; ++ u32 data; ++}; ++ ++struct hfi_session_fill_buffer_pkt { ++ struct hfi_session_hdr_pkt shdr; ++ u32 stream_id; ++ u32 offset; ++ u32 alloc_len; ++ u32 filled_len; ++ u32 output_tag; ++ u32 packet_buffer; ++ u32 extradata_buffer; ++ u32 data; ++}; ++ + struct hfi_session_flush_pkt { + struct hfi_session_hdr_pkt shdr; + u32 flush_type; +@@ -258,6 +301,43 @@ struct hfi_multi_stream { + u32 enable; + }; + ++struct hfi_msg_session_empty_buffer_done_pkt { ++ struct hfi_msg_session_hdr_pkt shdr; ++ u32 offset; ++ u32 filled_len; ++ u32 input_tag; ++ u32 packet_buffer; ++ u32 extradata_buffer; ++ u32 data[]; ++}; ++ ++struct hfi_msg_session_fbd_uncompressed_plane0_pkt { ++ struct hfi_session_hdr_pkt shdr; ++ u32 stream_id; ++ u32 view_id; ++ u32 error_type; ++ u32 time_stamp_hi; ++ u32 time_stamp_lo; ++ u32 flags; ++ u32 mark_target; ++ u32 mark_data; ++ u32 stats; ++ u32 alloc_len; ++ u32 filled_len; ++ u32 offset; ++ u32 frame_width; ++ u32 frame_height; ++ u32 start_x_coord; ++ u32 start_y_coord; ++ u32 input_tag; ++ u32 input_tag2; ++ u32 output_tag; ++ u32 picture_type; ++ u32 packet_buffer; ++ u32 extradata_buffer; ++ u32 data[]; ++}; ++ + struct hfi_msg_session_release_buffers_done_pkt { + struct hfi_msg_session_hdr_pkt shdr; + u32 num_buffers; +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c +index a84bb00388d9..23a8bf29e381 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c +@@ -3,6 +3,8 @@ + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + ++#include ++ + #include "iris_hfi_gen1.h" + #include "iris_hfi_gen1_defines.h" + #include "iris_instance.h" +@@ -130,6 +132,143 @@ static void iris_hfi_gen1_sys_property_info(struct iris_core *core, void *packet + } + } + ++static void iris_hfi_gen1_session_etb_done(struct iris_inst *inst, void *packet) ++{ ++ struct hfi_msg_session_empty_buffer_done_pkt *pkt = packet; ++ struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; ++ struct v4l2_m2m_buffer *m2m_buffer, *n; ++ struct iris_buffer *buf = NULL; ++ bool found = false; ++ ++ v4l2_m2m_for_each_src_buf_safe(m2m_ctx, m2m_buffer, n) { ++ buf = to_iris_buffer(&m2m_buffer->vb); ++ if (buf->index == pkt->input_tag) { ++ found = true; ++ break; ++ } ++ } ++ if (!found) ++ goto error; ++ ++ if (pkt->shdr.error_type == HFI_ERR_SESSION_UNSUPPORTED_STREAM) { ++ buf->flags = V4L2_BUF_FLAG_ERROR; ++ iris_vb2_queue_error(inst); ++ iris_inst_change_state(inst, IRIS_INST_ERROR); ++ } ++ ++ if (!(buf->attr & BUF_ATTR_QUEUED)) ++ return; ++ ++ buf->attr &= ~BUF_ATTR_QUEUED; ++ ++ if (!(buf->attr & BUF_ATTR_BUFFER_DONE)) { ++ buf->attr |= BUF_ATTR_BUFFER_DONE; ++ iris_vb2_buffer_done(inst, buf); ++ } ++ ++ return; ++ ++error: ++ iris_inst_change_state(inst, IRIS_INST_ERROR); ++ dev_err(inst->core->dev, "error in etb done\n"); ++} ++ ++static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet) ++{ ++ struct hfi_msg_session_fbd_uncompressed_plane0_pkt *pkt = packet; ++ struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; ++ struct v4l2_m2m_buffer *m2m_buffer, *n; ++ u32 timestamp_hi = pkt->time_stamp_hi; ++ u32 timestamp_lo = pkt->time_stamp_lo; ++ struct iris_core *core = inst->core; ++ u32 filled_len = pkt->filled_len; ++ u32 pic_type = pkt->picture_type; ++ u32 output_tag = pkt->output_tag; ++ struct iris_buffer *buf, *iter; ++ struct iris_buffers *buffers; ++ u32 offset = pkt->offset; ++ u64 timestamp_us = 0; ++ bool found = false; ++ u32 flags = 0; ++ ++ if (iris_split_mode_enabled(inst) && pkt->stream_id == 0) { ++ buffers = &inst->buffers[BUF_DPB]; ++ if (!buffers) ++ goto error; ++ ++ found = false; ++ list_for_each_entry(iter, &buffers->list, list) { ++ if (!(iter->attr & BUF_ATTR_QUEUED)) ++ continue; ++ ++ found = (iter->index == output_tag && ++ iter->data_offset == offset); ++ ++ if (found) { ++ buf = iter; ++ break; ++ } ++ } ++ } else { ++ v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, m2m_buffer, n) { ++ buf = to_iris_buffer(&m2m_buffer->vb); ++ if (!(buf->attr & BUF_ATTR_QUEUED)) ++ continue; ++ ++ found = (buf->index == output_tag && ++ buf->data_offset == offset); ++ ++ if (found) ++ break; ++ } ++ } ++ if (!found) ++ goto error; ++ ++ buf->data_offset = offset; ++ buf->data_size = filled_len; ++ ++ if (filled_len) { ++ timestamp_us = timestamp_hi; ++ timestamp_us = (timestamp_us << 32) | timestamp_lo; ++ } else { ++ flags |= V4L2_BUF_FLAG_LAST; ++ } ++ buf->timestamp = timestamp_us; ++ ++ switch (pic_type) { ++ case HFI_PICTURE_IDR: ++ case HFI_PICTURE_I: ++ flags |= V4L2_BUF_FLAG_KEYFRAME; ++ break; ++ case HFI_PICTURE_P: ++ flags |= V4L2_BUF_FLAG_PFRAME; ++ break; ++ case HFI_PICTURE_B: ++ flags |= V4L2_BUF_FLAG_BFRAME; ++ break; ++ case HFI_FRAME_NOTCODED: ++ case HFI_UNUSED_PICT: ++ case HFI_FRAME_YUV: ++ default: ++ break; ++ } ++ ++ buf->attr &= ~BUF_ATTR_QUEUED; ++ buf->attr |= BUF_ATTR_DEQUEUED; ++ buf->attr |= BUF_ATTR_BUFFER_DONE; ++ ++ buf->flags |= flags; ++ ++ iris_vb2_buffer_done(inst, buf); ++ ++ return; ++ ++error: ++ iris_inst_change_state(inst, IRIS_INST_ERROR); ++ dev_err(core->dev, "error in ftb done\n"); ++} ++ + struct iris_hfi_gen1_response_pkt_info { + u32 pkt; + u32 pkt_sz; +@@ -168,6 +307,14 @@ static const struct iris_hfi_gen1_response_pkt_info pkt_infos[] = { + .pkt = HFI_MSG_SESSION_STOP, + .pkt_sz = sizeof(struct hfi_msg_session_hdr_pkt), + }, ++ { ++ .pkt = HFI_MSG_SESSION_EMPTY_BUFFER, ++ .pkt_sz = sizeof(struct hfi_msg_session_empty_buffer_done_pkt), ++ }, ++ { ++ .pkt = HFI_MSG_SESSION_FILL_BUFFER, ++ .pkt_sz = sizeof(struct hfi_msg_session_fbd_uncompressed_plane0_pkt), ++ }, + { + .pkt = HFI_MSG_SESSION_FLUSH, + .pkt_sz = sizeof(struct hfi_msg_session_flush_done_pkt), +@@ -238,15 +385,21 @@ static void iris_hfi_gen1_handle_response(struct iris_core *core, void *response + } + + mutex_lock(&inst->lock); +- struct hfi_msg_session_hdr_pkt *shdr; ++ if (hdr->pkt_type == HFI_MSG_SESSION_EMPTY_BUFFER) { ++ iris_hfi_gen1_session_etb_done(inst, hdr); ++ } else if (hdr->pkt_type == HFI_MSG_SESSION_FILL_BUFFER) { ++ iris_hfi_gen1_session_ftb_done(inst, hdr); ++ } else { ++ struct hfi_msg_session_hdr_pkt *shdr; + +- shdr = (struct hfi_msg_session_hdr_pkt *)hdr; +- if (shdr->error_type != HFI_ERR_NONE) +- iris_inst_change_state(inst, IRIS_INST_ERROR); ++ shdr = (struct hfi_msg_session_hdr_pkt *)hdr; ++ if (shdr->error_type != HFI_ERR_NONE) ++ iris_inst_change_state(inst, IRIS_INST_ERROR); + +- done = pkt_info->pkt == HFI_MSG_SESSION_FLUSH ? +- &inst->flush_completion : &inst->completion; +- complete(done); ++ done = pkt_info->pkt == HFI_MSG_SESSION_FLUSH ? ++ &inst->flush_completion : &inst->completion; ++ complete(done); ++ } + mutex_unlock(&inst->lock); + + break; +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2.h +index 0a946c1e3a4c..b9d3749a10ef 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2.h +@@ -20,6 +20,7 @@ struct iris_core; + * @packet: HFI packet + * @ipsc_properties_set: boolean to set ipsc properties to fw + * @opsc_properties_set: boolean to set opsc properties to fw ++ * @hfi_frame_info: structure of frame info + * @src_subcr_params: subscription params to fw on input port + * @dst_subcr_params: subscription params to fw on output port + */ +@@ -28,6 +29,7 @@ struct iris_inst_hfi_gen2 { + struct iris_hfi_header *packet; + bool ipsc_properties_set; + bool opsc_properties_set; ++ struct iris_hfi_frame_info hfi_frame_info; + struct hfi_subscription_params src_subcr_params; + struct hfi_subscription_params dst_subcr_params; + }; +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +index afbdf1f1e68a..8a9f2b5517ad 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +@@ -71,6 +71,12 @@ + #define HFI_SYS_ERROR_WD_TIMEOUT 0x05000001 + #define HFI_SYSTEM_ERROR_END 0x05FFFFFF + ++#define HFI_INFORMATION_BEGIN 0x06000000 ++#define HFI_INFO_UNSUPPORTED 0x06000001 ++#define HFI_INFO_DATA_CORRUPT 0x06000002 ++#define HFI_INFO_BUFFER_OVERFLOW 0x06000004 ++#define HFI_INFORMATION_END 0x06FFFFFF ++ + enum hfi_property_mode_type { + HFI_MODE_PORT_SETTINGS_CHANGE = 0x00000001, + HFI_MODE_PROPERTY = 0x00000002, +@@ -92,6 +98,15 @@ enum hfi_codec_type { + HFI_CODEC_ENCODE_AVC = 2, + }; + ++enum hfi_picture_type { ++ HFI_PICTURE_IDR = 0x00000001, ++ HFI_PICTURE_P = 0x00000002, ++ HFI_PICTURE_B = 0x00000004, ++ HFI_PICTURE_I = 0x00000008, ++ HFI_PICTURE_CRA = 0x00000010, ++ HFI_PICTURE_BLA = 0x00000020, ++}; ++ + enum hfi_buffer_type { + HFI_BUFFER_BITSTREAM = 0x00000001, + HFI_BUFFER_RAW = 0x00000002, +@@ -115,6 +130,13 @@ enum hfi_buffer_host_flags { + HFI_BUF_HOST_FLAGS_CB_NON_SECURE = 0x00000200, + }; + ++enum hfi_buffer_firmware_flags { ++ HFI_BUF_FW_FLAG_RELEASE_DONE = 0x00000001, ++ HFI_BUF_FW_FLAG_READONLY = 0x00000010, ++ HFI_BUF_FW_FLAG_LAST = 0x10000000, ++ HFI_BUF_FW_FLAG_PSC_LAST = 0x20000000, ++}; ++ + enum hfi_packet_firmware_flags { + HFI_FW_FLAGS_SUCCESS = 0x00000001, + HFI_FW_FLAGS_INFORMATION = 0x00000002, +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c +index 9f3764f1903b..e8d8caeef021 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c +@@ -3,6 +3,8 @@ + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + ++#include ++ + #include "iris_hfi_gen2.h" + #include "iris_hfi_gen2_defines.h" + #include "iris_hfi_gen2_packet.h" +@@ -81,6 +83,29 @@ static bool iris_hfi_gen2_is_valid_hfi_port(u32 port, u32 buffer_type) + return true; + } + ++static int iris_hfi_gen2_get_driver_buffer_flags(struct iris_inst *inst, u32 hfi_flags) ++{ ++ u32 keyframe = HFI_PICTURE_IDR | HFI_PICTURE_I | HFI_PICTURE_CRA | HFI_PICTURE_BLA; ++ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); ++ u32 driver_flags = 0; ++ ++ if (inst_hfi_gen2->hfi_frame_info.picture_type & keyframe) ++ driver_flags |= V4L2_BUF_FLAG_KEYFRAME; ++ else if (inst_hfi_gen2->hfi_frame_info.picture_type & HFI_PICTURE_P) ++ driver_flags |= V4L2_BUF_FLAG_PFRAME; ++ else if (inst_hfi_gen2->hfi_frame_info.picture_type & HFI_PICTURE_B) ++ driver_flags |= V4L2_BUF_FLAG_BFRAME; ++ ++ if (inst_hfi_gen2->hfi_frame_info.data_corrupt || inst_hfi_gen2->hfi_frame_info.overflow) ++ driver_flags |= V4L2_BUF_FLAG_ERROR; ++ ++ if (hfi_flags & HFI_BUF_FW_FLAG_LAST || ++ hfi_flags & HFI_BUF_FW_FLAG_PSC_LAST) ++ driver_flags |= V4L2_BUF_FLAG_LAST; ++ ++ return driver_flags; ++} ++ + static bool iris_hfi_gen2_validate_packet_payload(struct iris_hfi_packet *pkt) + { + u32 payload_size = 0; +@@ -154,6 +179,37 @@ static int iris_hfi_gen2_validate_hdr_packet(struct iris_core *core, struct iris + return 0; + } + ++static int iris_hfi_gen2_handle_session_info(struct iris_inst *inst, ++ struct iris_hfi_packet *pkt) ++{ ++ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); ++ struct iris_core *core = inst->core; ++ int ret = 0; ++ char *info; ++ ++ switch (pkt->type) { ++ case HFI_INFO_UNSUPPORTED: ++ info = "unsupported"; ++ break; ++ case HFI_INFO_DATA_CORRUPT: ++ info = "data corrupt"; ++ inst_hfi_gen2->hfi_frame_info.data_corrupt = 1; ++ break; ++ case HFI_INFO_BUFFER_OVERFLOW: ++ info = "buffer overflow"; ++ inst_hfi_gen2->hfi_frame_info.overflow = 1; ++ break; ++ default: ++ info = "unknown"; ++ break; ++ } ++ ++ dev_dbg(core->dev, "session info received %#x: %s\n", ++ pkt->type, info); ++ ++ return ret; ++} ++ + static int iris_hfi_gen2_handle_session_error(struct iris_inst *inst, + struct iris_hfi_packet *pkt) + { +@@ -237,19 +293,108 @@ static void iris_hfi_gen2_handle_session_close(struct iris_inst *inst, + complete(&inst->completion); + } + ++static int iris_hfi_gen2_handle_input_buffer(struct iris_inst *inst, ++ struct iris_hfi_buffer *buffer) ++{ ++ struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; ++ struct v4l2_m2m_buffer *m2m_buffer, *n; ++ struct iris_buffer *buf; ++ bool found = false; ++ ++ v4l2_m2m_for_each_src_buf_safe(m2m_ctx, m2m_buffer, n) { ++ buf = to_iris_buffer(&m2m_buffer->vb); ++ if (buf->index == buffer->index) { ++ found = true; ++ break; ++ } ++ } ++ if (!found) ++ return -EINVAL; ++ ++ if (!(buf->attr & BUF_ATTR_QUEUED)) ++ return -EINVAL; ++ ++ buf->attr &= ~BUF_ATTR_QUEUED; ++ buf->attr |= BUF_ATTR_DEQUEUED; ++ ++ buf->flags = iris_hfi_gen2_get_driver_buffer_flags(inst, buffer->flags); ++ ++ return 0; ++} ++ ++static int iris_hfi_gen2_handle_output_buffer(struct iris_inst *inst, ++ struct iris_hfi_buffer *hfi_buffer) ++{ ++ struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; ++ struct v4l2_m2m_buffer *m2m_buffer, *n; ++ struct iris_buffer *buf; ++ bool found = false; ++ ++ v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, m2m_buffer, n) { ++ buf = to_iris_buffer(&m2m_buffer->vb); ++ if (buf->index == hfi_buffer->index && ++ buf->device_addr == hfi_buffer->base_address && ++ buf->data_offset == hfi_buffer->data_offset) { ++ found = true; ++ break; ++ } ++ } ++ if (!found) ++ return -EINVAL; ++ ++ if (!(buf->attr & BUF_ATTR_QUEUED)) ++ return -EINVAL; ++ ++ buf->data_offset = hfi_buffer->data_offset; ++ buf->data_size = hfi_buffer->data_size; ++ buf->timestamp = hfi_buffer->timestamp; ++ ++ buf->attr &= ~BUF_ATTR_QUEUED; ++ buf->attr |= BUF_ATTR_DEQUEUED; ++ ++ buf->flags = iris_hfi_gen2_get_driver_buffer_flags(inst, hfi_buffer->flags); ++ ++ return 0; ++} ++ ++static void iris_hfi_gen2_handle_dequeue_buffers(struct iris_inst *inst) ++{ ++ struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; ++ struct v4l2_m2m_buffer *buffer, *n; ++ struct iris_buffer *buf = NULL; ++ ++ v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buffer, n) { ++ buf = to_iris_buffer(&buffer->vb); ++ if (buf->attr & BUF_ATTR_DEQUEUED) { ++ buf->attr &= ~BUF_ATTR_DEQUEUED; ++ if (!(buf->attr & BUF_ATTR_BUFFER_DONE)) { ++ buf->attr |= BUF_ATTR_BUFFER_DONE; ++ iris_vb2_buffer_done(inst, buf); ++ } ++ } ++ } ++ ++ v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, buffer, n) { ++ buf = to_iris_buffer(&buffer->vb); ++ if (buf->attr & BUF_ATTR_DEQUEUED) { ++ buf->attr &= ~BUF_ATTR_DEQUEUED; ++ if (!(buf->attr & BUF_ATTR_BUFFER_DONE)) { ++ buf->attr |= BUF_ATTR_BUFFER_DONE; ++ iris_vb2_buffer_done(inst, buf); ++ } ++ } ++ } ++} ++ + static int iris_hfi_gen2_handle_release_internal_buffer(struct iris_inst *inst, + struct iris_hfi_buffer *buffer) + { ++ u32 buf_type = iris_hfi_gen2_buf_type_to_driver(buffer->type); ++ struct iris_buffers *buffers = &inst->buffers[buf_type]; + struct iris_buffer *buf, *iter; +- struct iris_buffers *buffers; +- u32 buf_type; ++ bool found = false; + int ret = 0; +- bool found; + +- buf_type = iris_hfi_gen2_buf_type_to_driver(buffer->type); +- buffers = &inst->buffers[buf_type]; +- +- found = false; + list_for_each_entry(iter, &buffers->list, list) { + if (iter->device_addr == buffer->base_address) { + found = true; +@@ -261,7 +406,6 @@ static int iris_hfi_gen2_handle_release_internal_buffer(struct iris_inst *inst, + return -EINVAL; + + buf->attr &= ~BUF_ATTR_QUEUED; +- + if (buf->attr & BUF_ATTR_PENDING_RELEASE) + ret = iris_destroy_internal_buffer(inst, buf); + +@@ -288,7 +432,12 @@ static int iris_hfi_gen2_handle_session_buffer(struct iris_inst *inst, + if (!iris_hfi_gen2_is_valid_hfi_port(pkt->port, buffer->type)) + return 0; + +- return iris_hfi_gen2_handle_release_internal_buffer(inst, buffer); ++ if (buffer->type == HFI_BUFFER_BITSTREAM) ++ return iris_hfi_gen2_handle_input_buffer(inst, buffer); ++ else if (buffer->type == HFI_BUFFER_RAW) ++ return iris_hfi_gen2_handle_output_buffer(inst, buffer); ++ else ++ return iris_hfi_gen2_handle_release_internal_buffer(inst, buffer); + } + + static int iris_hfi_gen2_handle_session_command(struct iris_inst *inst, +@@ -350,6 +499,12 @@ static int iris_hfi_gen2_handle_session_property(struct iris_inst *inst, + case HFI_PROP_LEVEL: + inst_hfi_gen2->src_subcr_params.level = pkt->payload[0]; + break; ++ case HFI_PROP_PICTURE_TYPE: ++ inst_hfi_gen2->hfi_frame_info.picture_type = pkt->payload[0]; ++ break; ++ case HFI_PROP_NO_OUTPUT: ++ inst_hfi_gen2->hfi_frame_info.no_output = 1; ++ break; + case HFI_PROP_QUALITY_MODE: + case HFI_PROP_STAGE: + case HFI_PROP_PIPE: +@@ -436,14 +591,18 @@ static int iris_hfi_gen2_handle_system_response(struct iris_core *core, + static int iris_hfi_gen2_handle_session_response(struct iris_core *core, + struct iris_hfi_header *hdr) + { ++ struct iris_inst_hfi_gen2 *inst_hfi_gen2; + struct iris_hfi_packet *packet; + struct iris_inst *inst; ++ bool dequeue = false; + int ret = 0; + u32 i, j; + u8 *pkt; + static const struct iris_hfi_gen2_inst_hfi_range range[] = { + {HFI_SESSION_ERROR_BEGIN, HFI_SESSION_ERROR_END, + iris_hfi_gen2_handle_session_error}, ++ {HFI_INFORMATION_BEGIN, HFI_INFORMATION_END, ++ iris_hfi_gen2_handle_session_info}, + {HFI_PROP_BEGIN, HFI_PROP_END, + iris_hfi_gen2_handle_session_property}, + {HFI_CMD_BEGIN, HFI_CMD_END, +@@ -455,6 +614,8 @@ static int iris_hfi_gen2_handle_session_response(struct iris_core *core, + return -EINVAL; + + mutex_lock(&inst->lock); ++ inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); ++ memset(&inst_hfi_gen2->hfi_frame_info, 0, sizeof(struct iris_hfi_frame_info)); + + pkt = (u8 *)((u8 *)hdr + sizeof(*hdr)); + for (i = 0; i < ARRAY_SIZE(range); i++) { +@@ -465,6 +626,7 @@ static int iris_hfi_gen2_handle_session_response(struct iris_core *core, + iris_hfi_gen2_handle_session_error(inst, packet); + + if (packet->type > range[i].begin && packet->type < range[i].end) { ++ dequeue |= (packet->type == HFI_CMD_BUFFER); + ret = range[i].handle(inst, packet); + if (ret) + iris_inst_change_state(inst, IRIS_INST_ERROR); +@@ -473,6 +635,9 @@ static int iris_hfi_gen2_handle_session_response(struct iris_core *core, + } + } + ++ if (dequeue) ++ iris_hfi_gen2_handle_dequeue_buffers(inst); ++ + mutex_unlock(&inst->lock); + + return ret; +diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/drivers/media/platform/qcom/iris/iris_instance.h +index 6b88daf31011..2886491ad59f 100644 +--- a/drivers/media/platform/qcom/iris/iris_instance.h ++++ b/drivers/media/platform/qcom/iris/iris_instance.h +@@ -34,6 +34,10 @@ + * @once_per_session_set: boolean to set once per session property + * @m2m_dev: a reference to m2m device structure + * @m2m_ctx: a reference to m2m context structure ++ * @sequence_cap: a sequence counter for capture queue ++ * @sequence_out: a sequence counter for output queue ++ * @tss: timestamp metadata ++ * @metadata_idx: index for metadata buffer + */ + + struct iris_inst { +@@ -56,6 +60,10 @@ struct iris_inst { + bool once_per_session_set; + struct v4l2_m2m_dev *m2m_dev; + struct v4l2_m2m_ctx *m2m_ctx; ++ u32 sequence_cap; ++ u32 sequence_out; ++ struct iris_ts_metadata tss[VIDEO_MAX_FRAME]; ++ u32 metadata_idx; + }; + + #endif +diff --git a/drivers/media/platform/qcom/iris/iris_utils.c b/drivers/media/platform/qcom/iris/iris_utils.c +index 8bcfa97db97d..83c70d6a2d90 100644 +--- a/drivers/media/platform/qcom/iris/iris_utils.c ++++ b/drivers/media/platform/qcom/iris/iris_utils.c +@@ -4,6 +4,7 @@ + */ + + #include ++#include + + #include "iris_instance.h" + #include "iris_utils.h" +@@ -36,6 +37,21 @@ bool iris_split_mode_enabled(struct iris_inst *inst) + return inst->fmt_dst->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_NV12; + } + ++void iris_helper_buffers_done(struct iris_inst *inst, unsigned int type, ++ enum vb2_buffer_state state) ++{ ++ struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; ++ struct vb2_v4l2_buffer *buf; ++ ++ if (V4L2_TYPE_IS_OUTPUT(type)) { ++ while ((buf = v4l2_m2m_src_buf_remove(m2m_ctx))) ++ v4l2_m2m_buf_done(buf, state); ++ } else if (V4L2_TYPE_IS_CAPTURE(type)) { ++ while ((buf = v4l2_m2m_dst_buf_remove(m2m_ctx))) ++ v4l2_m2m_buf_done(buf, state); ++ } ++} ++ + int iris_wait_for_session_response(struct iris_inst *inst, bool is_flush) + { + struct iris_core *core = inst->core; +diff --git a/drivers/media/platform/qcom/iris/iris_utils.h b/drivers/media/platform/qcom/iris/iris_utils.h +index 3400847f5e72..49869cf7a376 100644 +--- a/drivers/media/platform/qcom/iris/iris_utils.h ++++ b/drivers/media/platform/qcom/iris/iris_utils.h +@@ -16,6 +16,20 @@ struct iris_hfi_rect_desc { + u32 height; + }; + ++struct iris_hfi_frame_info { ++ u32 picture_type; ++ u32 no_output; ++ u32 data_corrupt; ++ u32 overflow; ++}; ++ ++struct iris_ts_metadata { ++ u64 ts_ns; ++ u64 ts_us; ++ u32 flags; ++ struct v4l2_timecode tc; ++}; ++ + #define NUM_MBS_PER_FRAME(height, width) \ + (DIV_ROUND_UP(height, 16) * DIV_ROUND_UP(width, 16)) + +@@ -32,6 +46,8 @@ bool iris_res_is_less_than(u32 width, u32 height, + int iris_get_mbpf(struct iris_inst *inst); + bool iris_split_mode_enabled(struct iris_inst *inst); + struct iris_inst *iris_get_instance(struct iris_core *core, u32 session_id); ++void iris_helper_buffers_done(struct iris_inst *inst, unsigned int type, ++ enum vb2_buffer_state state); + int iris_wait_for_session_response(struct iris_inst *inst, bool is_flush); + + #endif +diff --git a/drivers/media/platform/qcom/iris/iris_vb2.c b/drivers/media/platform/qcom/iris/iris_vb2.c +index b93da860d336..770e51f9ef91 100644 +--- a/drivers/media/platform/qcom/iris/iris_vb2.c ++++ b/drivers/media/platform/qcom/iris/iris_vb2.c +@@ -3,10 +3,23 @@ + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + ++#include ++#include ++ + #include "iris_instance.h" + #include "iris_vb2.h" + #include "iris_vdec.h" + ++int iris_vb2_buf_init(struct vb2_buffer *vb2) ++{ ++ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2); ++ struct iris_buffer *buf = to_iris_buffer(vbuf); ++ ++ buf->device_addr = vb2_dma_contig_plane_dma_addr(vb2, 0); ++ ++ return 0; ++} ++ + int iris_vb2_queue_setup(struct vb2_queue *q, + unsigned int *num_buffers, unsigned int *num_planes, + unsigned int sizes[], struct device *alloc_devs[]) +@@ -60,6 +73,7 @@ int iris_vb2_queue_setup(struct vb2_queue *q, + + int iris_vb2_start_streaming(struct vb2_queue *q, unsigned int count) + { ++ enum iris_buffer_type buf_type; + struct iris_inst *inst; + int ret = 0; + +@@ -87,11 +101,18 @@ int iris_vb2_start_streaming(struct vb2_queue *q, unsigned int count) + if (ret) + goto error; + ++ buf_type = iris_v4l2_type_to_driver(q->type); ++ ++ ret = iris_queue_deferred_buffers(inst, buf_type); ++ if (ret) ++ goto error; ++ + mutex_unlock(&inst->lock); + + return ret; + + error: ++ iris_helper_buffers_done(inst, q->type, VB2_BUF_STATE_QUEUED); + iris_inst_change_state(inst, IRIS_INST_ERROR); + mutex_unlock(&inst->lock); + +@@ -101,6 +122,7 @@ int iris_vb2_start_streaming(struct vb2_queue *q, unsigned int count) + void iris_vb2_stop_streaming(struct vb2_queue *q) + { + struct iris_inst *inst; ++ int ret = 0; + + inst = vb2_get_drv_priv(q); + +@@ -113,8 +135,82 @@ void iris_vb2_stop_streaming(struct vb2_queue *q) + !V4L2_TYPE_IS_CAPTURE(q->type)) + goto exit; + +- iris_vdec_session_streamoff(inst, q->type); ++ ret = iris_vdec_session_streamoff(inst, q->type); ++ if (ret) ++ goto exit; ++ ++exit: ++ iris_helper_buffers_done(inst, q->type, VB2_BUF_STATE_ERROR); ++ if (ret) ++ iris_inst_change_state(inst, IRIS_INST_ERROR); ++ ++ mutex_unlock(&inst->lock); ++} ++ ++int iris_vb2_buf_prepare(struct vb2_buffer *vb) ++{ ++ struct iris_inst *inst = vb2_get_drv_priv(vb->vb2_queue); ++ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); ++ ++ if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { ++ if (vbuf->field == V4L2_FIELD_ANY) ++ vbuf->field = V4L2_FIELD_NONE; ++ if (vbuf->field != V4L2_FIELD_NONE) ++ return -EINVAL; ++ } ++ ++ if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && ++ vb2_plane_size(vb, 0) < iris_get_buffer_size(inst, BUF_OUTPUT)) ++ return -EINVAL; ++ if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && ++ vb2_plane_size(vb, 0) < iris_get_buffer_size(inst, BUF_INPUT)) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++int iris_vb2_buf_out_validate(struct vb2_buffer *vb) ++{ ++ struct vb2_v4l2_buffer *v4l2_buf = to_vb2_v4l2_buffer(vb); ++ ++ v4l2_buf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++void iris_vb2_buf_queue(struct vb2_buffer *vb2) ++{ ++ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2); ++ struct v4l2_m2m_ctx *m2m_ctx; ++ struct iris_inst *inst; ++ int ret = 0; ++ ++ inst = vb2_get_drv_priv(vb2->vb2_queue); ++ ++ mutex_lock(&inst->lock); ++ if (inst->state == IRIS_INST_ERROR) { ++ ret = -EBUSY; ++ goto exit; ++ } ++ ++ if (vbuf->field == V4L2_FIELD_ANY) ++ vbuf->field = V4L2_FIELD_NONE; ++ ++ m2m_ctx = inst->m2m_ctx; ++ ++ if (!vb2->planes[0].bytesused && V4L2_TYPE_IS_OUTPUT(vb2->type)) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ v4l2_m2m_buf_queue(m2m_ctx, vbuf); ++ ++ ret = iris_vdec_qbuf(inst, vbuf); + + exit: ++ if (ret) { ++ iris_inst_change_state(inst, IRIS_INST_ERROR); ++ v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR); ++ } + mutex_unlock(&inst->lock); + } +diff --git a/drivers/media/platform/qcom/iris/iris_vb2.h b/drivers/media/platform/qcom/iris/iris_vb2.h +index 3906510fa71f..a88565fdd3e4 100644 +--- a/drivers/media/platform/qcom/iris/iris_vb2.h ++++ b/drivers/media/platform/qcom/iris/iris_vb2.h +@@ -6,10 +6,14 @@ + #ifndef __IRIS_VB2_H__ + #define __IRIS_VB2_H__ + ++int iris_vb2_buf_init(struct vb2_buffer *vb2); + int iris_vb2_queue_setup(struct vb2_queue *q, + unsigned int *num_buffers, unsigned int *num_planes, + unsigned int sizes[], struct device *alloc_devs[]); + int iris_vb2_start_streaming(struct vb2_queue *q, unsigned int count); + void iris_vb2_stop_streaming(struct vb2_queue *q); ++int iris_vb2_buf_prepare(struct vb2_buffer *vb); ++int iris_vb2_buf_out_validate(struct vb2_buffer *vb); ++void iris_vb2_buf_queue(struct vb2_buffer *vb2); + + #endif +diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c +index 8d489530da31..d6b092314b34 100644 +--- a/drivers/media/platform/qcom/iris/iris_vdec.c ++++ b/drivers/media/platform/qcom/iris/iris_vdec.c +@@ -223,6 +223,68 @@ int iris_vdec_subscribe_event(struct iris_inst *inst, const struct v4l2_event_su + return ret; + } + ++static int iris_vdec_get_num_queued_buffers(struct iris_inst *inst, ++ enum iris_buffer_type type) ++{ ++ struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; ++ struct v4l2_m2m_buffer *buffer, *n; ++ struct iris_buffer *buf; ++ u32 count = 0; ++ ++ switch (type) { ++ case BUF_INPUT: ++ v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buffer, n) { ++ buf = to_iris_buffer(&buffer->vb); ++ if (!(buf->attr & BUF_ATTR_QUEUED)) ++ continue; ++ count++; ++ } ++ return count; ++ case BUF_OUTPUT: ++ v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, buffer, n) { ++ buf = to_iris_buffer(&buffer->vb); ++ if (!(buf->attr & BUF_ATTR_QUEUED)) ++ continue; ++ count++; ++ } ++ return count; ++ default: ++ return count; ++ } ++} ++ ++static void iris_vdec_flush_deferred_buffers(struct iris_inst *inst, ++ enum iris_buffer_type type) ++{ ++ struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; ++ struct v4l2_m2m_buffer *buffer, *n; ++ struct iris_buffer *buf; ++ ++ if (type == BUF_INPUT) { ++ v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buffer, n) { ++ buf = to_iris_buffer(&buffer->vb); ++ if (buf->attr & BUF_ATTR_DEFERRED) { ++ if (!(buf->attr & BUF_ATTR_BUFFER_DONE)) { ++ buf->attr |= BUF_ATTR_BUFFER_DONE; ++ buf->data_size = 0; ++ iris_vb2_buffer_done(inst, buf); ++ } ++ } ++ } ++ } else { ++ v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, buffer, n) { ++ buf = to_iris_buffer(&buffer->vb); ++ if (buf->attr & BUF_ATTR_DEFERRED) { ++ if (!(buf->attr & BUF_ATTR_BUFFER_DONE)) { ++ buf->attr |= BUF_ATTR_BUFFER_DONE; ++ buf->data_size = 0; ++ iris_vb2_buffer_done(inst, buf); ++ } ++ } ++ } ++ } ++} ++ + static void iris_vdec_kill_session(struct iris_inst *inst) + { + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; +@@ -234,23 +296,47 @@ static void iris_vdec_kill_session(struct iris_inst *inst) + iris_inst_change_state(inst, IRIS_INST_ERROR); + } + +-void iris_vdec_session_streamoff(struct iris_inst *inst, u32 plane) ++int iris_vdec_session_streamoff(struct iris_inst *inst, u32 plane) + { + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; ++ enum iris_buffer_type buffer_type; ++ u32 count; + int ret; + ++ switch (plane) { ++ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: ++ buffer_type = BUF_INPUT; ++ break; ++ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: ++ buffer_type = BUF_OUTPUT; ++ break; ++ default: ++ return -EINVAL; ++ } ++ + ret = hfi_ops->session_stop(inst, plane); + if (ret) + goto error; + ++ count = iris_vdec_get_num_queued_buffers(inst, buffer_type); ++ if (count) { ++ ret = -EINVAL; ++ goto error; ++ } ++ + ret = iris_inst_state_change_streamoff(inst, plane); + if (ret) + goto error; + +- return; ++ iris_vdec_flush_deferred_buffers(inst, buffer_type); ++ ++ return 0; + + error: + iris_vdec_kill_session(inst); ++ iris_vdec_flush_deferred_buffers(inst, buffer_type); ++ ++ return ret; + } + + static int iris_vdec_process_streamon_input(struct iris_inst *inst) +@@ -340,3 +426,64 @@ int iris_vdec_streamon_output(struct iris_inst *inst) + + return ret; + } ++ ++static int ++iris_vdec_vb2_buffer_to_driver(struct vb2_buffer *vb2, struct iris_buffer *buf) ++{ ++ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2); ++ ++ buf->type = iris_v4l2_type_to_driver(vb2->type); ++ buf->index = vb2->index; ++ buf->fd = vb2->planes[0].m.fd; ++ buf->buffer_size = vb2->planes[0].length; ++ buf->data_offset = vb2->planes[0].data_offset; ++ buf->data_size = vb2->planes[0].bytesused - vb2->planes[0].data_offset; ++ buf->flags = vbuf->flags; ++ buf->timestamp = vb2->timestamp; ++ buf->attr = 0; ++ ++ return 0; ++} ++ ++static void ++iris_set_ts_metadata(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf) ++{ ++ u32 mask = V4L2_BUF_FLAG_TIMECODE | V4L2_BUF_FLAG_TSTAMP_SRC_MASK; ++ struct vb2_buffer *vb = &vbuf->vb2_buf; ++ u64 ts_us = vb->timestamp; ++ ++ if (inst->metadata_idx >= ARRAY_SIZE(inst->tss)) ++ inst->metadata_idx = 0; ++ ++ do_div(ts_us, NSEC_PER_USEC); ++ ++ inst->tss[inst->metadata_idx].flags = vbuf->flags & mask; ++ inst->tss[inst->metadata_idx].tc = vbuf->timecode; ++ inst->tss[inst->metadata_idx].ts_us = ts_us; ++ inst->tss[inst->metadata_idx].ts_ns = vb->timestamp; ++ ++ inst->metadata_idx++; ++} ++ ++int iris_vdec_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf) ++{ ++ struct iris_buffer *buf = to_iris_buffer(vbuf); ++ struct vb2_buffer *vb2 = &vbuf->vb2_buf; ++ struct vb2_queue *q; ++ int ret; ++ ++ ret = iris_vdec_vb2_buffer_to_driver(vb2, buf); ++ if (ret) ++ return ret; ++ ++ if (buf->type == BUF_INPUT) ++ iris_set_ts_metadata(inst, vbuf); ++ ++ q = v4l2_m2m_get_vq(inst->m2m_ctx, vb2->type); ++ if (!vb2_is_streaming(q)) { ++ buf->attr |= BUF_ATTR_DEFERRED; ++ return 0; ++ } ++ ++ return iris_queue_buffer(inst, buf); ++} +diff --git a/drivers/media/platform/qcom/iris/iris_vdec.h b/drivers/media/platform/qcom/iris/iris_vdec.h +index a17bb817b6e5..998d4970a42b 100644 +--- a/drivers/media/platform/qcom/iris/iris_vdec.h ++++ b/drivers/media/platform/qcom/iris/iris_vdec.h +@@ -16,6 +16,7 @@ int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f); + int iris_vdec_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub); + int iris_vdec_streamon_input(struct iris_inst *inst); + int iris_vdec_streamon_output(struct iris_inst *inst); +-void iris_vdec_session_streamoff(struct iris_inst *inst, u32 plane); ++int iris_vdec_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf); ++int iris_vdec_session_streamoff(struct iris_inst *inst, u32 plane); + + #endif +diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c +index ec5694c1c8de..2b27df6b1aad 100644 +--- a/drivers/media/platform/qcom/iris/iris_vidc.c ++++ b/drivers/media/platform/qcom/iris/iris_vidc.c +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + + #include "iris_vidc.h" + #include "iris_instance.h" +@@ -98,6 +99,7 @@ iris_m2m_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_ + src_vq->io_modes = VB2_MMAP | VB2_DMABUF; + src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; + src_vq->ops = inst->core->iris_vb2_ops; ++ src_vq->mem_ops = &vb2_dma_contig_memops; + src_vq->drv_priv = inst; + src_vq->buf_struct_size = sizeof(struct iris_buffer); + src_vq->min_reqbufs_allocation = MIN_BUFFERS; +@@ -111,6 +113,7 @@ iris_m2m_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_ + dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; + dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; + dst_vq->ops = inst->core->iris_vb2_ops; ++ dst_vq->mem_ops = &vb2_dma_contig_memops; + dst_vq->drv_priv = inst; + dst_vq->buf_struct_size = sizeof(struct iris_buffer); + dst_vq->min_reqbufs_allocation = MIN_BUFFERS; +@@ -372,9 +375,13 @@ static struct v4l2_file_operations iris_v4l2_file_ops = { + }; + + static const struct vb2_ops iris_vb2_ops = { ++ .buf_init = iris_vb2_buf_init, + .queue_setup = iris_vb2_queue_setup, + .start_streaming = iris_vb2_start_streaming, + .stop_streaming = iris_vb2_stop_streaming, ++ .buf_prepare = iris_vb2_buf_prepare, ++ .buf_out_validate = iris_vb2_buf_out_validate, ++ .buf_queue = iris_vb2_buf_queue, + }; + + static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops = { +@@ -388,6 +395,13 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops = { + .vidioc_g_fmt_vid_out_mplane = iris_g_fmt_vid_mplane, + .vidioc_enum_framesizes = iris_enum_framesizes, + .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, ++ .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, ++ .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, ++ .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, ++ .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, ++ .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, ++ .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, ++ .vidioc_remove_bufs = v4l2_m2m_ioctl_remove_bufs, + .vidioc_querycap = iris_querycap, + .vidioc_g_selection = iris_g_selection, + .vidioc_subscribe_event = iris_subscribe_event, +-- +2.34.1 + diff --git a/patch/kernel/archive/sm8550-6.12/0021_media--iris--add-support-for-dynamic-resolution-ch.patch b/patch/kernel/archive/sm8550-6.12/0021_media--iris--add-support-for-dynamic-resolution-ch.patch new file mode 100644 index 000000000..9c49f0d0c --- /dev/null +++ b/patch/kernel/archive/sm8550-6.12/0021_media--iris--add-support-for-dynamic-resolution-ch.patch @@ -0,0 +1,985 @@ +From e5ae667c7a8454ed54645d1706a21bd2c3e2882c Mon Sep 17 00:00:00 2001 +From: Dikshita Agarwal +Date: Fri, 7 Feb 2025 13:25:01 +0530 +Subject: [PATCH] media: iris: add support for dynamic resolution change + +Handle the response sent by the firmware, when a source change is +detected. Read the subscribed parameter to get the changed values. Raise +the source change event to the client and update the instance sub-state. + +Mark the last buffer from before the source change with the +V4L2_BUF_FLAG_LAST flag and return to the client. + +Reviewed-by: Hans Verkuil +Tested-by: Stefan Schmidt # x1e80100 (Dell XPS 13 9345) +Reviewed-by: Stefan Schmidt +Tested-by: Neil Armstrong # on SM8550-QRD +Tested-by: Neil Armstrong # on SM8550-HDK +Signed-off-by: Dikshita Agarwal +Link: https://lore.kernel.org/r/20250207-qcom-video-iris-v10-21-ab66eeffbd20@quicinc.com +Signed-off-by: Neil Armstrong +--- + .../platform/qcom/iris/iris_hfi_common.c | 64 ++++++ + .../platform/qcom/iris/iris_hfi_common.h | 3 + + .../qcom/iris/iris_hfi_gen1_defines.h | 82 +++++++ + .../qcom/iris/iris_hfi_gen1_response.c | 208 ++++++++++++++++++ + .../qcom/iris/iris_hfi_gen2_defines.h | 4 + + .../qcom/iris/iris_hfi_gen2_response.c | 183 ++++++++++++++- + .../media/platform/qcom/iris/iris_instance.h | 2 + + drivers/media/platform/qcom/iris/iris_state.c | 64 ++++++ + drivers/media/platform/qcom/iris/iris_state.h | 33 +++ + drivers/media/platform/qcom/iris/iris_vb2.c | 18 ++ + drivers/media/platform/qcom/iris/iris_vdec.c | 15 ++ + drivers/media/platform/qcom/iris/iris_vdec.h | 1 + + 12 files changed, 676 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.c b/drivers/media/platform/qcom/iris/iris_hfi_common.c +index 29f56c2bf74c..92112eb16c11 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_common.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_common.c +@@ -10,6 +10,70 @@ + #include "iris_hfi_common.h" + #include "iris_vpu_common.h" + ++u32 iris_hfi_get_v4l2_color_primaries(u32 hfi_primaries) ++{ ++ switch (hfi_primaries) { ++ case HFI_PRIMARIES_RESERVED: ++ return V4L2_COLORSPACE_DEFAULT; ++ case HFI_PRIMARIES_BT709: ++ return V4L2_COLORSPACE_REC709; ++ case HFI_PRIMARIES_BT470_SYSTEM_M: ++ return V4L2_COLORSPACE_470_SYSTEM_M; ++ case HFI_PRIMARIES_BT470_SYSTEM_BG: ++ return V4L2_COLORSPACE_470_SYSTEM_BG; ++ case HFI_PRIMARIES_BT601_525: ++ return V4L2_COLORSPACE_SMPTE170M; ++ case HFI_PRIMARIES_SMPTE_ST240M: ++ return V4L2_COLORSPACE_SMPTE240M; ++ case HFI_PRIMARIES_BT2020: ++ return V4L2_COLORSPACE_BT2020; ++ case V4L2_COLORSPACE_DCI_P3: ++ return HFI_PRIMARIES_SMPTE_RP431_2; ++ default: ++ return V4L2_COLORSPACE_DEFAULT; ++ } ++} ++ ++u32 iris_hfi_get_v4l2_transfer_char(u32 hfi_characterstics) ++{ ++ switch (hfi_characterstics) { ++ case HFI_TRANSFER_RESERVED: ++ return V4L2_XFER_FUNC_DEFAULT; ++ case HFI_TRANSFER_BT709: ++ return V4L2_XFER_FUNC_709; ++ case HFI_TRANSFER_SMPTE_ST240M: ++ return V4L2_XFER_FUNC_SMPTE240M; ++ case HFI_TRANSFER_SRGB_SYCC: ++ return V4L2_XFER_FUNC_SRGB; ++ case HFI_TRANSFER_SMPTE_ST2084_PQ: ++ return V4L2_XFER_FUNC_SMPTE2084; ++ default: ++ return V4L2_XFER_FUNC_DEFAULT; ++ } ++} ++ ++u32 iris_hfi_get_v4l2_matrix_coefficients(u32 hfi_coefficients) ++{ ++ switch (hfi_coefficients) { ++ case HFI_MATRIX_COEFF_RESERVED: ++ return V4L2_YCBCR_ENC_DEFAULT; ++ case HFI_MATRIX_COEFF_BT709: ++ return V4L2_YCBCR_ENC_709; ++ case HFI_MATRIX_COEFF_BT470_SYS_BG_OR_BT601_625: ++ return V4L2_YCBCR_ENC_XV601; ++ case HFI_MATRIX_COEFF_BT601_525_BT1358_525_OR_625: ++ return V4L2_YCBCR_ENC_601; ++ case HFI_MATRIX_COEFF_SMPTE_ST240: ++ return V4L2_YCBCR_ENC_SMPTE240M; ++ case HFI_MATRIX_COEFF_BT2020_NON_CONSTANT: ++ return V4L2_YCBCR_ENC_BT2020; ++ case HFI_MATRIX_COEFF_BT2020_CONSTANT: ++ return V4L2_YCBCR_ENC_BT2020_CONST_LUM; ++ default: ++ return V4L2_YCBCR_ENC_DEFAULT; ++ } ++} ++ + int iris_hfi_core_init(struct iris_core *core) + { + const struct iris_hfi_command_ops *hfi_ops = core->hfi_ops; +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.h b/drivers/media/platform/qcom/iris/iris_hfi_common.h +index c54c88658633..6241098dc31d 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_common.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_common.h +@@ -138,6 +138,9 @@ struct hfi_subscription_params { + u32 level; + }; + ++u32 iris_hfi_get_v4l2_color_primaries(u32 hfi_primaries); ++u32 iris_hfi_get_v4l2_transfer_char(u32 hfi_characterstics); ++u32 iris_hfi_get_v4l2_matrix_coefficients(u32 hfi_coefficients); + int iris_hfi_core_init(struct iris_core *core); + int iris_hfi_pm_suspend(struct iris_core *core); + int iris_hfi_pm_resume(struct iris_core *core); +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +index 108449d703e1..416e9a19a26f 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +@@ -44,18 +44,28 @@ + #define HFI_EVENT_SYS_ERROR 0x1 + #define HFI_EVENT_SESSION_ERROR 0x2 + ++#define HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUF_RESOURCES 0x1000001 ++#define HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUF_RESOURCES 0x1000002 ++#define HFI_EVENT_SESSION_SEQUENCE_CHANGED 0x1000003 ++ + #define HFI_BUFFERFLAG_TIMESTAMPINVALID 0x00000100 + + #define HFI_FLUSH_OUTPUT 0x1000002 + #define HFI_FLUSH_OUTPUT2 0x1000003 + #define HFI_FLUSH_ALL 0x1000004 + ++#define HFI_INDEX_EXTRADATA_INPUT_CROP 0x0700000e ++ + #define HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL 0x201001 + #define HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO 0x201002 + #define HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE 0x201008 + #define HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL 0x20100c + ++#define HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS 0x202001 ++ + #define HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER 0x1200001 ++#define HFI_PROPERTY_PARAM_VDEC_DPB_COUNTS 0x120300e ++#define HFI_PROPERTY_CONFIG_VDEC_ENTROPY 0x1204004 + + #define HFI_BUFFER_INPUT 0x1 + #define HFI_BUFFER_OUTPUT 0x2 +@@ -69,11 +79,15 @@ + + #define HFI_PROPERTY_PARAM_FRAME_SIZE 0x1001 + #define HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT 0x1003 ++#define HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT 0x1005 + #define HFI_PROPERTY_PARAM_WORK_MODE 0x1015 + #define HFI_PROPERTY_PARAM_WORK_ROUTE 0x1017 + #define HFI_PROPERTY_CONFIG_VIDEOCORES_USAGE 0x2002 + + #define HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM 0x1003001 ++#define HFI_PROPERTY_PARAM_VDEC_PIXEL_BITDEPTH 0x1003007 ++#define HFI_PROPERTY_PARAM_VDEC_PIC_STRUCT 0x1003009 ++#define HFI_PROPERTY_PARAM_VDEC_COLOUR_SPACE 0x100300a + #define HFI_CORE_ID_1 1 + #define HFI_COLOR_FORMAT_NV12 0x02 + #define HFI_COLOR_FORMAT_NV12_UBWC 0x8002 +@@ -249,6 +263,11 @@ struct hfi_enable { + u32 enable; + }; + ++struct hfi_profile_level { ++ u32 profile; ++ u32 level; ++}; ++ + struct hfi_framesize { + u32 buffer_type; + u32 width; +@@ -267,6 +286,37 @@ struct hfi_video_work_route { + u32 video_work_route; + }; + ++struct hfi_bit_depth { ++ u32 buffer_type; ++ u32 bit_depth; ++}; ++ ++struct hfi_pic_struct { ++ u32 progressive_only; ++}; ++ ++struct hfi_colour_space { ++ u32 colour_space; ++}; ++ ++struct hfi_extradata_input_crop { ++ u32 size; ++ u32 version; ++ u32 port_index; ++ u32 left; ++ u32 top; ++ u32 width; ++ u32 height; ++}; ++ ++struct hfi_dpb_counts { ++ u32 max_dpb_count; ++ u32 max_ref_frames; ++ u32 max_dec_buffering; ++ u32 max_reorder_frames; ++ u32 fw_min_count; ++}; ++ + struct hfi_uncompressed_format_select { + u32 buffer_type; + u32 format; +@@ -301,6 +351,38 @@ struct hfi_multi_stream { + u32 enable; + }; + ++struct hfi_buffer_requirements { ++ u32 type; ++ u32 size; ++ u32 region_size; ++ u32 hold_count; ++ u32 count_min; ++ u32 count_actual; ++ u32 contiguous; ++ u32 alignment; ++}; ++ ++struct hfi_event_data { ++ u32 error; ++ u32 height; ++ u32 width; ++ u32 event_type; ++ u32 packet_buffer; ++ u32 extradata_buffer; ++ u32 tag; ++ u32 profile; ++ u32 level; ++ u32 bit_depth; ++ u32 pic_struct; ++ u32 colour_space; ++ u32 entropy_mode; ++ u32 buf_count; ++ struct { ++ u32 left, top; ++ u32 width, height; ++ } input_crop; ++}; ++ + struct hfi_msg_session_empty_buffer_done_pkt { + struct hfi_msg_session_hdr_pkt shdr; + u32 offset; +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c +index 23a8bf29e381..3a47d9f39695 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c +@@ -3,11 +3,216 @@ + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + ++#include + #include + + #include "iris_hfi_gen1.h" + #include "iris_hfi_gen1_defines.h" + #include "iris_instance.h" ++#include "iris_vdec.h" ++#include "iris_vpu_buffer.h" ++ ++static void iris_hfi_gen1_read_changed_params(struct iris_inst *inst, ++ struct hfi_msg_event_notify_pkt *pkt) ++{ ++ struct v4l2_pix_format_mplane *pixmp_ip = &inst->fmt_src->fmt.pix_mp; ++ struct v4l2_pix_format_mplane *pixmp_op = &inst->fmt_dst->fmt.pix_mp; ++ u32 num_properties_changed = pkt->event_data2; ++ u8 *data_ptr = (u8 *)&pkt->ext_event_data[0]; ++ u32 primaries, matrix_coeff, transfer_char; ++ struct hfi_dpb_counts *iris_vpu_dpb_count; ++ struct hfi_profile_level *profile_level; ++ struct hfi_buffer_requirements *bufreq; ++ struct hfi_extradata_input_crop *crop; ++ struct hfi_colour_space *colour_info; ++ struct iris_core *core = inst->core; ++ u32 colour_description_present_flag; ++ u32 video_signal_type_present_flag; ++ struct hfi_event_data event = {0}; ++ struct hfi_bit_depth *pixel_depth; ++ struct hfi_pic_struct *pic_struct; ++ struct hfi_framesize *frame_sz; ++ struct vb2_queue *dst_q; ++ struct v4l2_ctrl *ctrl; ++ u32 full_range, ptype; ++ ++ do { ++ ptype = *((u32 *)data_ptr); ++ switch (ptype) { ++ case HFI_PROPERTY_PARAM_FRAME_SIZE: ++ data_ptr += sizeof(u32); ++ frame_sz = (struct hfi_framesize *)data_ptr; ++ event.width = frame_sz->width; ++ event.height = frame_sz->height; ++ data_ptr += sizeof(*frame_sz); ++ break; ++ case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT: ++ data_ptr += sizeof(u32); ++ profile_level = (struct hfi_profile_level *)data_ptr; ++ event.profile = profile_level->profile; ++ event.level = profile_level->level; ++ data_ptr += sizeof(*profile_level); ++ break; ++ case HFI_PROPERTY_PARAM_VDEC_PIXEL_BITDEPTH: ++ data_ptr += sizeof(u32); ++ pixel_depth = (struct hfi_bit_depth *)data_ptr; ++ event.bit_depth = pixel_depth->bit_depth; ++ data_ptr += sizeof(*pixel_depth); ++ break; ++ case HFI_PROPERTY_PARAM_VDEC_PIC_STRUCT: ++ data_ptr += sizeof(u32); ++ pic_struct = (struct hfi_pic_struct *)data_ptr; ++ event.pic_struct = pic_struct->progressive_only; ++ data_ptr += sizeof(*pic_struct); ++ break; ++ case HFI_PROPERTY_PARAM_VDEC_COLOUR_SPACE: ++ data_ptr += sizeof(u32); ++ colour_info = (struct hfi_colour_space *)data_ptr; ++ event.colour_space = colour_info->colour_space; ++ data_ptr += sizeof(*colour_info); ++ break; ++ case HFI_PROPERTY_CONFIG_VDEC_ENTROPY: ++ data_ptr += sizeof(u32); ++ event.entropy_mode = *(u32 *)data_ptr; ++ data_ptr += sizeof(u32); ++ break; ++ case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS: ++ data_ptr += sizeof(u32); ++ bufreq = (struct hfi_buffer_requirements *)data_ptr; ++ event.buf_count = bufreq->count_min; ++ data_ptr += sizeof(*bufreq); ++ break; ++ case HFI_INDEX_EXTRADATA_INPUT_CROP: ++ data_ptr += sizeof(u32); ++ crop = (struct hfi_extradata_input_crop *)data_ptr; ++ event.input_crop.left = crop->left; ++ event.input_crop.top = crop->top; ++ event.input_crop.width = crop->width; ++ event.input_crop.height = crop->height; ++ data_ptr += sizeof(*crop); ++ break; ++ case HFI_PROPERTY_PARAM_VDEC_DPB_COUNTS: ++ data_ptr += sizeof(u32); ++ iris_vpu_dpb_count = (struct hfi_dpb_counts *)data_ptr; ++ event.buf_count = iris_vpu_dpb_count->fw_min_count; ++ data_ptr += sizeof(*iris_vpu_dpb_count); ++ break; ++ default: ++ break; ++ } ++ num_properties_changed--; ++ } while (num_properties_changed > 0); ++ ++ pixmp_ip->width = event.width; ++ pixmp_ip->height = event.height; ++ ++ pixmp_op->width = ALIGN(event.width, 128); ++ pixmp_op->height = ALIGN(event.height, 32); ++ pixmp_op->plane_fmt[0].bytesperline = ALIGN(event.width, 128); ++ pixmp_op->plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_OUTPUT); ++ ++ matrix_coeff = FIELD_GET(GENMASK(7, 0), event.colour_space); ++ transfer_char = FIELD_GET(GENMASK(15, 8), event.colour_space); ++ primaries = FIELD_GET(GENMASK(23, 16), event.colour_space); ++ colour_description_present_flag = FIELD_GET(GENMASK(24, 24), event.colour_space); ++ full_range = FIELD_GET(GENMASK(25, 25), event.colour_space); ++ video_signal_type_present_flag = FIELD_GET(GENMASK(29, 29), event.colour_space); ++ ++ pixmp_op->colorspace = V4L2_COLORSPACE_DEFAULT; ++ pixmp_op->xfer_func = V4L2_XFER_FUNC_DEFAULT; ++ pixmp_op->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; ++ pixmp_op->quantization = V4L2_QUANTIZATION_DEFAULT; ++ ++ if (video_signal_type_present_flag) { ++ pixmp_op->quantization = ++ full_range ? ++ V4L2_QUANTIZATION_FULL_RANGE : ++ V4L2_QUANTIZATION_LIM_RANGE; ++ if (colour_description_present_flag) { ++ pixmp_op->colorspace = ++ iris_hfi_get_v4l2_color_primaries(primaries); ++ pixmp_op->xfer_func = ++ iris_hfi_get_v4l2_transfer_char(transfer_char); ++ pixmp_op->ycbcr_enc = ++ iris_hfi_get_v4l2_matrix_coefficients(matrix_coeff); ++ } ++ } ++ ++ pixmp_ip->colorspace = pixmp_op->colorspace; ++ pixmp_ip->xfer_func = pixmp_op->xfer_func; ++ pixmp_ip->ycbcr_enc = pixmp_op->ycbcr_enc; ++ pixmp_ip->quantization = pixmp_op->quantization; ++ ++ if (event.input_crop.width > 0 && event.input_crop.height > 0) { ++ inst->crop.left = event.input_crop.left; ++ inst->crop.top = event.input_crop.top; ++ inst->crop.width = event.input_crop.width; ++ inst->crop.height = event.input_crop.height; ++ } else { ++ inst->crop.left = 0; ++ inst->crop.top = 0; ++ inst->crop.width = event.width; ++ inst->crop.height = event.height; ++ } ++ ++ inst->fw_min_count = event.buf_count; ++ inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT); ++ inst->buffers[BUF_OUTPUT].size = pixmp_op->plane_fmt[0].sizeimage; ++ ctrl = v4l2_ctrl_find(&inst->ctrl_handler, V4L2_CID_MIN_BUFFERS_FOR_CAPTURE); ++ if (ctrl) ++ v4l2_ctrl_s_ctrl(ctrl, inst->buffers[BUF_OUTPUT].min_count); ++ ++ dst_q = v4l2_m2m_get_dst_vq(inst->m2m_ctx); ++ dst_q->min_reqbufs_allocation = inst->buffers[BUF_OUTPUT].min_count; ++ ++ if (event.bit_depth || !event.pic_struct) { ++ dev_err(core->dev, "unsupported content, bit depth: %x, pic_struct = %x\n", ++ event.bit_depth, event.pic_struct); ++ iris_inst_change_state(inst, IRIS_INST_ERROR); ++ } ++} ++ ++static void iris_hfi_gen1_event_seq_changed(struct iris_inst *inst, ++ struct hfi_msg_event_notify_pkt *pkt) ++{ ++ struct hfi_session_flush_pkt flush_pkt; ++ u32 num_properties_changed; ++ int ret; ++ ++ ret = iris_inst_sub_state_change_drc(inst); ++ if (ret) ++ return; ++ ++ switch (pkt->event_data1) { ++ case HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUF_RESOURCES: ++ case HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUF_RESOURCES: ++ break; ++ default: ++ iris_inst_change_state(inst, IRIS_INST_ERROR); ++ return; ++ } ++ ++ num_properties_changed = pkt->event_data2; ++ if (!num_properties_changed) { ++ iris_inst_change_state(inst, IRIS_INST_ERROR); ++ return; ++ } ++ ++ iris_hfi_gen1_read_changed_params(inst, pkt); ++ ++ if (inst->state != IRIS_INST_ERROR) { ++ reinit_completion(&inst->flush_completion); ++ ++ flush_pkt.shdr.hdr.size = sizeof(struct hfi_session_flush_pkt); ++ flush_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_FLUSH; ++ flush_pkt.shdr.session_id = inst->session_id; ++ flush_pkt.flush_type = HFI_FLUSH_OUTPUT; ++ iris_hfi_queue_cmd_write(inst->core, &flush_pkt, flush_pkt.shdr.hdr.size); ++ } ++ ++ iris_vdec_src_change(inst); ++ iris_inst_sub_state_change_drc_last(inst); ++} + + static void + iris_hfi_gen1_sys_event_notify(struct iris_core *core, void *packet) +@@ -66,6 +271,9 @@ static void iris_hfi_gen1_session_event_notify(struct iris_inst *inst, void *pac + case HFI_EVENT_SESSION_ERROR: + iris_hfi_gen1_event_session_error(inst, pkt); + break; ++ case HFI_EVENT_SESSION_SEQUENCE_CHANGED: ++ iris_hfi_gen1_event_seq_changed(inst, pkt); ++ break; + default: + break; + } +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +index 8a9f2b5517ad..42cd57d5e3b1 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +@@ -19,8 +19,11 @@ + #define HFI_CMD_STOP 0x01000006 + #define HFI_CMD_BUFFER 0x01000009 + #define HFI_CMD_SUBSCRIBE_MODE 0x0100000B ++#define HFI_CMD_SETTINGS_CHANGE 0x0100000C + #define HFI_CMD_END 0x01FFFFFF + ++#define HFI_BITMASK_BITSTREAM_WIDTH 0xffff0000 ++#define HFI_BITMASK_BITSTREAM_HEIGHT 0x0000ffff + #define HFI_BITMASK_FRAME_MBS_ONLY_FLAG 0x00000001 + + #define HFI_PROP_BEGIN 0x03000000 +@@ -75,6 +78,7 @@ + #define HFI_INFO_UNSUPPORTED 0x06000001 + #define HFI_INFO_DATA_CORRUPT 0x06000002 + #define HFI_INFO_BUFFER_OVERFLOW 0x06000004 ++#define HFI_INFO_HFI_FLAG_PSC_LAST 0x06000007 + #define HFI_INFORMATION_END 0x06FFFFFF + + enum hfi_property_mode_type { +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c +index e8d8caeef021..c7552e041138 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c +@@ -8,6 +8,8 @@ + #include "iris_hfi_gen2.h" + #include "iris_hfi_gen2_defines.h" + #include "iris_hfi_gen2_packet.h" ++#include "iris_vdec.h" ++#include "iris_vpu_buffer.h" + #include "iris_vpu_common.h" + + struct iris_hfi_gen2_core_hfi_range { +@@ -199,6 +201,10 @@ static int iris_hfi_gen2_handle_session_info(struct iris_inst *inst, + info = "buffer overflow"; + inst_hfi_gen2->hfi_frame_info.overflow = 1; + break; ++ case HFI_INFO_HFI_FLAG_PSC_LAST: ++ info = "drc last flag"; ++ ret = iris_inst_sub_state_change_drc_last(inst); ++ break; + default: + info = "unknown"; + break; +@@ -329,6 +335,13 @@ static int iris_hfi_gen2_handle_output_buffer(struct iris_inst *inst, + struct v4l2_m2m_buffer *m2m_buffer, *n; + struct iris_buffer *buf; + bool found = false; ++ int ret; ++ ++ if (hfi_buffer->flags & HFI_BUF_FW_FLAG_PSC_LAST) { ++ ret = iris_inst_sub_state_change_drc_last(inst); ++ if (ret) ++ return ret; ++ } + + v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, m2m_buffer, n) { + buf = to_iris_buffer(&m2m_buffer->vb); +@@ -440,6 +453,115 @@ static int iris_hfi_gen2_handle_session_buffer(struct iris_inst *inst, + return iris_hfi_gen2_handle_release_internal_buffer(inst, buffer); + } + ++static void iris_hfi_gen2_read_input_subcr_params(struct iris_inst *inst) ++{ ++ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); ++ struct v4l2_pix_format_mplane *pixmp_ip = &inst->fmt_src->fmt.pix_mp; ++ struct v4l2_pix_format_mplane *pixmp_op = &inst->fmt_dst->fmt.pix_mp; ++ u32 primaries, matrix_coeff, transfer_char; ++ struct hfi_subscription_params subsc_params; ++ u32 colour_description_present_flag; ++ u32 video_signal_type_present_flag; ++ struct iris_core *core = inst->core; ++ u32 full_range, width, height; ++ struct vb2_queue *dst_q; ++ struct v4l2_ctrl *ctrl; ++ ++ subsc_params = inst_hfi_gen2->src_subcr_params; ++ width = (subsc_params.bitstream_resolution & ++ HFI_BITMASK_BITSTREAM_WIDTH) >> 16; ++ height = subsc_params.bitstream_resolution & ++ HFI_BITMASK_BITSTREAM_HEIGHT; ++ ++ pixmp_ip->width = width; ++ pixmp_ip->height = height; ++ ++ pixmp_op->width = ALIGN(width, 128); ++ pixmp_op->height = ALIGN(height, 32); ++ pixmp_op->plane_fmt[0].bytesperline = ALIGN(width, 128); ++ pixmp_op->plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_OUTPUT); ++ ++ matrix_coeff = subsc_params.color_info & 0xFF; ++ transfer_char = (subsc_params.color_info & 0xFF00) >> 8; ++ primaries = (subsc_params.color_info & 0xFF0000) >> 16; ++ colour_description_present_flag = ++ (subsc_params.color_info & 0x1000000) >> 24; ++ full_range = (subsc_params.color_info & 0x2000000) >> 25; ++ video_signal_type_present_flag = ++ (subsc_params.color_info & 0x20000000) >> 29; ++ ++ pixmp_op->colorspace = V4L2_COLORSPACE_DEFAULT; ++ pixmp_op->xfer_func = V4L2_XFER_FUNC_DEFAULT; ++ pixmp_op->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; ++ pixmp_op->quantization = V4L2_QUANTIZATION_DEFAULT; ++ ++ if (video_signal_type_present_flag) { ++ pixmp_op->quantization = ++ full_range ? ++ V4L2_QUANTIZATION_FULL_RANGE : ++ V4L2_QUANTIZATION_LIM_RANGE; ++ if (colour_description_present_flag) { ++ pixmp_op->colorspace = ++ iris_hfi_get_v4l2_color_primaries(primaries); ++ pixmp_op->xfer_func = ++ iris_hfi_get_v4l2_transfer_char(transfer_char); ++ pixmp_op->ycbcr_enc = ++ iris_hfi_get_v4l2_matrix_coefficients(matrix_coeff); ++ } ++ } ++ ++ pixmp_ip->colorspace = pixmp_op->colorspace; ++ pixmp_ip->xfer_func = pixmp_op->xfer_func; ++ pixmp_ip->ycbcr_enc = pixmp_op->ycbcr_enc; ++ pixmp_ip->quantization = pixmp_op->quantization; ++ ++ inst->crop.top = subsc_params.crop_offsets[0] & 0xFFFF; ++ inst->crop.left = (subsc_params.crop_offsets[0] >> 16) & 0xFFFF; ++ inst->crop.height = pixmp_ip->height - ++ (subsc_params.crop_offsets[1] & 0xFFFF) - inst->crop.top; ++ inst->crop.width = pixmp_ip->width - ++ ((subsc_params.crop_offsets[1] >> 16) & 0xFFFF) - inst->crop.left; ++ ++ inst->fw_caps[PROFILE].value = subsc_params.profile; ++ inst->fw_caps[LEVEL].value = subsc_params.level; ++ inst->fw_caps[POC].value = subsc_params.pic_order_cnt; ++ ++ if (subsc_params.bit_depth != BIT_DEPTH_8 || ++ !(subsc_params.coded_frames & HFI_BITMASK_FRAME_MBS_ONLY_FLAG)) { ++ dev_err(core->dev, "unsupported content, bit depth: %x, pic_struct = %x\n", ++ subsc_params.bit_depth, subsc_params.coded_frames); ++ iris_inst_change_state(inst, IRIS_INST_ERROR); ++ } ++ ++ inst->fw_min_count = subsc_params.fw_min_count; ++ inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT); ++ inst->buffers[BUF_OUTPUT].size = pixmp_op->plane_fmt[0].sizeimage; ++ ctrl = v4l2_ctrl_find(&inst->ctrl_handler, V4L2_CID_MIN_BUFFERS_FOR_CAPTURE); ++ if (ctrl) ++ v4l2_ctrl_s_ctrl(ctrl, inst->buffers[BUF_OUTPUT].min_count); ++ ++ dst_q = v4l2_m2m_get_dst_vq(inst->m2m_ctx); ++ dst_q->min_reqbufs_allocation = inst->buffers[BUF_OUTPUT].min_count; ++} ++ ++static int iris_hfi_gen2_handle_src_change(struct iris_inst *inst, ++ struct iris_hfi_packet *pkt) ++{ ++ int ret; ++ ++ if (pkt->port != HFI_PORT_BITSTREAM) ++ return 0; ++ ++ ret = iris_inst_sub_state_change_drc(inst); ++ if (ret) ++ return ret; ++ ++ iris_hfi_gen2_read_input_subcr_params(inst); ++ iris_vdec_src_change(inst); ++ ++ return 0; ++} ++ + static int iris_hfi_gen2_handle_session_command(struct iris_inst *inst, + struct iris_hfi_packet *pkt) + { +@@ -455,6 +577,9 @@ static int iris_hfi_gen2_handle_session_command(struct iris_inst *inst, + case HFI_CMD_BUFFER: + ret = iris_hfi_gen2_handle_session_buffer(inst, pkt); + break; ++ case HFI_CMD_SETTINGS_CHANGE: ++ ret = iris_hfi_gen2_handle_src_change(inst, pkt); ++ break; + default: + break; + } +@@ -588,16 +713,61 @@ static int iris_hfi_gen2_handle_system_response(struct iris_core *core, + return 0; + } + ++static void iris_hfi_gen2_init_src_change_param(struct iris_inst *inst) ++{ ++ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); ++ struct v4l2_pix_format_mplane *pixmp_ip = &inst->fmt_src->fmt.pix_mp; ++ struct v4l2_pix_format_mplane *pixmp_op = &inst->fmt_dst->fmt.pix_mp; ++ u32 bottom_offset = (pixmp_ip->height - inst->crop.height); ++ u32 right_offset = (pixmp_ip->width - inst->crop.width); ++ struct hfi_subscription_params *subsc_params; ++ u32 primaries, matrix_coeff, transfer_char; ++ u32 colour_description_present_flag = 0; ++ u32 video_signal_type_present_flag = 0; ++ u32 full_range, video_format = 0; ++ u32 left_offset = inst->crop.left; ++ u32 top_offset = inst->crop.top; ++ ++ subsc_params = &inst_hfi_gen2->src_subcr_params; ++ subsc_params->bitstream_resolution = ++ pixmp_ip->width << 16 | pixmp_ip->height; ++ subsc_params->crop_offsets[0] = ++ left_offset << 16 | top_offset; ++ subsc_params->crop_offsets[1] = ++ right_offset << 16 | bottom_offset; ++ subsc_params->fw_min_count = inst->buffers[BUF_OUTPUT].min_count; ++ ++ primaries = iris_hfi_gen2_get_color_primaries(pixmp_op->colorspace); ++ matrix_coeff = iris_hfi_gen2_get_matrix_coefficients(pixmp_op->ycbcr_enc); ++ transfer_char = iris_hfi_gen2_get_transfer_char(pixmp_op->xfer_func); ++ full_range = pixmp_op->quantization == V4L2_QUANTIZATION_FULL_RANGE ? 1 : 0; ++ subsc_params->color_info = ++ iris_hfi_gen2_get_color_info(matrix_coeff, transfer_char, primaries, ++ colour_description_present_flag, ++ full_range, video_format, ++ video_signal_type_present_flag); ++ ++ subsc_params->profile = inst->fw_caps[PROFILE].value; ++ subsc_params->level = inst->fw_caps[LEVEL].value; ++ subsc_params->pic_order_cnt = inst->fw_caps[POC].value; ++ subsc_params->bit_depth = inst->fw_caps[BIT_DEPTH].value; ++ if (inst->fw_caps[CODED_FRAMES].value == ++ CODED_FRAMES_PROGRESSIVE) ++ subsc_params->coded_frames = HFI_BITMASK_FRAME_MBS_ONLY_FLAG; ++ else ++ subsc_params->coded_frames = 0; ++} ++ + static int iris_hfi_gen2_handle_session_response(struct iris_core *core, + struct iris_hfi_header *hdr) + { ++ u8 *pkt = (u8 *)((u8 *)hdr + sizeof(*hdr)); + struct iris_inst_hfi_gen2 *inst_hfi_gen2; + struct iris_hfi_packet *packet; + struct iris_inst *inst; + bool dequeue = false; + int ret = 0; + u32 i, j; +- u8 *pkt; + static const struct iris_hfi_gen2_inst_hfi_range range[] = { + {HFI_SESSION_ERROR_BEGIN, HFI_SESSION_ERROR_END, + iris_hfi_gen2_handle_session_error}, +@@ -617,6 +787,17 @@ static int iris_hfi_gen2_handle_session_response(struct iris_core *core, + inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); + memset(&inst_hfi_gen2->hfi_frame_info, 0, sizeof(struct iris_hfi_frame_info)); + ++ for (i = 0; i < hdr->num_packets; i++) { ++ packet = (struct iris_hfi_packet *)pkt; ++ if (packet->type == HFI_CMD_SETTINGS_CHANGE) { ++ if (packet->port == HFI_PORT_BITSTREAM) { ++ iris_hfi_gen2_init_src_change_param(inst); ++ break; ++ } ++ } ++ pkt += packet->size; ++ } ++ + pkt = (u8 *)((u8 *)hdr + sizeof(*hdr)); + for (i = 0; i < ARRAY_SIZE(range); i++) { + pkt = (u8 *)((u8 *)hdr + sizeof(*hdr)); +diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/drivers/media/platform/qcom/iris/iris_instance.h +index 2886491ad59f..89fb63644311 100644 +--- a/drivers/media/platform/qcom/iris/iris_instance.h ++++ b/drivers/media/platform/qcom/iris/iris_instance.h +@@ -31,6 +31,7 @@ + * @buffers: array of different iris buffers + * @fw_min_count: minimnum count of buffers needed by fw + * @state: instance state ++ * @sub_state: instance sub state + * @once_per_session_set: boolean to set once per session property + * @m2m_dev: a reference to m2m device structure + * @m2m_ctx: a reference to m2m context structure +@@ -57,6 +58,7 @@ struct iris_inst { + struct iris_buffers buffers[BUF_TYPE_MAX]; + u32 fw_min_count; + enum iris_inst_state state; ++ enum iris_inst_sub_state sub_state; + bool once_per_session_set; + struct v4l2_m2m_dev *m2m_dev; + struct v4l2_m2m_ctx *m2m_ctx; +diff --git a/drivers/media/platform/qcom/iris/iris_state.c b/drivers/media/platform/qcom/iris/iris_state.c +index 44362e8fe18f..aad7e734d5c8 100644 +--- a/drivers/media/platform/qcom/iris/iris_state.c ++++ b/drivers/media/platform/qcom/iris/iris_state.c +@@ -102,3 +102,67 @@ int iris_inst_state_change_streamoff(struct iris_inst *inst, u32 plane) + + return iris_inst_change_state(inst, new_state); + } ++ ++int iris_inst_change_sub_state(struct iris_inst *inst, ++ enum iris_inst_sub_state clear_sub_state, ++ enum iris_inst_sub_state set_sub_state) ++{ ++ enum iris_inst_sub_state prev_sub_state; ++ ++ if (inst->state == IRIS_INST_ERROR) ++ return 0; ++ ++ if (!clear_sub_state && !set_sub_state) ++ return 0; ++ ++ if ((clear_sub_state & set_sub_state) || ++ set_sub_state > IRIS_INST_MAX_SUB_STATE_VALUE || ++ clear_sub_state > IRIS_INST_MAX_SUB_STATE_VALUE) ++ return -EINVAL; ++ ++ prev_sub_state = inst->sub_state; ++ ++ inst->sub_state |= set_sub_state; ++ inst->sub_state &= ~clear_sub_state; ++ ++ if (inst->sub_state != prev_sub_state) ++ dev_dbg(inst->core->dev, "sub_state changed from %x to %x\n", ++ prev_sub_state, inst->sub_state); ++ ++ return 0; ++} ++ ++int iris_inst_sub_state_change_drc(struct iris_inst *inst) ++{ ++ enum iris_inst_sub_state set_sub_state = 0; ++ ++ if (inst->sub_state & IRIS_INST_SUB_DRC) ++ return -EINVAL; ++ ++ if (inst->state == IRIS_INST_INPUT_STREAMING || ++ inst->state == IRIS_INST_INIT) ++ set_sub_state = IRIS_INST_SUB_FIRST_IPSC | IRIS_INST_SUB_INPUT_PAUSE; ++ else ++ set_sub_state = IRIS_INST_SUB_DRC | IRIS_INST_SUB_INPUT_PAUSE; ++ ++ return iris_inst_change_sub_state(inst, 0, set_sub_state); ++} ++ ++int iris_inst_sub_state_change_drc_last(struct iris_inst *inst) ++{ ++ enum iris_inst_sub_state set_sub_state; ++ ++ if (inst->sub_state & IRIS_INST_SUB_DRC_LAST) ++ return -EINVAL; ++ ++ if (!(inst->sub_state & IRIS_INST_SUB_DRC) || ++ !(inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE)) ++ return -EINVAL; ++ ++ if (inst->sub_state & IRIS_INST_SUB_FIRST_IPSC) ++ return 0; ++ ++ set_sub_state = IRIS_INST_SUB_DRC_LAST | IRIS_INST_SUB_OUTPUT_PAUSE; ++ ++ return iris_inst_change_sub_state(inst, 0, set_sub_state); ++} +diff --git a/drivers/media/platform/qcom/iris/iris_state.h b/drivers/media/platform/qcom/iris/iris_state.h +index 0bf9d0e063ac..b5f0826142f0 100644 +--- a/drivers/media/platform/qcom/iris/iris_state.h ++++ b/drivers/media/platform/qcom/iris/iris_state.h +@@ -91,9 +91,42 @@ enum iris_inst_state { + IRIS_INST_ERROR, + }; + ++#define IRIS_INST_SUB_STATES 8 ++#define IRIS_INST_MAX_SUB_STATE_VALUE ((1 << IRIS_INST_SUB_STATES) - 1) ++ ++/** ++ * enum iris_inst_sub_state ++ * ++ * @IRIS_INST_SUB_FIRST_IPSC: indicates source change is received from firmware ++ * when output port is not yet streaming. ++ * @IRIS_INST_SUB_DRC: indicates source change is received from firmware ++ * when output port is streaming and source change event is ++ * sent to client. ++ * @IRIS_INST_SUB_DRC_LAST: indicates last buffer is received from firmware ++ * as part of source change. ++ * @IRIS_INST_SUB_INPUT_PAUSE: source change is received form firmware. This ++ * indicates that firmware is paused to process ++ * any further input frames. ++ * @IRIS_INST_SUB_OUTPUT_PAUSE: last buffer is received form firmware as part ++ * of drc sequence. This indicates that ++ * firmware is paused to process any further output frames. ++ */ ++enum iris_inst_sub_state { ++ IRIS_INST_SUB_FIRST_IPSC = BIT(0), ++ IRIS_INST_SUB_DRC = BIT(1), ++ IRIS_INST_SUB_DRC_LAST = BIT(2), ++ IRIS_INST_SUB_INPUT_PAUSE = BIT(3), ++ IRIS_INST_SUB_OUTPUT_PAUSE = BIT(4), ++}; ++ + int iris_inst_change_state(struct iris_inst *inst, + enum iris_inst_state request_state); ++int iris_inst_change_sub_state(struct iris_inst *inst, ++ enum iris_inst_sub_state clear_sub_state, ++ enum iris_inst_sub_state set_sub_state); + int iris_inst_state_change_streamon(struct iris_inst *inst, u32 plane); + int iris_inst_state_change_streamoff(struct iris_inst *inst, u32 plane); ++int iris_inst_sub_state_change_drc(struct iris_inst *inst); ++int iris_inst_sub_state_change_drc_last(struct iris_inst *inst); + + #endif +diff --git a/drivers/media/platform/qcom/iris/iris_vb2.c b/drivers/media/platform/qcom/iris/iris_vb2.c +index 770e51f9ef91..3b94011533e8 100644 +--- a/drivers/media/platform/qcom/iris/iris_vb2.c ++++ b/drivers/media/platform/qcom/iris/iris_vb2.c +@@ -4,6 +4,7 @@ + */ + + #include ++#include + #include + + #include "iris_instance.h" +@@ -180,6 +181,7 @@ int iris_vb2_buf_out_validate(struct vb2_buffer *vb) + + void iris_vb2_buf_queue(struct vb2_buffer *vb2) + { ++ static const struct v4l2_event eos = { .type = V4L2_EVENT_EOS }; + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2); + struct v4l2_m2m_ctx *m2m_ctx; + struct iris_inst *inst; +@@ -203,6 +205,22 @@ void iris_vb2_buf_queue(struct vb2_buffer *vb2) + goto exit; + } + ++ if (V4L2_TYPE_IS_CAPTURE(vb2->vb2_queue->type)) { ++ if (inst->sub_state & IRIS_INST_SUB_DRC && ++ inst->sub_state & IRIS_INST_SUB_DRC_LAST) { ++ vbuf->flags |= V4L2_BUF_FLAG_LAST; ++ vbuf->sequence = inst->sequence_cap++; ++ vbuf->field = V4L2_FIELD_NONE; ++ vb2_set_plane_payload(vb2, 0, 0); ++ v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE); ++ if (!v4l2_m2m_has_stopped(m2m_ctx)) { ++ v4l2_event_queue_fh(&inst->fh, &eos); ++ v4l2_m2m_mark_stopped(m2m_ctx); ++ } ++ goto exit; ++ } ++ } ++ + v4l2_m2m_buf_queue(m2m_ctx, vbuf); + + ret = iris_vdec_qbuf(inst, vbuf); +diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c +index d6b092314b34..1da277ed6cb3 100644 +--- a/drivers/media/platform/qcom/iris/iris_vdec.c ++++ b/drivers/media/platform/qcom/iris/iris_vdec.c +@@ -223,6 +223,21 @@ int iris_vdec_subscribe_event(struct iris_inst *inst, const struct v4l2_event_su + return ret; + } + ++void iris_vdec_src_change(struct iris_inst *inst) ++{ ++ struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; ++ struct v4l2_event event = {0}; ++ struct vb2_queue *src_q; ++ ++ src_q = v4l2_m2m_get_src_vq(m2m_ctx); ++ if (!vb2_is_streaming(src_q)) ++ return; ++ ++ event.type = V4L2_EVENT_SOURCE_CHANGE; ++ event.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION; ++ v4l2_event_queue_fh(&inst->fh, &event); ++} ++ + static int iris_vdec_get_num_queued_buffers(struct iris_inst *inst, + enum iris_buffer_type type) + { +diff --git a/drivers/media/platform/qcom/iris/iris_vdec.h b/drivers/media/platform/qcom/iris/iris_vdec.h +index 998d4970a42b..dfcc2089a1ef 100644 +--- a/drivers/media/platform/qcom/iris/iris_vdec.h ++++ b/drivers/media/platform/qcom/iris/iris_vdec.h +@@ -14,6 +14,7 @@ int iris_vdec_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f); + int iris_vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f); + int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f); + int iris_vdec_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub); ++void iris_vdec_src_change(struct iris_inst *inst); + int iris_vdec_streamon_input(struct iris_inst *inst); + int iris_vdec_streamon_output(struct iris_inst *inst); + int iris_vdec_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf); +-- +2.34.1 + diff --git a/patch/kernel/archive/sm8550-6.12/0022_media--iris--handle-streamoff-on-from-client-in-dy.patch b/patch/kernel/archive/sm8550-6.12/0022_media--iris--handle-streamoff-on-from-client-in-dy.patch new file mode 100644 index 000000000..dfafc0769 --- /dev/null +++ b/patch/kernel/archive/sm8550-6.12/0022_media--iris--handle-streamoff-on-from-client-in-dy.patch @@ -0,0 +1,343 @@ +From a05ae391b45408d171783c2ba08665c7e9f0fd4b Mon Sep 17 00:00:00 2001 +From: Dikshita Agarwal +Date: Fri, 7 Feb 2025 13:25:02 +0530 +Subject: [PATCH] media: iris: handle streamoff/on from client in dynamic + resolution change + +The decoder is stopped after it completes the dynamic resolution change +sequence. Handle VIDIOC_STREAMOFF() and VIDIOC_STREAMON() on the CAPTURE +queue to resume the decoding process. + +Tested-by: Stefan Schmidt # x1e80100 (Dell XPS 13 9345) +Reviewed-by: Stefan Schmidt +Tested-by: Neil Armstrong # on SM8550-QRD +Tested-by: Neil Armstrong # on SM8550-HDK +Signed-off-by: Dikshita Agarwal +Link: https://lore.kernel.org/r/20250207-qcom-video-iris-v10-22-ab66eeffbd20@quicinc.com +Signed-off-by: Neil Armstrong +--- + .../media/platform/qcom/iris/iris_buffer.c | 58 ++++++++++++++++ + .../media/platform/qcom/iris/iris_buffer.h | 1 + + .../platform/qcom/iris/iris_hfi_common.h | 2 + + .../qcom/iris/iris_hfi_gen1_command.c | 10 +++ + .../qcom/iris/iris_hfi_gen1_defines.h | 1 + + .../qcom/iris/iris_hfi_gen2_command.c | 39 +++++++++++ + .../qcom/iris/iris_hfi_gen2_defines.h | 2 + + drivers/media/platform/qcom/iris/iris_vdec.c | 69 ++++++++++++++++++- + 8 files changed, 179 insertions(+), 3 deletions(-) + +diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c +index de1267c387f1..dc096e5e95bf 100644 +--- a/drivers/media/platform/qcom/iris/iris_buffer.c ++++ b/drivers/media/platform/qcom/iris/iris_buffer.c +@@ -404,6 +404,47 @@ int iris_destroy_internal_buffers(struct iris_inst *inst, u32 plane) + return 0; + } + ++static int iris_release_internal_buffers(struct iris_inst *inst, ++ enum iris_buffer_type buffer_type) ++{ ++ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; ++ struct iris_buffers *buffers = &inst->buffers[buffer_type]; ++ struct iris_buffer *buffer, *next; ++ int ret; ++ ++ list_for_each_entry_safe(buffer, next, &buffers->list, list) { ++ if (buffer->attr & BUF_ATTR_PENDING_RELEASE) ++ continue; ++ if (!(buffer->attr & BUF_ATTR_QUEUED)) ++ continue; ++ ret = hfi_ops->session_release_buf(inst, buffer); ++ if (ret) ++ return ret; ++ buffer->attr |= BUF_ATTR_PENDING_RELEASE; ++ } ++ ++ return 0; ++} ++ ++static int iris_release_input_internal_buffers(struct iris_inst *inst) ++{ ++ const struct iris_platform_data *platform_data = inst->core->iris_platform_data; ++ const u32 *internal_buf_type; ++ u32 internal_buffer_count, i; ++ int ret; ++ ++ internal_buf_type = platform_data->dec_ip_int_buf_tbl; ++ internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size; ++ ++ for (i = 0; i < internal_buffer_count; i++) { ++ ret = iris_release_internal_buffers(inst, internal_buf_type[i]); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ + int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst) + { + struct iris_buffers *buffers = &inst->buffers[BUF_PERSIST]; +@@ -435,6 +476,23 @@ int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst) + return 0; + } + ++int iris_alloc_and_queue_input_int_bufs(struct iris_inst *inst) ++{ ++ int ret; ++ ++ iris_get_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); ++ ++ ret = iris_release_input_internal_buffers(inst); ++ if (ret) ++ return ret; ++ ++ ret = iris_create_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); ++ if (ret) ++ return ret; ++ ++ return iris_queue_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); ++} ++ + int iris_queue_deferred_buffers(struct iris_inst *inst, enum iris_buffer_type buf_type) + { + struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; +diff --git a/drivers/media/platform/qcom/iris/iris_buffer.h b/drivers/media/platform/qcom/iris/iris_buffer.h +index 2c7432a59906..c36b6347b077 100644 +--- a/drivers/media/platform/qcom/iris/iris_buffer.h ++++ b/drivers/media/platform/qcom/iris/iris_buffer.h +@@ -108,6 +108,7 @@ int iris_queue_internal_buffers(struct iris_inst *inst, u32 plane); + int iris_destroy_internal_buffer(struct iris_inst *inst, struct iris_buffer *buffer); + int iris_destroy_internal_buffers(struct iris_inst *inst, u32 plane); + int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst); ++int iris_alloc_and_queue_input_int_bufs(struct iris_inst *inst); + int iris_queue_buffer(struct iris_inst *inst, struct iris_buffer *buf); + int iris_queue_deferred_buffers(struct iris_inst *inst, enum iris_buffer_type buf_type); + int iris_vb2_buffer_done(struct iris_inst *inst, struct iris_buffer *buf); +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.h b/drivers/media/platform/qcom/iris/iris_hfi_common.h +index 6241098dc31d..8e14a61c9be4 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_common.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_common.h +@@ -118,6 +118,8 @@ struct iris_hfi_command_ops { + int (*session_start)(struct iris_inst *inst, u32 plane); + int (*session_queue_buf)(struct iris_inst *inst, struct iris_buffer *buffer); + int (*session_release_buf)(struct iris_inst *inst, struct iris_buffer *buffer); ++ int (*session_pause)(struct iris_inst *inst, u32 plane); ++ int (*session_resume_drc)(struct iris_inst *inst, u32 plane); + int (*session_stop)(struct iris_inst *inst, u32 plane); + int (*session_close)(struct iris_inst *inst); + }; +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +index 03f7e6ea4bf3..e0cb75a112e3 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +@@ -205,6 +205,15 @@ static int iris_hfi_gen1_session_stop(struct iris_inst *inst, u32 plane) + return ret; + } + ++static int iris_hfi_gen1_session_continue(struct iris_inst *inst, u32 plane) ++{ ++ struct hfi_session_pkt packet; ++ ++ iris_hfi_gen1_packet_session_cmd(inst, &packet, HFI_CMD_SESSION_CONTINUE); ++ ++ return iris_hfi_queue_cmd_write(inst->core, &packet, packet.shdr.hdr.size); ++} ++ + static int iris_hfi_gen1_queue_input_buffer(struct iris_inst *inst, struct iris_buffer *buf) + { + struct hfi_session_empty_buffer_compressed_pkt ip_pkt; +@@ -778,6 +787,7 @@ static const struct iris_hfi_command_ops iris_hfi_gen1_command_ops = { + .session_start = iris_hfi_gen1_session_start, + .session_queue_buf = iris_hfi_gen1_session_queue_buffer, + .session_release_buf = iris_hfi_gen1_session_unset_buffers, ++ .session_resume_drc = iris_hfi_gen1_session_continue, + .session_stop = iris_hfi_gen1_session_stop, + .session_close = iris_hfi_gen1_session_close, + }; +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +index 416e9a19a26f..c40e0a28b21f 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +@@ -34,6 +34,7 @@ + #define HFI_CMD_SESSION_FLUSH 0x211008 + #define HFI_CMD_SESSION_RELEASE_BUFFERS 0x21100b + #define HFI_CMD_SESSION_RELEASE_RESOURCES 0x21100c ++#define HFI_CMD_SESSION_CONTINUE 0x21100d + + #define HFI_ERR_SESSION_UNSUPPORTED_SETTING 0x1008 + #define HFI_ERR_SESSION_UNSUPPORTED_STREAM 0x100d +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +index cc75231f07f1..8efc6a70a57a 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +@@ -737,6 +737,43 @@ static int iris_hfi_gen2_session_stop(struct iris_inst *inst, u32 plane) + return iris_wait_for_session_response(inst, false); + } + ++static int iris_hfi_gen2_session_pause(struct iris_inst *inst, u32 plane) ++{ ++ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); ++ ++ iris_hfi_gen2_packet_session_command(inst, ++ HFI_CMD_PAUSE, ++ (HFI_HOST_FLAGS_RESPONSE_REQUIRED | ++ HFI_HOST_FLAGS_INTR_REQUIRED), ++ iris_hfi_gen2_get_port(plane), ++ inst->session_id, ++ HFI_PAYLOAD_NONE, ++ NULL, ++ 0); ++ ++ return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet, ++ inst_hfi_gen2->packet->size); ++} ++ ++static int iris_hfi_gen2_session_resume_drc(struct iris_inst *inst, u32 plane) ++{ ++ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); ++ u32 payload = HFI_CMD_SETTINGS_CHANGE; ++ ++ iris_hfi_gen2_packet_session_command(inst, ++ HFI_CMD_RESUME, ++ (HFI_HOST_FLAGS_RESPONSE_REQUIRED | ++ HFI_HOST_FLAGS_INTR_REQUIRED), ++ iris_hfi_gen2_get_port(plane), ++ inst->session_id, ++ HFI_PAYLOAD_U32, ++ &payload, ++ sizeof(u32)); ++ ++ return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet, ++ inst_hfi_gen2->packet->size); ++} ++ + static u32 iris_hfi_gen2_buf_type_from_driver(enum iris_buffer_type buffer_type) + { + switch (buffer_type) { +@@ -860,6 +897,8 @@ static const struct iris_hfi_command_ops iris_hfi_gen2_command_ops = { + .session_start = iris_hfi_gen2_session_start, + .session_queue_buf = iris_hfi_gen2_session_queue_buffer, + .session_release_buf = iris_hfi_gen2_session_release_buffer, ++ .session_pause = iris_hfi_gen2_session_pause, ++ .session_resume_drc = iris_hfi_gen2_session_resume_drc, + .session_stop = iris_hfi_gen2_session_stop, + .session_close = iris_hfi_gen2_session_close, + }; +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +index 42cd57d5e3b1..620bcb90c35f 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +@@ -17,9 +17,11 @@ + #define HFI_CMD_CLOSE 0x01000004 + #define HFI_CMD_START 0x01000005 + #define HFI_CMD_STOP 0x01000006 ++#define HFI_CMD_RESUME 0x01000008 + #define HFI_CMD_BUFFER 0x01000009 + #define HFI_CMD_SUBSCRIBE_MODE 0x0100000B + #define HFI_CMD_SETTINGS_CHANGE 0x0100000C ++#define HFI_CMD_PAUSE 0x01000011 + #define HFI_CMD_END 0x01FFFFFF + + #define HFI_BITMASK_BITSTREAM_WIDTH 0xffff0000 +diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c +index 1da277ed6cb3..47a44978869b 100644 +--- a/drivers/media/platform/qcom/iris/iris_vdec.c ++++ b/drivers/media/platform/qcom/iris/iris_vdec.c +@@ -357,13 +357,37 @@ int iris_vdec_session_streamoff(struct iris_inst *inst, u32 plane) + static int iris_vdec_process_streamon_input(struct iris_inst *inst) + { + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; ++ enum iris_inst_sub_state set_sub_state = 0; + int ret; + + ret = hfi_ops->session_start(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (ret) + return ret; + +- return iris_inst_state_change_streamon(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); ++ if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { ++ ret = iris_inst_change_sub_state(inst, IRIS_INST_SUB_INPUT_PAUSE, 0); ++ if (ret) ++ return ret; ++ } ++ ++ if (inst->sub_state & IRIS_INST_SUB_DRC || ++ inst->sub_state & IRIS_INST_SUB_FIRST_IPSC) { ++ if (!(inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE)) { ++ if (hfi_ops->session_pause) { ++ ret = hfi_ops->session_pause(inst, ++ V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); ++ if (ret) ++ return ret; ++ } ++ set_sub_state = IRIS_INST_SUB_INPUT_PAUSE; ++ } ++ } ++ ++ ret = iris_inst_state_change_streamon(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); ++ if (ret) ++ return ret; ++ ++ return iris_inst_change_sub_state(inst, 0, set_sub_state); + } + + int iris_vdec_streamon_input(struct iris_inst *inst) +@@ -398,13 +422,52 @@ int iris_vdec_streamon_input(struct iris_inst *inst) + static int iris_vdec_process_streamon_output(struct iris_inst *inst) + { + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; +- int ret; ++ enum iris_inst_sub_state clear_sub_state = 0; ++ bool drc_active = false; ++ int ret = 0; ++ ++ drc_active = inst->sub_state & IRIS_INST_SUB_DRC && ++ inst->sub_state & IRIS_INST_SUB_DRC_LAST; ++ ++ if (drc_active) ++ clear_sub_state = IRIS_INST_SUB_DRC | IRIS_INST_SUB_DRC_LAST; ++ ++ if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { ++ ret = iris_alloc_and_queue_input_int_bufs(inst); ++ if (ret) ++ return ret; ++ ret = iris_set_stage(inst, STAGE); ++ if (ret) ++ return ret; ++ ret = iris_set_pipe(inst, PIPE); ++ if (ret) ++ return ret; ++ } ++ ++ if (inst->state == IRIS_INST_INPUT_STREAMING && ++ inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { ++ ret = hfi_ops->session_resume_drc(inst, ++ V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); ++ if (ret) ++ return ret; ++ clear_sub_state |= IRIS_INST_SUB_INPUT_PAUSE; ++ } ++ ++ if (inst->sub_state & IRIS_INST_SUB_FIRST_IPSC) ++ clear_sub_state |= IRIS_INST_SUB_FIRST_IPSC; + + ret = hfi_ops->session_start(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + if (ret) + return ret; + +- return iris_inst_state_change_streamon(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); ++ if (inst->sub_state & IRIS_INST_SUB_OUTPUT_PAUSE) ++ clear_sub_state |= IRIS_INST_SUB_OUTPUT_PAUSE; ++ ++ ret = iris_inst_state_change_streamon(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); ++ if (ret) ++ return ret; ++ ++ return iris_inst_change_sub_state(inst, clear_sub_state, 0); + } + + int iris_vdec_streamon_output(struct iris_inst *inst) +-- +2.34.1 + diff --git a/patch/kernel/archive/sm8550-6.12/0023_media--iris--add-support-for-drain-sequence.patch b/patch/kernel/archive/sm8550-6.12/0023_media--iris--add-support-for-drain-sequence.patch new file mode 100644 index 000000000..3d1843633 --- /dev/null +++ b/patch/kernel/archive/sm8550-6.12/0023_media--iris--add-support-for-drain-sequence.patch @@ -0,0 +1,654 @@ +From 3949c6727fb8e4418c73108453c3c512b962d6f4 Mon Sep 17 00:00:00 2001 +From: Dikshita Agarwal +Date: Fri, 7 Feb 2025 13:25:03 +0530 +Subject: [PATCH] media: iris: add support for drain sequence + +handle the V4L2_DEC_CMD_STOP by initiating a drain sequence on the +firmware. Process and decode all OUTPUT buffers, that are queued by the +client, before the VIDIOC_DECODER_CMD() was issued and mark the last +buffer with the V4L2_BUF_FLAG_LAST flag. The decoder is stopped, after +processing the last buffer. + +Resume the decoder when one of these operations are issued by the client: +- V4L2_DEC_CMD_START +- pair of VIDIOC_STREAMOFF() and VIDIOC_STREAMON() on the CAPTURE queue +- pair of VIDIOC_STREAMOFF() and VIDIOC_STREAMON() on the OUTPUT queue + +Add the handling to resume decoding when client issues +V4L2_DEC_CMD_START to resume decoding after a source change is detected. + +Tested-by: Stefan Schmidt # x1e80100 (Dell XPS 13 9345) +Reviewed-by: Stefan Schmidt +Tested-by: Neil Armstrong # on SM8550-QRD +Tested-by: Neil Armstrong # on SM8550-HDK +Signed-off-by: Dikshita Agarwal +Link: https://lore.kernel.org/r/20250207-qcom-video-iris-v10-23-ab66eeffbd20@quicinc.com +Signed-off-by: Neil Armstrong +--- + .../platform/qcom/iris/iris_hfi_common.h | 2 + + .../qcom/iris/iris_hfi_gen1_command.c | 13 +++ + .../qcom/iris/iris_hfi_gen1_defines.h | 1 + + .../qcom/iris/iris_hfi_gen1_response.c | 15 +++ + .../qcom/iris/iris_hfi_gen2_command.c | 43 +++++++++ + .../qcom/iris/iris_hfi_gen2_defines.h | 2 + + .../qcom/iris/iris_hfi_gen2_response.c | 46 +++++++++- + drivers/media/platform/qcom/iris/iris_state.c | 68 ++++++++++++++ + drivers/media/platform/qcom/iris/iris_state.h | 13 ++- + drivers/media/platform/qcom/iris/iris_vb2.c | 6 +- + drivers/media/platform/qcom/iris/iris_vdec.c | 91 ++++++++++++++++++- + drivers/media/platform/qcom/iris/iris_vdec.h | 2 + + drivers/media/platform/qcom/iris/iris_vidc.c | 35 +++++++ + 13 files changed, 329 insertions(+), 8 deletions(-) + +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.h b/drivers/media/platform/qcom/iris/iris_hfi_common.h +index 8e14a61c9be4..b2c541367fc6 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_common.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_common.h +@@ -121,6 +121,8 @@ struct iris_hfi_command_ops { + int (*session_pause)(struct iris_inst *inst, u32 plane); + int (*session_resume_drc)(struct iris_inst *inst, u32 plane); + int (*session_stop)(struct iris_inst *inst, u32 plane); ++ int (*session_drain)(struct iris_inst *inst, u32 plane); ++ int (*session_resume_drain)(struct iris_inst *inst, u32 plane); + int (*session_close)(struct iris_inst *inst); + }; + +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +index e0cb75a112e3..e1fbbb3c196d 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +@@ -368,6 +368,18 @@ static int iris_hfi_gen1_session_unset_buffers(struct iris_inst *inst, struct ir + return ret; + } + ++static int iris_hfi_gen1_session_drain(struct iris_inst *inst, u32 plane) ++{ ++ struct hfi_session_empty_buffer_compressed_pkt ip_pkt = {0}; ++ ++ ip_pkt.shdr.hdr.size = sizeof(struct hfi_session_empty_buffer_compressed_pkt); ++ ip_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_EMPTY_BUFFER; ++ ip_pkt.shdr.session_id = inst->session_id; ++ ip_pkt.flags = HFI_BUFFERFLAG_EOS; ++ ++ return iris_hfi_queue_cmd_write(inst->core, &ip_pkt, ip_pkt.shdr.hdr.size); ++} ++ + static int + iris_hfi_gen1_packet_session_set_property(struct hfi_session_set_property_pkt *packet, + struct iris_inst *inst, u32 ptype, void *pdata) +@@ -789,6 +801,7 @@ static const struct iris_hfi_command_ops iris_hfi_gen1_command_ops = { + .session_release_buf = iris_hfi_gen1_session_unset_buffers, + .session_resume_drc = iris_hfi_gen1_session_continue, + .session_stop = iris_hfi_gen1_session_stop, ++ .session_drain = iris_hfi_gen1_session_drain, + .session_close = iris_hfi_gen1_session_close, + }; + +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +index c40e0a28b21f..9f246816a286 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +@@ -49,6 +49,7 @@ + #define HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUF_RESOURCES 0x1000002 + #define HFI_EVENT_SESSION_SEQUENCE_CHANGED 0x1000003 + ++#define HFI_BUFFERFLAG_EOS 0x00000001 + #define HFI_BUFFERFLAG_TIMESTAMPINVALID 0x00000100 + + #define HFI_FLUSH_OUTPUT 0x1000002 +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c +index 3a47d9f39695..b72d503dd740 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c +@@ -386,6 +386,7 @@ static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet) + struct hfi_msg_session_fbd_uncompressed_plane0_pkt *pkt = packet; + struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; + struct v4l2_m2m_buffer *m2m_buffer, *n; ++ struct hfi_session_flush_pkt flush_pkt; + u32 timestamp_hi = pkt->time_stamp_hi; + u32 timestamp_lo = pkt->time_stamp_lo; + struct iris_core *core = inst->core; +@@ -394,11 +395,25 @@ static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet) + u32 output_tag = pkt->output_tag; + struct iris_buffer *buf, *iter; + struct iris_buffers *buffers; ++ u32 hfi_flags = pkt->flags; + u32 offset = pkt->offset; + u64 timestamp_us = 0; + bool found = false; + u32 flags = 0; + ++ if ((hfi_flags & HFI_BUFFERFLAG_EOS) && !filled_len) { ++ reinit_completion(&inst->flush_completion); ++ ++ flush_pkt.shdr.hdr.size = sizeof(struct hfi_session_flush_pkt); ++ flush_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_FLUSH; ++ flush_pkt.shdr.session_id = inst->session_id; ++ flush_pkt.flush_type = HFI_FLUSH_OUTPUT; ++ iris_hfi_queue_cmd_write(core, &flush_pkt, flush_pkt.shdr.hdr.size); ++ iris_inst_sub_state_change_drain_last(inst); ++ ++ return; ++ } ++ + if (iris_split_mode_enabled(inst) && pkt->stream_id == 0) { + buffers = &inst->buffers[BUF_DPB]; + if (!buffers) +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +index 8efc6a70a57a..a908b41e2868 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +@@ -774,6 +774,47 @@ static int iris_hfi_gen2_session_resume_drc(struct iris_inst *inst, u32 plane) + inst_hfi_gen2->packet->size); + } + ++static int iris_hfi_gen2_session_resume_drain(struct iris_inst *inst, u32 plane) ++{ ++ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); ++ u32 payload = HFI_CMD_DRAIN; ++ ++ iris_hfi_gen2_packet_session_command(inst, ++ HFI_CMD_RESUME, ++ (HFI_HOST_FLAGS_RESPONSE_REQUIRED | ++ HFI_HOST_FLAGS_INTR_REQUIRED), ++ iris_hfi_gen2_get_port(plane), ++ inst->session_id, ++ HFI_PAYLOAD_U32, ++ &payload, ++ sizeof(u32)); ++ ++ return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet, ++ inst_hfi_gen2->packet->size); ++} ++ ++static int iris_hfi_gen2_session_drain(struct iris_inst *inst, u32 plane) ++{ ++ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); ++ ++ if (!V4L2_TYPE_IS_OUTPUT(plane)) ++ return 0; ++ ++ iris_hfi_gen2_packet_session_command(inst, ++ HFI_CMD_DRAIN, ++ (HFI_HOST_FLAGS_RESPONSE_REQUIRED | ++ HFI_HOST_FLAGS_INTR_REQUIRED | ++ HFI_HOST_FLAGS_NON_DISCARDABLE), ++ iris_hfi_gen2_get_port(plane), ++ inst->session_id, ++ HFI_PAYLOAD_NONE, ++ NULL, ++ 0); ++ ++ return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet, ++ inst_hfi_gen2->packet->size); ++} ++ + static u32 iris_hfi_gen2_buf_type_from_driver(enum iris_buffer_type buffer_type) + { + switch (buffer_type) { +@@ -900,6 +941,8 @@ static const struct iris_hfi_command_ops iris_hfi_gen2_command_ops = { + .session_pause = iris_hfi_gen2_session_pause, + .session_resume_drc = iris_hfi_gen2_session_resume_drc, + .session_stop = iris_hfi_gen2_session_stop, ++ .session_drain = iris_hfi_gen2_session_drain, ++ .session_resume_drain = iris_hfi_gen2_session_resume_drain, + .session_close = iris_hfi_gen2_session_close, + }; + +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +index 620bcb90c35f..806f8bb7f505 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +@@ -17,6 +17,7 @@ + #define HFI_CMD_CLOSE 0x01000004 + #define HFI_CMD_START 0x01000005 + #define HFI_CMD_STOP 0x01000006 ++#define HFI_CMD_DRAIN 0x01000007 + #define HFI_CMD_RESUME 0x01000008 + #define HFI_CMD_BUFFER 0x01000009 + #define HFI_CMD_SUBSCRIBE_MODE 0x0100000B +@@ -80,6 +81,7 @@ + #define HFI_INFO_UNSUPPORTED 0x06000001 + #define HFI_INFO_DATA_CORRUPT 0x06000002 + #define HFI_INFO_BUFFER_OVERFLOW 0x06000004 ++#define HFI_INFO_HFI_FLAG_DRAIN_LAST 0x06000006 + #define HFI_INFO_HFI_FLAG_PSC_LAST 0x06000007 + #define HFI_INFORMATION_END 0x06FFFFFF + +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c +index c7552e041138..b75a01641d5d 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c +@@ -201,6 +201,10 @@ static int iris_hfi_gen2_handle_session_info(struct iris_inst *inst, + info = "buffer overflow"; + inst_hfi_gen2->hfi_frame_info.overflow = 1; + break; ++ case HFI_INFO_HFI_FLAG_DRAIN_LAST: ++ info = "drain last flag"; ++ ret = iris_inst_sub_state_change_drain_last(inst); ++ break; + case HFI_INFO_HFI_FLAG_PSC_LAST: + info = "drc last flag"; + ret = iris_inst_sub_state_change_drc_last(inst); +@@ -337,6 +341,12 @@ static int iris_hfi_gen2_handle_output_buffer(struct iris_inst *inst, + bool found = false; + int ret; + ++ if (hfi_buffer->flags & HFI_BUF_FW_FLAG_LAST) { ++ ret = iris_inst_sub_state_change_drain_last(inst); ++ if (ret) ++ return ret; ++ } ++ + if (hfi_buffer->flags & HFI_BUF_FW_FLAG_PSC_LAST) { + ret = iris_inst_sub_state_change_drc_last(inst); + if (ret) +@@ -425,6 +435,21 @@ static int iris_hfi_gen2_handle_release_internal_buffer(struct iris_inst *inst, + return ret; + } + ++static int iris_hfi_gen2_handle_session_stop(struct iris_inst *inst, ++ struct iris_hfi_packet *pkt) ++{ ++ int ret = 0; ++ ++ if (pkt->port == HFI_PORT_RAW) ++ ret = iris_inst_sub_state_change_pause(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); ++ else if (pkt->port == HFI_PORT_BITSTREAM) ++ ret = iris_inst_sub_state_change_pause(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); ++ ++ complete(&inst->completion); ++ ++ return ret; ++} ++ + static int iris_hfi_gen2_handle_session_buffer(struct iris_inst *inst, + struct iris_hfi_packet *pkt) + { +@@ -453,6 +478,22 @@ static int iris_hfi_gen2_handle_session_buffer(struct iris_inst *inst, + return iris_hfi_gen2_handle_release_internal_buffer(inst, buffer); + } + ++static int iris_hfi_gen2_handle_session_drain(struct iris_inst *inst, ++ struct iris_hfi_packet *pkt) ++{ ++ int ret = 0; ++ ++ if (!(pkt->flags & HFI_FW_FLAGS_SUCCESS)) { ++ iris_inst_change_state(inst, IRIS_INST_ERROR); ++ return 0; ++ } ++ ++ if (inst->sub_state & IRIS_INST_SUB_DRAIN) ++ ret = iris_inst_change_sub_state(inst, 0, IRIS_INST_SUB_INPUT_PAUSE); ++ ++ return ret; ++} ++ + static void iris_hfi_gen2_read_input_subcr_params(struct iris_inst *inst) + { + struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); +@@ -572,7 +613,7 @@ static int iris_hfi_gen2_handle_session_command(struct iris_inst *inst, + iris_hfi_gen2_handle_session_close(inst, pkt); + break; + case HFI_CMD_STOP: +- complete(&inst->completion); ++ iris_hfi_gen2_handle_session_stop(inst, pkt); + break; + case HFI_CMD_BUFFER: + ret = iris_hfi_gen2_handle_session_buffer(inst, pkt); +@@ -580,6 +621,9 @@ static int iris_hfi_gen2_handle_session_command(struct iris_inst *inst, + case HFI_CMD_SETTINGS_CHANGE: + ret = iris_hfi_gen2_handle_src_change(inst, pkt); + break; ++ case HFI_CMD_DRAIN: ++ ret = iris_hfi_gen2_handle_session_drain(inst, pkt); ++ break; + default: + break; + } +diff --git a/drivers/media/platform/qcom/iris/iris_state.c b/drivers/media/platform/qcom/iris/iris_state.c +index aad7e734d5c8..f12306e735ec 100644 +--- a/drivers/media/platform/qcom/iris/iris_state.c ++++ b/drivers/media/platform/qcom/iris/iris_state.c +@@ -3,6 +3,8 @@ + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + ++#include ++ + #include "iris_instance.h" + + static bool iris_allow_inst_state_change(struct iris_inst *inst, +@@ -148,6 +150,21 @@ int iris_inst_sub_state_change_drc(struct iris_inst *inst) + return iris_inst_change_sub_state(inst, 0, set_sub_state); + } + ++int iris_inst_sub_state_change_drain_last(struct iris_inst *inst) ++{ ++ enum iris_inst_sub_state set_sub_state; ++ ++ if (inst->sub_state & IRIS_INST_SUB_DRAIN_LAST) ++ return -EINVAL; ++ ++ if (!(inst->sub_state & IRIS_INST_SUB_DRAIN)) ++ return -EINVAL; ++ ++ set_sub_state = IRIS_INST_SUB_DRAIN_LAST | IRIS_INST_SUB_OUTPUT_PAUSE; ++ ++ return iris_inst_change_sub_state(inst, 0, set_sub_state); ++} ++ + int iris_inst_sub_state_change_drc_last(struct iris_inst *inst) + { + enum iris_inst_sub_state set_sub_state; +@@ -166,3 +183,54 @@ int iris_inst_sub_state_change_drc_last(struct iris_inst *inst) + + return iris_inst_change_sub_state(inst, 0, set_sub_state); + } ++ ++int iris_inst_sub_state_change_pause(struct iris_inst *inst, u32 plane) ++{ ++ enum iris_inst_sub_state set_sub_state; ++ ++ if (V4L2_TYPE_IS_OUTPUT(plane)) { ++ if (inst->sub_state & IRIS_INST_SUB_DRC && ++ !(inst->sub_state & IRIS_INST_SUB_DRC_LAST)) ++ return -EINVAL; ++ ++ if (inst->sub_state & IRIS_INST_SUB_DRAIN && ++ !(inst->sub_state & IRIS_INST_SUB_DRAIN_LAST)) ++ return -EINVAL; ++ ++ set_sub_state = IRIS_INST_SUB_INPUT_PAUSE; ++ } else { ++ set_sub_state = IRIS_INST_SUB_OUTPUT_PAUSE; ++ } ++ ++ return iris_inst_change_sub_state(inst, 0, set_sub_state); ++} ++ ++static inline bool iris_drc_pending(struct iris_inst *inst) ++{ ++ return inst->sub_state & IRIS_INST_SUB_DRC && ++ inst->sub_state & IRIS_INST_SUB_DRC_LAST; ++} ++ ++static inline bool iris_drain_pending(struct iris_inst *inst) ++{ ++ return inst->sub_state & IRIS_INST_SUB_DRAIN && ++ inst->sub_state & IRIS_INST_SUB_DRAIN_LAST; ++} ++ ++bool iris_allow_cmd(struct iris_inst *inst, u32 cmd) ++{ ++ struct vb2_queue *src_q = v4l2_m2m_get_src_vq(inst->m2m_ctx); ++ struct vb2_queue *dst_q = v4l2_m2m_get_dst_vq(inst->m2m_ctx); ++ ++ if (cmd == V4L2_DEC_CMD_START) { ++ if (vb2_is_streaming(src_q) || vb2_is_streaming(dst_q)) ++ if (iris_drc_pending(inst) || iris_drain_pending(inst)) ++ return true; ++ } else if (cmd == V4L2_DEC_CMD_STOP) { ++ if (vb2_is_streaming(src_q)) ++ if (inst->sub_state != IRIS_INST_SUB_DRAIN) ++ return true; ++ } ++ ++ return false; ++} +diff --git a/drivers/media/platform/qcom/iris/iris_state.h b/drivers/media/platform/qcom/iris/iris_state.h +index b5f0826142f0..a5c0cad4a78c 100644 +--- a/drivers/media/platform/qcom/iris/iris_state.h ++++ b/drivers/media/platform/qcom/iris/iris_state.h +@@ -104,6 +104,9 @@ enum iris_inst_state { + * sent to client. + * @IRIS_INST_SUB_DRC_LAST: indicates last buffer is received from firmware + * as part of source change. ++ * @IRIS_INST_SUB_DRAIN: indicates drain is in progress. ++ * @IRIS_INST_SUB_DRAIN_LAST: indicates last buffer is received from firmware ++ * as part of drain sequence. + * @IRIS_INST_SUB_INPUT_PAUSE: source change is received form firmware. This + * indicates that firmware is paused to process + * any further input frames. +@@ -115,8 +118,10 @@ enum iris_inst_sub_state { + IRIS_INST_SUB_FIRST_IPSC = BIT(0), + IRIS_INST_SUB_DRC = BIT(1), + IRIS_INST_SUB_DRC_LAST = BIT(2), +- IRIS_INST_SUB_INPUT_PAUSE = BIT(3), +- IRIS_INST_SUB_OUTPUT_PAUSE = BIT(4), ++ IRIS_INST_SUB_DRAIN = BIT(3), ++ IRIS_INST_SUB_DRAIN_LAST = BIT(4), ++ IRIS_INST_SUB_INPUT_PAUSE = BIT(5), ++ IRIS_INST_SUB_OUTPUT_PAUSE = BIT(6), + }; + + int iris_inst_change_state(struct iris_inst *inst, +@@ -124,9 +129,13 @@ int iris_inst_change_state(struct iris_inst *inst, + int iris_inst_change_sub_state(struct iris_inst *inst, + enum iris_inst_sub_state clear_sub_state, + enum iris_inst_sub_state set_sub_state); ++ + int iris_inst_state_change_streamon(struct iris_inst *inst, u32 plane); + int iris_inst_state_change_streamoff(struct iris_inst *inst, u32 plane); + int iris_inst_sub_state_change_drc(struct iris_inst *inst); ++int iris_inst_sub_state_change_drain_last(struct iris_inst *inst); + int iris_inst_sub_state_change_drc_last(struct iris_inst *inst); ++int iris_inst_sub_state_change_pause(struct iris_inst *inst, u32 plane); ++bool iris_allow_cmd(struct iris_inst *inst, u32 cmd); + + #endif +diff --git a/drivers/media/platform/qcom/iris/iris_vb2.c b/drivers/media/platform/qcom/iris/iris_vb2.c +index 3b94011533e8..59fc133c9f98 100644 +--- a/drivers/media/platform/qcom/iris/iris_vb2.c ++++ b/drivers/media/platform/qcom/iris/iris_vb2.c +@@ -206,8 +206,10 @@ void iris_vb2_buf_queue(struct vb2_buffer *vb2) + } + + if (V4L2_TYPE_IS_CAPTURE(vb2->vb2_queue->type)) { +- if (inst->sub_state & IRIS_INST_SUB_DRC && +- inst->sub_state & IRIS_INST_SUB_DRC_LAST) { ++ if ((inst->sub_state & IRIS_INST_SUB_DRC && ++ inst->sub_state & IRIS_INST_SUB_DRC_LAST) || ++ (inst->sub_state & IRIS_INST_SUB_DRAIN && ++ inst->sub_state & IRIS_INST_SUB_DRAIN_LAST)) { + vbuf->flags |= V4L2_BUF_FLAG_LAST; + vbuf->sequence = inst->sequence_cap++; + vbuf->field = V4L2_FIELD_NONE; +diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c +index 47a44978869b..076e3ee7969f 100644 +--- a/drivers/media/platform/qcom/iris/iris_vdec.c ++++ b/drivers/media/platform/qcom/iris/iris_vdec.c +@@ -371,6 +371,7 @@ static int iris_vdec_process_streamon_input(struct iris_inst *inst) + } + + if (inst->sub_state & IRIS_INST_SUB_DRC || ++ inst->sub_state & IRIS_INST_SUB_DRAIN || + inst->sub_state & IRIS_INST_SUB_FIRST_IPSC) { + if (!(inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE)) { + if (hfi_ops->session_pause) { +@@ -422,15 +423,20 @@ int iris_vdec_streamon_input(struct iris_inst *inst) + static int iris_vdec_process_streamon_output(struct iris_inst *inst) + { + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; ++ bool drain_active = false, drc_active = false; + enum iris_inst_sub_state clear_sub_state = 0; +- bool drc_active = false; + int ret = 0; + ++ drain_active = inst->sub_state & IRIS_INST_SUB_DRAIN && ++ inst->sub_state & IRIS_INST_SUB_DRAIN_LAST; ++ + drc_active = inst->sub_state & IRIS_INST_SUB_DRC && + inst->sub_state & IRIS_INST_SUB_DRC_LAST; + + if (drc_active) + clear_sub_state = IRIS_INST_SUB_DRC | IRIS_INST_SUB_DRC_LAST; ++ else if (drain_active) ++ clear_sub_state = IRIS_INST_SUB_DRAIN | IRIS_INST_SUB_DRAIN_LAST; + + if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { + ret = iris_alloc_and_queue_input_int_bufs(inst); +@@ -446,8 +452,12 @@ static int iris_vdec_process_streamon_output(struct iris_inst *inst) + + if (inst->state == IRIS_INST_INPUT_STREAMING && + inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { +- ret = hfi_ops->session_resume_drc(inst, +- V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); ++ if (!drain_active) ++ ret = hfi_ops->session_resume_drc(inst, ++ V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); ++ else if (hfi_ops->session_resume_drain) ++ ret = hfi_ops->session_resume_drain(inst, ++ V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (ret) + return ret; + clear_sub_state |= IRIS_INST_SUB_INPUT_PAUSE; +@@ -565,3 +575,78 @@ int iris_vdec_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf) + + return iris_queue_buffer(inst, buf); + } ++ ++int iris_vdec_start_cmd(struct iris_inst *inst) ++{ ++ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; ++ enum iris_inst_sub_state clear_sub_state = 0; ++ struct vb2_queue *dst_vq; ++ int ret; ++ ++ dst_vq = v4l2_m2m_get_dst_vq(inst->m2m_ctx); ++ ++ if (inst->sub_state & IRIS_INST_SUB_DRC && ++ inst->sub_state & IRIS_INST_SUB_DRC_LAST) { ++ vb2_clear_last_buffer_dequeued(dst_vq); ++ clear_sub_state = IRIS_INST_SUB_DRC | IRIS_INST_SUB_DRC_LAST; ++ ++ if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { ++ ret = hfi_ops->session_resume_drc(inst, ++ V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); ++ if (ret) ++ return ret; ++ clear_sub_state |= IRIS_INST_SUB_INPUT_PAUSE; ++ } ++ if (inst->sub_state & IRIS_INST_SUB_OUTPUT_PAUSE) { ++ ret = hfi_ops->session_resume_drc(inst, ++ V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); ++ if (ret) ++ return ret; ++ clear_sub_state |= IRIS_INST_SUB_OUTPUT_PAUSE; ++ } ++ } else if (inst->sub_state & IRIS_INST_SUB_DRAIN && ++ inst->sub_state & IRIS_INST_SUB_DRAIN_LAST) { ++ vb2_clear_last_buffer_dequeued(dst_vq); ++ clear_sub_state = IRIS_INST_SUB_DRAIN | IRIS_INST_SUB_DRAIN_LAST; ++ if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { ++ if (hfi_ops->session_resume_drain) { ++ ret = ++ hfi_ops->session_resume_drain(inst, ++ V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); ++ if (ret) ++ return ret; ++ } ++ ++ clear_sub_state |= IRIS_INST_SUB_INPUT_PAUSE; ++ } ++ if (inst->sub_state & IRIS_INST_SUB_OUTPUT_PAUSE) { ++ if (hfi_ops->session_resume_drain) { ++ ret = ++ hfi_ops->session_resume_drain(inst, ++ V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); ++ if (ret) ++ return ret; ++ } ++ ++ clear_sub_state |= IRIS_INST_SUB_OUTPUT_PAUSE; ++ } ++ } else { ++ dev_err(inst->core->dev, "start called before receiving last_flag\n"); ++ iris_inst_change_state(inst, IRIS_INST_ERROR); ++ return -EBUSY; ++ } ++ ++ return iris_inst_change_sub_state(inst, clear_sub_state, 0); ++} ++ ++int iris_vdec_stop_cmd(struct iris_inst *inst) ++{ ++ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; ++ int ret; ++ ++ ret = hfi_ops->session_drain(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); ++ if (ret) ++ return ret; ++ ++ return iris_inst_change_sub_state(inst, 0, IRIS_INST_SUB_DRAIN); ++} +diff --git a/drivers/media/platform/qcom/iris/iris_vdec.h b/drivers/media/platform/qcom/iris/iris_vdec.h +index dfcc2089a1ef..b24932dc511a 100644 +--- a/drivers/media/platform/qcom/iris/iris_vdec.h ++++ b/drivers/media/platform/qcom/iris/iris_vdec.h +@@ -18,6 +18,8 @@ void iris_vdec_src_change(struct iris_inst *inst); + int iris_vdec_streamon_input(struct iris_inst *inst); + int iris_vdec_streamon_output(struct iris_inst *inst); + int iris_vdec_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf); ++int iris_vdec_start_cmd(struct iris_inst *inst); ++int iris_vdec_stop_cmd(struct iris_inst *inst); + int iris_vdec_session_streamoff(struct iris_inst *inst, u32 plane); + + #endif +diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c +index 2b27df6b1aad..ca0f4e310f77 100644 +--- a/drivers/media/platform/qcom/iris/iris_vidc.c ++++ b/drivers/media/platform/qcom/iris/iris_vidc.c +@@ -365,6 +365,39 @@ static int iris_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subs + return iris_vdec_subscribe_event(inst, sub); + } + ++static int iris_dec_cmd(struct file *filp, void *fh, ++ struct v4l2_decoder_cmd *dec) ++{ ++ struct iris_inst *inst = iris_get_inst(filp, NULL); ++ int ret = 0; ++ ++ mutex_lock(&inst->lock); ++ ++ ret = v4l2_m2m_ioctl_decoder_cmd(filp, fh, dec); ++ if (ret) ++ goto unlock; ++ ++ if (inst->state == IRIS_INST_DEINIT) ++ goto unlock; ++ ++ if (!iris_allow_cmd(inst, dec->cmd)) { ++ ret = -EBUSY; ++ goto unlock; ++ } ++ ++ if (dec->cmd == V4L2_DEC_CMD_START) ++ ret = iris_vdec_start_cmd(inst); ++ else if (dec->cmd == V4L2_DEC_CMD_STOP) ++ ret = iris_vdec_stop_cmd(inst); ++ else ++ ret = -EINVAL; ++ ++unlock: ++ mutex_unlock(&inst->lock); ++ ++ return ret; ++} ++ + static struct v4l2_file_operations iris_v4l2_file_ops = { + .owner = THIS_MODULE, + .open = iris_open, +@@ -408,6 +441,8 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops = { + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, + .vidioc_streamon = v4l2_m2m_ioctl_streamon, + .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, ++ .vidioc_try_decoder_cmd = v4l2_m2m_ioctl_try_decoder_cmd, ++ .vidioc_decoder_cmd = iris_dec_cmd, + }; + + void iris_init_ops(struct iris_core *core) +-- +2.34.1 + diff --git a/patch/kernel/archive/sm8550-6.12/0024_media--iris--add-check-whether-the-video-session-i.patch b/patch/kernel/archive/sm8550-6.12/0024_media--iris--add-check-whether-the-video-session-i.patch new file mode 100644 index 000000000..5530b1fcf --- /dev/null +++ b/patch/kernel/archive/sm8550-6.12/0024_media--iris--add-check-whether-the-video-session-i.patch @@ -0,0 +1,171 @@ +From b4921470cfb37b2d084bae53792149b47887a448 Mon Sep 17 00:00:00 2001 +From: Vedang Nagar +Date: Fri, 7 Feb 2025 13:25:04 +0530 +Subject: [PATCH] media: iris: add check whether the video session is supported + or not + +Based on the hardware capabilities, add a check during start_streaming +and queue_setup, whether the video session is supported by the hardware. + +Signed-off-by: Vedang Nagar +Tested-by: Stefan Schmidt # x1e80100 (Dell XPS 13 9345) +Reviewed-by: Stefan Schmidt +Tested-by: Neil Armstrong # on SM8550-QRD +Tested-by: Neil Armstrong # on SM8550-HDK +Signed-off-by: Dikshita Agarwal +Link: https://lore.kernel.org/r/20250207-qcom-video-iris-v10-24-ab66eeffbd20@quicinc.com +Signed-off-by: Neil Armstrong +--- + .../platform/qcom/iris/iris_platform_common.h | 1 + + .../platform/qcom/iris/iris_platform_sm8550.c | 1 + + drivers/media/platform/qcom/iris/iris_vb2.c | 96 +++++++++++++++++++ + 3 files changed, 98 insertions(+) + +diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h +index de0388a100c3..a5a7d6838d16 100644 +--- a/drivers/media/platform/qcom/iris/iris_platform_common.h ++++ b/drivers/media/platform/qcom/iris/iris_platform_common.h +@@ -144,6 +144,7 @@ struct iris_platform_data { + struct ubwc_config_data *ubwc_config; + u32 num_vpp_pipe; + u32 max_session_count; ++ u32 max_core_mbpf; + const u32 *input_config_params; + unsigned int input_config_params_size; + const u32 *output_config_params; +diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +index dc51df71c377..8d23978f5cee 100644 +--- a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c ++++ b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +@@ -233,6 +233,7 @@ struct iris_platform_data sm8550_data = { + .ubwc_config = &ubwc_config_sm8550, + .num_vpp_pipe = 4, + .max_session_count = 16, ++ .max_core_mbpf = ((8192 * 4352) / 256) * 2, + .input_config_params = + sm8550_vdec_input_config_params, + .input_config_params_size = +diff --git a/drivers/media/platform/qcom/iris/iris_vb2.c b/drivers/media/platform/qcom/iris/iris_vb2.c +index 59fc133c9f98..712d37723ec3 100644 +--- a/drivers/media/platform/qcom/iris/iris_vb2.c ++++ b/drivers/media/platform/qcom/iris/iris_vb2.c +@@ -11,6 +11,94 @@ + #include "iris_vb2.h" + #include "iris_vdec.h" + ++static int iris_check_core_mbpf(struct iris_inst *inst) ++{ ++ struct iris_core *core = inst->core; ++ struct iris_inst *instance; ++ u32 total_mbpf = 0; ++ ++ mutex_lock(&core->lock); ++ list_for_each_entry(instance, &core->instances, list) ++ total_mbpf += iris_get_mbpf(instance); ++ mutex_unlock(&core->lock); ++ ++ if (total_mbpf > core->iris_platform_data->max_core_mbpf) ++ return -ENOMEM; ++ ++ return 0; ++} ++ ++static int iris_check_inst_mbpf(struct iris_inst *inst) ++{ ++ struct platform_inst_caps *caps; ++ u32 mbpf, max_mbpf; ++ ++ caps = inst->core->iris_platform_data->inst_caps; ++ max_mbpf = caps->max_mbpf; ++ mbpf = iris_get_mbpf(inst); ++ if (mbpf > max_mbpf) ++ return -ENOMEM; ++ ++ return 0; ++} ++ ++static int iris_check_resolution_supported(struct iris_inst *inst) ++{ ++ u32 width, height, min_width, min_height, max_width, max_height; ++ struct platform_inst_caps *caps; ++ ++ caps = inst->core->iris_platform_data->inst_caps; ++ width = inst->fmt_src->fmt.pix_mp.width; ++ height = inst->fmt_src->fmt.pix_mp.height; ++ ++ min_width = caps->min_frame_width; ++ max_width = caps->max_frame_width; ++ min_height = caps->min_frame_height; ++ max_height = caps->max_frame_height; ++ ++ if (!(min_width <= width && width <= max_width) || ++ !(min_height <= height && height <= max_height)) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static int iris_check_session_supported(struct iris_inst *inst) ++{ ++ struct iris_core *core = inst->core; ++ struct iris_inst *instance = NULL; ++ bool found = false; ++ int ret; ++ ++ list_for_each_entry(instance, &core->instances, list) { ++ if (instance == inst) ++ found = true; ++ } ++ ++ if (!found) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ ret = iris_check_core_mbpf(inst); ++ if (ret) ++ goto exit; ++ ++ ret = iris_check_inst_mbpf(inst); ++ if (ret) ++ goto exit; ++ ++ ret = iris_check_resolution_supported(inst); ++ if (ret) ++ goto exit; ++ ++ return 0; ++exit: ++ dev_err(inst->core->dev, "current session not supported(%d)\n", ret); ++ ++ return ret; ++} ++ + int iris_vb2_buf_init(struct vb2_buffer *vb2) + { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2); +@@ -48,6 +136,10 @@ int iris_vb2_queue_setup(struct vb2_queue *q, + goto unlock; + } + ++ ret = iris_check_session_supported(inst); ++ if (ret) ++ goto unlock; ++ + if (!inst->once_per_session_set) { + inst->once_per_session_set = true; + +@@ -95,6 +187,10 @@ int iris_vb2_start_streaming(struct vb2_queue *q, unsigned int count) + goto error; + } + ++ ret = iris_check_session_supported(inst); ++ if (ret) ++ goto error; ++ + if (V4L2_TYPE_IS_OUTPUT(q->type)) + ret = iris_vdec_streamon_input(inst); + else if (V4L2_TYPE_IS_CAPTURE(q->type)) +-- +2.34.1 + diff --git a/patch/kernel/archive/sm8550-6.12/0025_media--iris--implement-power-scaling-for-vpu2-and-.patch b/patch/kernel/archive/sm8550-6.12/0025_media--iris--implement-power-scaling-for-vpu2-and-.patch new file mode 100644 index 000000000..3c24ba8bf --- /dev/null +++ b/patch/kernel/archive/sm8550-6.12/0025_media--iris--implement-power-scaling-for-vpu2-and-.patch @@ -0,0 +1,515 @@ +From e7574ebc04231fafe43d1cec2f4d363b8d8587ea Mon Sep 17 00:00:00 2001 +From: Vedang Nagar +Date: Fri, 7 Feb 2025 13:25:05 +0530 +Subject: [PATCH] media: iris: implement power scaling for vpu2 and vpu3 + +Implement power scaling including a specific vpu2 and vpu3 calculation +for clock and bus bandwidth, which depends on the hardware +configuration, codec format, resolution and frame rate. + +Signed-off-by: Vedang Nagar +Tested-by: Stefan Schmidt # x1e80100 (Dell XPS 13 9345) +Reviewed-by: Stefan Schmidt +Tested-by: Neil Armstrong # on SM8550-QRD +Tested-by: Neil Armstrong # on SM8550-HDK +Signed-off-by: Dikshita Agarwal +Link: https://lore.kernel.org/r/20250207-qcom-video-iris-v10-25-ab66eeffbd20@quicinc.com +Signed-off-by: Neil Armstrong +--- + drivers/media/platform/qcom/iris/Makefile | 1 + + .../media/platform/qcom/iris/iris_buffer.c | 3 + + .../media/platform/qcom/iris/iris_instance.h | 6 + + .../platform/qcom/iris/iris_platform_common.h | 23 +++ + .../platform/qcom/iris/iris_platform_sm8550.c | 12 ++ + drivers/media/platform/qcom/iris/iris_power.c | 140 ++++++++++++++++++ + drivers/media/platform/qcom/iris/iris_power.h | 13 ++ + drivers/media/platform/qcom/iris/iris_vb2.c | 3 + + drivers/media/platform/qcom/iris/iris_vdec.c | 7 + + drivers/media/platform/qcom/iris/iris_vpu2.c | 27 ++++ + drivers/media/platform/qcom/iris/iris_vpu3.c | 38 +++++ + .../platform/qcom/iris/iris_vpu_common.h | 1 + + 12 files changed, 274 insertions(+) + create mode 100644 drivers/media/platform/qcom/iris/iris_power.c + create mode 100644 drivers/media/platform/qcom/iris/iris_power.h + +diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile +index ab16189aa9e6..ca31db847273 100644 +--- a/drivers/media/platform/qcom/iris/Makefile ++++ b/drivers/media/platform/qcom/iris/Makefile +@@ -10,6 +10,7 @@ iris-objs += iris_buffer.o \ + iris_hfi_gen2_response.o \ + iris_hfi_queue.o \ + iris_platform_sm8550.o \ ++ iris_power.o \ + iris_probe.o \ + iris_resources.o \ + iris_state.o \ +diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c +index dc096e5e95bf..e5c5a564fcb8 100644 +--- a/drivers/media/platform/qcom/iris/iris_buffer.c ++++ b/drivers/media/platform/qcom/iris/iris_buffer.c +@@ -8,6 +8,7 @@ + + #include "iris_buffer.h" + #include "iris_instance.h" ++#include "iris_power.h" + #include "iris_vpu_buffer.h" + + #define PIXELS_4K 4096 +@@ -500,6 +501,8 @@ int iris_queue_deferred_buffers(struct iris_inst *inst, enum iris_buffer_type bu + struct iris_buffer *buf; + int ret; + ++ iris_scale_power(inst); ++ + if (buf_type == BUF_INPUT) { + v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buffer, n) { + buf = to_iris_buffer(&buffer->vb); +diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/drivers/media/platform/qcom/iris/iris_instance.h +index 89fb63644311..caa3c6507006 100644 +--- a/drivers/media/platform/qcom/iris/iris_instance.h ++++ b/drivers/media/platform/qcom/iris/iris_instance.h +@@ -33,6 +33,9 @@ + * @state: instance state + * @sub_state: instance sub state + * @once_per_session_set: boolean to set once per session property ++ * @max_input_data_size: max size of input data ++ * @power: structure of power info ++ * @icc_data: structure of interconnect data + * @m2m_dev: a reference to m2m device structure + * @m2m_ctx: a reference to m2m context structure + * @sequence_cap: a sequence counter for capture queue +@@ -60,6 +63,9 @@ struct iris_inst { + enum iris_inst_state state; + enum iris_inst_sub_state sub_state; + bool once_per_session_set; ++ size_t max_input_data_size; ++ struct iris_inst_power power; ++ struct icc_vote_data icc_data; + struct v4l2_m2m_dev *m2m_dev; + struct v4l2_m2m_ctx *m2m_ctx; + u32 sequence_cap; +diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h +index a5a7d6838d16..189dd081ad0a 100644 +--- a/drivers/media/platform/qcom/iris/iris_platform_common.h ++++ b/drivers/media/platform/qcom/iris/iris_platform_common.h +@@ -20,6 +20,8 @@ struct iris_inst; + #define CODED_FRAMES_PROGRESSIVE 0x0 + #define DEFAULT_MAX_HOST_BUF_COUNT 64 + #define DEFAULT_MAX_HOST_BURST_BUF_COUNT 256 ++#define DEFAULT_FPS 30 ++ + enum stage_type { + STAGE_1 = 1, + STAGE_2 = 2, +@@ -67,6 +69,10 @@ struct platform_inst_caps { + u32 min_frame_height; + u32 max_frame_height; + u32 max_mbpf; ++ u32 mb_cycles_vsp; ++ u32 mb_cycles_vpp; ++ u32 mb_cycles_fw; ++ u32 mb_cycles_fw_vpp; + u32 num_comv; + }; + +@@ -106,11 +112,26 @@ struct platform_inst_fw_cap { + enum platform_inst_fw_cap_type cap_id); + }; + ++struct bw_info { ++ u32 mbs_per_sec; ++ u32 bw_ddr; ++}; ++ + struct iris_core_power { + u64 clk_freq; + u64 icc_bw; + }; + ++struct iris_inst_power { ++ u64 min_freq; ++ u32 icc_bw; ++}; ++ ++struct icc_vote_data { ++ u32 height, width; ++ u32 fps; ++}; ++ + enum platform_pm_domain_type { + IRIS_CTRL_POWER_DOMAIN, + IRIS_HW_POWER_DOMAIN, +@@ -124,6 +145,8 @@ struct iris_platform_data { + void (*set_preset_registers)(struct iris_core *core); + const struct icc_info *icc_tbl; + unsigned int icc_tbl_size; ++ const struct bw_info *bw_tbl_dec; ++ unsigned int bw_tbl_dec_size; + const char * const *pmdomain_tbl; + unsigned int pmdomain_tbl_size; + const char * const *opp_pd_tbl; +diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +index 8d23978f5cee..35d278996c43 100644 +--- a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c ++++ b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +@@ -126,6 +126,9 @@ static struct platform_inst_caps platform_inst_cap_sm8550 = { + .min_frame_height = 96, + .max_frame_height = 8192, + .max_mbpf = (8192 * 4352) / 256, ++ .mb_cycles_vpp = 200, ++ .mb_cycles_fw = 489583, ++ .mb_cycles_fw_vpp = 66234, + .num_comv = 0, + }; + +@@ -141,6 +144,13 @@ static const struct icc_info sm8550_icc_table[] = { + + static const char * const sm8550_clk_reset_table[] = { "bus" }; + ++static const struct bw_info sm8550_bw_table_dec[] = { ++ { ((4096 * 2160) / 256) * 60, 1608000 }, ++ { ((4096 * 2160) / 256) * 30, 826000 }, ++ { ((1920 * 1080) / 256) * 60, 567000 }, ++ { ((1920 * 1080) / 256) * 30, 294000 }, ++}; ++ + static const char * const sm8550_pmdomain_table[] = { "venus", "vcodec0" }; + + static const char * const sm8550_opp_pd_table[] = { "mxc", "mmcx" }; +@@ -214,6 +224,8 @@ struct iris_platform_data sm8550_data = { + .icc_tbl_size = ARRAY_SIZE(sm8550_icc_table), + .clk_rst_tbl = sm8550_clk_reset_table, + .clk_rst_tbl_size = ARRAY_SIZE(sm8550_clk_reset_table), ++ .bw_tbl_dec = sm8550_bw_table_dec, ++ .bw_tbl_dec_size = ARRAY_SIZE(sm8550_bw_table_dec), + .pmdomain_tbl = sm8550_pmdomain_table, + .pmdomain_tbl_size = ARRAY_SIZE(sm8550_pmdomain_table), + .opp_pd_tbl = sm8550_opp_pd_table, +diff --git a/drivers/media/platform/qcom/iris/iris_power.c b/drivers/media/platform/qcom/iris/iris_power.c +new file mode 100644 +index 000000000000..dbca42df0910 +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_power.c +@@ -0,0 +1,140 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include ++#include ++#include ++ ++#include "iris_buffer.h" ++#include "iris_instance.h" ++#include "iris_power.h" ++#include "iris_resources.h" ++#include "iris_vpu_common.h" ++ ++static u32 iris_calc_bw(struct iris_inst *inst, struct icc_vote_data *data) ++{ ++ const struct bw_info *bw_tbl = NULL; ++ struct iris_core *core = inst->core; ++ u32 num_rows, i, mbs, mbps; ++ u32 icc_bw = 0; ++ ++ mbs = DIV_ROUND_UP(data->height, 16) * DIV_ROUND_UP(data->width, 16); ++ mbps = mbs * data->fps; ++ if (mbps == 0) ++ goto exit; ++ ++ bw_tbl = core->iris_platform_data->bw_tbl_dec; ++ num_rows = core->iris_platform_data->bw_tbl_dec_size; ++ ++ for (i = 0; i < num_rows; i++) { ++ if (i != 0 && mbps > bw_tbl[i].mbs_per_sec) ++ break; ++ ++ icc_bw = bw_tbl[i].bw_ddr; ++ } ++ ++exit: ++ return icc_bw; ++} ++ ++static int iris_set_interconnects(struct iris_inst *inst) ++{ ++ struct iris_core *core = inst->core; ++ struct iris_inst *instance; ++ u64 total_bw_ddr = 0; ++ int ret; ++ ++ mutex_lock(&core->lock); ++ list_for_each_entry(instance, &core->instances, list) { ++ if (!instance->max_input_data_size) ++ continue; ++ ++ total_bw_ddr += instance->power.icc_bw; ++ } ++ ++ ret = iris_set_icc_bw(core, total_bw_ddr); ++ ++ mutex_unlock(&core->lock); ++ ++ return ret; ++} ++ ++static int iris_vote_interconnects(struct iris_inst *inst) ++{ ++ struct icc_vote_data *vote_data = &inst->icc_data; ++ struct v4l2_format *inp_f = inst->fmt_src; ++ ++ vote_data->width = inp_f->fmt.pix_mp.width; ++ vote_data->height = inp_f->fmt.pix_mp.height; ++ vote_data->fps = DEFAULT_FPS; ++ ++ inst->power.icc_bw = iris_calc_bw(inst, vote_data); ++ ++ return iris_set_interconnects(inst); ++} ++ ++static int iris_set_clocks(struct iris_inst *inst) ++{ ++ struct iris_core *core = inst->core; ++ struct iris_inst *instance; ++ u64 freq = 0; ++ int ret; ++ ++ mutex_lock(&core->lock); ++ list_for_each_entry(instance, &core->instances, list) { ++ if (!instance->max_input_data_size) ++ continue; ++ ++ freq += instance->power.min_freq; ++ } ++ ++ core->power.clk_freq = freq; ++ ret = dev_pm_opp_set_rate(core->dev, freq); ++ mutex_unlock(&core->lock); ++ ++ return ret; ++} ++ ++static int iris_scale_clocks(struct iris_inst *inst) ++{ ++ const struct vpu_ops *vpu_ops = inst->core->iris_platform_data->vpu_ops; ++ struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; ++ struct v4l2_m2m_buffer *buffer, *n; ++ struct iris_buffer *buf; ++ size_t data_size = 0; ++ ++ v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buffer, n) { ++ buf = to_iris_buffer(&buffer->vb); ++ data_size = max(data_size, buf->data_size); ++ } ++ ++ inst->max_input_data_size = data_size; ++ if (!inst->max_input_data_size) ++ return 0; ++ ++ inst->power.min_freq = vpu_ops->calc_freq(inst, inst->max_input_data_size); ++ ++ return iris_set_clocks(inst); ++} ++ ++int iris_scale_power(struct iris_inst *inst) ++{ ++ struct iris_core *core = inst->core; ++ int ret; ++ ++ if (pm_runtime_suspended(core->dev)) { ++ ret = pm_runtime_resume_and_get(core->dev); ++ if (ret < 0) ++ return ret; ++ ++ pm_runtime_put_autosuspend(core->dev); ++ } ++ ++ ret = iris_scale_clocks(inst); ++ if (ret) ++ return ret; ++ ++ return iris_vote_interconnects(inst); ++} +diff --git a/drivers/media/platform/qcom/iris/iris_power.h b/drivers/media/platform/qcom/iris/iris_power.h +new file mode 100644 +index 000000000000..55212660e72d +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_power.h +@@ -0,0 +1,13 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef __IRIS_POWER_H__ ++#define __IRIS_POWER_H__ ++ ++struct iris_inst; ++ ++int iris_scale_power(struct iris_inst *inst); ++ ++#endif +diff --git a/drivers/media/platform/qcom/iris/iris_vb2.c b/drivers/media/platform/qcom/iris/iris_vb2.c +index 712d37723ec3..cdf11feb590b 100644 +--- a/drivers/media/platform/qcom/iris/iris_vb2.c ++++ b/drivers/media/platform/qcom/iris/iris_vb2.c +@@ -10,6 +10,7 @@ + #include "iris_instance.h" + #include "iris_vb2.h" + #include "iris_vdec.h" ++#include "iris_power.h" + + static int iris_check_core_mbpf(struct iris_inst *inst) + { +@@ -187,6 +188,8 @@ int iris_vb2_start_streaming(struct vb2_queue *q, unsigned int count) + goto error; + } + ++ iris_scale_power(inst); ++ + ret = iris_check_session_supported(inst); + if (ret) + goto error; +diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c +index 076e3ee7969f..4143acedfc57 100644 +--- a/drivers/media/platform/qcom/iris/iris_vdec.c ++++ b/drivers/media/platform/qcom/iris/iris_vdec.c +@@ -9,6 +9,7 @@ + #include "iris_buffer.h" + #include "iris_ctrls.h" + #include "iris_instance.h" ++#include "iris_power.h" + #include "iris_vdec.h" + #include "iris_vpu_buffer.h" + +@@ -360,6 +361,8 @@ static int iris_vdec_process_streamon_input(struct iris_inst *inst) + enum iris_inst_sub_state set_sub_state = 0; + int ret; + ++ iris_scale_power(inst); ++ + ret = hfi_ops->session_start(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (ret) + return ret; +@@ -427,6 +430,8 @@ static int iris_vdec_process_streamon_output(struct iris_inst *inst) + enum iris_inst_sub_state clear_sub_state = 0; + int ret = 0; + ++ iris_scale_power(inst); ++ + drain_active = inst->sub_state & IRIS_INST_SUB_DRAIN && + inst->sub_state & IRIS_INST_SUB_DRAIN_LAST; + +@@ -573,6 +578,8 @@ int iris_vdec_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf) + return 0; + } + ++ iris_scale_power(inst); ++ + return iris_queue_buffer(inst, buf); + } + +diff --git a/drivers/media/platform/qcom/iris/iris_vpu2.c b/drivers/media/platform/qcom/iris/iris_vpu2.c +index bd8427411576..8f502aed43ce 100644 +--- a/drivers/media/platform/qcom/iris/iris_vpu2.c ++++ b/drivers/media/platform/qcom/iris/iris_vpu2.c +@@ -6,6 +6,33 @@ + #include "iris_instance.h" + #include "iris_vpu_common.h" + ++static u64 iris_vpu2_calc_freq(struct iris_inst *inst, size_t data_size) ++{ ++ struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps; ++ struct v4l2_format *inp_f = inst->fmt_src; ++ u32 mbs_per_second, mbpf, height, width; ++ unsigned long vpp_freq, vsp_freq; ++ u32 fps = DEFAULT_FPS; ++ ++ width = max(inp_f->fmt.pix_mp.width, inst->crop.width); ++ height = max(inp_f->fmt.pix_mp.height, inst->crop.height); ++ ++ mbpf = NUM_MBS_PER_FRAME(height, width); ++ mbs_per_second = mbpf * fps; ++ ++ vpp_freq = mbs_per_second * caps->mb_cycles_vpp; ++ ++ /* 21 / 20 is overhead factor */ ++ vpp_freq += vpp_freq / 20; ++ vsp_freq = mbs_per_second * caps->mb_cycles_vsp; ++ ++ /* 10 / 7 is overhead factor */ ++ vsp_freq += ((fps * data_size * 8) * 10) / 7; ++ ++ return max(vpp_freq, vsp_freq); ++} ++ + const struct vpu_ops iris_vpu2_ops = { + .power_off_hw = iris_vpu_power_off_hw, ++ .calc_freq = iris_vpu2_calc_freq, + }; +diff --git a/drivers/media/platform/qcom/iris/iris_vpu3.c b/drivers/media/platform/qcom/iris/iris_vpu3.c +index 10599f1fa789..b484638e6105 100644 +--- a/drivers/media/platform/qcom/iris/iris_vpu3.c ++++ b/drivers/media/platform/qcom/iris/iris_vpu3.c +@@ -79,6 +79,44 @@ static void iris_vpu3_power_off_hardware(struct iris_core *core) + iris_vpu_power_off_hw(core); + } + ++static u64 iris_vpu3_calculate_frequency(struct iris_inst *inst, size_t data_size) ++{ ++ struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps; ++ struct v4l2_format *inp_f = inst->fmt_src; ++ u32 height, width, mbs_per_second, mbpf; ++ u64 fw_cycles, fw_vpp_cycles; ++ u64 vsp_cycles, vpp_cycles; ++ u32 fps = DEFAULT_FPS; ++ ++ width = max(inp_f->fmt.pix_mp.width, inst->crop.width); ++ height = max(inp_f->fmt.pix_mp.height, inst->crop.height); ++ ++ mbpf = NUM_MBS_PER_FRAME(height, width); ++ mbs_per_second = mbpf * fps; ++ ++ fw_cycles = fps * caps->mb_cycles_fw; ++ fw_vpp_cycles = fps * caps->mb_cycles_fw_vpp; ++ ++ vpp_cycles = mult_frac(mbs_per_second, caps->mb_cycles_vpp, (u32)inst->fw_caps[PIPE].value); ++ /* 21 / 20 is minimum overhead factor */ ++ vpp_cycles += max(div_u64(vpp_cycles, 20), fw_vpp_cycles); ++ ++ /* 1.059 is multi-pipe overhead */ ++ if (inst->fw_caps[PIPE].value > 1) ++ vpp_cycles += div_u64(vpp_cycles * 59, 1000); ++ ++ vsp_cycles = fps * data_size * 8; ++ vsp_cycles = div_u64(vsp_cycles, 2); ++ /* VSP FW overhead 1.05 */ ++ vsp_cycles = div_u64(vsp_cycles * 21, 20); ++ ++ if (inst->fw_caps[STAGE].value == STAGE_1) ++ vsp_cycles = vsp_cycles * 3; ++ ++ return max3(vpp_cycles, vsp_cycles, fw_cycles); ++} ++ + const struct vpu_ops iris_vpu3_ops = { + .power_off_hw = iris_vpu3_power_off_hardware, ++ .calc_freq = iris_vpu3_calculate_frequency, + }; +diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.h b/drivers/media/platform/qcom/iris/iris_vpu_common.h +index d3efa7c0ce9a..63fa1fa5a498 100644 +--- a/drivers/media/platform/qcom/iris/iris_vpu_common.h ++++ b/drivers/media/platform/qcom/iris/iris_vpu_common.h +@@ -13,6 +13,7 @@ extern const struct vpu_ops iris_vpu3_ops; + + struct vpu_ops { + void (*power_off_hw)(struct iris_core *core); ++ u64 (*calc_freq)(struct iris_inst *inst, size_t data_size); + }; + + int iris_vpu_boot_firmware(struct iris_core *core); +-- +2.34.1 + diff --git a/patch/kernel/archive/sm8550-6.12/0026_media--iris--add-check-to-allow-sub-states-transit.patch b/patch/kernel/archive/sm8550-6.12/0026_media--iris--add-check-to-allow-sub-states-transit.patch new file mode 100644 index 000000000..b5d3d86cd --- /dev/null +++ b/patch/kernel/archive/sm8550-6.12/0026_media--iris--add-check-to-allow-sub-states-transit.patch @@ -0,0 +1,141 @@ +From 0d739925590b4a67db4468920a6288b707b87f7e Mon Sep 17 00:00:00 2001 +From: Vedang Nagar +Date: Fri, 7 Feb 2025 13:25:06 +0530 +Subject: [PATCH] media: iris: add check to allow sub states transitions + +Based on the design of the state machine, add checks whether the +transition from one sub-state to another is allowed. + +Signed-off-by: Vedang Nagar +Tested-by: Stefan Schmidt # x1e80100 (Dell XPS 13 9345) +Reviewed-by: Stefan Schmidt +Tested-by: Neil Armstrong # on SM8550-QRD +Tested-by: Neil Armstrong # on SM8550-HDK +Signed-off-by: Dikshita Agarwal +Link: https://lore.kernel.org/r/20250207-qcom-video-iris-v10-26-ab66eeffbd20@quicinc.com +Signed-off-by: Neil Armstrong +--- + .../qcom/iris/iris_hfi_gen1_command.c | 12 +++++- + drivers/media/platform/qcom/iris/iris_state.c | 40 +++++++++++++++++++ + drivers/media/platform/qcom/iris/iris_state.h | 3 ++ + 3 files changed, 54 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +index e1fbbb3c196d..64f887d9a17d 100644 +--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c ++++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +@@ -135,6 +135,9 @@ static int iris_hfi_gen1_session_start(struct iris_inst *inst, u32 plane) + if (!V4L2_TYPE_IS_OUTPUT(plane)) + return 0; + ++ if (inst->sub_state & IRIS_INST_SUB_LOAD_RESOURCES) ++ return 0; ++ + reinit_completion(&inst->completion); + iris_hfi_gen1_packet_session_cmd(inst, &packet, HFI_CMD_SESSION_LOAD_RESOURCES); + +@@ -153,7 +156,11 @@ static int iris_hfi_gen1_session_start(struct iris_inst *inst, u32 plane) + if (ret) + return ret; + +- return iris_wait_for_session_response(inst, false); ++ ret = iris_wait_for_session_response(inst, false); ++ if (ret) ++ return ret; ++ ++ return iris_inst_change_sub_state(inst, 0, IRIS_INST_SUB_LOAD_RESOURCES); + } + + static int iris_hfi_gen1_session_stop(struct iris_inst *inst, u32 plane) +@@ -180,6 +187,9 @@ static int iris_hfi_gen1_session_stop(struct iris_inst *inst, u32 plane) + ret = iris_hfi_queue_cmd_write(core, &pkt, pkt.shdr.hdr.size); + if (!ret) + ret = iris_wait_for_session_response(inst, false); ++ ++ iris_inst_change_sub_state(inst, IRIS_INST_SUB_LOAD_RESOURCES, 0); ++ + iris_helper_buffers_done(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + VB2_BUF_STATE_ERROR); + iris_helper_buffers_done(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, +diff --git a/drivers/media/platform/qcom/iris/iris_state.c b/drivers/media/platform/qcom/iris/iris_state.c +index f12306e735ec..5976e926c83d 100644 +--- a/drivers/media/platform/qcom/iris/iris_state.c ++++ b/drivers/media/platform/qcom/iris/iris_state.c +@@ -105,6 +105,43 @@ int iris_inst_state_change_streamoff(struct iris_inst *inst, u32 plane) + return iris_inst_change_state(inst, new_state); + } + ++static bool iris_inst_allow_sub_state(struct iris_inst *inst, enum iris_inst_sub_state sub_state) ++{ ++ if (!sub_state) ++ return true; ++ ++ switch (inst->state) { ++ case IRIS_INST_INIT: ++ if (sub_state & IRIS_INST_SUB_LOAD_RESOURCES) ++ return true; ++ return false; ++ case IRIS_INST_INPUT_STREAMING: ++ if (sub_state & (IRIS_INST_SUB_FIRST_IPSC | IRIS_INST_SUB_DRC | ++ IRIS_INST_SUB_DRAIN | IRIS_INST_SUB_INPUT_PAUSE)) ++ return true; ++ return false; ++ case IRIS_INST_OUTPUT_STREAMING: ++ if (sub_state & (IRIS_INST_SUB_DRC_LAST | ++ IRIS_INST_SUB_DRAIN_LAST | IRIS_INST_SUB_OUTPUT_PAUSE)) ++ return true; ++ return false; ++ case IRIS_INST_STREAMING: ++ if (sub_state & (IRIS_INST_SUB_DRC | IRIS_INST_SUB_DRAIN | ++ IRIS_INST_SUB_DRC_LAST | IRIS_INST_SUB_DRAIN_LAST | ++ IRIS_INST_SUB_INPUT_PAUSE | IRIS_INST_SUB_OUTPUT_PAUSE)) ++ return true; ++ return false; ++ case IRIS_INST_DEINIT: ++ if (sub_state & (IRIS_INST_SUB_DRC | IRIS_INST_SUB_DRAIN | ++ IRIS_INST_SUB_DRC_LAST | IRIS_INST_SUB_DRAIN_LAST | ++ IRIS_INST_SUB_INPUT_PAUSE | IRIS_INST_SUB_OUTPUT_PAUSE)) ++ return true; ++ return false; ++ default: ++ return false; ++ } ++} ++ + int iris_inst_change_sub_state(struct iris_inst *inst, + enum iris_inst_sub_state clear_sub_state, + enum iris_inst_sub_state set_sub_state) +@@ -124,6 +161,9 @@ int iris_inst_change_sub_state(struct iris_inst *inst, + + prev_sub_state = inst->sub_state; + ++ if (!iris_inst_allow_sub_state(inst, set_sub_state)) ++ return -EINVAL; ++ + inst->sub_state |= set_sub_state; + inst->sub_state &= ~clear_sub_state; + +diff --git a/drivers/media/platform/qcom/iris/iris_state.h b/drivers/media/platform/qcom/iris/iris_state.h +index a5c0cad4a78c..78c61aac5e7e 100644 +--- a/drivers/media/platform/qcom/iris/iris_state.h ++++ b/drivers/media/platform/qcom/iris/iris_state.h +@@ -113,6 +113,8 @@ enum iris_inst_state { + * @IRIS_INST_SUB_OUTPUT_PAUSE: last buffer is received form firmware as part + * of drc sequence. This indicates that + * firmware is paused to process any further output frames. ++ * @IRIS_INST_SUB_LOAD_RESOURCES: indicates all the resources have been loaded by the ++ * firmware and it is ready for processing. + */ + enum iris_inst_sub_state { + IRIS_INST_SUB_FIRST_IPSC = BIT(0), +@@ -122,6 +124,7 @@ enum iris_inst_sub_state { + IRIS_INST_SUB_DRAIN_LAST = BIT(4), + IRIS_INST_SUB_INPUT_PAUSE = BIT(5), + IRIS_INST_SUB_OUTPUT_PAUSE = BIT(6), ++ IRIS_INST_SUB_LOAD_RESOURCES = BIT(7), + }; + + int iris_inst_change_state(struct iris_inst *inst, +-- +2.34.1 + diff --git a/patch/kernel/archive/sm8550-6.12/0027_media--iris--enable-video-driver-probe-of-SM8250-S.patch b/patch/kernel/archive/sm8550-6.12/0027_media--iris--enable-video-driver-probe-of-SM8250-S.patch new file mode 100644 index 000000000..be89ab0cf --- /dev/null +++ b/patch/kernel/archive/sm8550-6.12/0027_media--iris--enable-video-driver-probe-of-SM8250-S.patch @@ -0,0 +1,223 @@ +From 22bd43173801987066a8379a0d0f7c5b02dfc1b1 Mon Sep 17 00:00:00 2001 +From: Dikshita Agarwal +Date: Fri, 7 Feb 2025 13:25:07 +0530 +Subject: [PATCH] media: iris: enable video driver probe of SM8250 SoC + +Initialize the platform data and enable video driver probe of SM8250 +SoC. + +Tested-by: Stefan Schmidt # x1e80100 (Dell XPS 13 9345) +Reviewed-by: Stefan Schmidt +Tested-by: Neil Armstrong # on SM8550-QRD +Tested-by: Neil Armstrong # on SM8550-HDK +Signed-off-by: Dikshita Agarwal +Link: https://lore.kernel.org/r/20250207-qcom-video-iris-v10-27-ab66eeffbd20@quicinc.com +Signed-off-by: Neil Armstrong +--- + drivers/media/platform/qcom/iris/Makefile | 4 + + .../platform/qcom/iris/iris_platform_common.h | 1 + + .../platform/qcom/iris/iris_platform_sm8250.c | 149 ++++++++++++++++++ + drivers/media/platform/qcom/iris/iris_probe.c | 6 + + 4 files changed, 160 insertions(+) + create mode 100644 drivers/media/platform/qcom/iris/iris_platform_sm8250.c + +diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile +index ca31db847273..f6d22b88f6db 100644 +--- a/drivers/media/platform/qcom/iris/Makefile ++++ b/drivers/media/platform/qcom/iris/Makefile +@@ -23,4 +23,8 @@ iris-objs += iris_buffer.o \ + iris_vpu_buffer.o \ + iris_vpu_common.o \ + ++ifeq ($(CONFIG_VIDEO_QCOM_VENUS),) ++iris-objs += iris_platform_sm8250.o ++endif ++ + obj-$(CONFIG_VIDEO_QCOM_IRIS) += iris.o +diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h +index 189dd081ad0a..f6b15d2805fb 100644 +--- a/drivers/media/platform/qcom/iris/iris_platform_common.h ++++ b/drivers/media/platform/qcom/iris/iris_platform_common.h +@@ -33,6 +33,7 @@ enum pipe_type { + PIPE_4 = 4, + }; + ++extern struct iris_platform_data sm8250_data; + extern struct iris_platform_data sm8550_data; + + enum platform_clk_type { +diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c +new file mode 100644 +index 000000000000..5c86fd7b7b6f +--- /dev/null ++++ b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c +@@ -0,0 +1,149 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include "iris_core.h" ++#include "iris_ctrls.h" ++#include "iris_platform_common.h" ++#include "iris_resources.h" ++#include "iris_hfi_gen1.h" ++#include "iris_hfi_gen1_defines.h" ++#include "iris_vpu_common.h" ++ ++static struct platform_inst_fw_cap inst_fw_cap_sm8250[] = { ++ { ++ .cap_id = PIPE, ++ .min = PIPE_1, ++ .max = PIPE_4, ++ .step_or_mask = 1, ++ .value = PIPE_4, ++ .hfi_id = HFI_PROPERTY_PARAM_WORK_ROUTE, ++ .set = iris_set_pipe, ++ }, ++ { ++ .cap_id = STAGE, ++ .min = STAGE_1, ++ .max = STAGE_2, ++ .step_or_mask = 1, ++ .value = STAGE_2, ++ .hfi_id = HFI_PROPERTY_PARAM_WORK_MODE, ++ .set = iris_set_stage, ++ }, ++ { ++ .cap_id = DEBLOCK, ++ .min = 0, ++ .max = 1, ++ .step_or_mask = 1, ++ .value = 0, ++ .hfi_id = HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER, ++ .set = iris_set_u32, ++ }, ++}; ++ ++static struct platform_inst_caps platform_inst_cap_sm8250 = { ++ .min_frame_width = 128, ++ .max_frame_width = 8192, ++ .min_frame_height = 128, ++ .max_frame_height = 8192, ++ .max_mbpf = 138240, ++ .mb_cycles_vsp = 25, ++ .mb_cycles_vpp = 200, ++}; ++ ++static void iris_set_sm8250_preset_registers(struct iris_core *core) ++{ ++ writel(0x0, core->reg_base + 0xB0088); ++} ++ ++static const struct icc_info sm8250_icc_table[] = { ++ { "cpu-cfg", 1000, 1000 }, ++ { "video-mem", 1000, 15000000 }, ++}; ++ ++static const char * const sm8250_clk_reset_table[] = { "bus", "core" }; ++ ++static const struct bw_info sm8250_bw_table_dec[] = { ++ { ((4096 * 2160) / 256) * 60, 2403000 }, ++ { ((4096 * 2160) / 256) * 30, 1224000 }, ++ { ((1920 * 1080) / 256) * 60, 812000 }, ++ { ((1920 * 1080) / 256) * 30, 416000 }, ++}; ++ ++static const char * const sm8250_pmdomain_table[] = { "venus", "vcodec0" }; ++ ++static const char * const sm8250_opp_pd_table[] = { "mx" }; ++ ++static const struct platform_clk_data sm8250_clk_table[] = { ++ {IRIS_AXI_CLK, "iface" }, ++ {IRIS_CTRL_CLK, "core" }, ++ {IRIS_HW_CLK, "vcodec0_core" }, ++}; ++ ++static struct tz_cp_config tz_cp_config_sm8250 = { ++ .cp_start = 0, ++ .cp_size = 0x25800000, ++ .cp_nonpixel_start = 0x01000000, ++ .cp_nonpixel_size = 0x24800000, ++}; ++ ++static const u32 sm8250_vdec_input_config_param_default[] = { ++ HFI_PROPERTY_CONFIG_VIDEOCORES_USAGE, ++ HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT, ++ HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO, ++ HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL, ++ HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM, ++ HFI_PROPERTY_PARAM_FRAME_SIZE, ++ HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL, ++ HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE, ++}; ++ ++static const u32 sm8250_dec_ip_int_buf_tbl[] = { ++ BUF_BIN, ++ BUF_SCRATCH_1, ++}; ++ ++static const u32 sm8250_dec_op_int_buf_tbl[] = { ++ BUF_DPB, ++}; ++ ++struct iris_platform_data sm8250_data = { ++ .get_instance = iris_hfi_gen1_get_instance, ++ .init_hfi_command_ops = &iris_hfi_gen1_command_ops_init, ++ .init_hfi_response_ops = iris_hfi_gen1_response_ops_init, ++ .vpu_ops = &iris_vpu2_ops, ++ .set_preset_registers = iris_set_sm8250_preset_registers, ++ .icc_tbl = sm8250_icc_table, ++ .icc_tbl_size = ARRAY_SIZE(sm8250_icc_table), ++ .clk_rst_tbl = sm8250_clk_reset_table, ++ .clk_rst_tbl_size = ARRAY_SIZE(sm8250_clk_reset_table), ++ .bw_tbl_dec = sm8250_bw_table_dec, ++ .bw_tbl_dec_size = ARRAY_SIZE(sm8250_bw_table_dec), ++ .pmdomain_tbl = sm8250_pmdomain_table, ++ .pmdomain_tbl_size = ARRAY_SIZE(sm8250_pmdomain_table), ++ .opp_pd_tbl = sm8250_opp_pd_table, ++ .opp_pd_tbl_size = ARRAY_SIZE(sm8250_opp_pd_table), ++ .clk_tbl = sm8250_clk_table, ++ .clk_tbl_size = ARRAY_SIZE(sm8250_clk_table), ++ /* Upper bound of DMA address range */ ++ .dma_mask = 0xe0000000 - 1, ++ .fwname = "qcom/vpu-1.0/venus.mbn", ++ .pas_id = IRIS_PAS_ID, ++ .inst_caps = &platform_inst_cap_sm8250, ++ .inst_fw_caps = inst_fw_cap_sm8250, ++ .inst_fw_caps_size = ARRAY_SIZE(inst_fw_cap_sm8250), ++ .tz_cp_config_data = &tz_cp_config_sm8250, ++ .hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE, ++ .num_vpp_pipe = 4, ++ .max_session_count = 16, ++ .max_core_mbpf = (8192 * 4352) / 256, ++ .input_config_params = ++ sm8250_vdec_input_config_param_default, ++ .input_config_params_size = ++ ARRAY_SIZE(sm8250_vdec_input_config_param_default), ++ ++ .dec_ip_int_buf_tbl = sm8250_dec_ip_int_buf_tbl, ++ .dec_ip_int_buf_tbl_size = ARRAY_SIZE(sm8250_dec_ip_int_buf_tbl), ++ .dec_op_int_buf_tbl = sm8250_dec_op_int_buf_tbl, ++ .dec_op_int_buf_tbl_size = ARRAY_SIZE(sm8250_dec_op_int_buf_tbl), ++}; +diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c +index 954cc7c0cc97..aca442dcc153 100644 +--- a/drivers/media/platform/qcom/iris/iris_probe.c ++++ b/drivers/media/platform/qcom/iris/iris_probe.c +@@ -324,6 +324,12 @@ static const struct of_device_id iris_dt_match[] = { + .compatible = "qcom,sm8550-iris", + .data = &sm8550_data, + }, ++#if (!IS_ENABLED(CONFIG_VIDEO_QCOM_VENUS)) ++ { ++ .compatible = "qcom,sm8250-venus", ++ .data = &sm8250_data, ++ }, ++#endif + { }, + }; + MODULE_DEVICE_TABLE(of, iris_dt_match); +-- +2.34.1 + diff --git a/patch/kernel/archive/sm8550-6.12/0028_media--MAINTAINERS--add-Qualcomm-iris-video-accele.patch b/patch/kernel/archive/sm8550-6.12/0028_media--MAINTAINERS--add-Qualcomm-iris-video-accele.patch new file mode 100644 index 000000000..39d7c34b8 --- /dev/null +++ b/patch/kernel/archive/sm8550-6.12/0028_media--MAINTAINERS--add-Qualcomm-iris-video-accele.patch @@ -0,0 +1,44 @@ +From 0018ef7f51ba5f9001b8870aab40d4db86cccf90 Mon Sep 17 00:00:00 2001 +From: Dikshita Agarwal +Date: Fri, 7 Feb 2025 13:25:08 +0530 +Subject: [PATCH] media: MAINTAINERS: add Qualcomm iris video accelerator + driver + +Add an entry for the iris video decoder accelerator driver. + +Signed-off-by: Vikash Garodia +Tested-by: Stefan Schmidt # x1e80100 (Dell XPS 13 9345) +Reviewed-by: Stefan Schmidt +Tested-by: Neil Armstrong # on SM8550-QRD +Tested-by: Neil Armstrong # on SM8550-HDK +Signed-off-by: Dikshita Agarwal +Link: https://lore.kernel.org/r/20250207-qcom-video-iris-v10-28-ab66eeffbd20@quicinc.com +Signed-off-by: Neil Armstrong +--- + MAINTAINERS | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/MAINTAINERS b/MAINTAINERS +index 0fa7c5728f1e..fb253f68816b 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -19352,6 +19352,16 @@ S: Maintained + F: Documentation/devicetree/bindings/regulator/vqmmc-ipq4019-regulator.yaml + F: drivers/regulator/vqmmc-ipq4019-regulator.c + ++QUALCOMM IRIS VIDEO ACCELERATOR DRIVER ++M: Vikash Garodia ++M: Dikshita Agarwal ++R: Abhinav Kumar ++L: linux-media@vger.kernel.org ++L: linux-arm-msm@vger.kernel.org ++S: Maintained ++F: Documentation/devicetree/bindings/media/qcom,*-iris.yaml ++F: drivers/media/platform/qcom/iris/ ++ + QUALCOMM NAND CONTROLLER DRIVER + M: Manivannan Sadhasivam + L: linux-mtd@lists.infradead.org +-- +2.34.1 + diff --git a/patch/kernel/archive/sm8550-6.12/0029_arm64--dts--qcom--sm8550--Add-iris-video-codec-nod.patch b/patch/kernel/archive/sm8550-6.12/0029_arm64--dts--qcom--sm8550--Add-iris-video-codec-nod.patch new file mode 100644 index 000000000..57f089efd --- /dev/null +++ b/patch/kernel/archive/sm8550-6.12/0029_arm64--dts--qcom--sm8550--Add-iris-video-codec-nod.patch @@ -0,0 +1,100 @@ +From 8b02771befadcb1b666488c48fa92ec14a07407a Mon Sep 17 00:00:00 2001 +From: Teguh Sobirin +Date: Wed, 12 Feb 2025 20:50:35 +0800 +Subject: [PATCH] arm64: dts: qcom: sm8550: Add iris video-codec node + +Signed-off-by: Teguh Sobirin +--- + arch/arm64/boot/dts/qcom/sm8550.dtsi | 69 ++++++++++++++++++++++++++++ + 1 file changed, 69 insertions(+) + +diff --git a/arch/arm64/boot/dts/qcom/sm8550.dtsi b/arch/arm64/boot/dts/qcom/sm8550.dtsi +index a2daf9712fc0..42cd9649a962 100644 +--- a/arch/arm64/boot/dts/qcom/sm8550.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm8550.dtsi +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -2867,6 +2868,74 @@ opp-202000000 { + }; + }; + ++ video-codec@aa00000 { ++ compatible = "qcom,sm8550-iris"; ++ reg = <0 0x0aa00000 0 0xf0000>; ++ interrupts = ; ++ ++ power-domains = <&videocc VIDEO_CC_MVS0C_GDSC>, ++ <&videocc VIDEO_CC_MVS0_GDSC>, ++ <&rpmhpd RPMHPD_MXC>, ++ <&rpmhpd RPMHPD_MMCX>; ++ power-domain-names = "venus", "vcodec0", "mxc", "mmcx"; ++ ++ clocks = <&gcc GCC_VIDEO_AXI0_CLK>, ++ <&videocc VIDEO_CC_MVS0C_CLK>, ++ <&videocc VIDEO_CC_MVS0_CLK>; ++ clock-names = "iface", "core", "vcodec0_core"; ++ ++ interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS ++ &config_noc SLAVE_VENUS_CFG QCOM_ICC_TAG_ALWAYS>, ++ <&mmss_noc MASTER_VIDEO QCOM_ICC_TAG_ALWAYS ++ &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; ++ interconnect-names = "cpu-cfg", "video-mem"; ++ ++ memory-region = <&video_mem>; ++ ++ resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>; ++ reset-names = "bus"; ++ ++ iommus = <&apps_smmu 0x1940 0x0000>, ++ <&apps_smmu 0x1947 0x0000>; ++ dma-coherent; ++ ++ operating-points-v2 = <&iris_opp_table>; ++ ++ iris_opp_table: opp-table { ++ compatible = "operating-points-v2"; ++ ++ opp-240000000 { ++ opp-hz = /bits/ 64 <240000000>; ++ required-opps = <&rpmhpd_opp_svs>, ++ <&rpmhpd_opp_low_svs>; ++ }; ++ ++ opp-338000000 { ++ opp-hz = /bits/ 64 <338000000>; ++ required-opps = <&rpmhpd_opp_svs>, ++ <&rpmhpd_opp_svs>; ++ }; ++ ++ opp-366000000 { ++ opp-hz = /bits/ 64 <366000000>; ++ required-opps = <&rpmhpd_opp_svs_l1>, ++ <&rpmhpd_opp_svs_l1>; ++ }; ++ ++ opp-444000000 { ++ opp-hz = /bits/ 64 <444000000>; ++ required-opps = <&rpmhpd_opp_turbo>, ++ <&rpmhpd_opp_turbo>; ++ }; ++ ++ opp-533333334 { ++ opp-hz = /bits/ 64 <533333334>; ++ required-opps = <&rpmhpd_opp_turbo_l1>, ++ <&rpmhpd_opp_turbo_l1>; ++ }; ++ }; ++ }; ++ + videocc: clock-controller@aaf0000 { + compatible = "qcom,sm8550-videocc"; + reg = <0 0x0aaf0000 0 0x10000>; +-- +2.34.1 + diff --git a/patch/kernel/archive/sm8550-6.12/0030_arm64--dts--qcom--sm8550--add-UART15.patch b/patch/kernel/archive/sm8550-6.12/0030_arm64--dts--qcom--sm8550--add-UART15.patch new file mode 100644 index 000000000..b3e265bd2 --- /dev/null +++ b/patch/kernel/archive/sm8550-6.12/0030_arm64--dts--qcom--sm8550--add-UART15.patch @@ -0,0 +1,53 @@ +From 21978408039e18129cad415257317407aa6482f3 Mon Sep 17 00:00:00 2001 +From: Teguh Sobirin +Date: Wed, 12 Feb 2025 17:53:48 +0800 +Subject: [PATCH] arm64: dts: qcom: sm8550: add UART15 + +Signed-off-by: Teguh Sobirin +--- + arch/arm64/boot/dts/qcom/sm8550.dtsi | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +diff --git a/arch/arm64/boot/dts/qcom/sm8550.dtsi b/arch/arm64/boot/dts/qcom/sm8550.dtsi +index 42cd9649a962..86fc8bd0af1f 100644 +--- a/arch/arm64/boot/dts/qcom/sm8550.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm8550.dtsi +@@ -1133,6 +1133,20 @@ spi15: spi@89c000 { + #size-cells = <0>; + status = "disabled"; + }; ++ ++ uart15: serial@89c000 { ++ compatible = "qcom,geni-uart"; ++ reg = <0 0x89c000 0 0x4000>; ++ clock-names = "se"; ++ clocks = <&gcc GCC_QUPV3_WRAP2_S7_CLK>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&qup_uart15_default>; ++ interrupts = ; ++ interconnects = <&clk_virt MASTER_QUP_CORE_2 0 &clk_virt SLAVE_QUP_CORE_2 0>, ++ <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_QUP_2 0>; ++ interconnect-names = "qup-core", "qup-config"; ++ status = "disabled"; ++ }; + }; + + i2c_master_hub_0: geniqup@9c0000 { +@@ -4325,6 +4339,14 @@ qup_uart14_cts_rts: qup-uart14-cts-rts-state { + bias-pull-down; + }; + ++ qup_uart15_default: qup-uart15-default-state { ++ /* TX, RX */ ++ pins = "gpio74", "gpio75"; ++ function = "qup2_se7"; ++ drive-strength = <2>; ++ bias-pull-up; ++ }; ++ + sdc2_sleep: sdc2-sleep-state { + clk-pins { + pins = "sdc2_clk"; +-- +2.34.1 + diff --git a/patch/kernel/archive/sm8550-6.12/0031_input--Add-driver-for-RSInput-Gamepad.patch b/patch/kernel/archive/sm8550-6.12/0031_input--Add-driver-for-RSInput-Gamepad.patch new file mode 100644 index 000000000..0c27f6f12 --- /dev/null +++ b/patch/kernel/archive/sm8550-6.12/0031_input--Add-driver-for-RSInput-Gamepad.patch @@ -0,0 +1,467 @@ +From 63cf9c45ac695a062d47213b5bc962785b6f9147 Mon Sep 17 00:00:00 2001 +From: Teguh Sobirin +Date: Thu, 20 Feb 2025 14:50:30 +0800 +Subject: [PATCH] input: Add driver for RSInput Gamepad + +Signed-off-by: Teguh Sobirin +--- + drivers/input/joystick/Kconfig | 4 + + drivers/input/joystick/Makefile | 1 + + drivers/input/joystick/rsinput.c | 418 +++++++++++++++++++++++++++++++ + 3 files changed, 423 insertions(+) + create mode 100644 drivers/input/joystick/rsinput.c + +diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig +index 7755e5b454d2..0da3c0f44ecf 100644 +--- a/drivers/input/joystick/Kconfig ++++ b/drivers/input/joystick/Kconfig +@@ -383,6 +383,10 @@ config JOYSTICK_QWIIC + To compile this driver as a module, choose M here: the + module will be called qwiic-joystick. + ++config JOYSTICK_RSINPUT ++ tristate "UART Based gamepad driver that found in AYN and Retroid Pocket products" ++ depends on SERIAL_DEV_BUS ++ + config JOYSTICK_FSIA6B + tristate "FlySky FS-iA6B RC Receiver" + select SERIO +diff --git a/drivers/input/joystick/Makefile b/drivers/input/joystick/Makefile +index 9976f596a920..3de503e29489 100644 +--- a/drivers/input/joystick/Makefile ++++ b/drivers/input/joystick/Makefile +@@ -28,6 +28,7 @@ obj-$(CONFIG_JOYSTICK_N64) += n64joy.o + obj-$(CONFIG_JOYSTICK_PSXPAD_SPI) += psxpad-spi.o + obj-$(CONFIG_JOYSTICK_PXRC) += pxrc.o + obj-$(CONFIG_JOYSTICK_QWIIC) += qwiic-joystick.o ++obj-$(CONFIG_JOYSTICK_RSINPUT) += rsinput.o + obj-$(CONFIG_JOYSTICK_SEESAW) += adafruit-seesaw.o + obj-$(CONFIG_JOYSTICK_SENSEHAT) += sensehat-joystick.o + obj-$(CONFIG_JOYSTICK_SIDEWINDER) += sidewinder.o +diff --git a/drivers/input/joystick/rsinput.c b/drivers/input/joystick/rsinput.c +new file mode 100644 +index 000000000000..4a7096407712 +--- /dev/null ++++ b/drivers/input/joystick/rsinput.c +@@ -0,0 +1,418 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * RSInput Gamepad Driver ++ * ++ * Copyright (C) 2024 Teguh Sobirin ++ * ++ */ ++#define DEBUG ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define FRAME_HEAD_1 0xA5 ++#define FRAME_HEAD_2 0xD3 ++#define FRAME_HEAD_3 0x5A ++#define FRAME_HEAD_4 0x3D ++ ++#define CMD_COMMOD 0x01 ++#define CMD_STATUS 0x02 ++ ++#define DATA_COMMOD_VERSION 0x02 ++#define DATA_COMMOD_SET_PAR 0x05 ++ ++#define FRAME_POS_SEQ 4 ++#define FRAME_POS_CMD 5 ++#define FRAME_POS_LEN_L 6 ++#define FRAME_POS_LEN_H 7 ++#define FRAME_POS_DATA_1 8 ++#define FRAME_POS_DATA_2 9 ++#define FRAME_POS_DATA_3 10 ++#define FRAME_POS_DATA_4 11 ++#define FRAME_POS_DATA_5 12 ++#define FRAME_POS_DATA_6 13 ++#define FRAME_POS_DATA_7 14 ++#define FRAME_POS_DATA_8 15 ++#define FRAME_POS_DATA_9 16 ++#define FRAME_POS_DATA_10 17 ++#define FRAME_POS_DATA_11 18 ++#define FRAME_POS_DATA_12 19 ++#define FRAME_POS_DATA_13 20 ++#define FRAME_POS_DATA_14 21 ++ ++#define MCU_PKT_SIZE_MIN 9 ++ ++#define MCU_VERSION_MAX_LEN 64 ++ ++struct rsinput_driver { ++ struct serdev_device *serdev; ++ struct input_dev *input; ++ struct gpio_desc *boot_gpio; ++ struct gpio_desc *enable_gpio; ++ struct gpio_desc *reset_gpio; ++ uint8_t rx_buf[256]; ++ uint8_t sequence_number; ++}; ++ ++static const unsigned int keymap[] = { ++ BTN_DPAD_UP, BTN_DPAD_DOWN, BTN_DPAD_LEFT, BTN_DPAD_RIGHT, ++ BTN_NORTH, BTN_WEST, BTN_EAST, BTN_SOUTH, ++ BTN_TL, BTN_TR, BTN_SELECT, BTN_START, ++ BTN_THUMBL, BTN_THUMBR, BTN_MODE, BTN_BACK ++}; ++ ++static uint8_t compute_checksum(const uint8_t *data, size_t len) { ++ uint8_t checksum = 0; ++ ++ for (size_t i = FRAME_POS_SEQ; i < len - 1; i++) { ++ checksum ^= data[i]; ++ } ++ ++ return checksum; ++} ++ ++static int rsinput_send_command(struct rsinput_driver *drv, uint8_t cmd, const uint8_t *data, size_t len) { ++ uint8_t frame[256]; ++ uint8_t checksum = 0; ++ size_t frame_len = 0; ++ ++ frame[frame_len++] = FRAME_HEAD_1; ++ frame[frame_len++] = FRAME_HEAD_2; ++ frame[frame_len++] = FRAME_HEAD_3; ++ frame[frame_len++] = FRAME_HEAD_4; ++ ++ frame[frame_len++] = drv->sequence_number; ++ drv->sequence_number++; ++ ++ frame[frame_len++] = cmd; ++ ++ frame[frame_len++] = len & 0xFF; ++ frame[frame_len++] = (len >> 8) & 0xFF; ++ ++ if (data && len) { ++ memcpy(&frame[frame_len], data, len); ++ frame_len += len; ++ } ++ ++ checksum = compute_checksum(frame, frame_len + 1); ++ frame[frame_len++] = checksum; ++ ++ return serdev_device_write_buf(drv->serdev, frame, frame_len); ++} ++ ++static int rsinput_init_commands(struct rsinput_driver *drv) { ++ int error; ++ ++ msleep(100); ++ uint8_t version_request[] = {DATA_COMMOD_VERSION}; ++ error = rsinput_send_command(drv, CMD_COMMOD, version_request, sizeof(version_request)); ++ if (error < 0) { ++ dev_err(&drv->serdev->dev, "Failed to request MCU version: %d\n", error); ++ return error; ++ } ++ ++ msleep(100); ++ uint8_t mcu_params[] = { ++ DATA_COMMOD_SET_PAR, ++ 0x01, ++ 0x00, 0x00, 0x00, 0x28, ++ 0x00, 0x00, 0x00, 0x07 ++ }; ++ error = rsinput_send_command(drv, CMD_COMMOD, mcu_params, sizeof(mcu_params)); ++ if (error < 0) { ++ dev_err(&drv->serdev->dev, "Failed to set MCU parameters: %d\n", error); ++ return error; ++ } ++ ++ return 0; ++} ++ ++static void handle_cmd_commod(struct rsinput_driver *drv, const uint8_t *data, size_t payload_length) { ++ switch (data[FRAME_POS_DATA_1]) { ++ case DATA_COMMOD_VERSION: ++ if (payload_length >= 1) { ++ char mcu_version[MCU_VERSION_MAX_LEN] = {0}; ++ size_t version_length = payload_length; ++ if (version_length > MCU_VERSION_MAX_LEN - 1) { ++ version_length = MCU_VERSION_MAX_LEN - 1; ++ } ++ memcpy(mcu_version, &data[FRAME_POS_DATA_1], version_length); ++ mcu_version[version_length] = '\0'; ++ dev_info(&drv->serdev->dev, "MCU Version: %s\n", mcu_version); ++ } else { ++ dev_err(&drv->serdev->dev, "Invalid MCU version response length\n"); ++ } ++ break; ++ case DATA_COMMOD_SET_PAR: ++ dev_info(&drv->serdev->dev, "MCU parameters set successfully\n"); ++ break; ++ default: ++ dev_warn(&drv->serdev->dev, "Unhandled CMD_COMMOD sub-command: 0x%02x\n", data[FRAME_POS_DATA_1]); ++ break; ++ } ++} ++ ++static void handle_cmd_status(struct rsinput_driver *drv, const uint8_t *data, size_t payload_length) { ++ if (payload_length >= 6) { ++ static unsigned long prev_states; ++ unsigned long keys = data[FRAME_POS_DATA_1] | (data[FRAME_POS_DATA_2] << 8); ++ unsigned long current_states = keys, changes; ++ int i; ++ ++ bitmap_xor(&changes, ¤t_states, &prev_states, ARRAY_SIZE(keymap)); ++ ++ for_each_set_bit(i, &changes, ARRAY_SIZE(keymap)) { ++ input_report_key(drv->input, keymap[i], (current_states & BIT(i))); ++ } ++ ++ input_report_abs(drv->input, ABS_HAT2X, ++ 0x650 - (data[FRAME_POS_DATA_3] | (data[FRAME_POS_DATA_4] << 8))); ++ input_report_abs(drv->input, ABS_HAT2Y, ++ 0x650 - (data[FRAME_POS_DATA_5] | (data[FRAME_POS_DATA_6] << 8))); ++ input_report_abs(drv->input, ABS_X, ++ -(int16_t)(data[FRAME_POS_DATA_7] | (data[FRAME_POS_DATA_8] << 8))); ++ input_report_abs(drv->input, ABS_Y, ++ -(int16_t)(data[FRAME_POS_DATA_9] | (data[FRAME_POS_DATA_10] << 8))); ++ input_report_abs(drv->input, ABS_RX, ++ -(int16_t)(data[FRAME_POS_DATA_11] | (data[FRAME_POS_DATA_12] << 8))); ++ input_report_abs(drv->input, ABS_RY, ++ -(int16_t)(data[FRAME_POS_DATA_13] | (data[FRAME_POS_DATA_14] << 8))); ++ ++ input_sync(drv->input); ++ prev_states = keys; ++ ++ } else { ++ dev_warn(&drv->serdev->dev, "Invalid CMD_STATUS response length\n"); ++ } ++} ++ ++static void rsinput_process_data(struct rsinput_driver *drv, const uint8_t *data, size_t len) { ++ while (len >= MCU_PKT_SIZE_MIN) { ++ uint16_t payload_length = data[FRAME_POS_LEN_L] | (data[FRAME_POS_LEN_H] << 8); ++ size_t frame_length = MCU_PKT_SIZE_MIN + payload_length; ++ ++ if (len < frame_length) { ++ return; ++ } ++ ++ uint8_t received_checksum = data[frame_length - 1]; ++ uint8_t computed_checksum = compute_checksum(data, frame_length); ++ if (computed_checksum != received_checksum) { ++ data += frame_length; ++ len -= frame_length; ++ continue; ++ } ++ ++ switch (data[FRAME_POS_CMD]) { ++ case CMD_COMMOD: ++ handle_cmd_commod(drv, data, payload_length); ++ break; ++ case CMD_STATUS: ++ handle_cmd_status(drv, data, payload_length); ++ break; ++ default: ++ dev_warn(&drv->serdev->dev, "Unhandled command: 0x%02X\n", data[FRAME_POS_CMD]); ++ break; ++ } ++ ++ data += frame_length; ++ len -= frame_length; ++ } ++ ++ if (len > 0) { ++ dev_warn(&drv->serdev->dev, "Trailing bytes after processing: %zu\n", len); ++ } ++} ++ ++static size_t rsinput_rx(struct serdev_device *serdev, const u8 *data, size_t count) { ++ struct rsinput_driver *drv = serdev_device_get_drvdata(serdev); ++ uint8_t received_checksum, computed_checksum; ++ ++ if (!drv || !data || count == 0) { ++ dev_warn_ratelimited(&serdev->dev, "Invalid RX data\n"); ++ goto error; ++ } ++ ++ if (count > sizeof(drv->rx_buf)) { ++ dev_warn_ratelimited(&serdev->dev, "RX buffer overflow\n"); ++ goto error; ++ } ++ ++ memcpy(drv->rx_buf, data, count); ++ ++ if (count < MCU_PKT_SIZE_MIN) { ++ dev_warn_ratelimited(&serdev->dev, "Frame too short for checksum validation\n"); ++ goto error; ++ } ++ ++ received_checksum = drv->rx_buf[count - 1]; ++ ++ computed_checksum = compute_checksum(drv->rx_buf, count); ++ ++ if (computed_checksum != received_checksum) { ++ rsinput_init_commands(drv); ++ goto error; ++ } ++ ++ rsinput_process_data(drv, drv->rx_buf, count); ++ ++error: ++ return count; ++} ++ ++static const struct serdev_device_ops rsinput_rx_ops = { ++ .receive_buf = rsinput_rx, ++}; ++ ++static int rsinput_probe(struct serdev_device *serdev) { ++ struct rsinput_driver *drv; ++ u32 gamepad_bus = 0; ++ u32 gamepad_vid = 0; ++ u32 gamepad_pid = 0; ++ u32 gamepad_rev = 0; ++ int error; ++ ++ drv = devm_kzalloc(&serdev->dev, sizeof(*drv), GFP_KERNEL); ++ if (!drv) ++ return -ENOMEM; ++ ++ drv->boot_gpio = ++ devm_gpiod_get_optional(&serdev->dev, "boot", GPIOD_OUT_HIGH); ++ if (IS_ERR(drv->boot_gpio)) { ++ error = PTR_ERR(drv->boot_gpio); ++ dev_warn(&serdev->dev, "Unable to get boot gpio: %d\n", error); ++ } ++ ++ drv->enable_gpio = ++ devm_gpiod_get_optional(&serdev->dev, "enable", GPIOD_OUT_HIGH); ++ if (IS_ERR(drv->enable_gpio)) { ++ error = PTR_ERR(drv->enable_gpio); ++ dev_warn(&serdev->dev, "Unable to get enable gpio: %d\n", error); ++ } ++ ++ drv->reset_gpio = ++ devm_gpiod_get_optional(&serdev->dev, "reset", GPIOD_OUT_HIGH); ++ if (IS_ERR(drv->reset_gpio)) { ++ error = PTR_ERR(drv->reset_gpio); ++ dev_warn(&serdev->dev, "Unable to get reset gpio: %d\n", error); ++ } ++ ++ if (drv->boot_gpio) ++ gpiod_set_value_cansleep(drv->boot_gpio, 0); ++ ++ if (drv->reset_gpio) ++ gpiod_set_value_cansleep(drv->reset_gpio, 0); ++ ++ msleep(100); ++ ++ if (drv->enable_gpio) ++ gpiod_set_value_cansleep(drv->enable_gpio, 1); ++ ++ if (drv->reset_gpio) ++ gpiod_set_value_cansleep(drv->reset_gpio, 1); ++ ++ msleep(100); ++ ++ error = serdev_device_open(serdev); ++ if (error) ++ return dev_err_probe(&serdev->dev, error, "Unable to open UART device\n"); ++ ++ drv->serdev = serdev; ++ drv->sequence_number = 0; ++ ++ serdev_device_set_drvdata(serdev, drv); ++ ++ error = serdev_device_set_baudrate(serdev, 115200); ++ if (error < 0) ++ return dev_err_probe(&serdev->dev, error, "Failed to set up host baud rate\n"); ++ ++ serdev_device_set_flow_control(serdev, false); ++ ++ drv->input = devm_input_allocate_device(&serdev->dev); ++ if (!drv->input) ++ return -ENOMEM; ++ ++ drv->input->phys = "rsinput-gamepad/input0"; ++ ++ error = device_property_read_string(&serdev->dev, "gamepad-name", &drv->input->name); ++ if (error) { ++ drv->input->name = "RSInput Gamepad"; ++ } ++ ++ device_property_read_u32(&serdev->dev, "gamepad-bus", &gamepad_bus); ++ device_property_read_u32(&serdev->dev, "gamepad-vid", &gamepad_vid); ++ device_property_read_u32(&serdev->dev, "gamepad-pid", &gamepad_pid); ++ device_property_read_u32(&serdev->dev, "gamepad-rev", &gamepad_rev); ++ ++ drv->input->id.bustype = (u16)gamepad_bus; ++ drv->input->id.vendor = (u16)gamepad_vid; ++ drv->input->id.product = (u16)gamepad_pid; ++ drv->input->id.version = (u16)gamepad_rev; ++ ++ __set_bit(EV_KEY, drv->input->evbit); ++ for (int i = 0; i < ARRAY_SIZE(keymap); i++) ++ input_set_capability(drv->input, EV_KEY, keymap[i]); ++ ++ __set_bit(EV_ABS, drv->input->evbit); ++ for (int i = ABS_X; i <= ABS_RZ; i++) ++ input_set_abs_params(drv->input, i, -0x580, 0x580, ++ 0, 0); ++ ++ input_set_abs_params(drv->input, ABS_HAT2X, 0, 1830, 0, 30); ++ input_set_abs_params(drv->input, ABS_HAT2Y, 0, 1830, 0, 30); ++ ++ error = input_register_device(drv->input); ++ if (error) ++ return error; ++ ++ serdev_device_set_client_ops(serdev, &rsinput_rx_ops); ++ ++ error = rsinput_init_commands(drv); ++ if (error < 0) { ++ serdev_device_close(serdev); ++ return error; ++ } ++ ++ return 0; ++} ++ ++static void rsinput_remove(struct serdev_device *serdev) { ++ struct rsinput_driver *drv = serdev_device_get_drvdata(serdev); ++ ++ serdev_device_close(serdev); ++ input_unregister_device(drv->input); ++ if (drv->enable_gpio) ++ gpiod_set_value_cansleep(drv->enable_gpio, 0); ++ ++ if (drv->reset_gpio) ++ gpiod_set_value_cansleep(drv->reset_gpio, 0); ++} ++ ++static const struct of_device_id rsinput_of_match[] = { ++ { .compatible = "gamepad,rsinput" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, rsinput_of_match); ++ ++static struct serdev_device_driver rsinput_driver = { ++ .probe = rsinput_probe, ++ .remove = rsinput_remove, ++ .driver = { ++ .name = "rsinput", ++ .of_match_table = rsinput_of_match, ++ }, ++}; ++ ++module_serdev_device_driver(rsinput_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("RSInput Gamepad Driver"); ++MODULE_AUTHOR("Teguh Sobirin "); +-- +2.34.1 + diff --git a/patch/kernel/archive/sm8550-6.12/0032_drm-panel--Add-panel-driver-for-Chipone-ICNA3512-b.patch b/patch/kernel/archive/sm8550-6.12/0032_drm-panel--Add-panel-driver-for-Chipone-ICNA3512-b.patch new file mode 100644 index 000000000..6d4db21c8 --- /dev/null +++ b/patch/kernel/archive/sm8550-6.12/0032_drm-panel--Add-panel-driver-for-Chipone-ICNA3512-b.patch @@ -0,0 +1,530 @@ +From aae567ecbda8e1c3a8d4aaebc90914b6ff740785 Mon Sep 17 00:00:00 2001 +From: Teguh Sobirin +Date: Thu, 13 Feb 2025 18:25:19 +0800 +Subject: [PATCH] drm/panel: Add panel driver for Chipone ICNA3512 based panels + +Signed-off-by: Teguh Sobirin +--- + drivers/gpu/drm/panel/Kconfig | 11 + + drivers/gpu/drm/panel/Makefile | 1 + + .../gpu/drm/panel/panel-chipone-icna3512.c | 473 ++++++++++++++++++ + 3 files changed, 485 insertions(+) + create mode 100644 drivers/gpu/drm/panel/panel-chipone-icna3512.c + +diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig +index d7469c565d1d..112a7bfcd169 100644 +--- a/drivers/gpu/drm/panel/Kconfig ++++ b/drivers/gpu/drm/panel/Kconfig +@@ -96,6 +96,17 @@ config DRM_PANEL_BOE_TV101WUM_LL2 + Say Y here if you want to support for BOE TV101WUM-LL2 + WUXGA PANEL DSI Video Mode panel + ++config DRM_PANEL_CHIPONE_ICNA3512 ++ tristate "Chipone ICNA3512 panel driver" ++ depends on OF ++ depends on DRM_MIPI_DSI ++ depends on BACKLIGHT_CLASS_DEVICE ++ select DRM_DISPLAY_HELPER ++ help ++ Say Y here if you want to enable support for the panels built ++ around the Chipone ICNA3512 display controller, such as some ++ Tianma panels used in AYN Odin2 Portal. ++ + config DRM_PANEL_EBBG_FT8719 + tristate "EBBG FT8719 panel driver" + depends on OF +diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile +index 7dcf72646cac..8773117908c8 100644 +--- a/drivers/gpu/drm/panel/Makefile ++++ b/drivers/gpu/drm/panel/Makefile +@@ -8,6 +8,7 @@ obj-$(CONFIG_DRM_PANEL_BOE_HIMAX8279D) += panel-boe-himax8279d.o + obj-$(CONFIG_DRM_PANEL_BOE_TH101MB31UIG002_28A) += panel-boe-th101mb31ig002-28a.o + obj-$(CONFIG_DRM_PANEL_BOE_TV101WUM_LL2) += panel-boe-tv101wum-ll2.o + obj-$(CONFIG_DRM_PANEL_BOE_TV101WUM_NL6) += panel-boe-tv101wum-nl6.o ++obj-$(CONFIG_DRM_PANEL_CHIPONE_ICNA3512) += panel-chipone-icna3512.o + obj-$(CONFIG_DRM_PANEL_DSI_CM) += panel-dsi-cm.o + obj-$(CONFIG_DRM_PANEL_LVDS) += panel-lvds.o + obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o +diff --git a/drivers/gpu/drm/panel/panel-chipone-icna3512.c b/drivers/gpu/drm/panel/panel-chipone-icna3512.c +new file mode 100644 +index 000000000000..cbda976df1db +--- /dev/null ++++ b/drivers/gpu/drm/panel/panel-chipone-icna3512.c +@@ -0,0 +1,473 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Chipone ICNA3512 Driver IC panels driver ++ * ++ * Copyright (c) 2025 Teguh Sobirin ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include