1
0
Fork 0
mirror of https://github.com/Ysurac/openmptcprouter.git synced 2025-03-09 15:40:20 +00:00

Fix RPI5 support

This commit is contained in:
Ycarus (Yannick Chabanois) 2023-11-17 17:31:36 +01:00
parent 57beb2ec60
commit 3743692973
1017 changed files with 232368 additions and 4124 deletions

View file

@ -0,0 +1,208 @@
Package/brcmfmac-firmware-4339-sdio = $(call Package/firmware-default,Broadcom 4339 FullMAC SDIO firmware)
define Package/brcmfmac-firmware-4339-sdio/install
$(INSTALL_DIR) $(1)/lib/firmware/cypress
$(INSTALL_DATA) \
$(PKG_BUILD_DIR)/cypress/cyfmac4339-sdio.bin \
$(1)/lib/firmware/cypress/
$(INSTALL_DIR) $(1)/lib/firmware/brcm
$(LN) \
../cypress/cyfmac4339-sdio.bin \
$(1)/lib/firmware/brcm/brcmfmac4339-sdio.bin
endef
$(eval $(call BuildPackage,brcmfmac-firmware-4339-sdio))
Package/brcmfmac-firmware-43602a1-pcie = $(call Package/firmware-default,Broadcom 43602a1 FullMAC PCIe firmware)
define Package/brcmfmac-firmware-43602a1-pcie/install
$(INSTALL_DIR) $(1)/lib/firmware/brcm
$(INSTALL_DATA) \
$(PKG_BUILD_DIR)/brcm/brcmfmac43602-pcie.ap.bin \
$(1)/lib/firmware/brcm/brcmfmac43602-pcie.bin
endef
$(eval $(call BuildPackage,brcmfmac-firmware-43602a1-pcie))
Package/brcmfmac-firmware-4366b1-pcie = $(call Package/firmware-default,Broadcom 4366b1 FullMAC PCIe firmware)
define Package/brcmfmac-firmware-4366b1-pcie/install
$(INSTALL_DIR) $(1)/lib/firmware/brcm
$(INSTALL_DATA) \
$(PKG_BUILD_DIR)/brcm/brcmfmac4366b-pcie.bin \
$(1)/lib/firmware/brcm/
endef
$(eval $(call BuildPackage,brcmfmac-firmware-4366b1-pcie))
Package/brcmfmac-firmware-4366c0-pcie = $(call Package/firmware-default,Broadcom 4366c0 FullMAC PCIe firmware)
define Package/brcmfmac-firmware-4366c0-pcie/install
$(INSTALL_DIR) $(1)/lib/firmware/brcm
$(INSTALL_DATA) \
$(PKG_BUILD_DIR)/brcm/brcmfmac4366c-pcie.bin \
$(1)/lib/firmware/brcm/
endef
$(eval $(call BuildPackage,brcmfmac-firmware-4366c0-pcie))
Package/brcmfmac-firmware-4329-sdio = $(call Package/firmware-default,Broadcom BCM4329 FullMac SDIO firmware)
define Package/brcmfmac-firmware-4329-sdio/install
$(INSTALL_DIR) $(1)/lib/firmware/brcm
$(INSTALL_DATA) \
$(PKG_BUILD_DIR)/brcm/brcmfmac4329-sdio.bin \
$(1)/lib/firmware/brcm/brcmfmac4329-sdio.bin
endef
$(eval $(call BuildPackage,brcmfmac-firmware-4329-sdio))
Package/brcmfmac-nvram-43430-sdio = $(call Package/firmware-default,Broadcom BCM43430 SDIO NVRAM)
define Package/brcmfmac-nvram-43430-sdio/install
$(INSTALL_DIR) $(1)/lib/firmware/brcm
$(INSTALL_DATA) \
$(PKG_BUILD_DIR)/brcm/brcmfmac43430-sdio.AP6212.txt \
$(1)/lib/firmware/brcm/
$(LN) \
brcmfmac43430-sdio.AP6212.txt \
$(1)/lib/firmware/brcm/brcmfmac43430-sdio.sinovoip,bpi-m2-plus.txt
$(LN) \
brcmfmac43430-sdio.AP6212.txt \
$(1)/lib/firmware/brcm/brcmfmac43430-sdio.sinovoip,bpi-m2-zero.txt
$(LN) \
brcmfmac43430-sdio.AP6212.txt \
$(1)/lib/firmware/brcm/brcmfmac43430-sdio.sinovoip,bpi-m2-ultra.txt
$(LN) \
brcmfmac43430-sdio.AP6212.txt \
$(1)/lib/firmware/brcm/brcmfmac43430-sdio.sinovoip,bpi-m3.txt
$(LN) \
brcmfmac43430-sdio.AP6212.txt \
$(1)/lib/firmware/brcm/brcmfmac43430-sdio.friendlyarm,nanopi-r1.txt
$(LN) \
brcmfmac43430-sdio.AP6212.txt \
$(1)/lib/firmware/brcm/brcmfmac43430-sdio.starfive,visionfive-v1.txt
$(LN) \
brcmfmac43430-sdio.AP6212.txt \
$(1)/lib/firmware/brcm/brcmfmac43430-sdio.beagle,beaglev-starlight-jh7100-a1.txt
$(LN) \
brcmfmac43430-sdio.AP6212.txt \
$(1)/lib/firmware/brcm/brcmfmac43430-sdio.beagle,beaglev-starlight-jh7100-r0.txt
$(INSTALL_DATA) \
$(PKG_BUILD_DIR)/brcm/brcmfmac43430-sdio.Hampoo-D2D3_Vi8A1.txt \
$(1)/lib/firmware/brcm/
$(INSTALL_DATA) \
$(PKG_BUILD_DIR)/brcm/brcmfmac43430-sdio.MUR1DX.txt \
$(1)/lib/firmware/brcm/
$(INSTALL_DATA) \
$(PKG_BUILD_DIR)/brcm/brcmfmac43430-sdio.raspberrypi,3-model-b.txt \
$(1)/lib/firmware/brcm/
$(LN) \
brcmfmac43430-sdio.raspberrypi,3-model-b.txt \
$(1)/lib/firmware/brcm/brcmfmac43430-sdio.raspberrypi,model-zero-w.txt
$(LN) \
brcmfmac43430-sdio.raspberrypi,3-model-b.txt \
$(1)/lib/firmware/brcm/brcmfmac43430-sdio.raspberrypi,model-zero-2-w.txt
endef
$(eval $(call BuildPackage,brcmfmac-nvram-43430-sdio))
Package/brcmfmac-firmware-43430a0-sdio = $(call Package/firmware-default,Broadcom BCM43430a0 FullMac SDIO firmware)
define Package/brcmfmac-firmware-43430a0-sdio/install
$(INSTALL_DIR) $(1)/lib/firmware/brcm
$(INSTALL_DATA) \
$(PKG_BUILD_DIR)/brcm/brcmfmac43430a0-sdio.bin \
$(1)/lib/firmware/brcm/brcmfmac43430a0-sdio.bin
endef
$(eval $(call BuildPackage,brcmfmac-firmware-43430a0-sdio))
Package/brcmfmac-nvram-43455-sdio = $(call Package/firmware-default,Broadcom BCM43455 SDIO NVRAM)
define Package/brcmfmac-nvram-43455-sdio/install
$(INSTALL_DIR) $(1)/lib/firmware/brcm
$(INSTALL_DATA) \
$(PKG_BUILD_DIR)/brcm/brcmfmac43455-sdio.acepc-t8.txt \
$(1)/lib/firmware/brcm/
$(INSTALL_DATA) \
$(PKG_BUILD_DIR)/brcm/brcmfmac43455-sdio.raspberrypi,3-model-b-plus.txt \
$(1)/lib/firmware/brcm/
$(LN) \
brcmfmac43455-sdio.raspberrypi,3-model-b-plus.txt \
$(1)/lib/firmware/brcm/brcmfmac43455-sdio.raspberrypi,3-model-a-plus.txt
$(INSTALL_DATA) \
$(PKG_BUILD_DIR)/brcm/brcmfmac43455-sdio.raspberrypi,4-model-b.txt \
$(1)/lib/firmware/brcm/
$(LN) \
brcmfmac43455-sdio.raspberrypi,4-model-b.txt \
$(1)/lib/firmware/brcm/brcmfmac43455-sdio.raspberrypi,4-compute-module.txt
$(LN) \
brcmfmac43455-sdio.raspberrypi,4-model-b.txt \
$(1)/lib/firmware/brcm/brcmfmac43455-sdio.Raspberry\ Pi\ Foundation-Raspberry\ Pi\ 4\ Model\ B.txt
$(LN) \
brcmfmac43455-sdio.raspberrypi,4-model-b.txt \
$(1)/lib/firmware/brcm/brcmfmac43455-sdio.raspberry,5-model-b.txt
$(LN) \
brcmfmac43455-sdio.raspberrypi,4-model-b.txt \
$(1)/lib/firmware/brcm/brcmfmac43455-sdio.Raspberry\ Pi\ Foundation-Raspberry\ Pi\ 5\ Model\ B.txt
$(LN) \
brcmfmac43455-sdio.raspberrypi,4-model-b.txt \
$(1)/lib/firmware/brcm/brcmfmac43455-sdio.Raspberry\ Pi\ Foundation-Raspberry\ Pi\ Compute\ Module\ 4.txt
$(INSTALL_DATA) \
$(PKG_BUILD_DIR)/brcm/brcmfmac43455-sdio.MINIX-NEO\ Z83-4.txt \
$(1)/lib/firmware/brcm/
$(INSTALL_DATA) \
$(PKG_BUILD_DIR)/brcm/brcmfmac43455-sdio.AW-CM256SM.txt \
$(1)/lib/firmware/brcm/
$(LN) \
brcmfmac43455-sdio.AW-CM256SM.txt \
$(1)/lib/firmware/brcm/brcmfmac43455-sdio.beagle,am5729-beagleboneai.txt
$(LN) \
brcmfmac43455-sdio.AW-CM256SM.txt \
$(1)/lib/firmware/brcm/brcmfmac43455-sdio.pine64,pinebook-pro.txt
$(LN) \
brcmfmac43455-sdio.AW-CM256SM.txt \
$(1)/lib/firmware/brcm/brcmfmac43455-sdio.pine64,pinephone-pro.txt
$(LN) \
brcmfmac43455-sdio.AW-CM256SM.txt \
$(1)/lib/firmware/brcm/brcmfmac43455-sdio.pine64,quartz64-b.txt
endef
$(eval $(call BuildPackage,brcmfmac-nvram-43455-sdio))
Package/brcmfmac-nvram-4356-sdio = $(call Package/firmware-default,Broadcom BCM4356 SDIO NVRAM)
define Package/brcmfmac-nvram-4356-sdio/install
$(INSTALL_DIR) $(1)/lib/firmware/brcm
$(INSTALL_DATA) \
$(PKG_BUILD_DIR)/brcm/brcmfmac4356-sdio.AP6356S.txt \
$(1)/lib/firmware/brcm/
$(LN) \
brcmfmac4356-sdio.AP6356S.txt \
$(1)/lib/firmware/brcm/brcmfmac4356-sdio.friendlyarm,nanopc-t4.txt
endef
$(eval $(call BuildPackage,brcmfmac-nvram-4356-sdio))
Package/brcmfmac-firmware-usb = $(call Package/firmware-default,Broadcom BCM43xx fullmac USB firmware)
define Package/brcmfmac-firmware-usb/install
$(INSTALL_DIR) $(1)/lib/firmware/brcm
$(INSTALL_DATA) \
$(PKG_BUILD_DIR)/brcm/brcmfmac43236b.bin \
$(1)/lib/firmware/brcm/
$(INSTALL_DATA) \
$(PKG_BUILD_DIR)/brcm/brcmfmac43143.bin \
$(1)/lib/firmware/brcm/
endef
$(eval $(call BuildPackage,brcmfmac-firmware-usb))
Package/brcmsmac-firmware = $(call Package/firmware-default,Broadcom BCM43xx softmac PCIe firmware)
define Package/brcmsmac-firmware/install
$(INSTALL_DIR) $(1)/lib/firmware/brcm
$(INSTALL_DATA) \
$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/brcm/bcm43xx-0.fw \
$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/brcm/bcm43xx_hdr-0.fw \
$(1)/lib/firmware/brcm/
endef
$(eval $(call BuildPackage,brcmsmac-firmware))
Package/bnx2-firmware = $(call Package/firmware-default,Broadcom BCM5706/5708/5709/5716 firmware)
define Package/bnx2-firmware/install
$(INSTALL_DIR) $(1)/lib/firmware/bnx2
$(INSTALL_DATA) \
$(PKG_BUILD_DIR)/bnx2/* \
$(1)/lib/firmware/bnx2/
endef
$(eval $(call BuildPackage,bnx2-firmware))
Package/bnx2x-firmware = $(call Package/firmware-default,=QLogic 5771x/578xx firmware)
define Package/bnx2x-firmware/install
$(INSTALL_DIR) $(1)/lib/firmware/bnx2x
$(INSTALL_DATA) \
$(PKG_BUILD_DIR)/bnx2x/* \
$(1)/lib/firmware/bnx2x/
endef
$(eval $(call BuildPackage,bnx2x-firmware))

View file

@ -0,0 +1,185 @@
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=bcm27xx-gpu-fw
PKG_VERSION:=2023-10-19
PKG_RELEASE:=ce3a0b4197eaf311ba0734efdb9f5bdedefe5e27
PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)/rpi-firmware-$(PKG_RELEASE)
PKG_FLAGS:=nonshared
include $(INCLUDE_DIR)/package.mk
RPI_FIRMWARE_URL:=@GITHUB/raspberrypi/firmware/$(PKG_RELEASE)/boot/
RPI_FIRMWARE_FILE:=rpi-firmware-$(PKG_RELEASE)
define Download/LICENCE_broadcom
FILE:=$(RPI_FIRMWARE_FILE)-LICENCE.broadcom
URL:=$(RPI_FIRMWARE_URL)
URL_FILE:=LICENCE.broadcom
HASH:=c7283ff51f863d93a275c66e3b4cb08021a5dd4d8c1e7acc47d872fbe52d3d6b
endef
$(eval $(call Download,LICENCE_broadcom))
define Download/bootcode_bin
FILE:=$(RPI_FIRMWARE_FILE)-bootcode.bin
URL:=$(RPI_FIRMWARE_URL)
URL_FILE:=bootcode.bin
HASH:=af603ebd97e7b692c30195563f7b25656eb05d57838cf1a715ebb470d1614ce4
endef
$(eval $(call Download,bootcode_bin))
define Download/fixup_dat
FILE:=$(RPI_FIRMWARE_FILE)-fixup.dat
URL:=$(RPI_FIRMWARE_URL)
URL_FILE:=fixup.dat
HASH:=c28ea955e672e374016dca61d63afa026490f0473a98115908586ab48e324aeb
endef
$(eval $(call Download,fixup_dat))
define Download/fixup_cd_dat
FILE:=$(RPI_FIRMWARE_FILE)-fixup_cd.dat
URL:=$(RPI_FIRMWARE_URL)
URL_FILE:=fixup_cd.dat
HASH:=3cf1aef5f596ca106203ed5dac9ad45e85929ec55ce44c813588645e174442ec
endef
$(eval $(call Download,fixup_cd_dat))
define Download/fixup_x_dat
FILE:=$(RPI_FIRMWARE_FILE)-fixup_x.dat
URL:=$(RPI_FIRMWARE_URL)
URL_FILE:=fixup_x.dat
HASH:=56525c8feabde1ab86f36bb09bc55171659b2993f94132cf81ffc4293d62269d
endef
$(eval $(call Download,fixup_x_dat))
define Download/fixup4_dat
FILE:=$(RPI_FIRMWARE_FILE)-fixup4.dat
URL:=$(RPI_FIRMWARE_URL)
URL_FILE:=fixup4.dat
HASH:=615f8595801bf52373039f73ad5ad9513f83400d355eb1b2c075c7ae907e927c
endef
$(eval $(call Download,fixup4_dat))
define Download/fixup4cd_dat
FILE:=$(RPI_FIRMWARE_FILE)-fixup4cd.dat
URL:=$(RPI_FIRMWARE_URL)
URL_FILE:=fixup4cd.dat
HASH:=3cf1aef5f596ca106203ed5dac9ad45e85929ec55ce44c813588645e174442ec
endef
$(eval $(call Download,fixup4cd_dat))
define Download/fixup4x_dat
FILE:=$(RPI_FIRMWARE_FILE)-fixup4x.dat
URL:=$(RPI_FIRMWARE_URL)
URL_FILE:=fixup4x.dat
HASH:=6d27a4b8ecb78cef9e1f03751b4aaec5ce8749d36988f381145a8a41dbf164ae
endef
$(eval $(call Download,fixup4x_dat))
define Download/start_elf
FILE:=$(RPI_FIRMWARE_FILE)-start.elf
URL:=$(RPI_FIRMWARE_URL)
URL_FILE:=start.elf
HASH:=e8348e88522e7a1d0e2b0944ab66d7d8f4f30da98f326e2b3c123522e45f71b2
endef
$(eval $(call Download,start_elf))
define Download/start_cd_elf
FILE:=$(RPI_FIRMWARE_FILE)-start_cd.elf
URL:=$(RPI_FIRMWARE_URL)
URL_FILE:=start_cd.elf
HASH:=c9b4de3f12bec7808868b898c49f656b5378ddc315f12ccab83d6519bad51680
endef
$(eval $(call Download,start_cd_elf))
define Download/start_x_elf
FILE:=$(RPI_FIRMWARE_FILE)-start_x.elf
URL:=$(RPI_FIRMWARE_URL)
URL_FILE:=start_x.elf
HASH:=0b5c06c109984361eeed0ab14d146f686d8aa8da2025689b887e9cb098636db9
endef
$(eval $(call Download,start_x_elf))
define Download/start4_elf
FILE:=$(RPI_FIRMWARE_FILE)-start4.elf
URL:=$(RPI_FIRMWARE_URL)
URL_FILE:=start4.elf
HASH:=fedc4ecd72c9d21018e210240dcd2e41a8bb5f936fb5674c3351f2a447a22203
endef
$(eval $(call Download,start4_elf))
define Download/start4cd_elf
FILE:=$(RPI_FIRMWARE_FILE)-start4cd.elf
URL:=$(RPI_FIRMWARE_URL)
URL_FILE:=start4cd.elf
HASH:=ea22282a77666801378137a651e7e0b17cc186f63cdbdc8b9bb98749cd12b256
endef
$(eval $(call Download,start4cd_elf))
define Download/start4x_elf
FILE:=$(RPI_FIRMWARE_FILE)-start4x.elf
URL:=$(RPI_FIRMWARE_URL)
URL_FILE:=start4x.elf
HASH:=c509e73a9cba7af3223dea885f58294bd04845e822aa3d6278500fa4dcdb112f
endef
$(eval $(call Download,start4x_elf))
define Package/bcm27xx-gpu-fw
SECTION:=boot
CATEGORY:=Boot Loaders
DEPENDS:=@TARGET_bcm27xx
TITLE:=bcm27xx-gpu-fw
DEFAULT:=y if TARGET_bcm27xx
endef
define Package/bcm27xx-gpu-fw/description
GPU and kernel boot firmware for bcm27xx.
endef
define Build/Prepare
rm -rf $(PKG_BUILD_DIR)
mkdir -p $(PKG_BUILD_DIR)
$(CP) $(DL_DIR)/$(RPI_FIRMWARE_FILE)-LICENCE.broadcom $(PKG_BUILD_DIR)/LICENCE.broadcom
$(CP) $(DL_DIR)/$(RPI_FIRMWARE_FILE)-bootcode.bin $(PKG_BUILD_DIR)/bootcode.bin
$(CP) $(DL_DIR)/$(RPI_FIRMWARE_FILE)-fixup.dat $(PKG_BUILD_DIR)/fixup.dat
$(CP) $(DL_DIR)/$(RPI_FIRMWARE_FILE)-fixup_cd.dat $(PKG_BUILD_DIR)/fixup_cd.dat
$(CP) $(DL_DIR)/$(RPI_FIRMWARE_FILE)-fixup_x.dat $(PKG_BUILD_DIR)/fixup_x.dat
$(CP) $(DL_DIR)/$(RPI_FIRMWARE_FILE)-fixup4.dat $(PKG_BUILD_DIR)/fixup4.dat
$(CP) $(DL_DIR)/$(RPI_FIRMWARE_FILE)-fixup4cd.dat $(PKG_BUILD_DIR)/fixup4cd.dat
$(CP) $(DL_DIR)/$(RPI_FIRMWARE_FILE)-fixup4x.dat $(PKG_BUILD_DIR)/fixup4x.dat
$(CP) $(DL_DIR)/$(RPI_FIRMWARE_FILE)-start.elf $(PKG_BUILD_DIR)/start.elf
$(CP) $(DL_DIR)/$(RPI_FIRMWARE_FILE)-start_cd.elf $(PKG_BUILD_DIR)/start_cd.elf
$(CP) $(DL_DIR)/$(RPI_FIRMWARE_FILE)-start_x.elf $(PKG_BUILD_DIR)/start_x.elf
$(CP) $(DL_DIR)/$(RPI_FIRMWARE_FILE)-start4.elf $(PKG_BUILD_DIR)/start4.elf
$(CP) $(DL_DIR)/$(RPI_FIRMWARE_FILE)-start4cd.elf $(PKG_BUILD_DIR)/start4cd.elf
$(CP) $(DL_DIR)/$(RPI_FIRMWARE_FILE)-start4x.elf $(PKG_BUILD_DIR)/start4x.elf
endef
define Build/Compile
true
endef
define Package/bcm27xx-gpu-fw/install
true
endef
define Build/InstallDev
$(CP) $(PKG_BUILD_DIR)/bootcode.bin $(KERNEL_BUILD_DIR)
$(CP) $(PKG_BUILD_DIR)/LICENCE.broadcom $(KERNEL_BUILD_DIR)
$(CP) $(PKG_BUILD_DIR)/start.elf $(KERNEL_BUILD_DIR)
$(CP) $(PKG_BUILD_DIR)/start_cd.elf $(KERNEL_BUILD_DIR)
$(CP) $(PKG_BUILD_DIR)/start_x.elf $(KERNEL_BUILD_DIR)
$(CP) $(PKG_BUILD_DIR)/start4.elf $(KERNEL_BUILD_DIR)
$(CP) $(PKG_BUILD_DIR)/start4cd.elf $(KERNEL_BUILD_DIR)
$(CP) $(PKG_BUILD_DIR)/start4x.elf $(KERNEL_BUILD_DIR)
$(CP) $(PKG_BUILD_DIR)/fixup.dat $(KERNEL_BUILD_DIR)
$(CP) $(PKG_BUILD_DIR)/fixup_cd.dat $(KERNEL_BUILD_DIR)
$(CP) $(PKG_BUILD_DIR)/fixup_x.dat $(KERNEL_BUILD_DIR)
$(CP) $(PKG_BUILD_DIR)/fixup4.dat $(KERNEL_BUILD_DIR)
$(CP) $(PKG_BUILD_DIR)/fixup4cd.dat $(KERNEL_BUILD_DIR)
$(CP) $(PKG_BUILD_DIR)/fixup4x.dat $(KERNEL_BUILD_DIR)
endef
$(eval $(call BuildPackage,bcm27xx-gpu-fw))

View file

@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk
ARCH:=arm
BOARD:=bcm27xx
BOARDNAME:=Broadcom BCM27xx
FEATURES:=audio boot-part display ext4 fpu gpio rootfs-part rtc squashfs usb usbgadget
FEATURES:=audio boot-part display ext4 fpu gpio rootfs-part rtc squashfs usb usbgadget pci pcie
SUBTARGETS:=bcm2708 bcm2709 bcm2710 bcm2711 bcm2712
KERNEL_PATCHVER:=6.1
@ -24,9 +24,9 @@ DEFAULT_PACKAGES := $(filter-out urngd,$(DEFAULT_PACKAGES))
DEFAULT_PACKAGES += \
bcm27xx-gpu-fw \
kmod-usb-hid \
kmod-sound-core kmod-sound-arm-bcm2835 \
kmod-fs-vfat kmod-nls-cp437 kmod-nls-iso8859-1 \
partx-utils mkf2fs e2fsprogs
# kmod-sound-core kmod-sound-arm-bcm2835 \
KERNELNAME:=Image dtbs

View file

@ -0,0 +1,35 @@
# Copyright (C) 2014-2016 OpenWrt.org
# Copyright (C) 2017 LEDE project
. /lib/functions/uci-defaults.sh
. /lib/functions.sh
. /lib/functions/system.sh
board_config_update
board=$(board_name)
case "$board" in
raspberrypi,2-model-b |\
raspberrypi,2-model-b-rev2 |\
raspberrypi,3-model-b |\
raspberrypi,3-model-b-plus |\
raspberrypi,400 |\
raspberrypi,4-compute-module |\
raspberrypi,4-model-b |\
raspberrypi,5-model-b |\
raspberrypi,model-b |\
raspberrypi,model-b-plus |\
raspberrypi,model-b-rev2)
ucidef_set_interface_lan "eth0"
;;
raspberrypi,model-zero-2 |\
raspberrypi,model-zero-w)
ucidef_set_interface_lan "wlan0"
;;
esac
board_config_flush
exit 0

View file

@ -0,0 +1,44 @@
#!/bin/sh
# Copyright (C) 2015-2016 OpenWrt.org
# Copyright (C) 2017 LEDE project
. /lib/functions.sh
. /lib/functions/leds.sh
set_state() {
case "$(board_name)" in
raspberrypi,2-model-b |\
raspberrypi,2-model-b-rev2 |\
raspberrypi,3-model-b |\
raspberrypi,3-model-b-plus |\
raspberrypi,400 |\
raspberrypi,4-compute-module |\
raspberrypi,4-model-b |\
raspberrypi,5-model-b |\
raspberrypi,model-b-plus)
status_led="led1"
;;
raspberrypi,3-compute-module |\
raspberrypi,model-b |\
raspberrypi,model-zero |\
raspberrypi,model-zero-2 |\
raspberrypi,model-zero-w)
status_led="led0"
;;
esac
case "$1" in
preinit)
status_led_blink_preinit
;;
failsafe)
status_led_blink_failsafe
;;
preinit_regular)
status_led_blink_preinit_regular
;;
done)
status_led_on
;;
esac
}

View file

@ -4,6 +4,7 @@ CONFIG_APERTURE_HELPERS=y
CONFIG_ARCH_BCM=y
CONFIG_ARCH_BCM2835=y
CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS=y
CONFIG_ARCH_BRCMSTB=y
CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y
CONFIG_ARCH_DMA_ADDR_T_64BIT=y
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
@ -47,28 +48,45 @@ CONFIG_ARM_AMBA=y
CONFIG_ARM_ARCH_TIMER=y
CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y
CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND=y
CONFIG_ARM_BRCMSTB_AVS_CPUFREQ=y
CONFIG_ARM_GIC=y
CONFIG_ARM_GIC_V2M=y
CONFIG_ARM_GIC_V3=y
CONFIG_ARM_GIC_V3_ITS=y
CONFIG_ARM_GIC_V3_ITS_PCI=y
# CONFIG_ARM_MHU_V2 is not set
# CONFIG_ARM_PL172_MPMC is not set
CONFIG_ARM_PSCI_FW=y
CONFIG_ARM_RASPBERRYPI_CPUFREQ=y
# CONFIG_ARM_SMMU is not set
# CONFIG_ARM_SMMU_V3 is not set
CONFIG_ARM_TIMER_SP804=y
CONFIG_ASSOCIATIVE_ARRAY=y
CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y
CONFIG_BCM2708_VCMEM=y
CONFIG_BCM2711_THERMAL=y
CONFIG_BCM2835_DEVGPIOMEM=y
CONFIG_BCM2712_IOMMU=y
CONFIG_BCM2712_MIP=y
CONFIG_BCM2835_MBOX=y
CONFIG_BCM2835_POWER=y
# CONFIG_BCM2835_SMI is not set
# CONFIG_BCM2835_THERMAL is not set
CONFIG_BCM2835_SMI=y
CONFIG_BCM2835_SMI_DEV=m
CONFIG_BCM2835_THERMAL=y
CONFIG_BCM2835_VCHIQ=y
# CONFIG_BCM2835_VCHIQ_MMAL is not set
CONFIG_BCM2835_WDT=y
CONFIG_BCM7038_L1_IRQ=y
CONFIG_BCM7120_L2_IRQ=y
CONFIG_BCM7XXX_PHY=y
CONFIG_BCMA=y
CONFIG_BCMA_BLOCKIO=y
# CONFIG_BCMA_DEBUG is not set
# CONFIG_BCMA_DRIVER_GMAC_CMN is not set
CONFIG_BCMA_DRIVER_PCI=y
CONFIG_BCMA_FALLBACK_SPROM=y
CONFIG_BCMA_HOST_PCI=y
CONFIG_BCMA_HOST_PCI_POSSIBLE=y
# CONFIG_BCMA_HOST_SOC is not set
CONFIG_BCMGENET=y
CONFIG_BCM_NET_PHYLIB=y
CONFIG_BCM_VCIO=y
@ -76,14 +94,20 @@ CONFIG_BCM_VCIO=y
CONFIG_BCM_VIDEOCORE=y
# CONFIG_BLK_DEV_INITRD is not set
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_NVME=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_SD=y
CONFIG_BLK_MQ_PCI=y
CONFIG_BLK_PM=y
CONFIG_BRCMSTB_DPFE=y
CONFIG_BRCMSTB_L2_IRQ=y
CONFIG_BRCMSTB_MEMC=y
CONFIG_BRCMSTB_PM=y
# CONFIG_BRCMSTB_THERMAL is not set
CONFIG_BRCM_CHAR_DRIVERS=y
CONFIG_BRCM_USB_PINMAP=y
CONFIG_BROADCOM_PHY=y
CONFIG_CAVIUM_ERRATUM_22375=y
CONFIG_CAVIUM_ERRATUM_23154=y
@ -109,6 +133,8 @@ CONFIG_CMA_SIZE_SEL_MBYTES=y
# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set
# CONFIG_CMA_SYSFS is not set
CONFIG_COMMON_CLK=y
CONFIG_COMMON_CLK_RP1=y
# CONFIG_COMMON_CLK_RP1_SDIO is not set
CONFIG_COMMON_CLK_XGENE=y
CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1
# CONFIG_COMPAT_32BIT_TIME is not set
@ -140,6 +166,9 @@ CONFIG_CPU_RMAP=y
CONFIG_CRC16=y
CONFIG_CRYPTO_AES_ARM64=y
CONFIG_CRYPTO_AES_ARM64_BS=y
CONFIG_CRYPTO_AES_ARM64_CE=y
CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_CRC32=y
@ -150,23 +179,32 @@ CONFIG_CRYPTO_DRBG=y
CONFIG_CRYPTO_DRBG_HMAC=y
CONFIG_CRYPTO_DRBG_MENU=y
CONFIG_CRYPTO_ECB=y
CONFIG_CRYPTO_GHASH_ARM64_CE=y
CONFIG_CRYPTO_HMAC=y
CONFIG_CRYPTO_JITTERENTROPY=y
CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
CONFIG_CRYPTO_LIB_SHA1=y
CONFIG_CRYPTO_LIB_SHA256=y
CONFIG_CRYPTO_LIB_UTILS=y
# CONFIG_CRYPTO_POLYVAL_ARM64_CE is not set
CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_RNG_DEFAULT=y
CONFIG_CRYPTO_SEQIV=y
CONFIG_CRYPTO_SHA1=y
CONFIG_CRYPTO_SHA1_ARM64_CE=y
CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_SHA256_ARM64=y
CONFIG_CRYPTO_SHA2_ARM64_CE=y
CONFIG_CRYPTO_SHA3=y
CONFIG_CRYPTO_SHA3_ARM64=y
CONFIG_CRYPTO_SHA512=y
CONFIG_CRYPTO_SHA512_ARM64=y
# CONFIG_CRYPTO_SM4_ARM64_CE_BLK is not set
# CONFIG_CRYPTO_SM4_ARM64_NEON_BLK is not set
CONFIG_CRYPTO_SHA512_ARM64_CE=y
CONFIG_CRYPTO_SM3=y
CONFIG_CRYPTO_SM3_ARM64_CE=y
CONFIG_CRYPTO_SM4=y
CONFIG_CRYPTO_SM4_ARM64_CE=y
CONFIG_CRYPTO_SM4_ARM64_CE_BLK=y
CONFIG_CRYPTO_XTS=y
CONFIG_DCACHE_WORD_ACCESS=y
CONFIG_DEBUG_BUGVERBOSE=y
@ -182,6 +220,7 @@ CONFIG_DMA_CMA=y
CONFIG_DMA_DIRECT_REMAP=y
CONFIG_DMA_ENGINE=y
CONFIG_DMA_OF=y
CONFIG_DMA_OPS=y
CONFIG_DMA_SHARED_BUFFER=y
CONFIG_DMA_VIRTUAL_CHANNELS=y
CONFIG_DNOTIFY=y
@ -239,6 +278,7 @@ CONFIG_GENERIC_IDLE_POLL_SETUP=y
CONFIG_GENERIC_IOREMAP=y
CONFIG_GENERIC_IRQ_CHIP=y
CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
CONFIG_GENERIC_IRQ_INJECTION=y
CONFIG_GENERIC_IRQ_MIGRATION=y
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
@ -255,32 +295,58 @@ CONFIG_GENERIC_SMP_IDLE_THREAD=y
CONFIG_GENERIC_STRNCPY_FROM_USER=y
CONFIG_GENERIC_STRNLEN_USER=y
CONFIG_GENERIC_TIME_VSYSCALL=y
CONFIG_GLOB=y
CONFIG_GPIOLIB_IRQCHIP=y
CONFIG_GPIO_BCM_VIRT=y
CONFIG_GPIO_BRCMSTB=y
CONFIG_GPIO_CDEV=y
# CONFIG_GPIO_FSM is not set
CONFIG_GPIO_GENERIC=y
CONFIG_GPIO_RASPBERRYPI_EXP=y
CONFIG_HARDIRQS_SW_RESEND=y
CONFIG_HAS_DMA=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT_MAP=y
CONFIG_HOTPLUG_CPU=y
CONFIG_HOTPLUG_PCI=y
# CONFIG_HOTPLUG_PCI_CPCI is not set
# CONFIG_HOTPLUG_PCI_PCIE is not set
CONFIG_HOTPLUG_PCI_SHPC=y
CONFIG_HWMON=y
CONFIG_HW_CONSOLE=y
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_IPROC_RNG200=y
CONFIG_I2C=y
CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_BCM2708 is not set
CONFIG_I2C_BCM2835=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_BRCMSTB=y
CONFIG_I2C_DESIGNWARE_CORE=y
CONFIG_I2C_DESIGNWARE_PLATFORM=y
CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
CONFIG_INPUT=y
CONFIG_INPUT_MOUSEDEV=y
# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
CONFIG_INPUT_RASPBERRYPI_BUTTON=y
CONFIG_IOMMU_API=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
CONFIG_IOMMU_DEFAULT_DMA_STRICT=y
# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_IOVA=y
# CONFIG_IOMMU_IO_PGTABLE_ARMV7S is not set
# CONFIG_IOMMU_IO_PGTABLE_DART is not set
# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set
CONFIG_IOMMU_SUPPORT=y
CONFIG_IRQCHIP=y
CONFIG_IRQ_DOMAIN=y
CONFIG_IRQ_DOMAIN_HIERARCHY=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_IRQ_MSI_IOMMU=y
CONFIG_IRQ_WORK=y
CONFIG_JBD2=y
CONFIG_KEYS=y
@ -295,6 +361,9 @@ CONFIG_LOGO=y
CONFIG_LOGO_LINUX_CLUT224=y
# CONFIG_LOGO_LINUX_MONO is not set
# CONFIG_LOGO_LINUX_VGA16 is not set
CONFIG_MACB=y
CONFIG_MACB_PCI=y
CONFIG_MACB_USE_HWSTAMP=y
CONFIG_MAC_PARTITION=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_MAILBOX=y
@ -304,11 +373,14 @@ CONFIG_MDIO_BUS=y
CONFIG_MDIO_DEVICE=y
CONFIG_MDIO_DEVRES=y
CONFIG_MEMFD_CREATE=y
CONFIG_MEMORY=y
CONFIG_MEMORY_ISOLATION=y
CONFIG_MFD_CORE=y
# CONFIG_MFD_RASPBERRYPI_POE_HAT is not set
CONFIG_MFD_RP1=y
# CONFIG_MFD_RPISENSE_CORE is not set
CONFIG_MFD_RASPBERRYPI_POE_HAT=y
CONFIG_MFD_SYSCON=y
CONFIG_MICROCHIP_PHY=y
CONFIG_MIGRATION=y
CONFIG_MMC=y
# CONFIG_MMC_BCM2835 is not set
@ -318,13 +390,15 @@ CONFIG_MMC_BCM2835_PIO_DMA_BARRIER=2
CONFIG_MMC_BCM2835_SDHOST=y
CONFIG_MMC_BLOCK=y
CONFIG_MMC_BLOCK_MINORS=32
CONFIG_MMC_CQHCI=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_BRCMSTB=y
CONFIG_MMC_SDHCI_IO_ACCESSORS=y
CONFIG_MMC_SDHCI_IPROC=y
CONFIG_MMC_SDHCI_OF_DWCMSHC=y
# CONFIG_MMC_SDHCI_PCI is not set
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MODULES_USE_ELF_RELA=y
# CONFIG_MTD is not set
CONFIG_MUTEX_SPIN_ON_OWNER=y
CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_NEED_SG_DMA_LENGTH=y
@ -339,6 +413,9 @@ CONFIG_NO_HZ_COMMON=y
CONFIG_NO_HZ_IDLE=y
CONFIG_NR_CPUS=4
CONFIG_NVMEM=y
CONFIG_NVME_CORE=y
# CONFIG_NVME_HWMON is not set
# CONFIG_NVME_MULTIPATH is not set
CONFIG_OF=y
CONFIG_OF_ADDRESS=y
CONFIG_OF_CONFIGFS=y
@ -346,6 +423,7 @@ CONFIG_OF_DYNAMIC=y
CONFIG_OF_EARLY_FLATTREE=y
CONFIG_OF_FLATTREE=y
CONFIG_OF_GPIO=y
CONFIG_OF_IOMMU=y
CONFIG_OF_IRQ=y
CONFIG_OF_KOBJ=y
CONFIG_OF_MDIO=y
@ -358,18 +436,38 @@ CONFIG_PAGE_SIZE_LESS_THAN_64KB=y
CONFIG_PARTITION_PERCPU=y
CONFIG_PCI=y
CONFIG_PCIEAER=y
CONFIG_PCIEAER_INJECT=y
CONFIG_PCIEASPM=y
# CONFIG_PCIEASPM_DEFAULT is not set
# CONFIG_PCIEASPM_PERFORMANCE is not set
# CONFIG_PCIEASPM_POWERSAVE is not set
CONFIG_PCIEASPM_POWER_SUPERSAVE=y
CONFIG_PCIEPORTBUS=y
CONFIG_PCIE_BRCMSTB=y
CONFIG_PCIE_DW=y
CONFIG_PCIE_DW_HOST=y
CONFIG_PCIE_DW_PLAT=y
CONFIG_PCIE_DW_PLAT_HOST=y
CONFIG_PCIE_MICROCHIP_HOST=y
CONFIG_PCIE_PME=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCI_DOMAINS_GENERIC=y
CONFIG_PCI_ECAM=y
CONFIG_PCI_HOST_COMMON=y
CONFIG_PCI_HOST_GENERIC=y
CONFIG_PCI_MSI=y
CONFIG_PCI_MSI_IRQ_DOMAIN=y
CONFIG_PCI_STUB=y
CONFIG_PGTABLE_LEVELS=3
CONFIG_PHYLIB=y
CONFIG_PHYLINK=y
CONFIG_PHYS_ADDR_T_64BIT=y
# CONFIG_PHY_BRCM_SATA is not set
CONFIG_PHY_BRCM_USB=y
CONFIG_PINCTRL=y
CONFIG_PINCTRL_BCM2712=y
CONFIG_PINCTRL_BCM2835=y
CONFIG_PINCTRL_RP1=y
CONFIG_PM=y
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
@ -378,7 +476,6 @@ CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
CONFIG_PM_OPP=y
CONFIG_PM_SLEEP=y
CONFIG_PM_SLEEP_SMP=y
# CONFIG_PM_USERSPACE_AUTOSLEEP is not set
CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y
CONFIG_POWER_RESET=y
CONFIG_POWER_SUPPLY=y
@ -389,12 +486,15 @@ CONFIG_PTP_1588_CLOCK=y
CONFIG_PTP_1588_CLOCK_OPTIONAL=y
CONFIG_PWM=y
CONFIG_PWM_BCM2835=y
CONFIG_PWM_BRCMSTB=y
CONFIG_PWM_RP1=y
CONFIG_PWM_SYSFS=y
CONFIG_QUEUED_RWLOCKS=y
CONFIG_QUEUED_SPINLOCKS=y
CONFIG_RANDSTRUCT_NONE=y
CONFIG_RAS=y
CONFIG_RASPBERRYPI_FIRMWARE=y
CONFIG_RASPBERRYPI_GPIOMEM=y
CONFIG_RASPBERRYPI_POWER=y
CONFIG_RATIONAL=y
# CONFIG_RAVE_SP_CORE is not set
@ -403,6 +503,8 @@ CONFIG_REGMAP_MMIO=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_GPIO=y
CONFIG_RESET_BRCMSTB=y
CONFIG_RESET_BRCMSTB_RESCAL=y
CONFIG_RESET_CONTROLLER=y
CONFIG_RESET_RASPBERRYPI=y
CONFIG_RESET_SIMPLE=y
@ -411,12 +513,19 @@ CONFIG_RODATA_FULL_DEFAULT_ENABLED=y
# CONFIG_RPIVID_MEM is not set
# CONFIG_RPI_POE_POWER is not set
CONFIG_RPS=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_BRCMSTB=y
CONFIG_RTC_DRV_RPI=y
CONFIG_RTC_I2C_AND_SPI=y
CONFIG_RWSEM_SPIN_ON_OWNER=y
CONFIG_SCSI=y
CONFIG_SCSI_COMMON=y
# CONFIG_SCSI_LOWLEVEL is not set
# CONFIG_SCSI_PROC_FS is not set
CONFIG_SENSORS_RASPBERRYPI_HWMON=y
CONFIG_SENSORS_RP1_ADC=y
CONFIG_SERIAL_8250_BCM2835AUX=y
CONFIG_SERIAL_8250_BCM7271=y
# CONFIG_SERIAL_8250_DMA is not set
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_FSL=y
@ -431,7 +540,10 @@ CONFIG_SERIAL_MCTRL_GPIO=y
CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_SG_POOL=y
CONFIG_SMP=y
CONFIG_SMSC_PHY=y
CONFIG_SOCK_RX_QUEUE_MAPPING=y
CONFIG_SOC_BRCMSTB=y
CONFIG_SOC_BUS=y
CONFIG_SOFTIRQ_ON_OWN_STACK=y
CONFIG_SPARSEMEM=y
CONFIG_SPARSEMEM_EXTREME=y
@ -460,14 +572,17 @@ CONFIG_TMPFS_POSIX_ACL=y
CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y
CONFIG_TREE_RCU=y
CONFIG_TREE_SRCU=y
# CONFIG_UACCE is not set
# CONFIG_UCLAMP_TASK is not set
CONFIG_UEVENT_HELPER_PATH=""
CONFIG_UNMAP_KERNEL_AT_EL0=y
CONFIG_USB=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
# CONFIG_USB_BRCMSTB is not set
CONFIG_USB_COMMON=y
CONFIG_USB_DWCOTG=y
CONFIG_USB_GADGET=y
# CONFIG_USB_HCD_BCMA is not set
CONFIG_USB_PCI=y
CONFIG_USB_PHY=y
CONFIG_USB_STORAGE=y
@ -488,19 +603,5 @@ CONFIG_XPS=y
CONFIG_XZ_DEC_ARM=y
CONFIG_XZ_DEC_BCJ=y
CONFIG_ZONE_DMA32=y
CONFIG_INPUT_RASPBERRYPI_BUTTON=y
CONFIG_RASPBERRYPI_GPIOMEM=y
CONFIG_PINCTRL_RP1=y
CONFIG_MFD_RP1=y
CONFIG_DRM_RP1_DSI=m
CONFIG_DRM_RP1_DPI=m
CONFIG_DRM_RP1_VEC=m
CONFIG_COMMON_CLK_RP1=y
CONFIG_COMMON_CLK_RP1_SDIO=y
CONFIG_PWM_RP1=y
CONFIG_SENSORS_RP1_ADC=m
CONFIG_BCM2712_MIP=y
CONFIG_RESET_BRCMSTB=y
CONFIG_PHY_BRCM_USB=y
CONFIG_PINCTRL_BCM2712=y
CONFIG_GPIO_BRCMSTB=y
# CONFIG_SND_BCM2835_SOC_I2S is not set
# CONFIG_SND_BCM2835 is not set

View file

@ -193,12 +193,9 @@ define Device/rpi-5
cypress-firmware-43455-sdio \
brcmfmac-nvram-43455-sdio \
kmod-brcmfmac wpad-basic-mbedtls \
kmod-usb-net-lan78xx \
kmod-r8169
# IMAGE/sysupgrade.img.gz := boot-common | boot-2712 | sdcard-img | gzip | append-metadata
# IMAGE/factory.img.gz := boot-common | boot-2712 | sdcard-img | gzip
IMAGE/sysupgrade.img.gz := boot-common | sdcard-img | gzip | append-metadata
IMAGE/factory.img.gz := boot-common | sdcard-img | gzip
kmod-usb-dwc3 kmod-hwmon-pwfan kmod-usb3
IMAGE/sysupgrade.img.gz := boot-common | boot-2712 | sdcard-img | gzip | append-metadata
IMAGE/factory.img.gz := boot-common | boot-2712 | sdcard-img | gzip
endef
ifeq ($(SUBTARGET),bcm2712)
TARGET_DEVICES += rpi-5

View file

@ -0,0 +1,69 @@
From 2b0d70ec4fba339947992252c949c8cbd9be04af Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.com>
Date: Tue, 10 Oct 2023 14:49:50 +0100
Subject: [PATCH] Revert "Revert "xhci: add quirk for host controllers that
don't update endpoint DCS""
This reverts commit 96a0b80eb1b02e1330d525d4c866ccdfa8c67434.
---
drivers/usb/host/xhci-pci.c | 4 +++-
drivers/usb/host/xhci-ring.c | 25 ++++++++++++++++++++++++-
2 files changed, 27 insertions(+), 2 deletions(-)
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -293,8 +293,10 @@ static void xhci_pci_quirks(struct devic
pdev->device == 0x3432)
xhci->quirks |= XHCI_BROKEN_STREAMS;
- if (pdev->vendor == PCI_VENDOR_ID_VIA && pdev->device == 0x3483)
+ if (pdev->vendor == PCI_VENDOR_ID_VIA && pdev->device == 0x3483) {
xhci->quirks |= XHCI_LPM_SUPPORT;
+ xhci->quirks |= XHCI_EP_CTX_BROKEN_DCS;
+ }
if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
pdev->device == PCI_DEVICE_ID_ASMEDIA_1042_XHCI) {
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -592,8 +592,11 @@ static int xhci_move_dequeue_past_td(str
struct xhci_ring *ep_ring;
struct xhci_command *cmd;
struct xhci_segment *new_seg;
+ struct xhci_segment *halted_seg = NULL;
union xhci_trb *new_deq;
int new_cycle;
+ union xhci_trb *halted_trb;
+ int index = 0;
dma_addr_t addr;
u64 hw_dequeue;
bool cycle_found = false;
@@ -631,7 +634,27 @@ static int xhci_move_dequeue_past_td(str
hw_dequeue = xhci_get_hw_deq(xhci, dev, ep_index, stream_id);
new_seg = ep_ring->deq_seg;
new_deq = ep_ring->dequeue;
- new_cycle = hw_dequeue & 0x1;
+
+ /*
+ * Quirk: xHC write-back of the DCS field in the hardware dequeue
+ * pointer is wrong - use the cycle state of the TRB pointed to by
+ * the dequeue pointer.
+ */
+ if (xhci->quirks & XHCI_EP_CTX_BROKEN_DCS &&
+ !(ep->ep_state & EP_HAS_STREAMS))
+ halted_seg = trb_in_td(xhci, td->start_seg,
+ td->first_trb, td->last_trb,
+ hw_dequeue & ~0xf, false);
+ if (halted_seg) {
+ index = ((dma_addr_t)(hw_dequeue & ~0xf) - halted_seg->dma) /
+ sizeof(*halted_trb);
+ halted_trb = &halted_seg->trbs[index];
+ new_cycle = halted_trb->generic.field[3] & 0x1;
+ xhci_dbg(xhci, "Endpoint DCS = %d TRB index = %d cycle = %d\n",
+ (u8)(hw_dequeue & 0x1), index, new_cycle);
+ } else {
+ new_cycle = hw_dequeue & 0x1;
+ }
/*
* We want to find the pointer, segment and cycle state of the new trb

View file

@ -0,0 +1,32 @@
From d290d16da3157fe9fa6fddff6153fd533109a3f3 Mon Sep 17 00:00:00 2001
From: Joerg Quinten <aBUGSworstnightmare@gmail.com>
Date: Fri, 18 Jun 2021 13:02:29 +0200
Subject: [PATCH] Support RPi DPI interface in mode6 for 18-bit color
A matching media bus format was added and an overlay for using it,
both with FB and VC4 was added as well.
Signed-off-by: Joerg Quinten <aBUGSworstnightmare@gmail.com>
---
drivers/gpu/drm/vc4/vc4_dpi.c | 6 ++++++
1 file changed, 6 insertions(+)
--- a/drivers/gpu/drm/vc4/vc4_dpi.c
+++ b/drivers/gpu/drm/vc4/vc4_dpi.c
@@ -170,10 +170,16 @@ static void vc4_dpi_encoder_enable(struc
dpi_c |= VC4_SET_FIELD(DPI_ORDER_BGR,
DPI_ORDER);
break;
+ case MEDIA_BUS_FMT_BGR666_1X24_CPADHI:
+ dpi_c |= VC4_SET_FIELD(DPI_ORDER_BGR, DPI_ORDER);
+ fallthrough;
case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
dpi_c |= VC4_SET_FIELD(DPI_FORMAT_18BIT_666_RGB_2,
DPI_FORMAT);
break;
+ case MEDIA_BUS_FMT_BGR666_1X18:
+ dpi_c |= VC4_SET_FIELD(DPI_ORDER_BGR, DPI_ORDER);
+ fallthrough;
case MEDIA_BUS_FMT_RGB666_1X18:
dpi_c |= VC4_SET_FIELD(DPI_FORMAT_18BIT_666_RGB_1,
DPI_FORMAT);

View file

@ -0,0 +1,26 @@
From 378c0fb11b0a3b2fd873728379fc276f20564770 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Tue, 19 May 2020 16:20:30 +0100
Subject: [PATCH] drm/vc4: Add FKMS as an acceptable node for dma ranges.
Under FKMS, the firmware (via FKMS) also requires the VideoCore cache
aliases for image planes, as defined by the dma-ranges under /soc.
Add rpi-firmware-kms to the list of acceptable nodes to look for
to copy dma config from.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/vc4/vc4_drv.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/gpu/drm/vc4/vc4_drv.c
+++ b/drivers/gpu/drm/vc4/vc4_drv.c
@@ -276,6 +276,7 @@ static void vc4_component_unbind_all(voi
static const struct of_device_id vc4_dma_range_matches[] = {
{ .compatible = "brcm,bcm2711-hvs" },
{ .compatible = "brcm,bcm2835-hvs" },
+ { .compatible = "raspberrypi,rpi-firmware-kms" },
{ .compatible = "brcm,bcm2835-v3d" },
{ .compatible = "brcm,cygnus-v3d" },
{ .compatible = "brcm,vc4-v3d" },

View file

@ -0,0 +1,24 @@
From fdea56559f905b8397630fedd72833ee80e8503f Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Mon, 26 Oct 2020 12:38:27 +0000
Subject: [PATCH] drm/vc4: Add the 2711 HVS as a suitable DMA node
With vc4-drv node not being under /soc on Pi4, we need to
adopt the correct DMA parameters from a suitable sub-component.
Add "brcm,bcm2711-hvs" to that list of components.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/vc4/vc4_drv.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/gpu/drm/vc4/vc4_drv.c
+++ b/drivers/gpu/drm/vc4/vc4_drv.c
@@ -276,6 +276,7 @@ static void vc4_component_unbind_all(voi
static const struct of_device_id vc4_dma_range_matches[] = {
{ .compatible = "brcm,bcm2711-hvs" },
{ .compatible = "brcm,bcm2835-hvs" },
+ { .compatible = "brcm,bcm2711-hvs" },
{ .compatible = "raspberrypi,rpi-firmware-kms" },
{ .compatible = "brcm,bcm2835-v3d" },
{ .compatible = "brcm,cygnus-v3d" },

View file

@ -0,0 +1,34 @@
From 5ed2ba8530cfb805fa494f4c8a8577e3239e9198 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Fri, 12 Feb 2021 17:31:37 +0000
Subject: [PATCH] drm/vc4: Change the default DPI format to being 18bpp, not
24.
DPI hasn't really been used up until now, so the default has
been meaningless.
In theory we should be able to pass the desired format for the
adjacent bridge chip through, but framework seems to be missing
for that.
As the main device to use DPI is the VGA666 or Adafruit Kippah,
both of which use RGB666, change the default to being RGB666 instead
of RGB888.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/vc4/vc4_dpi.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/gpu/drm/vc4/vc4_dpi.c
+++ b/drivers/gpu/drm/vc4/vc4_dpi.c
@@ -150,8 +150,8 @@ static void vc4_dpi_encoder_enable(struc
}
drm_connector_list_iter_end(&conn_iter);
- /* Default to 24bit if no connector or format found. */
- dpi_c |= VC4_SET_FIELD(DPI_FORMAT_24BIT_888_RGB, DPI_FORMAT);
+ /* Default to 18bit if no connector or format found. */
+ dpi_c |= VC4_SET_FIELD(DPI_FORMAT_18BIT_666_RGB_1, DPI_FORMAT);
if (connector) {
if (connector->display_info.num_bus_formats) {

View file

@ -0,0 +1,24 @@
From 72b0f65ba954201286e99cf89583cbb0cfa2ecc6 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Thu, 7 Jan 2021 16:30:55 +0000
Subject: [PATCH] drm/atomic: Don't fixup modes that haven't been reset
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/drm_atomic_helper.c | 5 +++++
1 file changed, 5 insertions(+)
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -443,6 +443,11 @@ mode_fixup(struct drm_atomic_state *stat
new_crtc_state =
drm_atomic_get_new_crtc_state(state, new_conn_state->crtc);
+ if (!new_crtc_state->mode_changed &&
+ !new_crtc_state->connectors_changed) {
+ continue;
+ }
+
/*
* Each encoder has at most one connector (since we always steal
* it away), so we won't call ->mode_fixup twice.

View file

@ -0,0 +1,127 @@
From 30a8ce6736c11903c205b667d61e059b1510913f Mon Sep 17 00:00:00 2001
From: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
Date: Thu, 15 Jul 2021 01:07:30 +0200
Subject: [PATCH] drm/vc4: Fix timings for VEC modes
This commit fixes vertical timings of the VEC (composite output) modes
to accurately represent the 525-line ("NTSC") and 625-line ("PAL") ITU-R
standards.
Previous timings were actually defined as 502 and 601 lines, resulting
in non-standard 62.69 Hz and 52 Hz signals being generated,
respectively.
Changes to vc4_crtc.c have also been made, to make the PixelValve
vertical timings accurately correspond to the DRM modeline in interlaced
modes. The resulting VERTA/VERTB register values have been verified
against the reference values set by the Raspberry Pi firmware.
Signed-off-by: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
---
drivers/gpu/drm/vc4/vc4_crtc.c | 70 +++++++++++++++++++++-------------
1 file changed, 43 insertions(+), 27 deletions(-)
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -326,8 +326,14 @@ static void vc4_crtc_config_pv(struct dr
bool is_dsi = (vc4_encoder->type == VC4_ENCODER_TYPE_DSI0 ||
vc4_encoder->type == VC4_ENCODER_TYPE_DSI1);
bool is_dsi1 = vc4_encoder->type == VC4_ENCODER_TYPE_DSI1;
+ bool is_vec = vc4_encoder->type == VC4_ENCODER_TYPE_VEC;
u32 format = is_dsi1 ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24;
u8 ppc = pv_data->pixels_per_clock;
+
+ u16 vert_bp = mode->crtc_vtotal - mode->crtc_vsync_end;
+ u16 vert_sync = mode->crtc_vsync_end - mode->crtc_vsync_start;
+ u16 vert_fp = mode->crtc_vsync_start - mode->crtc_vdisplay;
+
bool debug_dump_regs = false;
int idx;
@@ -355,49 +361,59 @@ static void vc4_crtc_config_pv(struct dr
VC4_SET_FIELD(mode->hdisplay * pixel_rep / ppc,
PV_HORZB_HACTIVE));
- CRTC_WRITE(PV_VERTA,
- VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end +
- interlace,
- PV_VERTA_VBP) |
- VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start,
- PV_VERTA_VSYNC));
- CRTC_WRITE(PV_VERTB,
- VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay,
- PV_VERTB_VFP) |
- VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE));
-
if (interlace) {
+ bool odd_field_first = false;
+ u32 field_delay = mode->htotal * pixel_rep / (2 * ppc);
+ u16 vert_bp_even = vert_bp;
+ u16 vert_fp_even = vert_fp;
+
+ if (is_vec) {
+ /* VEC (composite output) */
+ ++field_delay;
+ if (mode->htotal == 858) {
+ /* 525-line mode (NTSC or PAL-M) */
+ odd_field_first = true;
+ }
+ }
+
+ if (odd_field_first)
+ ++vert_fp_even;
+ else
+ ++vert_bp;
+
CRTC_WRITE(PV_VERTA_EVEN,
- VC4_SET_FIELD(mode->crtc_vtotal -
- mode->crtc_vsync_end,
- PV_VERTA_VBP) |
- VC4_SET_FIELD(mode->crtc_vsync_end -
- mode->crtc_vsync_start,
- PV_VERTA_VSYNC));
+ VC4_SET_FIELD(vert_bp_even, PV_VERTA_VBP) |
+ VC4_SET_FIELD(vert_sync, PV_VERTA_VSYNC));
CRTC_WRITE(PV_VERTB_EVEN,
- VC4_SET_FIELD(mode->crtc_vsync_start -
- mode->crtc_vdisplay,
- PV_VERTB_VFP) |
+ VC4_SET_FIELD(vert_fp_even, PV_VERTB_VFP) |
VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE));
- /* We set up first field even mode for HDMI. VEC's
- * NTSC mode would want first field odd instead, once
- * we support it (to do so, set ODD_FIRST and put the
- * delay in VSYNCD_EVEN instead).
+ /* We set up first field even mode for HDMI and VEC's PAL.
+ * For NTSC, we need first field odd.
*/
CRTC_WRITE(PV_V_CONTROL,
PV_VCONTROL_CONTINUOUS |
(is_dsi ? PV_VCONTROL_DSI : 0) |
PV_VCONTROL_INTERLACE |
- VC4_SET_FIELD(mode->htotal * pixel_rep / (2 * ppc),
- PV_VCONTROL_ODD_DELAY));
- CRTC_WRITE(PV_VSYNCD_EVEN, 0);
+ (odd_field_first
+ ? PV_VCONTROL_ODD_FIRST
+ : VC4_SET_FIELD(field_delay,
+ PV_VCONTROL_ODD_DELAY)));
+ CRTC_WRITE(PV_VSYNCD_EVEN,
+ (odd_field_first ? field_delay : 0));
} else {
CRTC_WRITE(PV_V_CONTROL,
PV_VCONTROL_CONTINUOUS |
(is_dsi ? PV_VCONTROL_DSI : 0));
}
+ CRTC_WRITE(PV_VERTA,
+ VC4_SET_FIELD(vert_bp, PV_VERTA_VBP) |
+ VC4_SET_FIELD(vert_sync, PV_VERTA_VSYNC));
+ CRTC_WRITE(PV_VERTB,
+ VC4_SET_FIELD(vert_fp, PV_VERTB_VFP) |
+ VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE));
+
if (is_dsi)
CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep);

View file

@ -0,0 +1,77 @@
From b42ffab72e99a43ca50c1cbbd981d8e60e5973a7 Mon Sep 17 00:00:00 2001
From: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
Date: Thu, 15 Jul 2021 01:07:53 +0200
Subject: [PATCH] drm/vc4: Fix definition of PAL-M mode
PAL-M is a Brazilian analog TV standard that uses a PAL-style chroma
subcarrier at 3.575611[888111] MHz on top of 525-line (480i60) timings.
This commit makes the driver actually use the proper VEC preset for this
mode instead of just changing PAL subcarrier frequency.
DRM mode constant names have also been changed, as they no longer
correspond to the "NTSC" or "PAL" terms.
Signed-off-by: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
---
drivers/gpu/drm/vc4/vc4_vec.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -69,6 +69,7 @@
#define VEC_CONFIG0_STD_MASK GENMASK(1, 0)
#define VEC_CONFIG0_NTSC_STD 0
#define VEC_CONFIG0_PAL_BDGHI_STD 1
+#define VEC_CONFIG0_PAL_M_STD 2
#define VEC_CONFIG0_PAL_N_STD 3
#define VEC_SCHPH 0x108
@@ -224,14 +225,14 @@ static const struct debugfs_reg32 vec_re
VC4_REG32(VEC_DAC_MISC),
};
-static const struct drm_display_mode ntsc_mode = {
+static const struct drm_display_mode drm_mode_480i = {
DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 13500,
720, 720 + 14, 720 + 14 + 64, 720 + 14 + 64 + 60, 0,
480, 480 + 7, 480 + 7 + 6, 525, 0,
DRM_MODE_FLAG_INTERLACE)
};
-static const struct drm_display_mode pal_mode = {
+static const struct drm_display_mode drm_mode_576i = {
DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 13500,
720, 720 + 20, 720 + 20 + 64, 720 + 20 + 64 + 60, 0,
576, 576 + 4, 576 + 4 + 6, 625, 0,
@@ -240,25 +241,24 @@ static const struct drm_display_mode pal
static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = {
[VC4_VEC_TV_MODE_NTSC] = {
- .mode = &ntsc_mode,
+ .mode = &drm_mode_480i,
.config0 = VEC_CONFIG0_NTSC_STD | VEC_CONFIG0_PDEN,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
[VC4_VEC_TV_MODE_NTSC_J] = {
- .mode = &ntsc_mode,
+ .mode = &drm_mode_480i,
.config0 = VEC_CONFIG0_NTSC_STD,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
[VC4_VEC_TV_MODE_PAL] = {
- .mode = &pal_mode,
+ .mode = &drm_mode_576i,
.config0 = VEC_CONFIG0_PAL_BDGHI_STD,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
[VC4_VEC_TV_MODE_PAL_M] = {
- .mode = &pal_mode,
- .config0 = VEC_CONFIG0_PAL_BDGHI_STD,
- .config1 = VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ,
- .custom_freq = 0x223b61d1,
+ .mode = &drm_mode_480i,
+ .config0 = VEC_CONFIG0_PAL_M_STD,
+ .config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
};

View file

@ -0,0 +1,148 @@
From 80848aa95fcdffe65cb430b362e3be1910c2a6c6 Mon Sep 17 00:00:00 2001
From: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
Date: Thu, 15 Jul 2021 01:07:58 +0200
Subject: [PATCH] drm/vc4: Add support for more analog TV standards
Add support for the following composite output modes (all of them are
somewhat more obscure than the previously defined ones):
- NTSC_443 - NTSC-style signal with the chroma subcarrier shifted to
4.43361875 MHz (the PAL subcarrier frequency). Never used for
broadcasting, but sometimes used as a hack to play NTSC content in PAL
regions (e.g. on VCRs).
- PAL_N - PAL with alternative chroma subcarrier frequency,
3.58205625 MHz. Used as a broadcast standard in Argentina, Paraguay
and Uruguay to fit 576i50 with colour in 6 MHz channel raster.
- PAL60 - 480i60 signal with PAL-style color at normal European PAL
frequency. Another non-standard, non-broadcast mode, used in similar
contexts as NTSC_443. Some displays support one but not the other.
- SECAM - French frequency-modulated analog color standard; also have
been broadcast in Eastern Europe and various parts of Africa and Asia.
Uses the same 576i50 timings as PAL.
Also added some comments explaining color subcarrier frequency
registers.
Signed-off-by: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
---
drivers/gpu/drm/vc4/vc4_vec.c | 63 +++++++++++++++++++++++++++++++++++
1 file changed, 63 insertions(+)
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -46,6 +46,7 @@
#define VEC_CONFIG0_YDEL(x) ((x) << 26)
#define VEC_CONFIG0_CDEL_MASK GENMASK(25, 24)
#define VEC_CONFIG0_CDEL(x) ((x) << 24)
+#define VEC_CONFIG0_SECAM_STD BIT(21)
#define VEC_CONFIG0_PBPR_FIL BIT(18)
#define VEC_CONFIG0_CHROMA_GAIN_MASK GENMASK(17, 16)
#define VEC_CONFIG0_CHROMA_GAIN_UNITY (0 << 16)
@@ -76,6 +77,27 @@
#define VEC_SOFT_RESET 0x10c
#define VEC_CLMP0_START 0x144
#define VEC_CLMP0_END 0x148
+
+/*
+ * These set the color subcarrier frequency
+ * if VEC_CONFIG1_CUSTOM_FREQ is enabled.
+ *
+ * VEC_FREQ1_0 contains the most significant 16-bit half-word,
+ * VEC_FREQ3_2 contains the least significant 16-bit half-word.
+ * 0x80000000 seems to be equivalent to the pixel clock
+ * (which itself is the VEC clock divided by 8).
+ *
+ * Reference values (with the default pixel clock of 13.5 MHz):
+ *
+ * NTSC (3579545.[45] Hz) - 0x21F07C1F
+ * PAL (4433618.75 Hz) - 0x2A098ACB
+ * PAL-M (3575611.[888111] Hz) - 0x21E6EFE3
+ * PAL-N (3582056.25 Hz) - 0x21F69446
+ *
+ * NOTE: For SECAM, it is used as the Dr center frequency,
+ * regardless of whether VEC_CONFIG1_CUSTOM_FREQ is enabled or not;
+ * that is specified as 4406250 Hz, which corresponds to 0x29C71C72.
+ */
#define VEC_FREQ3_2 0x180
#define VEC_FREQ1_0 0x184
@@ -118,6 +140,14 @@
#define VEC_INTERRUPT_CONTROL 0x190
#define VEC_INTERRUPT_STATUS 0x194
+
+/*
+ * Db center frequency for SECAM; the clock for this is the same as for
+ * VEC_FREQ3_2/VEC_FREQ1_0, which is used for Dr center frequency.
+ *
+ * This is specified as 4250000 Hz, which corresponds to 0x284BDA13.
+ * That is also the default value, so no need to set it explicitly.
+ */
#define VEC_FCW_SECAM_B 0x198
#define VEC_SECAM_GAIN_VAL 0x19c
@@ -187,8 +217,12 @@ encoder_to_vc4_vec(struct drm_encoder *e
enum vc4_vec_tv_mode_id {
VC4_VEC_TV_MODE_NTSC,
VC4_VEC_TV_MODE_NTSC_J,
+ VC4_VEC_TV_MODE_NTSC_443,
VC4_VEC_TV_MODE_PAL,
VC4_VEC_TV_MODE_PAL_M,
+ VC4_VEC_TV_MODE_PAL_N,
+ VC4_VEC_TV_MODE_PAL60,
+ VC4_VEC_TV_MODE_SECAM,
};
struct vc4_vec_tv_mode {
@@ -250,6 +284,13 @@ static const struct vc4_vec_tv_mode vc4_
.config0 = VEC_CONFIG0_NTSC_STD,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
+ [VC4_VEC_TV_MODE_NTSC_443] = {
+ /* NTSC with PAL chroma frequency */
+ .mode = &drm_mode_480i,
+ .config0 = VEC_CONFIG0_NTSC_STD,
+ .config1 = VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ,
+ .custom_freq = 0x2a098acb,
+ },
[VC4_VEC_TV_MODE_PAL] = {
.mode = &drm_mode_576i,
.config0 = VEC_CONFIG0_PAL_BDGHI_STD,
@@ -260,6 +301,24 @@ static const struct vc4_vec_tv_mode vc4_
.config0 = VEC_CONFIG0_PAL_M_STD,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
+ [VC4_VEC_TV_MODE_PAL_N] = {
+ .mode = &drm_mode_576i,
+ .config0 = VEC_CONFIG0_PAL_N_STD,
+ .config1 = VEC_CONFIG1_C_CVBS_CVBS,
+ },
+ [VC4_VEC_TV_MODE_PAL60] = {
+ /* PAL-M with chroma frequency of regular PAL */
+ .mode = &drm_mode_480i,
+ .config0 = VEC_CONFIG0_PAL_M_STD,
+ .config1 = VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ,
+ .custom_freq = 0x2a098acb,
+ },
+ [VC4_VEC_TV_MODE_SECAM] = {
+ .mode = &drm_mode_576i,
+ .config0 = VEC_CONFIG0_SECAM_STD,
+ .config1 = VEC_CONFIG1_C_CVBS_CVBS,
+ .custom_freq = 0x29c71c72,
+ },
};
static enum drm_connector_status
@@ -503,8 +562,12 @@ static const struct of_device_id vc4_vec
static const char * const tv_mode_names[] = {
[VC4_VEC_TV_MODE_NTSC] = "NTSC",
[VC4_VEC_TV_MODE_NTSC_J] = "NTSC-J",
+ [VC4_VEC_TV_MODE_NTSC_443] = "NTSC-443",
[VC4_VEC_TV_MODE_PAL] = "PAL",
[VC4_VEC_TV_MODE_PAL_M] = "PAL-M",
+ [VC4_VEC_TV_MODE_PAL_N] = "PAL-N",
+ [VC4_VEC_TV_MODE_PAL60] = "PAL60",
+ [VC4_VEC_TV_MODE_SECAM] = "SECAM",
};
static int vc4_vec_bind(struct device *dev, struct device *master, void *data)

View file

@ -0,0 +1,142 @@
From 29dc851079145c632f1d1b0edcefa107bd98e982 Mon Sep 17 00:00:00 2001
From: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
Date: Thu, 15 Jul 2021 01:08:01 +0200
Subject: [PATCH] drm/vc4: Allow setting the TV norm via module parameter
Similar to the ch7006 and nouveau drivers, introduce a "tv_mode" module
parameter that allow setting the TV norm by specifying vc4.tv_norm= on
the kernel command line.
If that is not specified, try inferring one of the most popular norms
(PAL or NTSC) from the video mode specified on the command line. On
Raspberry Pis, this causes the most common cases of the sdtv_mode
setting in config.txt to be respected.
Signed-off-by: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
---
drivers/gpu/drm/vc4/vc4_vec.c | 72 ++++++++++++++++++++++++++++-------
1 file changed, 58 insertions(+), 14 deletions(-)
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -67,7 +67,7 @@
#define VEC_CONFIG0_YCDELAY BIT(4)
#define VEC_CONFIG0_RAMPEN BIT(2)
#define VEC_CONFIG0_YCDIS BIT(2)
-#define VEC_CONFIG0_STD_MASK GENMASK(1, 0)
+#define VEC_CONFIG0_STD_MASK (VEC_CONFIG0_SECAM_STD | GENMASK(1, 0))
#define VEC_CONFIG0_NTSC_STD 0
#define VEC_CONFIG0_PAL_BDGHI_STD 1
#define VEC_CONFIG0_PAL_M_STD 2
@@ -186,6 +186,8 @@
#define VEC_DAC_MISC_DAC_RST_N BIT(0)
+static char *vc4_vec_tv_norm;
+
struct vc4_vec_variant {
u32 dac_config;
};
@@ -321,6 +323,44 @@ static const struct vc4_vec_tv_mode vc4_
},
};
+static const char * const tv_mode_names[] = {
+ [VC4_VEC_TV_MODE_NTSC] = "NTSC",
+ [VC4_VEC_TV_MODE_NTSC_J] = "NTSC-J",
+ [VC4_VEC_TV_MODE_NTSC_443] = "NTSC-443",
+ [VC4_VEC_TV_MODE_PAL] = "PAL",
+ [VC4_VEC_TV_MODE_PAL_M] = "PAL-M",
+ [VC4_VEC_TV_MODE_PAL_N] = "PAL-N",
+ [VC4_VEC_TV_MODE_PAL60] = "PAL60",
+ [VC4_VEC_TV_MODE_SECAM] = "SECAM",
+};
+
+enum vc4_vec_tv_mode_id
+vc4_vec_get_default_mode(struct drm_connector *connector)
+{
+ int i;
+
+ if (vc4_vec_tv_norm) {
+ for (i = 0; i < ARRAY_SIZE(tv_mode_names); i++)
+ if (strcmp(vc4_vec_tv_norm, tv_mode_names[i]) == 0)
+ return (enum vc4_vec_tv_mode_id) i;
+ } else if (connector->cmdline_mode.specified &&
+ ((connector->cmdline_mode.refresh_specified &&
+ (connector->cmdline_mode.refresh == 25 ||
+ connector->cmdline_mode.refresh == 50)) ||
+ (!connector->cmdline_mode.refresh_specified &&
+ (connector->cmdline_mode.yres == 288 ||
+ connector->cmdline_mode.yres == 576)))) {
+ /*
+ * no explicitly specified TV norm; use PAL if a mode that
+ * looks like PAL has been specified on the command line
+ */
+ return VC4_VEC_TV_MODE_PAL;
+ }
+
+ /* in all other cases, default to NTSC */
+ return VC4_VEC_TV_MODE_NTSC;
+}
+
static enum drm_connector_status
vc4_vec_connector_detect(struct drm_connector *connector, bool force)
{
@@ -344,10 +384,18 @@ static int vc4_vec_connector_get_modes(s
return 1;
}
+static void vc4_vec_connector_reset(struct drm_connector *connector)
+{
+ drm_atomic_helper_connector_reset(connector);
+ /* preserve TV standard */
+ if (connector->state)
+ connector->state->tv.mode = vc4_vec_get_default_mode(connector);
+}
+
static const struct drm_connector_funcs vc4_vec_connector_funcs = {
.detect = vc4_vec_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
- .reset = drm_atomic_helper_connector_reset,
+ .reset = vc4_vec_connector_reset,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
@@ -372,7 +420,7 @@ static int vc4_vec_connector_init(struct
drm_object_attach_property(&connector->base,
dev->mode_config.tv_mode_property,
- VC4_VEC_TV_MODE_NTSC);
+ vc4_vec_get_default_mode(connector));
drm_connector_attach_encoder(connector, &vec->encoder.base);
@@ -559,17 +607,6 @@ static const struct of_device_id vc4_vec
{ /* sentinel */ },
};
-static const char * const tv_mode_names[] = {
- [VC4_VEC_TV_MODE_NTSC] = "NTSC",
- [VC4_VEC_TV_MODE_NTSC_J] = "NTSC-J",
- [VC4_VEC_TV_MODE_NTSC_443] = "NTSC-443",
- [VC4_VEC_TV_MODE_PAL] = "PAL",
- [VC4_VEC_TV_MODE_PAL_M] = "PAL-M",
- [VC4_VEC_TV_MODE_PAL_N] = "PAL-N",
- [VC4_VEC_TV_MODE_PAL60] = "PAL60",
- [VC4_VEC_TV_MODE_SECAM] = "SECAM",
-};
-
static int vc4_vec_bind(struct device *dev, struct device *master, void *data)
{
struct platform_device *pdev = to_platform_device(dev);
@@ -650,3 +687,10 @@ struct platform_driver vc4_vec_driver =
.of_match_table = vc4_vec_dt_match,
},
};
+
+module_param_named(tv_norm, vc4_vec_tv_norm, charp, 0600);
+MODULE_PARM_DESC(tv_norm, "Default TV norm.\n"
+ "\t\tSupported: NTSC, NTSC-J, NTSC-443, PAL, PAL-M, PAL-N,\n"
+ "\t\t\tPAL60, SECAM.\n"
+ "\t\tDefault: PAL if a 50 Hz mode has been set via video=,\n"
+ "\t\t\tNTSC otherwise");

View file

@ -0,0 +1,82 @@
From 51db525c675adb41eeae0d23a8e13cbc7ce76284 Mon Sep 17 00:00:00 2001
From: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
Date: Thu, 15 Jul 2021 01:08:05 +0200
Subject: [PATCH] drm/vc4: Refactor mode checking logic
Replace drm_encoder_helper_funcs::atomic_check with
drm_connector_helper_funcs::atomic_check - the former is not called
during drm_mode_obj_set_property_ioctl(). Set crtc_state->mode_changed
if TV norm changes even without explicit mode change. This makes things
like "xrandr --output Composite-1 --set mode PAL-M" work properly.
Signed-off-by: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
---
drivers/gpu/drm/vc4/vc4_vec.c | 42 ++++++++++++++++++++++-------------
1 file changed, 26 insertions(+), 16 deletions(-)
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -392,6 +392,31 @@ static void vc4_vec_connector_reset(stru
connector->state->tv.mode = vc4_vec_get_default_mode(connector);
}
+static int vc4_vec_connector_atomic_check(struct drm_connector *conn,
+ struct drm_atomic_state *state)
+{
+ struct drm_connector_state *old_state =
+ drm_atomic_get_old_connector_state(state, conn);
+ struct drm_connector_state *new_state =
+ drm_atomic_get_new_connector_state(state, conn);
+
+ const struct vc4_vec_tv_mode *vec_mode =
+ &vc4_vec_tv_modes[new_state->tv.mode];
+
+ if (new_state->crtc) {
+ struct drm_crtc_state *crtc_state =
+ drm_atomic_get_new_crtc_state(state, new_state->crtc);
+
+ if (!drm_mode_equal(vec_mode->mode, &crtc_state->mode))
+ return -EINVAL;
+
+ if (old_state->tv.mode != new_state->tv.mode)
+ crtc_state->mode_changed = true;
+ }
+
+ return 0;
+}
+
static const struct drm_connector_funcs vc4_vec_connector_funcs = {
.detect = vc4_vec_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
@@ -402,6 +427,7 @@ static const struct drm_connector_funcs
static const struct drm_connector_helper_funcs vc4_vec_connector_helper_funcs = {
.get_modes = vc4_vec_connector_get_modes,
+ .atomic_check = vc4_vec_connector_atomic_check,
};
static int vc4_vec_connector_init(struct drm_device *dev, struct vc4_vec *vec)
@@ -550,23 +576,7 @@ err_dev_exit:
drm_dev_exit(idx);
}
-static int vc4_vec_encoder_atomic_check(struct drm_encoder *encoder,
- struct drm_crtc_state *crtc_state,
- struct drm_connector_state *conn_state)
-{
- const struct vc4_vec_tv_mode *vec_mode;
-
- vec_mode = &vc4_vec_tv_modes[conn_state->tv.mode];
-
- if (conn_state->crtc &&
- !drm_mode_equal(vec_mode->mode, &crtc_state->adjusted_mode))
- return -EINVAL;
-
- return 0;
-}
-
static const struct drm_encoder_helper_funcs vc4_vec_encoder_helper_funcs = {
- .atomic_check = vc4_vec_encoder_atomic_check,
.atomic_disable = vc4_vec_encoder_disable,
.atomic_enable = vc4_vec_encoder_enable,
};

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,276 @@
From ef1315fc9e665d4ca9c8743ac43c7849dcd07605 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Tue, 27 Apr 2021 14:24:21 +0200
Subject: [PATCH] drm/vc4: Add support for gamma on BCM2711
BCM2711 changes from a 256 entry lookup table to a 16 point
piecewise linear function as the pipeline bitdepth has increased
to make a LUT unwieldy.
Implement a simple conversion from a 256 entry LUT that userspace
is likely to expect to 16 evenly spread points in the PWL. This
could be improved with curve fitting at a later date.
Co-developed-by: Juerg Haefliger <juergh@canonical.com>
Signed-off-by: Juerg Haefliger <juergh@canonical.com>
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
drivers/gpu/drm/vc4/vc4_crtc.c | 35 ++++++++++---
drivers/gpu/drm/vc4/vc4_drv.h | 28 +++++++++--
drivers/gpu/drm/vc4/vc4_hvs.c | 89 ++++++++++++++++++++++++++++++++--
drivers/gpu/drm/vc4/vc4_regs.h | 22 +++++++++
4 files changed, 162 insertions(+), 12 deletions(-)
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -1326,19 +1326,42 @@ int vc4_crtc_init(struct drm_device *drm
if (!vc4->is_vc5) {
drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r));
+ } else {
+ /* This is a lie for hvs5 which uses a 16 point PWL, but it
+ * allows for something smarter than just 16 linearly spaced
+ * segments. Conversion is done in vc5_hvs_update_gamma_lut.
+ */
+ drm_mode_crtc_set_gamma_size(crtc, 256);
+ }
- drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size);
+ drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size);
+ if (!vc4->is_vc5) {
/* We support CTM, but only for one CRTC at a time. It's therefore
* implemented as private driver state in vc4_kms, not here.
*/
drm_crtc_enable_color_mgmt(crtc, 0, true, crtc->gamma_size);
- }
- for (i = 0; i < crtc->gamma_size; i++) {
- vc4_crtc->lut_r[i] = i;
- vc4_crtc->lut_g[i] = i;
- vc4_crtc->lut_b[i] = i;
+ /* Initialize the VC4 gamma LUTs */
+ for (i = 0; i < crtc->gamma_size; i++) {
+ vc4_crtc->lut_r[i] = i;
+ vc4_crtc->lut_g[i] = i;
+ vc4_crtc->lut_b[i] = i;
+ }
+ } else {
+ /* Initialize the VC5 gamma PWL entries. Assume 12-bit pipeline,
+ * evenly spread over full range.
+ */
+ for (i = 0; i < SCALER5_DSPGAMMA_NUM_POINTS; i++) {
+ vc4_crtc->pwl_r[i] =
+ VC5_HVS_SET_GAMMA_ENTRY(i << 8, i << 12, 1 << 8);
+ vc4_crtc->pwl_g[i] =
+ VC5_HVS_SET_GAMMA_ENTRY(i << 8, i << 12, 1 << 8);
+ vc4_crtc->pwl_b[i] =
+ VC5_HVS_SET_GAMMA_ENTRY(i << 8, i << 12, 1 << 8);
+ vc4_crtc->pwl_a[i] =
+ VC5_HVS_SET_GAMMA_ENTRY(i << 8, i << 12, 1 << 8);
+ }
}
return 0;
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -20,6 +20,7 @@
#include <drm/drm_modeset_lock.h>
#include "uapi/drm/vc4_drm.h"
+#include "vc4_regs.h"
struct drm_device;
struct drm_gem_object;
@@ -481,6 +482,17 @@ struct vc4_pv_data {
enum vc4_encoder_type encoder_types[4];
};
+struct vc5_gamma_entry {
+ u32 x_c_terms;
+ u32 grad_term;
+};
+
+#define VC5_HVS_SET_GAMMA_ENTRY(x, c, g) (struct vc5_gamma_entry){ \
+ .x_c_terms = VC4_SET_FIELD((x), SCALER5_DSPGAMMA_OFF_X) | \
+ VC4_SET_FIELD((c), SCALER5_DSPGAMMA_OFF_C), \
+ .grad_term = (g) \
+}
+
struct vc4_crtc {
struct drm_crtc base;
struct platform_device *pdev;
@@ -490,9 +502,19 @@ struct vc4_crtc {
/* Timestamp at start of vblank irq - unaffected by lock delays. */
ktime_t t_vblank;
- u8 lut_r[256];
- u8 lut_g[256];
- u8 lut_b[256];
+ union {
+ struct { /* VC4 gamma LUT */
+ u8 lut_r[256];
+ u8 lut_g[256];
+ u8 lut_b[256];
+ };
+ struct { /* VC5 gamma PWL entries */
+ struct vc5_gamma_entry pwl_r[SCALER5_DSPGAMMA_NUM_POINTS];
+ struct vc5_gamma_entry pwl_g[SCALER5_DSPGAMMA_NUM_POINTS];
+ struct vc5_gamma_entry pwl_b[SCALER5_DSPGAMMA_NUM_POINTS];
+ struct vc5_gamma_entry pwl_a[SCALER5_DSPGAMMA_NUM_POINTS];
+ };
+ };
struct drm_pending_vblank_event *event;
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -241,7 +241,8 @@ static void vc4_hvs_lut_load(struct vc4_
static void vc4_hvs_update_gamma_lut(struct vc4_hvs *hvs,
struct vc4_crtc *vc4_crtc)
{
- struct drm_crtc_state *crtc_state = vc4_crtc->base.state;
+ struct drm_crtc *crtc = &vc4_crtc->base;
+ struct drm_crtc_state *crtc_state = crtc->state;
struct drm_color_lut *lut = crtc_state->gamma_lut->data;
u32 length = drm_color_lut_size(crtc_state->gamma_lut);
u32 i;
@@ -255,6 +256,81 @@ static void vc4_hvs_update_gamma_lut(str
vc4_hvs_lut_load(hvs, vc4_crtc);
}
+static void vc5_hvs_write_gamma_entry(struct vc4_hvs *hvs,
+ u32 offset,
+ struct vc5_gamma_entry *gamma)
+{
+ HVS_WRITE(offset, gamma->x_c_terms);
+ HVS_WRITE(offset + 4, gamma->grad_term);
+}
+
+static void vc5_hvs_lut_load(struct vc4_hvs *hvs,
+ struct vc4_crtc *vc4_crtc)
+{
+ struct drm_crtc *crtc = &vc4_crtc->base;
+ struct drm_crtc_state *crtc_state = crtc->state;
+ struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state);
+ u32 i;
+ u32 offset = SCALER5_DSPGAMMA_START +
+ vc4_state->assigned_channel * SCALER5_DSPGAMMA_CHAN_OFFSET;
+
+ for (i = 0; i < SCALER5_DSPGAMMA_NUM_POINTS; i++, offset += 8)
+ vc5_hvs_write_gamma_entry(hvs, offset, &vc4_crtc->pwl_r[i]);
+ for (i = 0; i < SCALER5_DSPGAMMA_NUM_POINTS; i++, offset += 8)
+ vc5_hvs_write_gamma_entry(hvs, offset, &vc4_crtc->pwl_g[i]);
+ for (i = 0; i < SCALER5_DSPGAMMA_NUM_POINTS; i++, offset += 8)
+ vc5_hvs_write_gamma_entry(hvs, offset, &vc4_crtc->pwl_b[i]);
+
+ if (vc4_state->assigned_channel == 2) {
+ /* Alpha only valid on channel 2 */
+ for (i = 0; i < SCALER5_DSPGAMMA_NUM_POINTS; i++, offset += 8)
+ vc5_hvs_write_gamma_entry(hvs, offset, &vc4_crtc->pwl_a[i]);
+ }
+}
+
+static void vc5_hvs_update_gamma_lut(struct vc4_hvs *hvs,
+ struct vc4_crtc *vc4_crtc)
+{
+ struct drm_crtc *crtc = &vc4_crtc->base;
+ struct drm_color_lut *lut = crtc->state->gamma_lut->data;
+ unsigned int step, i;
+ u32 start, end;
+
+#define VC5_HVS_UPDATE_GAMMA_ENTRY_FROM_LUT(pwl, chan) \
+ start = drm_color_lut_extract(lut[i * step].chan, 12); \
+ end = drm_color_lut_extract(lut[(i + 1) * step - 1].chan, 12); \
+ \
+ /* Negative gradients not permitted by the hardware, so \
+ * flatten such points out. \
+ */ \
+ if (end < start) \
+ end = start; \
+ \
+ /* Assume 12bit pipeline. \
+ * X evenly spread over full range (12 bit). \
+ * C as U12.4 format. \
+ * Gradient as U4.8 format. \
+ */ \
+ vc4_crtc->pwl[i] = \
+ VC5_HVS_SET_GAMMA_ENTRY(i << 8, start << 4, \
+ ((end - start) << 4) / (step - 1))
+
+ /* HVS5 has a 16 point piecewise linear function for each colour
+ * channel (including alpha on channel 2) on each display channel.
+ *
+ * Currently take a crude subsample of the gamma LUT, but this could
+ * be improved to implement curve fitting.
+ */
+ step = crtc->gamma_size / SCALER5_DSPGAMMA_NUM_POINTS;
+ for (i = 0; i < SCALER5_DSPGAMMA_NUM_POINTS; i++) {
+ VC5_HVS_UPDATE_GAMMA_ENTRY_FROM_LUT(pwl_r, red);
+ VC5_HVS_UPDATE_GAMMA_ENTRY_FROM_LUT(pwl_g, green);
+ VC5_HVS_UPDATE_GAMMA_ENTRY_FROM_LUT(pwl_b, blue);
+ }
+
+ vc5_hvs_lut_load(hvs, vc4_crtc);
+}
+
u8 vc4_hvs_get_fifo_frame_count(struct vc4_hvs *hvs, unsigned int fifo)
{
struct drm_device *drm = &hvs->vc4->base;
@@ -398,7 +474,10 @@ static int vc4_hvs_init_channel(struct v
/* Reload the LUT, since the SRAMs would have been disabled if
* all CRTCs had SCALER_DISPBKGND_GAMMA unset at once.
*/
- vc4_hvs_lut_load(hvs, vc4_crtc);
+ if (!vc4->is_vc5)
+ vc4_hvs_lut_load(hvs, vc4_crtc);
+ else
+ vc5_hvs_lut_load(hvs, vc4_crtc);
drm_dev_exit(idx);
@@ -628,7 +707,11 @@ void vc4_hvs_atomic_flush(struct drm_crt
u32 dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(channel));
if (crtc->state->gamma_lut) {
- vc4_hvs_update_gamma_lut(hvs, vc4_crtc);
+ if (!vc4->is_vc5)
+ vc4_hvs_update_gamma_lut(hvs, vc4_crtc);
+ else
+ vc5_hvs_update_gamma_lut(hvs, vc4_crtc);
+
dispbkgndx |= SCALER_DISPBKGND_GAMMA;
} else {
/* Unsetting DISPBKGND_GAMMA skips the gamma lut step
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -512,6 +512,28 @@
#define SCALER_DLIST_START 0x00002000
#define SCALER_DLIST_SIZE 0x00004000
+/* Gamma PWL for each channel. 16 points for each of 4 colour channels (alpha
+ * only on channel 2). 8 bytes per entry, offsets first, then gradient:
+ * Y = GRAD * X + C
+ *
+ * Values for X and C are left justified, and vary depending on the width of
+ * the HVS channel:
+ * 8-bit pipeline: X uses [31:24], C is U8.8 format, and GRAD is U4.8.
+ * 12-bit pipeline: X uses [31:20], C is U12.4 format, and GRAD is U4.8.
+ *
+ * The 3 HVS channels start at 0x400 offsets (ie chan 1 starts at 0x2400, and
+ * chan 2 at 0x2800).
+ */
+#define SCALER5_DSPGAMMA_NUM_POINTS 16
+#define SCALER5_DSPGAMMA_START 0x00002000
+#define SCALER5_DSPGAMMA_CHAN_OFFSET 0x400
+# define SCALER5_DSPGAMMA_OFF_X_MASK VC4_MASK(31, 20)
+# define SCALER5_DSPGAMMA_OFF_X_SHIFT 20
+# define SCALER5_DSPGAMMA_OFF_C_MASK VC4_MASK(15, 0)
+# define SCALER5_DSPGAMMA_OFF_C_SHIFT 0
+# define SCALER5_DSPGAMMA_GRAD_MASK VC4_MASK(11, 0)
+# define SCALER5_DSPGAMMA_GRAD_SHIFT 0
+
#define SCALER5_DLIST_START 0x00004000
# define VC4_HDMI_SW_RESET_FORMAT_DETECT BIT(1)

View file

@ -0,0 +1,122 @@
From 1c28783729a1b8f68d26950874a92538beafa04f Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Wed, 28 Apr 2021 12:32:10 +0200
Subject: [PATCH] drm/vc4: Add debugfs node that dumps the vc5 gamma PWL
entries
This helps with debugging the conversion from a 256 point gamma LUT to
16 point PWL entries as used by the BCM2711.
Co-developed-by: Juerg Haefliger <juergh@canonical.com>
Signed-off-by: Juerg Haefliger <juergh@canonical.com>
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
drivers/gpu/drm/vc4/vc4_hvs.c | 85 ++++++++++++++++++++++++++++++++++-
1 file changed, 84 insertions(+), 1 deletion(-)
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -141,6 +141,85 @@ static int vc4_hvs_debugfs_dlist(struct
return 0;
}
+static int vc5_hvs_debugfs_gamma(struct seq_file *m, void *data)
+{
+ struct drm_info_node *node = m->private;
+ struct drm_device *dev = node->minor->dev;
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ struct vc4_hvs *hvs = vc4->hvs;
+ struct drm_printer p = drm_seq_file_printer(m);
+ unsigned int i, chan;
+ u32 dispstat, dispbkgndx;
+
+ for (chan = 0; chan < SCALER_CHANNELS_COUNT; chan++) {
+ u32 x_c, grad;
+ u32 offset = SCALER5_DSPGAMMA_START +
+ chan * SCALER5_DSPGAMMA_CHAN_OFFSET;
+
+ dispstat = VC4_GET_FIELD(HVS_READ(SCALER_DISPSTATX(chan)),
+ SCALER_DISPSTATX_MODE);
+ if (dispstat == SCALER_DISPSTATX_MODE_DISABLED ||
+ dispstat == SCALER_DISPSTATX_MODE_EOF) {
+ drm_printf(&p, "HVS channel %u: Channel disabled\n", chan);
+ continue;
+ }
+
+ dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(chan));
+ if (!(dispbkgndx & SCALER_DISPBKGND_GAMMA)) {
+ drm_printf(&p, "HVS channel %u: Gamma disabled\n", chan);
+ continue;
+ }
+
+ drm_printf(&p, "HVS channel %u:\n", chan);
+ drm_printf(&p, " red:\n");
+ for (i = 0; i < SCALER5_DSPGAMMA_NUM_POINTS; i++, offset += 8) {
+ x_c = HVS_READ(offset);
+ grad = HVS_READ(offset + 4);
+ drm_printf(&p, " %08x %08x - x %u, c %u, grad %u\n",
+ x_c, grad,
+ VC4_GET_FIELD(x_c, SCALER5_DSPGAMMA_OFF_X),
+ VC4_GET_FIELD(x_c, SCALER5_DSPGAMMA_OFF_C),
+ grad);
+ }
+ drm_printf(&p, " green:\n");
+ for (i = 0; i < SCALER5_DSPGAMMA_NUM_POINTS; i++, offset += 8) {
+ x_c = HVS_READ(offset);
+ grad = HVS_READ(offset + 4);
+ drm_printf(&p, " %08x %08x - x %u, c %u, grad %u\n",
+ x_c, grad,
+ VC4_GET_FIELD(x_c, SCALER5_DSPGAMMA_OFF_X),
+ VC4_GET_FIELD(x_c, SCALER5_DSPGAMMA_OFF_C),
+ grad);
+ }
+ drm_printf(&p, " blue:\n");
+ for (i = 0; i < SCALER5_DSPGAMMA_NUM_POINTS; i++, offset += 8) {
+ x_c = HVS_READ(offset);
+ grad = HVS_READ(offset + 4);
+ drm_printf(&p, " %08x %08x - x %u, c %u, grad %u\n",
+ x_c, grad,
+ VC4_GET_FIELD(x_c, SCALER5_DSPGAMMA_OFF_X),
+ VC4_GET_FIELD(x_c, SCALER5_DSPGAMMA_OFF_C),
+ grad);
+ }
+
+ /* Alpha only valid on channel 2 */
+ if (chan != 2)
+ continue;
+
+ drm_printf(&p, " alpha:\n");
+ for (i = 0; i < SCALER5_DSPGAMMA_NUM_POINTS; i++, offset += 8) {
+ x_c = HVS_READ(offset);
+ grad = HVS_READ(offset + 4);
+ drm_printf(&p, " %08x %08x - x %u, c %u, grad %u\n",
+ x_c, grad,
+ VC4_GET_FIELD(x_c, SCALER5_DSPGAMMA_OFF_X),
+ VC4_GET_FIELD(x_c, SCALER5_DSPGAMMA_OFF_C),
+ grad);
+ }
+ }
+ return 0;
+}
+
/* The filter kernel is composed of dwords each containing 3 9-bit
* signed integers packed next to each other.
*/
@@ -833,11 +912,15 @@ int vc4_hvs_debugfs_init(struct drm_mino
if (!vc4->hvs)
return -ENODEV;
- if (!vc4->is_vc5)
+ if (!vc4->is_vc5) {
debugfs_create_bool("hvs_load_tracker", S_IRUGO | S_IWUSR,
minor->debugfs_root,
&vc4->load_tracker_enabled);
+ vc4_debugfs_add_file(minor, "hvs_gamma", vc5_hvs_debugfs_gamma,
+ NULL);
+ }
+
ret = vc4_debugfs_add_file(minor, "hvs_dlists",
vc4_hvs_debugfs_dlist, NULL);
if (ret)

View file

@ -0,0 +1,105 @@
From 3d1acc837abb35e453ca1fe88222dad8e8307f76 Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime@cerno.tech>
Date: Mon, 14 Jun 2021 15:28:30 +0200
Subject: [PATCH] drm/vc4: hvs: Force modeset on gamma lut change
The HVS Gamma block can only be updated when idle, so we need to disable
the HVS channel when the gamma property is set in an atomic commit.
Since the pixelvalve cannot have its assigned channel halted without
stalling unless it's disabled as well, in our case that means forcing a
full disable / enable cycle on the pipeline.
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
drivers/gpu/drm/vc4/vc4_crtc.c | 17 +++++++++++++++++
drivers/gpu/drm/vc4/vc4_drv.h | 3 +++
drivers/gpu/drm/vc4/vc4_hvs.c | 32 +++++++++++++++++++++++++++++++-
3 files changed, 51 insertions(+), 1 deletion(-)
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -293,6 +293,23 @@ struct drm_encoder *vc4_get_crtc_encoder
return NULL;
}
+#define drm_for_each_connector_mask(connector, dev, connector_mask) \
+ list_for_each_entry((connector), &(dev)->mode_config.connector_list, head) \
+ for_each_if ((connector_mask) & drm_connector_mask(connector))
+
+struct drm_connector *vc4_get_crtc_connector(struct drm_crtc *crtc,
+ struct drm_crtc_state *state)
+{
+ struct drm_connector *connector;
+
+ WARN_ON(hweight32(state->connector_mask) > 1);
+
+ drm_for_each_connector_mask(connector, crtc->dev, state->connector_mask)
+ return connector;
+
+ return NULL;
+}
+
static void vc4_crtc_pixelvalve_reset(struct drm_crtc *crtc)
{
struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -568,6 +568,9 @@ vc4_crtc_to_vc4_pv_data(const struct vc4
return container_of(data, struct vc4_pv_data, base);
}
+struct drm_connector *vc4_get_crtc_connector(struct drm_crtc *crtc,
+ struct drm_crtc_state *state);
+
struct drm_encoder *vc4_get_crtc_encoder(struct drm_crtc *crtc,
struct drm_crtc_state *state);
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -594,6 +594,36 @@ out:
drm_dev_exit(idx);
}
+static int vc4_hvs_gamma_check(struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
+{
+ struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+ struct drm_connector_state *conn_state;
+ struct drm_connector *connector;
+ struct drm_device *dev = crtc->dev;
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+
+ if (!vc4->is_vc5)
+ return 0;
+
+ if (!crtc_state->color_mgmt_changed)
+ return 0;
+
+ connector = vc4_get_crtc_connector(crtc, crtc_state);
+ if (!connector)
+ return -EINVAL;
+
+ if (!(connector->connector_type == DRM_MODE_CONNECTOR_HDMIA))
+ return 0;
+
+ conn_state = drm_atomic_get_connector_state(state, connector);
+ if (!conn_state)
+ return -EINVAL;
+
+ crtc_state->mode_changed = true;
+ return 0;
+}
+
int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state)
{
struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
@@ -624,7 +654,7 @@ int vc4_hvs_atomic_check(struct drm_crtc
if (ret)
return ret;
- return 0;
+ return vc4_hvs_gamma_check(crtc, state);
}
static void vc4_hvs_install_dlist(struct drm_crtc *crtc)

View file

@ -0,0 +1,149 @@
From 7232a4e31a7a38b4376596b386777d030923c9bb Mon Sep 17 00:00:00 2001
From: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
Date: Thu, 15 Jul 2021 01:08:08 +0200
Subject: [PATCH] drm/vc4: Relax VEC modeline requirements and add progressive
mode support
Make vc4_vec_encoder_atomic_check() accept arbitrary modelines, as long
as they result in somewhat sane output from the VEC. The bounds have
been determined empirically. Additionally, add support for the
progressive 262-line and 312-line modes.
Signed-off-by: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
---
drivers/gpu/drm/vc4/vc4_crtc.c | 1 +
drivers/gpu/drm/vc4/vc4_vec.c | 94 ++++++++++++++++++++++++++++++----
2 files changed, 85 insertions(+), 10 deletions(-)
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -422,6 +422,7 @@ static void vc4_crtc_config_pv(struct dr
CRTC_WRITE(PV_V_CONTROL,
PV_VCONTROL_CONTINUOUS |
(is_dsi ? PV_VCONTROL_DSI : 0));
+ CRTC_WRITE(PV_VSYNCD_EVEN, 0);
}
CRTC_WRITE(PV_VERTA,
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -400,18 +400,11 @@ static int vc4_vec_connector_atomic_chec
struct drm_connector_state *new_state =
drm_atomic_get_new_connector_state(state, conn);
- const struct vc4_vec_tv_mode *vec_mode =
- &vc4_vec_tv_modes[new_state->tv.mode];
-
- if (new_state->crtc) {
+ if (new_state->crtc && old_state->tv.mode != new_state->tv.mode) {
struct drm_crtc_state *crtc_state =
drm_atomic_get_new_crtc_state(state, new_state->crtc);
- if (!drm_mode_equal(vec_mode->mode, &crtc_state->mode))
- return -EINVAL;
-
- if (old_state->tv.mode != new_state->tv.mode)
- crtc_state->mode_changed = true;
+ crtc_state->mode_changed = true;
}
return 0;
@@ -546,7 +539,10 @@ static void vc4_vec_encoder_enable(struc
VEC_WRITE(VEC_CLMP0_START, 0xac);
VEC_WRITE(VEC_CLMP0_END, 0xec);
VEC_WRITE(VEC_CONFIG2,
- VEC_CONFIG2_UV_DIG_DIS | VEC_CONFIG2_RGB_DIG_DIS);
+ VEC_CONFIG2_UV_DIG_DIS |
+ VEC_CONFIG2_RGB_DIG_DIS |
+ ((encoder->crtc->state->adjusted_mode.flags &
+ DRM_MODE_FLAG_INTERLACE) ? 0 : VEC_CONFIG2_PROG_SCAN));
VEC_WRITE(VEC_CONFIG3, VEC_CONFIG3_HORIZ_LEN_STD);
VEC_WRITE(VEC_DAC_CONFIG, vec->variant->dac_config);
@@ -575,8 +571,86 @@ err_put_runtime_pm:
err_dev_exit:
drm_dev_exit(idx);
}
+static int vc4_vec_encoder_atomic_check(struct drm_encoder *encoder,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
+{
+ const struct drm_display_mode *reference_mode =
+ vc4_vec_tv_modes[conn_state->tv.mode].mode;
+
+ if (crtc_state->adjusted_mode.crtc_clock != reference_mode->clock ||
+ crtc_state->adjusted_mode.crtc_htotal != reference_mode->htotal ||
+ crtc_state->adjusted_mode.crtc_hdisplay % 4 != 0 ||
+ crtc_state->adjusted_mode.crtc_hsync_end -
+ crtc_state->adjusted_mode.crtc_hsync_start < 1)
+ return -EINVAL;
+
+ switch (reference_mode->vtotal) {
+ case 525:
+ if (crtc_state->adjusted_mode.crtc_vdisplay < 1 ||
+ crtc_state->adjusted_mode.crtc_vdisplay > 253 ||
+ crtc_state->adjusted_mode.crtc_vsync_start -
+ crtc_state->adjusted_mode.crtc_vdisplay < 1 ||
+ crtc_state->adjusted_mode.crtc_vsync_end -
+ crtc_state->adjusted_mode.crtc_vsync_start != 3 ||
+ crtc_state->adjusted_mode.crtc_vtotal -
+ crtc_state->adjusted_mode.crtc_vsync_end < 4 ||
+ crtc_state->adjusted_mode.crtc_vtotal > 262)
+ return -EINVAL;
+
+ if ((crtc_state->adjusted_mode.flags &
+ DRM_MODE_FLAG_INTERLACE) &&
+ (crtc_state->adjusted_mode.vdisplay % 2 != 0 ||
+ crtc_state->adjusted_mode.vsync_start % 2 != 1 ||
+ crtc_state->adjusted_mode.vsync_end % 2 != 1 ||
+ crtc_state->adjusted_mode.vtotal % 2 != 1))
+ return -EINVAL;
+
+ /* progressive mode is hard-wired to 262 total lines */
+ if (!(crtc_state->adjusted_mode.flags &
+ DRM_MODE_FLAG_INTERLACE) &&
+ crtc_state->adjusted_mode.crtc_vtotal != 262)
+ return -EINVAL;
+
+ break;
+
+ case 625:
+ if (crtc_state->adjusted_mode.crtc_vdisplay < 1 ||
+ crtc_state->adjusted_mode.crtc_vdisplay > 305 ||
+ crtc_state->adjusted_mode.crtc_vsync_start -
+ crtc_state->adjusted_mode.crtc_vdisplay < 1 ||
+ crtc_state->adjusted_mode.crtc_vsync_end -
+ crtc_state->adjusted_mode.crtc_vsync_start != 3 ||
+ crtc_state->adjusted_mode.crtc_vtotal -
+ crtc_state->adjusted_mode.crtc_vsync_end < 2 ||
+ crtc_state->adjusted_mode.crtc_vtotal > 312)
+ return -EINVAL;
+
+ if ((crtc_state->adjusted_mode.flags &
+ DRM_MODE_FLAG_INTERLACE) &&
+ (crtc_state->adjusted_mode.vdisplay % 2 != 0 ||
+ crtc_state->adjusted_mode.vsync_start % 2 != 0 ||
+ crtc_state->adjusted_mode.vsync_end % 2 != 0 ||
+ crtc_state->adjusted_mode.vtotal % 2 != 1))
+ return -EINVAL;
+
+ /* progressive mode is hard-wired to 312 total lines */
+ if (!(crtc_state->adjusted_mode.flags &
+ DRM_MODE_FLAG_INTERLACE) &&
+ crtc_state->adjusted_mode.crtc_vtotal != 312)
+ return -EINVAL;
+
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
static const struct drm_encoder_helper_funcs vc4_vec_encoder_helper_funcs = {
+ .atomic_check = vc4_vec_encoder_atomic_check,
.atomic_disable = vc4_vec_encoder_disable,
.atomic_enable = vc4_vec_encoder_enable,
};

View file

@ -0,0 +1,164 @@
From acef474b7826abe16fb140da1f3ee03cdc9928b8 Mon Sep 17 00:00:00 2001
From: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
Date: Thu, 15 Jul 2021 01:08:11 +0200
Subject: [PATCH] drm/vc4: Make VEC progressive modes readily accessible
Add predefined modelines for the 240p (NTSC) and 288p (PAL) progressive
modes, and report them through vc4_vec_connector_get_modes().
Signed-off-by: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
---
drivers/gpu/drm/vc4/vc4_vec.c | 73 ++++++++++++++++++++++++++---------
1 file changed, 55 insertions(+), 18 deletions(-)
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -228,7 +228,8 @@ enum vc4_vec_tv_mode_id {
};
struct vc4_vec_tv_mode {
- const struct drm_display_mode *mode;
+ const struct drm_display_mode *interlaced_mode;
+ const struct drm_display_mode *progressive_mode;
u32 config0;
u32 config1;
u32 custom_freq;
@@ -262,61 +263,81 @@ static const struct debugfs_reg32 vec_re
};
static const struct drm_display_mode drm_mode_480i = {
- DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 13500,
+ DRM_MODE("720x480i", DRM_MODE_TYPE_DRIVER, 13500,
720, 720 + 14, 720 + 14 + 64, 720 + 14 + 64 + 60, 0,
480, 480 + 7, 480 + 7 + 6, 525, 0,
DRM_MODE_FLAG_INTERLACE)
};
+static const struct drm_display_mode drm_mode_240p = {
+ DRM_MODE("720x240", DRM_MODE_TYPE_DRIVER, 13500,
+ 720, 720 + 14, 720 + 14 + 64, 720 + 14 + 64 + 60, 0,
+ 240, 240 + 3, 240 + 3 + 3, 262, 0, 0)
+};
+
static const struct drm_display_mode drm_mode_576i = {
- DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 13500,
+ DRM_MODE("720x576i", DRM_MODE_TYPE_DRIVER, 13500,
720, 720 + 20, 720 + 20 + 64, 720 + 20 + 64 + 60, 0,
576, 576 + 4, 576 + 4 + 6, 625, 0,
DRM_MODE_FLAG_INTERLACE)
};
+static const struct drm_display_mode drm_mode_288p = {
+ DRM_MODE("720x288", DRM_MODE_TYPE_DRIVER, 13500,
+ 720, 720 + 20, 720 + 20 + 64, 720 + 20 + 64 + 60, 0,
+ 288, 288 + 2, 288 + 2 + 3, 312, 0, 0)
+};
+
static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = {
[VC4_VEC_TV_MODE_NTSC] = {
- .mode = &drm_mode_480i,
+ .interlaced_mode = &drm_mode_480i,
+ .progressive_mode = &drm_mode_240p,
.config0 = VEC_CONFIG0_NTSC_STD | VEC_CONFIG0_PDEN,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
[VC4_VEC_TV_MODE_NTSC_J] = {
- .mode = &drm_mode_480i,
+ .interlaced_mode = &drm_mode_480i,
+ .progressive_mode = &drm_mode_240p,
.config0 = VEC_CONFIG0_NTSC_STD,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
[VC4_VEC_TV_MODE_NTSC_443] = {
/* NTSC with PAL chroma frequency */
- .mode = &drm_mode_480i,
+ .interlaced_mode = &drm_mode_480i,
+ .progressive_mode = &drm_mode_240p,
.config0 = VEC_CONFIG0_NTSC_STD,
.config1 = VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ,
.custom_freq = 0x2a098acb,
},
[VC4_VEC_TV_MODE_PAL] = {
- .mode = &drm_mode_576i,
+ .interlaced_mode = &drm_mode_576i,
+ .progressive_mode = &drm_mode_288p,
.config0 = VEC_CONFIG0_PAL_BDGHI_STD,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
[VC4_VEC_TV_MODE_PAL_M] = {
- .mode = &drm_mode_480i,
+ .interlaced_mode = &drm_mode_480i,
+ .progressive_mode = &drm_mode_240p,
.config0 = VEC_CONFIG0_PAL_M_STD,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
[VC4_VEC_TV_MODE_PAL_N] = {
- .mode = &drm_mode_576i,
+ .interlaced_mode = &drm_mode_576i,
+ .progressive_mode = &drm_mode_288p,
.config0 = VEC_CONFIG0_PAL_N_STD,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
[VC4_VEC_TV_MODE_PAL60] = {
/* PAL-M with chroma frequency of regular PAL */
- .mode = &drm_mode_480i,
+ .interlaced_mode = &drm_mode_480i,
+ .progressive_mode = &drm_mode_240p,
.config0 = VEC_CONFIG0_PAL_M_STD,
.config1 = VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ,
.custom_freq = 0x2a098acb,
},
[VC4_VEC_TV_MODE_SECAM] = {
- .mode = &drm_mode_576i,
+ .interlaced_mode = &drm_mode_576i,
+ .progressive_mode = &drm_mode_288p,
.config0 = VEC_CONFIG0_SECAM_STD,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
.custom_freq = 0x29c71c72,
@@ -370,16 +391,32 @@ vc4_vec_connector_detect(struct drm_conn
static int vc4_vec_connector_get_modes(struct drm_connector *connector)
{
struct drm_connector_state *state = connector->state;
- struct drm_display_mode *mode;
+ struct drm_display_mode *interlaced_mode, *progressive_mode;
- mode = drm_mode_duplicate(connector->dev,
- vc4_vec_tv_modes[state->tv.mode].mode);
- if (!mode) {
+ interlaced_mode =
+ drm_mode_duplicate(connector->dev,
+ vc4_vec_tv_modes[state->tv.mode].interlaced_mode);
+ progressive_mode =
+ drm_mode_duplicate(connector->dev,
+ vc4_vec_tv_modes[state->tv.mode].progressive_mode);
+ if (!interlaced_mode || !progressive_mode) {
DRM_ERROR("Failed to create a new display mode\n");
+ drm_mode_destroy(connector->dev, interlaced_mode);
+ drm_mode_destroy(connector->dev, progressive_mode);
return -ENOMEM;
}
- drm_mode_probed_add(connector, mode);
+ if (connector->cmdline_mode.specified &&
+ connector->cmdline_mode.refresh_specified &&
+ !connector->cmdline_mode.interlace)
+ /* progressive mode set at boot, let's make it preferred */
+ progressive_mode->type |= DRM_MODE_TYPE_PREFERRED;
+ else
+ /* otherwise, interlaced mode is preferred */
+ interlaced_mode->type |= DRM_MODE_TYPE_PREFERRED;
+
+ drm_mode_probed_add(connector, interlaced_mode);
+ drm_mode_probed_add(connector, progressive_mode);
return 1;
}
@@ -576,7 +613,7 @@ static int vc4_vec_encoder_atomic_check(
struct drm_connector_state *conn_state)
{
const struct drm_display_mode *reference_mode =
- vc4_vec_tv_modes[conn_state->tv.mode].mode;
+ vc4_vec_tv_modes[conn_state->tv.mode].interlaced_mode;
if (crtc_state->adjusted_mode.crtc_clock != reference_mode->clock ||
crtc_state->adjusted_mode.crtc_htotal != reference_mode->htotal ||

View file

@ -0,0 +1,29 @@
From 61cdd8f4f24116cf877a3b865fb3c01b74d018f4 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Tue, 2 Nov 2021 16:01:36 +0000
Subject: [PATCH] drm: Check whether the gamma lut has changed before updating
drm_crtc_legacy_gamma_set updates the gamma_lut blob unconditionally,
which leads to unnecessary reprogramming of hardware.
Check whether the blob contents has actually changed before
signalling that it has been updated.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/drm_color_mgmt.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/gpu/drm/drm_color_mgmt.c
+++ b/drivers/gpu/drm/drm_color_mgmt.c
@@ -330,7 +330,9 @@ static int drm_crtc_legacy_gamma_set(str
replaced = drm_property_replace_blob(&crtc_state->degamma_lut,
use_gamma_lut ? NULL : blob);
replaced |= drm_property_replace_blob(&crtc_state->ctm, NULL);
- replaced |= drm_property_replace_blob(&crtc_state->gamma_lut,
+ if (!crtc_state->gamma_lut || !crtc_state->gamma_lut->data ||
+ memcmp(crtc_state->gamma_lut->data, blob_data, blob->length))
+ replaced |= drm_property_replace_blob(&crtc_state->gamma_lut,
use_gamma_lut ? blob : NULL);
crtc_state->color_mgmt_changed |= replaced;

View file

@ -0,0 +1,66 @@
From 8757ab629ec26bd78885c66ea24a65df2b48bd55 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Mon, 8 Nov 2021 17:32:45 +0000
Subject: [PATCH] drm/vc4: Enable gamma block only when required.
With HVS5 the gamma block is now only reprogrammed with
a disable/enable. Loading the table from vc4_hvs_init_channel
(called from vc4_hvs_atomic_enable) appears to be at an
invalid point in time and so isn't applied.
Switch to enabling and disabling the gamma table instead. This
isn't safe if the pipeline is running, but it isn't now.
For HVS4 it is safe to enable and disable dynamically, so
adopt that approach there too.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/vc4/vc4_hvs.c | 22 ++++++++++++++++------
1 file changed, 16 insertions(+), 6 deletions(-)
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -546,8 +546,11 @@ static int vc4_hvs_init_channel(struct v
dispbkgndx &= ~SCALER_DISPBKGND_GAMMA;
dispbkgndx &= ~SCALER_DISPBKGND_INTERLACE;
+ if (crtc->state->gamma_lut)
+ /* Enable gamma on if required */
+ dispbkgndx |= SCALER_DISPBKGND_GAMMA;
+
HVS_WRITE(SCALER_DISPBKGNDX(chan), dispbkgndx |
- ((!vc4->is_vc5) ? SCALER_DISPBKGND_GAMMA : 0) |
(interlace ? SCALER_DISPBKGND_INTERLACE : 0));
/* Reload the LUT, since the SRAMs would have been disabled if
@@ -816,18 +819,25 @@ void vc4_hvs_atomic_flush(struct drm_crt
u32 dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(channel));
if (crtc->state->gamma_lut) {
- if (!vc4->is_vc5)
+ if (!vc4->is_vc5) {
vc4_hvs_update_gamma_lut(hvs, vc4_crtc);
- else
+ dispbkgndx |= SCALER_DISPBKGND_GAMMA;
+ } else {
vc5_hvs_update_gamma_lut(hvs, vc4_crtc);
-
- dispbkgndx |= SCALER_DISPBKGND_GAMMA;
+ }
} else {
/* Unsetting DISPBKGND_GAMMA skips the gamma lut step
* in hardware, which is the same as a linear lut that
* DRM expects us to use in absence of a user lut.
+ *
+ * Do NOT change state dynamically for hvs5 as it
+ * inserts a delay in the pipeline that will cause
+ * stalls if enabled/disabled whilst running. The other
+ * should already be disabling/enabling the pipeline
+ * when gamma changes.
*/
- dispbkgndx &= ~SCALER_DISPBKGND_GAMMA;
+ if (!vc4->is_vc5)
+ dispbkgndx &= ~SCALER_DISPBKGND_GAMMA;
}
HVS_WRITE(SCALER_DISPBKGNDX(channel), dispbkgndx);
}

View file

@ -0,0 +1,26 @@
From 0f75707bf8c04af5a931b8e991c26aeef4ba881e Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Mon, 8 Nov 2021 18:25:49 +0000
Subject: [PATCH] drm/vc4: Only add gamma properties once.
Two calls were made to drm_crtc_enable_color_mgmt to add gamma
and CTM, however they were both set to add the gamma properties,
so they ended up added twice.
Fixes: 766cc6b1f7fc "drm/vc4: Add CTM support"
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/vc4/vc4_crtc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -1358,7 +1358,7 @@ int vc4_crtc_init(struct drm_device *drm
/* We support CTM, but only for one CRTC at a time. It's therefore
* implemented as private driver state in vc4_kms, not here.
*/
- drm_crtc_enable_color_mgmt(crtc, 0, true, crtc->gamma_size);
+ drm_crtc_enable_color_mgmt(crtc, 0, true, 0);
/* Initialize the VC4 gamma LUTs */
for (i = 0; i < crtc->gamma_size; i++) {

View file

@ -0,0 +1,32 @@
From a3133296825850c7f7328b91eb25dbeec65628e4 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Wed, 10 Nov 2021 16:36:12 +0000
Subject: [PATCH] drm/vc4: Validate the size of the gamma_lut
Add a check to vc4_hvs_gamma_check to ensure a new non-empty
gamma LUT is of the correct length before accepting it.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/vc4/vc4_hvs.c | 10 ++++++++++
1 file changed, 10 insertions(+)
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -612,6 +612,16 @@ static int vc4_hvs_gamma_check(struct dr
if (!crtc_state->color_mgmt_changed)
return 0;
+ if (crtc_state->gamma_lut) {
+ unsigned int len = drm_color_lut_size(crtc_state->gamma_lut);
+
+ if (len != crtc->gamma_size) {
+ DRM_DEBUG_KMS("Invalid LUT size; got %u, expected %u\n",
+ len, crtc->gamma_size);
+ return -EINVAL;
+ }
+ }
+
connector = vc4_get_crtc_connector(crtc, crtc_state);
if (!connector)
return -EINVAL;

View file

@ -0,0 +1,36 @@
From 8f2abdff33e32469f735aa68197969306d847727 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Thu, 13 Jan 2022 11:30:42 +0000
Subject: [PATCH] drm/vc4: Disable Gamma control on HVS5 due to issues writing
the table
Still under investigation, but the conditions under which the HVS
will accept values written to the gamma PWL are not straightforward.
Disable gamma on HVS5 again until it can be resolved to avoid
gamma being enabled with an incorrect table.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/vc4/vc4_crtc.c | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -1344,15 +1344,9 @@ int vc4_crtc_init(struct drm_device *drm
if (!vc4->is_vc5) {
drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r));
- } else {
- /* This is a lie for hvs5 which uses a 16 point PWL, but it
- * allows for something smarter than just 16 linearly spaced
- * segments. Conversion is done in vc5_hvs_update_gamma_lut.
- */
- drm_mode_crtc_set_gamma_size(crtc, 256);
+ drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size);
}
- drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size);
if (!vc4->is_vc5) {
/* We support CTM, but only for one CRTC at a time. It's therefore

View file

@ -0,0 +1,223 @@
From 06389a94233146be1104c6e90f0d5d99360d67ff Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Wed, 8 Apr 2020 16:12:02 +0100
Subject: [PATCH] drm/vc4_hdmi: Add Broadcast RGB property to allow override of
RGB range
Copy Intel's "Broadcast RGB" property semantics to add manual override
of the HDMI pixel range for monitors that don't abide by the content
of the AVI Infoframe.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/vc4/vc4_hdmi.c | 104 +++++++++++++++++++++++++++++++++
drivers/gpu/drm/vc4/vc4_hdmi.h | 15 +++++
2 files changed, 119 insertions(+)
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -57,6 +57,14 @@
#include "vc4_hdmi_regs.h"
#include "vc4_regs.h"
+/*
+ * "Broadcast RGB" property.
+ * Allows overriding of HDMI full or limited range RGB
+ */
+#define VC4_BROADCAST_RGB_AUTO 0
+#define VC4_BROADCAST_RGB_FULL 1
+#define VC4_BROADCAST_RGB_LIMITED 2
+
#define VC5_HDMI_HORZA_HFP_SHIFT 16
#define VC5_HDMI_HORZA_HFP_MASK VC4_MASK(28, 16)
#define VC5_HDMI_HORZA_VPOS BIT(15)
@@ -155,6 +163,11 @@ static bool vc4_hdmi_is_full_range_rgb(s
{
struct drm_display_info *display = &vc4_hdmi->connector.display_info;
+ if (vc4_hdmi->broadcast_rgb == VC4_BROADCAST_RGB_LIMITED)
+ return false;
+ else if (vc4_hdmi->broadcast_rgb == VC4_BROADCAST_RGB_FULL)
+ return true;
+
return !display->is_hdmi ||
drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_FULL;
}
@@ -544,6 +557,65 @@ static int vc4_hdmi_connector_atomic_che
return 0;
}
+/**
+ * vc4_hdmi_connector_atomic_get_property - hook for
+ * connector->atomic_get_property.
+ * @connector: Connector to get the property for.
+ * @state: Connector state to retrieve the property from.
+ * @property: Property to retrieve.
+ * @val: Return value for the property.
+ *
+ * Returns the atomic property value for a digital connector.
+ */
+int vc4_hdmi_connector_get_property(struct drm_connector *connector,
+ const struct drm_connector_state *state,
+ struct drm_property *property,
+ uint64_t *val)
+{
+ struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector);
+ const struct vc4_hdmi_connector_state *vc4_conn_state =
+ const_conn_state_to_vc4_hdmi_conn_state(state);
+
+ if (property == vc4_hdmi->broadcast_rgb_property) {
+ *val = vc4_conn_state->broadcast_rgb;
+ } else {
+ DRM_DEBUG_ATOMIC("Unknown property [PROP:%d:%s]\n",
+ property->base.id, property->name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * vc4_hdmi_connector_atomic_set_property - hook for
+ * connector->atomic_set_property.
+ * @connector: Connector to set the property for.
+ * @state: Connector state to set the property on.
+ * @property: Property to set.
+ * @val: New value for the property.
+ *
+ * Sets the atomic property value for a digital connector.
+ */
+int vc4_hdmi_connector_set_property(struct drm_connector *connector,
+ struct drm_connector_state *state,
+ struct drm_property *property,
+ uint64_t val)
+{
+ struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector);
+ struct vc4_hdmi_connector_state *vc4_conn_state =
+ conn_state_to_vc4_hdmi_conn_state(state);
+
+ if (property == vc4_hdmi->broadcast_rgb_property) {
+ vc4_conn_state->broadcast_rgb = val;
+ return 0;
+ }
+
+ DRM_DEBUG_ATOMIC("Unknown property [PROP:%d:%s]\n",
+ property->base.id, property->name);
+ return -EINVAL;
+}
+
static void vc4_hdmi_connector_reset(struct drm_connector *connector)
{
struct vc4_hdmi_connector_state *old_state =
@@ -580,6 +652,7 @@ vc4_hdmi_connector_duplicate_state(struc
new_state->tmds_char_rate = vc4_state->tmds_char_rate;
new_state->output_bpc = vc4_state->output_bpc;
new_state->output_format = vc4_state->output_format;
+ new_state->broadcast_rgb = vc4_state->broadcast_rgb;
__drm_atomic_helper_connector_duplicate_state(connector, &new_state->base);
return &new_state->base;
@@ -590,6 +663,8 @@ static const struct drm_connector_funcs
.reset = vc4_hdmi_connector_reset,
.atomic_duplicate_state = vc4_hdmi_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+ .atomic_get_property = vc4_hdmi_connector_get_property,
+ .atomic_set_property = vc4_hdmi_connector_set_property,
};
static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs = {
@@ -598,6 +673,32 @@ static const struct drm_connector_helper
.atomic_check = vc4_hdmi_connector_atomic_check,
};
+static const struct drm_prop_enum_list broadcast_rgb_names[] = {
+ { VC4_BROADCAST_RGB_AUTO, "Automatic" },
+ { VC4_BROADCAST_RGB_FULL, "Full" },
+ { VC4_BROADCAST_RGB_LIMITED, "Limited 16:235" },
+};
+
+static void
+vc4_hdmi_attach_broadcast_rgb_property(struct drm_device *dev,
+ struct vc4_hdmi *vc4_hdmi)
+{
+ struct drm_property *prop = vc4_hdmi->broadcast_rgb_property;
+
+ if (!prop) {
+ prop = drm_property_create_enum(dev, DRM_MODE_PROP_ENUM,
+ "Broadcast RGB",
+ broadcast_rgb_names,
+ ARRAY_SIZE(broadcast_rgb_names));
+ if (!prop)
+ return;
+
+ vc4_hdmi->broadcast_rgb_property = prop;
+ }
+
+ drm_object_attach_property(&vc4_hdmi->connector.base, prop, 0);
+}
+
static int vc4_hdmi_connector_init(struct drm_device *dev,
struct vc4_hdmi *vc4_hdmi)
{
@@ -644,6 +745,8 @@ static int vc4_hdmi_connector_init(struc
if (vc4_hdmi->variant->supports_hdr)
drm_connector_attach_hdr_output_metadata_property(connector);
+ vc4_hdmi_attach_broadcast_rgb_property(dev, vc4_hdmi);
+
drm_connector_attach_encoder(connector, encoder);
return 0;
@@ -1683,6 +1786,7 @@ static void vc4_hdmi_encoder_atomic_mode
mutex_lock(&vc4_hdmi->mutex);
drm_mode_copy(&vc4_hdmi->saved_adjusted_mode,
&crtc_state->adjusted_mode);
+ vc4_hdmi->broadcast_rgb = vc4_state->broadcast_rgb;
vc4_hdmi->output_bpc = vc4_state->output_bpc;
vc4_hdmi->output_format = vc4_state->output_format;
mutex_unlock(&vc4_hdmi->mutex);
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -129,6 +129,8 @@ struct vc4_hdmi {
struct delayed_work scrambling_work;
+ struct drm_property *broadcast_rgb_property;
+
struct i2c_adapter *ddc;
void __iomem *hdmicore_regs;
void __iomem *hd_regs;
@@ -229,6 +231,12 @@ struct vc4_hdmi {
* for use outside of KMS hooks. Protected by @mutex.
*/
enum vc4_hdmi_output_format output_format;
+
+ /**
+ * @broadcast_rgb: Copy of @vc4_connector_state.broadcast_rgb
+ * for use outside of KMS hooks. Protected by @mutex.
+ */
+ int broadcast_rgb;
};
static inline struct vc4_hdmi *
@@ -249,6 +257,7 @@ struct vc4_hdmi_connector_state {
unsigned long long tmds_char_rate;
unsigned int output_bpc;
enum vc4_hdmi_output_format output_format;
+ int broadcast_rgb;
};
static inline struct vc4_hdmi_connector_state *
@@ -256,6 +265,12 @@ conn_state_to_vc4_hdmi_conn_state(struct
{
return container_of(conn_state, struct vc4_hdmi_connector_state, base);
}
+
+static inline const struct vc4_hdmi_connector_state *
+const_conn_state_to_vc4_hdmi_conn_state(const struct drm_connector_state *conn_state)
+{
+ return container_of(conn_state, struct vc4_hdmi_connector_state, base);
+}
void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
struct vc4_hdmi_connector_state *vc4_conn_state);

View file

@ -0,0 +1,51 @@
From c898725a27960d08d3aa31a4b23e3ba8840388cd Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Mon, 31 Jan 2022 16:28:43 +0000
Subject: [PATCH] drm/vc4: Add DRM 210101010 RGB formats for hvs5.
HVS5 supports the 210101010 RGB[A|X] formats, but they were
missing from the DRM to HVS mapping list, so weren't available.
Add them in.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/vc4/vc4_plane.c | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -139,6 +139,34 @@ static const struct hvs_format {
.pixel_order = HVS_PIXEL_ORDER_XYCBCR,
.hvs5_only = true,
},
+ {
+ .drm = DRM_FORMAT_XRGB2101010,
+ .hvs = HVS_PIXEL_FORMAT_RGBA1010102,
+ .pixel_order = HVS_PIXEL_ORDER_ABGR,
+ .pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB,
+ .hvs5_only = true,
+ },
+ {
+ .drm = DRM_FORMAT_ARGB2101010,
+ .hvs = HVS_PIXEL_FORMAT_RGBA1010102,
+ .pixel_order = HVS_PIXEL_ORDER_ABGR,
+ .pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB,
+ .hvs5_only = true,
+ },
+ {
+ .drm = DRM_FORMAT_ABGR2101010,
+ .hvs = HVS_PIXEL_FORMAT_RGBA1010102,
+ .pixel_order = HVS_PIXEL_ORDER_ARGB,
+ .pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR,
+ .hvs5_only = true,
+ },
+ {
+ .drm = DRM_FORMAT_XBGR2101010,
+ .hvs = HVS_PIXEL_FORMAT_RGBA1010102,
+ .pixel_order = HVS_PIXEL_ORDER_ARGB,
+ .pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR,
+ .hvs5_only = true,
+ },
};
static const struct hvs_format *vc4_get_hvs_format(u32 drm_format)

View file

@ -0,0 +1,30 @@
From 0fefc9f03f94ba67d97736c884d995b98547d2f0 Mon Sep 17 00:00:00 2001
From: Chris Morgan <macromorgan@hotmail.com>
Date: Fri, 28 Jan 2022 17:39:54 -0600
Subject: [PATCH] drm/vc4: dpi: Support DPI interface in mode3 for RGB565
Add support for the VC4 DPI driver to utilize DPI mode 3. This is
defined here as xxxRRRRRxxGGGGGGxxxBBBBB:
https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#parallel-display-interface-dpi
This mode is required to use the Geekworm MZP280 DPI display.
Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/vc4/vc4_dpi.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/drivers/gpu/drm/vc4/vc4_dpi.c
+++ b/drivers/gpu/drm/vc4/vc4_dpi.c
@@ -188,6 +188,10 @@ static void vc4_dpi_encoder_enable(struc
dpi_c |= VC4_SET_FIELD(DPI_FORMAT_16BIT_565_RGB_1,
DPI_FORMAT);
break;
+ case MEDIA_BUS_FMT_RGB565_1X24_CPADHI:
+ dpi_c |= VC4_SET_FIELD(DPI_FORMAT_16BIT_565_RGB_2,
+ DPI_FORMAT);
+ break;
default:
DRM_ERROR("Unknown media bus format %d\n",
bus_format);

View file

@ -0,0 +1,89 @@
From 311cdb11c4efd3c5c4a64c1f6569794728a4d45f Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Tue, 1 Feb 2022 12:20:20 +0000
Subject: [PATCH] drm/panel: Add and initialise an orientation field to
drm_panel
Current usage of drm_connector_set_panel_orientation is from a panel's
get_modes call. However if the panel orientation property doesn't
exist on the connector at this point, then drm_mode_object triggers
WARNs as the connector is already registered.
Add an orientation variable to struct drm_panel and initialise it from
drm_panel_init.
panel_bridge_attach can then create the property before the connector
is registered.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/bridge/panel.c | 4 ++++
drivers/gpu/drm/drm_panel.c | 15 ++++++++++-----
include/drm/drm_panel.h | 8 ++++++++
3 files changed, 22 insertions(+), 5 deletions(-)
--- a/drivers/gpu/drm/bridge/panel.c
+++ b/drivers/gpu/drm/bridge/panel.c
@@ -81,6 +81,10 @@ static int panel_bridge_attach(struct dr
return ret;
}
+ /* set up connector's "panel orientation" property */
+ drm_connector_set_panel_orientation(&panel_bridge->connector,
+ panel_bridge->panel->orientation);
+
drm_connector_attach_encoder(&panel_bridge->connector,
bridge->encoder);
--- a/drivers/gpu/drm/drm_panel.c
+++ b/drivers/gpu/drm/drm_panel.c
@@ -61,6 +61,9 @@ void drm_panel_init(struct drm_panel *pa
panel->dev = dev;
panel->funcs = funcs;
panel->connector_type = connector_type;
+
+ panel->orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
+ of_drm_get_panel_orientation(dev->of_node, &panel->orientation);
}
EXPORT_SYMBOL(drm_panel_init);
@@ -289,16 +292,18 @@ int of_drm_get_panel_orientation(const s
if (ret < 0)
return ret;
- if (rotation == 0)
+ if (rotation == 0) {
*orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL;
- else if (rotation == 90)
+ } else if (rotation == 90) {
*orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP;
- else if (rotation == 180)
+ } else if (rotation == 180) {
*orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP;
- else if (rotation == 270)
+ } else if (rotation == 270) {
*orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP;
- else
+ } else {
+ DRM_ERROR("%pOF: invalid orientation %d\n", np, ret);
return -EINVAL;
+ }
return 0;
}
--- a/include/drm/drm_panel.h
+++ b/include/drm/drm_panel.h
@@ -183,6 +183,14 @@ struct drm_panel {
int connector_type;
/**
+ * @orientation:
+ *
+ * Panel orientation at initialisation. This is used to initialise the
+ * drm_connector property for panel orientation.
+ */
+ enum drm_panel_orientation orientation;
+
+ /**
* @list:
*
* Panel entry in registry.

View file

@ -0,0 +1,76 @@
From b41713786d56c559cfd093b313145cf34cb624d1 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Fri, 17 Dec 2021 13:36:52 +0000
Subject: [PATCH] drm/dsi: Document the meaning and spec references for
MIPI_DSI_MODE_*
The MIPI_DSI_MODE_* flags have fairly terse descriptions and no reference
to the DSI specification as to their exact meaning. Usage has therefore
been rather fluid.
Extend the descriptions and provide references to the part of the
MIPI DSI specification regarding what they mean.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
include/drm/drm_mipi_dsi.h | 38 ++++++++++++++++++++++++++------------
1 file changed, 26 insertions(+), 12 deletions(-)
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -113,29 +113,43 @@ struct mipi_dsi_host *of_find_mipi_dsi_h
/* DSI mode flags */
-/* video mode */
+/* Video mode display.
+ * Not set denotes a command mode display.
+ */
#define MIPI_DSI_MODE_VIDEO BIT(0)
-/* video burst mode */
+/* Video burst mode.
+ * Link frequency to be configured via platform configuration.
+ * This should always be set in conjunction with MIPI_DSI_MODE_VIDEO.
+ * (DSI spec V1.1 8.11.4)
+ */
#define MIPI_DSI_MODE_VIDEO_BURST BIT(1)
-/* video pulse mode */
+/* Video pulse mode.
+ * Not set denotes sync event mode. (DSI spec V1.1 8.11.2)
+ */
#define MIPI_DSI_MODE_VIDEO_SYNC_PULSE BIT(2)
-/* enable auto vertical count mode */
+/* Enable auto vertical count mode */
#define MIPI_DSI_MODE_VIDEO_AUTO_VERT BIT(3)
-/* enable hsync-end packets in vsync-pulse and v-porch area */
+/* Enable hsync-end packets in vsync-pulse and v-porch area */
#define MIPI_DSI_MODE_VIDEO_HSE BIT(4)
-/* disable hfront-porch area */
+/* Transmit NULL packets or LP mode during hfront-porch area.
+ * Not set denotes sending a blanking packet instead. (DSI spec V1.1 8.11.1)
+ */
#define MIPI_DSI_MODE_VIDEO_NO_HFP BIT(5)
-/* disable hback-porch area */
+/* Transmit NULL packets or LP mode during hback-porch area.
+ * Not set denotes sending a blanking packet instead. (DSI spec V1.1 8.11.1)
+ */
#define MIPI_DSI_MODE_VIDEO_NO_HBP BIT(6)
-/* disable hsync-active area */
+/* Transmit NULL packets or LP mode during hsync-active area.
+ * Not set denotes sending a blanking packet instead. (DSI spec V1.1 8.11.1)
+ */
#define MIPI_DSI_MODE_VIDEO_NO_HSA BIT(7)
-/* flush display FIFO on vsync pulse */
+/* Flush display FIFO on vsync pulse */
#define MIPI_DSI_MODE_VSYNC_FLUSH BIT(8)
-/* disable EoT packets in HS mode */
+/* Disable EoT packets in HS mode. (DSI spec V1.1 8.1) */
#define MIPI_DSI_MODE_NO_EOT_PACKET BIT(9)
-/* device supports non-continuous clock behavior (DSI spec 5.6.1) */
+/* Device supports non-continuous clock behavior (DSI spec V1.1 5.6.1) */
#define MIPI_DSI_CLOCK_NON_CONTINUOUS BIT(10)
-/* transmit data in low power */
+/* Transmit data in low power */
#define MIPI_DSI_MODE_LPM BIT(11)
/* transmit data ending at the same time for all lanes within one hsync */
#define MIPI_DSI_HS_PKT_END_ALIGNED BIT(12)

View file

@ -0,0 +1,24 @@
From 6638f69e510fe49de651d7ab0e2012e58fc2e6ca Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Thu, 20 Jan 2022 17:29:36 +0000
Subject: [PATCH] drm/bridge: tc358762: Ignore EPROBE_DEFER when logging errors
mipi_dsi_attach can fail due to resources not being available
yet, therefore do not log error messages should they occur.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/bridge/tc358762.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/gpu/drm/bridge/tc358762.c
+++ b/drivers/gpu/drm/bridge/tc358762.c
@@ -235,7 +235,7 @@ static int tc358762_probe(struct mipi_ds
ret = mipi_dsi_attach(dsi);
if (ret < 0) {
drm_bridge_remove(&ctx->bridge);
- dev_err(dev, "failed to attach dsi\n");
+ dev_err_probe(dev, ret, "failed to attach dsi\n");
}
return ret;

View file

@ -0,0 +1,56 @@
From 150b1bb8b1406807b94103e6beca1e023377e3a6 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Thu, 30 Sep 2021 17:51:16 +0100
Subject: [PATCH] drm/vc4: Rename bridge to out_bridge
In preparation for converting the encoder to being a bridge,
rename the variable holding the next bridge in the chain to
out_bridge, so that our bridge can be called bridge.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/vc4/vc4_dsi.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
--- a/drivers/gpu/drm/vc4/vc4_dsi.c
+++ b/drivers/gpu/drm/vc4/vc4_dsi.c
@@ -556,7 +556,7 @@ struct vc4_dsi {
struct platform_device *pdev;
- struct drm_bridge *bridge;
+ struct drm_bridge *out_bridge;
struct list_head bridge_chain;
void __iomem *regs;
@@ -800,7 +800,7 @@ static void vc4_dsi_encoder_disable(stru
if (iter->funcs->disable)
iter->funcs->disable(iter);
- if (iter == dsi->bridge)
+ if (iter == dsi->out_bridge)
break;
}
@@ -1723,9 +1723,9 @@ static int vc4_dsi_bind(struct device *d
return ret;
}
- dsi->bridge = drmm_of_get_bridge(drm, dev->of_node, 0, 0);
- if (IS_ERR(dsi->bridge))
- return PTR_ERR(dsi->bridge);
+ dsi->out_bridge = drmm_of_get_bridge(drm, dev->of_node, 0, 0);
+ if (IS_ERR(dsi->out_bridge))
+ return PTR_ERR(dsi->out_bridge);
/* The esc clock rate is supposed to always be 100Mhz. */
ret = clk_set_rate(dsi->escape_clock, 100 * 1000000);
@@ -1751,7 +1751,7 @@ static int vc4_dsi_bind(struct device *d
if (ret)
return ret;
- ret = drm_bridge_attach(encoder, dsi->bridge, NULL, 0);
+ ret = drm_bridge_attach(encoder, dsi->out_bridge, NULL, 0);
if (ret)
return ret;
/* Disable the atomic helper calls into the bridge. We

View file

@ -0,0 +1,64 @@
From ccd746cc3efa45ce3a657bbe3729133ef8d20495 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Mon, 7 Feb 2022 17:14:51 +0000
Subject: [PATCH] drm/vc4: Move DSI initialisation to encoder_mode_set.
Breaking the bridge chain does not work for atomic bridges/panels
and generally causes issues.
We need to initialise the DSI host before the bridge pre_enables
are called, so move that to encoder_mode_set in the same way that
dw-mipi-dsi does.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/vc4/vc4_dsi.c | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
--- a/drivers/gpu/drm/vc4/vc4_dsi.c
+++ b/drivers/gpu/drm/vc4/vc4_dsi.c
@@ -867,18 +867,18 @@ static bool vc4_dsi_encoder_mode_fixup(s
return true;
}
-static void vc4_dsi_encoder_enable(struct drm_encoder *encoder)
+static void vc4_dsi_encoder_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
{
- struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
struct vc4_dsi *dsi = to_vc4_dsi(encoder);
struct device *dev = &dsi->pdev->dev;
bool debug_dump_regs = false;
- struct drm_bridge *iter;
unsigned long hs_clock;
u32 ui_ns;
/* Minimum LP state duration in escape clock cycles. */
u32 lpx = dsi_esc_timing(60);
- unsigned long pixel_clock_hz = mode->clock * 1000;
+ unsigned long pixel_clock_hz = adjusted_mode->clock * 1000;
unsigned long dsip_clock;
unsigned long phy_clock;
int ret;
@@ -1105,6 +1105,14 @@ static void vc4_dsi_encoder_enable(struc
~DSI_PORT_BIT(PHY_AFEC0_RESET));
vc4_dsi_ulps(dsi, false);
+}
+
+static void vc4_dsi_encoder_enable(struct drm_encoder *encoder)
+{
+ struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder);
+ struct vc4_dsi *dsi = vc4_encoder->dsi;
+ bool debug_dump_regs = false;
+ struct drm_bridge *iter;
list_for_each_entry_reverse(iter, &dsi->bridge_chain, chain_node) {
if (iter->funcs->pre_enable)
@@ -1370,6 +1378,7 @@ static const struct drm_encoder_helper_f
.disable = vc4_dsi_encoder_disable,
.enable = vc4_dsi_encoder_enable,
.mode_fixup = vc4_dsi_encoder_mode_fixup,
+ .mode_set = vc4_dsi_encoder_mode_set,
};
static int vc4_dsi_late_register(struct drm_encoder *encoder)

View file

@ -0,0 +1,117 @@
From 5dc162306c4e5ff17493db7eaeccaaa60734ff8f Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Wed, 15 Dec 2021 17:44:49 +0000
Subject: [PATCH] drm/vc4: Remove splitting the bridge chain from the driver.
Splitting the bridge chain fails for atomic bridges as the
framework can't add the relevant state in
drm_atomic_add_encoder_bridges.
The chain was split because we needed to power up before
calling pre_enable, but that is now done in mode_set, and will
move into the framework.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/vc4/vc4_dsi.c | 47 -----------------------------------
1 file changed, 47 deletions(-)
--- a/drivers/gpu/drm/vc4/vc4_dsi.c
+++ b/drivers/gpu/drm/vc4/vc4_dsi.c
@@ -557,7 +557,6 @@ struct vc4_dsi {
struct platform_device *pdev;
struct drm_bridge *out_bridge;
- struct list_head bridge_chain;
void __iomem *regs;
@@ -794,23 +793,9 @@ static void vc4_dsi_encoder_disable(stru
{
struct vc4_dsi *dsi = to_vc4_dsi(encoder);
struct device *dev = &dsi->pdev->dev;
- struct drm_bridge *iter;
-
- list_for_each_entry_reverse(iter, &dsi->bridge_chain, chain_node) {
- if (iter->funcs->disable)
- iter->funcs->disable(iter);
-
- if (iter == dsi->out_bridge)
- break;
- }
vc4_dsi_ulps(dsi, true);
- list_for_each_entry_from(iter, &dsi->bridge_chain, chain_node) {
- if (iter->funcs->post_disable)
- iter->funcs->post_disable(iter);
- }
-
clk_disable_unprepare(dsi->pll_phy_clock);
clk_disable_unprepare(dsi->escape_clock);
clk_disable_unprepare(dsi->pixel_clock);
@@ -1112,12 +1097,6 @@ static void vc4_dsi_encoder_enable(struc
struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder);
struct vc4_dsi *dsi = vc4_encoder->dsi;
bool debug_dump_regs = false;
- struct drm_bridge *iter;
-
- list_for_each_entry_reverse(iter, &dsi->bridge_chain, chain_node) {
- if (iter->funcs->pre_enable)
- iter->funcs->pre_enable(iter);
- }
if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
DSI_PORT_WRITE(DISP0_CTRL,
@@ -1134,11 +1113,6 @@ static void vc4_dsi_encoder_enable(struc
DSI_DISP0_ENABLE);
}
- list_for_each_entry(iter, &dsi->bridge_chain, chain_node) {
- if (iter->funcs->enable)
- iter->funcs->enable(iter);
- }
-
if (debug_dump_regs) {
struct drm_printer p = drm_info_printer(&dsi->pdev->dev);
dev_info(&dsi->pdev->dev, "DSI regs after:\n");
@@ -1626,7 +1600,6 @@ static int vc4_dsi_bind(struct device *d
dsi->variant = of_device_get_match_data(dev);
- INIT_LIST_HEAD(&dsi->bridge_chain);
dsi->encoder.type = dsi->variant->port ?
VC4_ENCODER_TYPE_DSI1 : VC4_ENCODER_TYPE_DSI0;
@@ -1763,32 +1736,12 @@ static int vc4_dsi_bind(struct device *d
ret = drm_bridge_attach(encoder, dsi->out_bridge, NULL, 0);
if (ret)
return ret;
- /* Disable the atomic helper calls into the bridge. We
- * manually call the bridge pre_enable / enable / etc. calls
- * from our driver, since we need to sequence them within the
- * encoder's enable/disable paths.
- */
- list_splice_init(&encoder->bridge_chain, &dsi->bridge_chain);
return 0;
}
-static void vc4_dsi_unbind(struct device *dev, struct device *master,
- void *data)
-{
- struct vc4_dsi *dsi = dev_get_drvdata(dev);
- struct drm_encoder *encoder = &dsi->encoder.base;
-
- /*
- * Restore the bridge_chain so the bridge detach procedure can happen
- * normally.
- */
- list_splice_init(&dsi->bridge_chain, &encoder->bridge_chain);
-}
-
static const struct component_ops vc4_dsi_ops = {
.bind = vc4_dsi_bind,
- .unbind = vc4_dsi_unbind,
};
static int vc4_dsi_dev_probe(struct platform_device *pdev)

View file

@ -0,0 +1,84 @@
From fbb674cc8153a69d8224e8c5bb15ebbd1440fdc2 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Wed, 15 Dec 2021 17:47:14 +0000
Subject: [PATCH] drm/vc4: Convert vc4_dsi to use atomic
enable/disable/mode_set.
The atomic calls are preferred as the non-atomic ones
are deprecated. In preparation for conversion to a bridge,
switch to the atomic calls.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/vc4/vc4_dsi.c | 23 +++++++++++++++--------
1 file changed, 15 insertions(+), 8 deletions(-)
--- a/drivers/gpu/drm/vc4/vc4_dsi.c
+++ b/drivers/gpu/drm/vc4/vc4_dsi.c
@@ -789,7 +789,8 @@ dsi_esc_timing(u32 ns)
return DIV_ROUND_UP(ns, ESC_TIME_NS);
}
-static void vc4_dsi_encoder_disable(struct drm_encoder *encoder)
+static void vc4_dsi_encoder_disable(struct drm_encoder *encoder,
+ struct drm_atomic_state *state)
{
struct vc4_dsi *dsi = to_vc4_dsi(encoder);
struct device *dev = &dsi->pdev->dev;
@@ -853,17 +854,18 @@ static bool vc4_dsi_encoder_mode_fixup(s
}
static void vc4_dsi_encoder_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
{
struct vc4_dsi *dsi = to_vc4_dsi(encoder);
struct device *dev = &dsi->pdev->dev;
+ const struct drm_display_mode *mode;
bool debug_dump_regs = false;
unsigned long hs_clock;
u32 ui_ns;
/* Minimum LP state duration in escape clock cycles. */
u32 lpx = dsi_esc_timing(60);
- unsigned long pixel_clock_hz = adjusted_mode->clock * 1000;
+ unsigned long pixel_clock_hz;
unsigned long dsip_clock;
unsigned long phy_clock;
int ret;
@@ -880,6 +882,10 @@ static void vc4_dsi_encoder_mode_set(str
drm_print_regset32(&p, &dsi->regset);
}
+ mode = &crtc_state->adjusted_mode;
+
+ pixel_clock_hz = mode->clock * 1000;
+
/* Round up the clk_set_rate() request slightly, since
* PLLD_DSI1 is an integer divider and its rate selection will
* never round up.
@@ -1092,7 +1098,8 @@ static void vc4_dsi_encoder_mode_set(str
vc4_dsi_ulps(dsi, false);
}
-static void vc4_dsi_encoder_enable(struct drm_encoder *encoder)
+static void vc4_dsi_encoder_enable(struct drm_encoder *encoder,
+ struct drm_atomic_state *state)
{
struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder);
struct vc4_dsi *dsi = vc4_encoder->dsi;
@@ -1349,10 +1356,10 @@ static const struct mipi_dsi_host_ops vc
};
static const struct drm_encoder_helper_funcs vc4_dsi_encoder_helper_funcs = {
- .disable = vc4_dsi_encoder_disable,
- .enable = vc4_dsi_encoder_enable,
+ .atomic_disable = vc4_dsi_encoder_disable,
+ .atomic_enable = vc4_dsi_encoder_enable,
.mode_fixup = vc4_dsi_encoder_mode_fixup,
- .mode_set = vc4_dsi_encoder_mode_set,
+ .atomic_mode_set = vc4_dsi_encoder_mode_set,
};
static int vc4_dsi_late_register(struct drm_encoder *encoder)

View file

@ -0,0 +1,266 @@
From e80165b59d158eb60ac5ade9553127497c4631d9 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Wed, 15 Dec 2021 17:57:45 +0000
Subject: [PATCH] drm/vc4: Convert vc4_dsi to using a bridge instead of
encoder.
Remove the encoder functions, and create a bridge attached to
this dumb encoder which implements the same functionality.
As a bridge has state which an encoder doesn't, we need to
add the state management functions as well.
As there is no bridge atomic_mode_set, move the initialisation
code that was in mode_set into _pre_enable.
The code to actually enable and disable sending video are split
from the general control into _enable and _disable.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/vc4/vc4_dsi.c | 122 +++++++++++++++++++++++++---------
1 file changed, 90 insertions(+), 32 deletions(-)
--- a/drivers/gpu/drm/vc4/vc4_dsi.c
+++ b/drivers/gpu/drm/vc4/vc4_dsi.c
@@ -557,6 +557,7 @@ struct vc4_dsi {
struct platform_device *pdev;
struct drm_bridge *out_bridge;
+ struct drm_bridge bridge;
void __iomem *regs;
@@ -608,6 +609,12 @@ to_vc4_dsi(struct drm_encoder *encoder)
return container_of(encoder, struct vc4_dsi, encoder.base);
}
+static inline struct vc4_dsi *
+bridge_to_vc4_dsi(struct drm_bridge *bridge)
+{
+ return container_of(bridge, struct vc4_dsi, bridge);
+}
+
static inline void
dsi_dma_workaround_write(struct vc4_dsi *dsi, u32 offset, u32 val)
{
@@ -789,10 +796,21 @@ dsi_esc_timing(u32 ns)
return DIV_ROUND_UP(ns, ESC_TIME_NS);
}
-static void vc4_dsi_encoder_disable(struct drm_encoder *encoder,
- struct drm_atomic_state *state)
+static void vc4_dsi_bridge_disable(struct drm_bridge *bridge,
+ struct drm_bridge_state *state)
{
- struct vc4_dsi *dsi = to_vc4_dsi(encoder);
+ struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
+ u32 disp0_ctrl;
+
+ disp0_ctrl = DSI_PORT_READ(DISP0_CTRL);
+ disp0_ctrl &= ~DSI_DISP0_ENABLE;
+ DSI_PORT_WRITE(DISP0_CTRL, disp0_ctrl);
+}
+
+static void vc4_dsi_bridge_post_disable(struct drm_bridge *bridge,
+ struct drm_bridge_state *state)
+{
+ struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
struct device *dev = &dsi->pdev->dev;
vc4_dsi_ulps(dsi, true);
@@ -817,11 +835,11 @@ static void vc4_dsi_encoder_disable(stru
* higher-than-expected clock rate to the panel, but that's what the
* firmware does too.
*/
-static bool vc4_dsi_encoder_mode_fixup(struct drm_encoder *encoder,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
+static bool vc4_dsi_bridge_mode_fixup(struct drm_bridge *bridge,
+ const struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
{
- struct vc4_dsi *dsi = to_vc4_dsi(encoder);
+ struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
struct clk *phy_parent = clk_get_parent(dsi->pll_phy_clock);
unsigned long parent_rate = clk_get_rate(phy_parent);
unsigned long pixel_clock_hz = mode->clock * 1000;
@@ -853,15 +871,18 @@ static bool vc4_dsi_encoder_mode_fixup(s
return true;
}
-static void vc4_dsi_encoder_mode_set(struct drm_encoder *encoder,
- struct drm_crtc_state *crtc_state,
- struct drm_connector_state *conn_state)
+static void vc4_dsi_bridge_pre_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state *old_state)
{
- struct vc4_dsi *dsi = to_vc4_dsi(encoder);
+ struct drm_atomic_state *state = old_state->base.state;
+ struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
+ const struct drm_crtc_state *crtc_state;
struct device *dev = &dsi->pdev->dev;
const struct drm_display_mode *mode;
+ struct drm_connector *connector;
bool debug_dump_regs = false;
unsigned long hs_clock;
+ struct drm_crtc *crtc;
u32 ui_ns;
/* Minimum LP state duration in escape clock cycles. */
u32 lpx = dsi_esc_timing(60);
@@ -882,6 +903,14 @@ static void vc4_dsi_encoder_mode_set(str
drm_print_regset32(&p, &dsi->regset);
}
+ /*
+ * Retrieve the CRTC adjusted mode. This requires a little dance to go
+ * from the bridge to the encoder, to the connector and to the CRTC.
+ */
+ connector = drm_atomic_get_new_connector_for_encoder(state,
+ bridge->encoder);
+ crtc = drm_atomic_get_new_connector_state(state, connector)->crtc;
+ crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
mode = &crtc_state->adjusted_mode;
pixel_clock_hz = mode->clock * 1000;
@@ -1096,14 +1125,6 @@ static void vc4_dsi_encoder_mode_set(str
~DSI_PORT_BIT(PHY_AFEC0_RESET));
vc4_dsi_ulps(dsi, false);
-}
-
-static void vc4_dsi_encoder_enable(struct drm_encoder *encoder,
- struct drm_atomic_state *state)
-{
- struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder);
- struct vc4_dsi *dsi = vc4_encoder->dsi;
- bool debug_dump_regs = false;
if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
DSI_PORT_WRITE(DISP0_CTRL,
@@ -1112,13 +1133,23 @@ static void vc4_dsi_encoder_enable(struc
VC4_SET_FIELD(dsi->format, DSI_DISP0_PFORMAT) |
VC4_SET_FIELD(DSI_DISP0_LP_STOP_PERFRAME,
DSI_DISP0_LP_STOP_CTRL) |
- DSI_DISP0_ST_END |
- DSI_DISP0_ENABLE);
+ DSI_DISP0_ST_END);
} else {
DSI_PORT_WRITE(DISP0_CTRL,
- DSI_DISP0_COMMAND_MODE |
- DSI_DISP0_ENABLE);
+ DSI_DISP0_COMMAND_MODE);
}
+}
+
+static void vc4_dsi_bridge_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state *old_state)
+{
+ struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
+ bool debug_dump_regs = false;
+ u32 disp0_ctrl;
+
+ disp0_ctrl = DSI_PORT_READ(DISP0_CTRL);
+ disp0_ctrl |= DSI_DISP0_ENABLE;
+ DSI_PORT_WRITE(DISP0_CTRL, disp0_ctrl);
if (debug_dump_regs) {
struct drm_printer p = drm_info_printer(&dsi->pdev->dev);
@@ -1127,6 +1158,16 @@ static void vc4_dsi_encoder_enable(struc
}
}
+static int vc4_dsi_bridge_attach(struct drm_bridge *bridge,
+ enum drm_bridge_attach_flags flags)
+{
+ struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
+
+ /* Attach the panel or bridge to the dsi bridge */
+ return drm_bridge_attach(bridge->encoder, dsi->out_bridge,
+ &dsi->bridge, flags);
+}
+
static ssize_t vc4_dsi_host_transfer(struct mipi_dsi_host *host,
const struct mipi_dsi_msg *msg)
{
@@ -1303,6 +1344,7 @@ static int vc4_dsi_host_attach(struct mi
struct mipi_dsi_device *device)
{
struct vc4_dsi *dsi = host_to_dsi(host);
+ int ret;
dsi->lanes = device->lanes;
dsi->channel = device->channel;
@@ -1337,7 +1379,15 @@ static int vc4_dsi_host_attach(struct mi
return 0;
}
- return component_add(&dsi->pdev->dev, &vc4_dsi_ops);
+ drm_bridge_add(&dsi->bridge);
+
+ ret = component_add(&dsi->pdev->dev, &vc4_dsi_ops);
+ if (ret) {
+ drm_bridge_remove(&dsi->bridge);
+ return ret;
+ }
+
+ return 0;
}
static int vc4_dsi_host_detach(struct mipi_dsi_host *host,
@@ -1346,6 +1396,7 @@ static int vc4_dsi_host_detach(struct mi
struct vc4_dsi *dsi = host_to_dsi(host);
component_del(&dsi->pdev->dev, &vc4_dsi_ops);
+ drm_bridge_remove(&dsi->bridge);
return 0;
}
@@ -1355,11 +1406,16 @@ static const struct mipi_dsi_host_ops vc
.transfer = vc4_dsi_host_transfer,
};
-static const struct drm_encoder_helper_funcs vc4_dsi_encoder_helper_funcs = {
- .atomic_disable = vc4_dsi_encoder_disable,
- .atomic_enable = vc4_dsi_encoder_enable,
- .mode_fixup = vc4_dsi_encoder_mode_fixup,
- .atomic_mode_set = vc4_dsi_encoder_mode_set,
+static const struct drm_bridge_funcs vc4_dsi_bridge_funcs = {
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_reset = drm_atomic_helper_bridge_reset,
+ .atomic_pre_enable = vc4_dsi_bridge_pre_enable,
+ .atomic_enable = vc4_dsi_bridge_enable,
+ .atomic_disable = vc4_dsi_bridge_disable,
+ .atomic_post_disable = vc4_dsi_bridge_post_disable,
+ .attach = vc4_dsi_bridge_attach,
+ .mode_fixup = vc4_dsi_bridge_mode_fixup,
};
static int vc4_dsi_late_register(struct drm_encoder *encoder)
@@ -1734,13 +1790,11 @@ static int vc4_dsi_bind(struct device *d
if (ret)
return ret;
- drm_encoder_helper_add(encoder, &vc4_dsi_encoder_helper_funcs);
-
ret = devm_pm_runtime_enable(dev);
if (ret)
return ret;
- ret = drm_bridge_attach(encoder, dsi->out_bridge, NULL, 0);
+ ret = drm_bridge_attach(encoder, &dsi->bridge, NULL, 0);
if (ret)
return ret;
@@ -1762,7 +1816,11 @@ static int vc4_dsi_dev_probe(struct plat
dev_set_drvdata(dev, dsi);
kref_init(&dsi->kref);
+
dsi->pdev = pdev;
+ dsi->bridge.funcs = &vc4_dsi_bridge_funcs;
+ dsi->bridge.of_node = dev->of_node;
+ dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
dsi->dsi_host.ops = &vc4_dsi_host_ops;
dsi->dsi_host.dev = dev;
mipi_dsi_host_register(&dsi->dsi_host);

View file

@ -0,0 +1,31 @@
From 8e57d84f06b6847efff162a69223200fe6553319 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Fri, 11 Feb 2022 14:15:26 +0000
Subject: [PATCH] drm/vc4: Remove entry to ULPS from vc4_dsi post_disable
Post_disable was sending the D-PHY sequence to put any device
into ULPS suspend mode, and then cutting power to the DSI block.
The power-on reset state of the DSI block is for DSI to be in
an operational state, not ULPS, so it then never sent the sequence
for exiting ULPS. Any attached device that didn't have an external
reset therefore remained in ULPS / standby, and didn't function.
Use of ULPS isn't well specified in DRM, therefore remove entering
it to avoid the above situation.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/vc4/vc4_dsi.c | 2 --
1 file changed, 2 deletions(-)
--- a/drivers/gpu/drm/vc4/vc4_dsi.c
+++ b/drivers/gpu/drm/vc4/vc4_dsi.c
@@ -813,8 +813,6 @@ static void vc4_dsi_bridge_post_disable(
struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
struct device *dev = &dsi->pdev->dev;
- vc4_dsi_ulps(dsi, true);
-
clk_disable_unprepare(dsi->pll_phy_clock);
clk_disable_unprepare(dsi->escape_clock);
clk_disable_unprepare(dsi->pixel_clock);

View file

@ -0,0 +1,47 @@
From beb8ee0d475c6320eed3024686702d439db24f66 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Wed, 23 Feb 2022 15:36:56 +0000
Subject: [PATCH] drm/panel: Add prepare_upstream_first flag to drm_panel
Mapping to the drm_bridge flag pre_enable_upstream_first,
add a new flag prepare_upstream_first to drm_panel to allow
the panel driver to request that the upstream bridge should
be pre_enabled before the panel prepare.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/bridge/panel.c | 3 +++
include/drm/drm_panel.h | 10 ++++++++++
2 files changed, 13 insertions(+)
--- a/drivers/gpu/drm/bridge/panel.c
+++ b/drivers/gpu/drm/bridge/panel.c
@@ -258,6 +258,9 @@ struct drm_bridge *drm_panel_bridge_add_
panel_bridge->bridge.ops = DRM_BRIDGE_OP_MODES;
panel_bridge->bridge.type = connector_type;
+ panel_bridge->bridge.pre_enable_upstream_first =
+ panel->prepare_upstream_first;
+
drm_bridge_add(&panel_bridge->bridge);
return &panel_bridge->bridge;
--- a/include/drm/drm_panel.h
+++ b/include/drm/drm_panel.h
@@ -196,6 +196,16 @@ struct drm_panel {
* Panel entry in registry.
*/
struct list_head list;
+
+ /**
+ * @prepare_upstream_first:
+ *
+ * The upstream controller should be prepared first, before the prepare
+ * for the panel is called. This is largely required for DSI panels
+ * where the DSI host controller should be initialised to LP-11 before
+ * the panel is powered up.
+ */
+ bool prepare_upstream_first;
};
void drm_panel_init(struct drm_panel *panel, struct device *dev,

View file

@ -0,0 +1,36 @@
From 115fd0087451349c1e2761e89984545fe614c181 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Fri, 11 Mar 2022 17:24:37 +0000
Subject: [PATCH] drm: Include drm_connector.h from drm_panel.h
drm_panel.h wants to reference enum drm_panel_orientation which is defined
in drm_connector.h (despite the name).
Include drm_connector.h in drm_panel.h to avoid the rare situation where
drm_panel.h is used with drm_connector.h
https://github.com/raspberrypi/linux/issues/4919
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
include/drm/drm_panel.h | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
--- a/include/drm/drm_panel.h
+++ b/include/drm/drm_panel.h
@@ -24,6 +24,7 @@
#ifndef __DRM_PANEL_H__
#define __DRM_PANEL_H__
+#include <drm/drm_connector.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/list.h>
@@ -36,8 +37,6 @@ struct drm_device;
struct drm_panel;
struct display_timing;
-enum drm_panel_orientation;
-
/**
* struct drm_panel_funcs - perform operations on a given panel
*

View file

@ -0,0 +1,25 @@
From 4c5c0fa5ae4aeee2ca588935960aa48e666dafda Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Thu, 16 Dec 2021 15:33:43 +0000
Subject: [PATCH] drm/tc358762: Set the pre_enable_upstream_first flag to
configure DSI host
TC358762 wants the DSI host to be prepared before it is powered up, so
set the flag to request that the upstream bridges have their
pre_enable called first.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/bridge/tc358762.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/gpu/drm/bridge/tc358762.c
+++ b/drivers/gpu/drm/bridge/tc358762.c
@@ -229,6 +229,7 @@ static int tc358762_probe(struct mipi_ds
ctx->bridge.funcs = &tc358762_bridge_funcs;
ctx->bridge.type = DRM_MODE_CONNECTOR_DPI;
ctx->bridge.of_node = dev->of_node;
+ ctx->bridge.pre_enable_upstream_first = true;
drm_bridge_add(&ctx->bridge);

View file

@ -0,0 +1,144 @@
From 5680572cb50065d522e64792a64f915cee0f6cfb Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Tue, 25 Jan 2022 17:28:18 +0000
Subject: [PATCH] drm/vc4: Support zpos on all planes
Adds the zpos property to all planes, and creates the dlist
by placing the fragments in the correct order based on zpos.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/vc4/vc4_hvs.c | 43 +++++++++++++++++++++------------
drivers/gpu/drm/vc4/vc4_kms.c | 3 +--
drivers/gpu/drm/vc4/vc4_plane.c | 22 ++++++++++++++---
3 files changed, 48 insertions(+), 20 deletions(-)
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -769,6 +769,8 @@ void vc4_hvs_atomic_flush(struct drm_crt
bool enable_bg_fill = false;
u32 __iomem *dlist_start = vc4->hvs->dlist + vc4_state->mm.start;
u32 __iomem *dlist_next = dlist_start;
+ unsigned int zpos = 0;
+ bool found = false;
int idx;
if (!drm_dev_enter(dev, &idx)) {
@@ -782,23 +784,34 @@ void vc4_hvs_atomic_flush(struct drm_crt
}
/* Copy all the active planes' dlist contents to the hardware dlist. */
- drm_atomic_crtc_for_each_plane(plane, crtc) {
- /* Is this the first active plane? */
- if (dlist_next == dlist_start) {
- /* We need to enable background fill when a plane
- * could be alpha blending from the background, i.e.
- * where no other plane is underneath. It suffices to
- * consider the first active plane here since we set
- * needs_bg_fill such that either the first plane
- * already needs it or all planes on top blend from
- * the first or a lower plane.
- */
- vc4_plane_state = to_vc4_plane_state(plane->state);
- enable_bg_fill = vc4_plane_state->needs_bg_fill;
+ do {
+ found = false;
+
+ drm_atomic_crtc_for_each_plane(plane, crtc) {
+ if (plane->state->normalized_zpos != zpos)
+ continue;
+
+ /* Is this the first active plane? */
+ if (dlist_next == dlist_start) {
+ /* We need to enable background fill when a plane
+ * could be alpha blending from the background, i.e.
+ * where no other plane is underneath. It suffices to
+ * consider the first active plane here since we set
+ * needs_bg_fill such that either the first plane
+ * already needs it or all planes on top blend from
+ * the first or a lower plane.
+ */
+ vc4_plane_state = to_vc4_plane_state(plane->state);
+ enable_bg_fill = vc4_plane_state->needs_bg_fill;
+ }
+
+ dlist_next += vc4_plane_write_dlist(plane, dlist_next);
+
+ found = true;
}
- dlist_next += vc4_plane_write_dlist(plane, dlist_next);
- }
+ zpos++;
+ } while (found);
writel(SCALER_CTL0_END, dlist_next);
dlist_next++;
--- a/drivers/gpu/drm/vc4/vc4_kms.c
+++ b/drivers/gpu/drm/vc4/vc4_kms.c
@@ -1066,8 +1066,7 @@ int vc4_kms_load(struct drm_device *dev)
dev->mode_config.helper_private = &vc4_mode_config_helpers;
dev->mode_config.preferred_depth = 24;
dev->mode_config.async_page_flip = true;
- if (vc4->firmware_kms)
- dev->mode_config.normalize_zpos = true;
+ dev->mode_config.normalize_zpos = true;
ret = vc4_ctm_obj_init(vc4);
if (ret)
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -1600,9 +1600,14 @@ struct drm_plane *vc4_plane_init(struct
DRM_COLOR_YCBCR_BT709,
DRM_COLOR_YCBCR_LIMITED_RANGE);
+ if (type == DRM_PLANE_TYPE_PRIMARY)
+ drm_plane_create_zpos_immutable_property(plane, 0);
+
return plane;
}
+#define VC4_NUM_OVERLAY_PLANES 16
+
int vc4_plane_create_additional_planes(struct drm_device *drm)
{
struct drm_plane *cursor_plane;
@@ -1618,24 +1623,35 @@ int vc4_plane_create_additional_planes(s
* modest number of planes to expose, that should hopefully
* still cover any sane usecase.
*/
- for (i = 0; i < 16; i++) {
+ for (i = 0; i < VC4_NUM_OVERLAY_PLANES; i++) {
struct drm_plane *plane =
vc4_plane_init(drm, DRM_PLANE_TYPE_OVERLAY,
GENMASK(drm->mode_config.num_crtc - 1, 0));
if (IS_ERR(plane))
continue;
+
+ /* Create zpos property. Max of all the overlays + 1 primary +
+ * 1 cursor plane on a crtc.
+ */
+ drm_plane_create_zpos_property(plane, i + 1, 1,
+ VC4_NUM_OVERLAY_PLANES + 1);
}
drm_for_each_crtc(crtc, drm) {
/* Set up the legacy cursor after overlay initialization,
- * since we overlay planes on the CRTC in the order they were
- * initialized.
+ * since the zpos fallback is that planes are rendered by plane
+ * ID order, and that then puts the cursor on top.
*/
cursor_plane = vc4_plane_init(drm, DRM_PLANE_TYPE_CURSOR,
drm_crtc_mask(crtc));
if (!IS_ERR(cursor_plane)) {
crtc->cursor = cursor_plane;
+
+ drm_plane_create_zpos_property(cursor_plane,
+ VC4_NUM_OVERLAY_PLANES + 1,
+ 1,
+ VC4_NUM_OVERLAY_PLANES + 1);
}
}

View file

@ -0,0 +1,301 @@
From a363b78747ab3cbb671848c9d313deff4e3ef929 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Mon, 7 Mar 2022 15:19:38 +0000
Subject: [PATCH] drm/vc4: hdmi: Add CSC for BT601/709/2020 limited and full
range output
The HVS always composes in the RGB domain, but there is a colourspace
conversion block on the output to allow for sending YCbCr over the
HDMI interface.
The colourspace on that link is configurable via the "Colorspace"
property on the connector, and that updates the infoframes. There
is also selection of limited or full range based on the mode selected
or an override.
Add code to update the CSC as well so that the metadata matches the
image data.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/vc4/vc4_hdmi.c | 196 ++++++++++++++++++++++++---------
1 file changed, 145 insertions(+), 51 deletions(-)
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -158,8 +158,8 @@ static bool vc4_hdmi_mode_needs_scrambli
return clock > HDMI_14_MAX_TMDS_CLK;
}
-static bool vc4_hdmi_is_full_range_rgb(struct vc4_hdmi *vc4_hdmi,
- const struct drm_display_mode *mode)
+static bool vc4_hdmi_is_full_range(struct vc4_hdmi *vc4_hdmi,
+ const struct drm_display_mode *mode)
{
struct drm_display_info *display = &vc4_hdmi->connector.display_info;
@@ -901,7 +901,7 @@ static void vc4_hdmi_set_avi_infoframe(s
drm_hdmi_avi_infoframe_quant_range(&frame.avi,
connector, mode,
- vc4_hdmi_is_full_range_rgb(vc4_hdmi, mode) ?
+ vc4_hdmi_is_full_range(vc4_hdmi, mode) ?
HDMI_QUANTIZATION_RANGE_FULL :
HDMI_QUANTIZATION_RANGE_LIMITED);
drm_hdmi_avi_infoframe_colorimetry(&frame.avi, cstate);
@@ -1154,7 +1154,7 @@ static void vc4_hdmi_csc_setup(struct vc
csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
VC4_HD_CSC_CTL_ORDER);
- if (!vc4_hdmi_is_full_range_rgb(vc4_hdmi, mode)) {
+ if (!vc4_hdmi_is_full_range(vc4_hdmi, mode)) {
/* CEA VICs other than #1 requre limited range RGB
* output unless overridden by an AVI infoframe.
* Apply a colorspace conversion to squash 0-255 down
@@ -1193,15 +1193,6 @@ static void vc4_hdmi_csc_setup(struct vc
* [ 0 1 0 0]
* [ 0 0 1 0]
*
- * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
- */
-static const u16 vc5_hdmi_csc_full_rgb_unity[3][4] = {
- { 0x2000, 0x0000, 0x0000, 0x0000 },
- { 0x0000, 0x2000, 0x0000, 0x0000 },
- { 0x0000, 0x0000, 0x2000, 0x0000 },
-};
-
-/*
* CEA VICs other than #1 require limited range RGB output unless
* overridden by an AVI infoframe. Apply a colorspace conversion to
* squash 0-255 down to 16-235. The matrix here is:
@@ -1212,43 +1203,105 @@ static const u16 vc5_hdmi_csc_full_rgb_u
*
* Matrix is signed 2p13 fixed point, with signed 9p6 offsets
*/
-static const u16 vc5_hdmi_csc_full_rgb_to_limited_rgb[3][4] = {
- { 0x1b80, 0x0000, 0x0000, 0x0400 },
- { 0x0000, 0x1b80, 0x0000, 0x0400 },
- { 0x0000, 0x0000, 0x1b80, 0x0400 },
+static const u16 vc5_hdmi_csc_full_rgb_to_rgb[2][3][4] = {
+ {
+ /* Full range - unity */
+ { 0x2000, 0x0000, 0x0000, 0x0000 },
+ { 0x0000, 0x2000, 0x0000, 0x0000 },
+ { 0x0000, 0x0000, 0x2000, 0x0000 },
+ }, {
+ /* Limited range */
+ { 0x1b80, 0x0000, 0x0000, 0x0400 },
+ { 0x0000, 0x1b80, 0x0000, 0x0400 },
+ { 0x0000, 0x0000, 0x1b80, 0x0400 },
+ }
+};
+
+/*
+ * Conversion between Full Range RGB and YUV using the BT.601 Colorspace
+ *
+ * Full range
+ * [ 0.299000 0.587000 0.114000 0.000000 ]
+ * [ -0.168736 -0.331264 0.500000 128.000000 ]
+ * [ 0.500000 -0.418688 -0.081312 128.000000 ]
+ *
+ * Limited range
+ * [ 0.255785 0.502160 0.097523 16.000000 ]
+ * [ -0.147644 -0.289856 0.437500 128.000000 ]
+ * [ 0.437500 -0.366352 -0.071148 128.000000 ]
+ *
+ * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
+ */
+static const u16 vc5_hdmi_csc_full_rgb_to_yuv_bt601[2][3][4] = {
+ {
+ /* Full range */
+ { 0x0991, 0x12c9, 0x03a6, 0x0000 },
+ { 0xfa9b, 0xf567, 0x1000, 0x2000 },
+ { 0x1000, 0xf29b, 0xfd67, 0x2000 },
+ }, {
+ /* Limited range */
+ { 0x082f, 0x1012, 0x031f, 0x0400 },
+ { 0xfb48, 0xf6ba, 0x0e00, 0x2000 },
+ { 0x0e00, 0xf448, 0xfdba, 0x2000 },
+ }
};
/*
- * Conversion between Full Range RGB and Full Range YUV422 using the
- * BT.709 Colorspace
+ * Conversion between Full Range RGB and YUV using the BT.709 Colorspace
*
+ * Full range
+ * [ 0.212600 0.715200 0.072200 0.000000 ]
+ * [ -0.114572 -0.385428 0.500000 128.000000 ]
+ * [ 0.500000 -0.454153 -0.045847 128.000000 ]
*
- * [ 0.181906 0.611804 0.061758 16 ]
- * [ -0.100268 -0.337232 0.437500 128 ]
- * [ 0.437500 -0.397386 -0.040114 128 ]
+ * Limited range
+ * [ 0.181873 0.611831 0.061765 16.000000 ]
+ * [ -0.100251 -0.337249 0.437500 128.000000 ]
+ * [ 0.437500 -0.397384 -0.040116 128.000000 ]
*
* Matrix is signed 2p13 fixed point, with signed 9p6 offsets
*/
-static const u16 vc5_hdmi_csc_full_rgb_to_limited_yuv422_bt709[3][4] = {
- { 0x05d2, 0x1394, 0x01fa, 0x0400 },
- { 0xfccc, 0xf536, 0x0e00, 0x2000 },
- { 0x0e00, 0xf34a, 0xfeb8, 0x2000 },
+static const u16 vc5_hdmi_csc_full_rgb_to_yuv_bt709[2][3][4] = {
+ {
+ /* Full range */
+ { 0x06ce, 0x16e3, 0x024f, 0x0000 },
+ { 0xfc56, 0xf3ac, 0x1000, 0x2000 },
+ { 0x1000, 0xf179, 0xfe89, 0x2000 },
+ }, {
+ /* Limited range */
+ { 0x05d2, 0x1394, 0x01fa, 0x0400 },
+ { 0xfccc, 0xf536, 0x0e00, 0x2000 },
+ { 0x0e00, 0xf34a, 0xfeb8, 0x2000 },
+ }
};
/*
- * Conversion between Full Range RGB and Full Range YUV444 using the
- * BT.709 Colorspace
+ * Conversion between Full Range RGB and YUV using the BT.2020 Colorspace
*
- * [ -0.100268 -0.337232 0.437500 128 ]
- * [ 0.437500 -0.397386 -0.040114 128 ]
- * [ 0.181906 0.611804 0.061758 16 ]
+ * Full range
+ * [ 0.262700 0.678000 0.059300 0.000000 ]
+ * [ -0.139630 -0.360370 0.500000 128.000000 ]
+ * [ 0.500000 -0.459786 -0.040214 128.000000 ]
+ *
+ * Limited range
+ * [ 0.224732 0.580008 0.050729 16.000000 ]
+ * [ -0.122176 -0.315324 0.437500 128.000000 ]
+ * [ 0.437500 -0.402312 -0.035188 128.000000 ]
*
* Matrix is signed 2p13 fixed point, with signed 9p6 offsets
*/
-static const u16 vc5_hdmi_csc_full_rgb_to_limited_yuv444_bt709[3][4] = {
- { 0xfccc, 0xf536, 0x0e00, 0x2000 },
- { 0x0e00, 0xf34a, 0xfeb8, 0x2000 },
- { 0x05d2, 0x1394, 0x01fa, 0x0400 },
+static const u16 vc5_hdmi_csc_full_rgb_to_yuv_bt2020[2][3][4] = {
+ {
+ /* Full range */
+ { 0x0868, 0x15b2, 0x01e6, 0x0000 },
+ { 0xfb89, 0xf479, 0x1000, 0x2000 },
+ { 0x1000, 0xf14a, 0xfeb8, 0x2000 },
+ }, {
+ /* Limited range */
+ { 0x0731, 0x128f, 0x01a0, 0x0400 },
+ { 0xfc18, 0xf5ea, 0x0e00, 0x2000 },
+ { 0x0e00, 0xf321, 0xfee1, 0x2000 },
+ }
};
static void vc5_hdmi_set_csc_coeffs(struct vc4_hdmi *vc4_hdmi,
@@ -1264,6 +1317,20 @@ static void vc5_hdmi_set_csc_coeffs(stru
HDMI_WRITE(HDMI_CSC_34_33, (coeffs[2][3] << 16) | coeffs[2][2]);
}
+static void vc5_hdmi_set_csc_coeffs_swap(struct vc4_hdmi *vc4_hdmi,
+ const u16 coeffs[3][4])
+{
+ lockdep_assert_held(&vc4_hdmi->hw_lock);
+
+ /* YUV444 needs the CSC matrices using the channels in a different order */
+ HDMI_WRITE(HDMI_CSC_12_11, (coeffs[2][1] << 16) | coeffs[2][0]);
+ HDMI_WRITE(HDMI_CSC_14_13, (coeffs[2][3] << 16) | coeffs[2][2]);
+ HDMI_WRITE(HDMI_CSC_22_21, (coeffs[0][1] << 16) | coeffs[0][0]);
+ HDMI_WRITE(HDMI_CSC_24_23, (coeffs[0][3] << 16) | coeffs[0][2]);
+ HDMI_WRITE(HDMI_CSC_32_31, (coeffs[1][1] << 16) | coeffs[1][0]);
+ HDMI_WRITE(HDMI_CSC_34_33, (coeffs[1][3] << 16) | coeffs[1][2]);
+}
+
static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
struct drm_connector_state *state,
const struct drm_display_mode *mode)
@@ -1271,6 +1338,8 @@ static void vc5_hdmi_csc_setup(struct vc
struct drm_device *drm = vc4_hdmi->connector.dev;
struct vc4_hdmi_connector_state *vc4_state =
conn_state_to_vc4_hdmi_conn_state(state);
+ unsigned int lim_range = vc4_hdmi_is_full_range(vc4_hdmi, mode) ? 0 : 1;
+ const u16 (*csc)[4];
unsigned long flags;
u32 if_cfg = 0;
u32 if_xbar = 0x543210;
@@ -1286,31 +1355,56 @@ static void vc5_hdmi_csc_setup(struct vc
switch (vc4_state->output_format) {
case VC4_HDMI_OUTPUT_YUV444:
- vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_to_limited_yuv444_bt709);
- break;
-
case VC4_HDMI_OUTPUT_YUV422:
- csc_ctl |= VC4_SET_FIELD(VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422_STANDARD,
- VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422) |
- VC5_MT_CP_CSC_CTL_USE_444_TO_422 |
- VC5_MT_CP_CSC_CTL_USE_RNG_SUPPRESSION;
-
- csc_chan_ctl |= VC4_SET_FIELD(VC5_MT_CP_CHANNEL_CTL_OUTPUT_REMAP_LEGACY_STYLE,
- VC5_MT_CP_CHANNEL_CTL_OUTPUT_REMAP);
+ switch (state->colorspace) {
+ default:
+ case DRM_MODE_COLORIMETRY_NO_DATA:
+ case DRM_MODE_COLORIMETRY_BT709_YCC:
+ case DRM_MODE_COLORIMETRY_XVYCC_709:
+ case DRM_MODE_COLORIMETRY_RGB_WIDE_FIXED:
+ case DRM_MODE_COLORIMETRY_RGB_WIDE_FLOAT:
+ csc = vc5_hdmi_csc_full_rgb_to_yuv_bt709[lim_range];
+ break;
+ case DRM_MODE_COLORIMETRY_SMPTE_170M_YCC:
+ case DRM_MODE_COLORIMETRY_XVYCC_601:
+ case DRM_MODE_COLORIMETRY_SYCC_601:
+ case DRM_MODE_COLORIMETRY_OPYCC_601:
+ case DRM_MODE_COLORIMETRY_BT601_YCC:
+ csc = vc5_hdmi_csc_full_rgb_to_yuv_bt601[lim_range];
+ break;
+ case DRM_MODE_COLORIMETRY_BT2020_CYCC:
+ case DRM_MODE_COLORIMETRY_BT2020_YCC:
+ case DRM_MODE_COLORIMETRY_BT2020_RGB:
+ case DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65:
+ case DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER:
+ csc = vc5_hdmi_csc_full_rgb_to_yuv_bt2020[lim_range];
+ break;
+ }
- if_cfg |= VC4_SET_FIELD(VC5_DVP_HT_VEC_INTERFACE_CFG_SEL_422_FORMAT_422_LEGACY,
- VC5_DVP_HT_VEC_INTERFACE_CFG_SEL_422);
+ if (vc4_state->output_format == VC4_HDMI_OUTPUT_YUV422) {
+ csc_ctl |= VC4_SET_FIELD(VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422_STANDARD,
+ VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422) |
+ VC5_MT_CP_CSC_CTL_USE_444_TO_422 |
+ VC5_MT_CP_CSC_CTL_USE_RNG_SUPPRESSION;
+
+ csc_chan_ctl |= VC4_SET_FIELD(VC5_MT_CP_CHANNEL_CTL_OUTPUT_REMAP_LEGACY_STYLE,
+ VC5_MT_CP_CHANNEL_CTL_OUTPUT_REMAP);
+
+ if_cfg |= VC4_SET_FIELD(VC5_DVP_HT_VEC_INTERFACE_CFG_SEL_422_FORMAT_422_LEGACY,
+ VC5_DVP_HT_VEC_INTERFACE_CFG_SEL_422);
+
+ vc5_hdmi_set_csc_coeffs(vc4_hdmi, csc);
+ } else {
+ vc5_hdmi_set_csc_coeffs_swap(vc4_hdmi, csc);
+ }
- vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_to_limited_yuv422_bt709);
break;
case VC4_HDMI_OUTPUT_RGB:
if_xbar = 0x354021;
- if (!vc4_hdmi_is_full_range_rgb(vc4_hdmi, mode))
- vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_to_limited_rgb);
- else
- vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_unity);
+ vc5_hdmi_set_csc_coeffs(vc4_hdmi,
+ vc5_hdmi_csc_full_rgb_to_rgb[lim_range]);
break;
default:

View file

@ -0,0 +1,212 @@
From 75f54e3341ac80fc7d9a25b70f18fd0c1f586fb0 Mon Sep 17 00:00:00 2001
From: Dom Cobley <popcornmix@gmail.com>
Date: Mon, 14 Mar 2022 17:56:10 +0000
Subject: [PATCH] vc4/drm: vc4_plane: Keep fractional source coords inside
state
Signed-off-by: Dom Cobley <popcornmix@gmail.com>
---
drivers/gpu/drm/vc4/vc4_drv.h | 2 +-
drivers/gpu/drm/vc4/vc4_plane.c | 68 ++++++++++++++++-----------------
2 files changed, 34 insertions(+), 36 deletions(-)
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -384,7 +384,7 @@ struct vc4_plane_state {
/* Clipped coordinates of the plane on the display. */
int crtc_x, crtc_y, crtc_w, crtc_h;
- /* Clipped area being scanned from in the FB. */
+ /* Clipped area being scanned from in the FB in u16.16 format */
u32 src_x, src_y;
u32 src_w[2], src_h[2];
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -183,9 +183,9 @@ static const struct hvs_format *vc4_get_
static enum vc4_scaling_mode vc4_get_scaling_mode(u32 src, u32 dst)
{
- if (dst == src)
+ if (dst == src >> 16)
return VC4_SCALING_NONE;
- if (3 * dst >= 2 * src)
+ if (3 * dst >= 2 * (src >> 16))
return VC4_SCALING_PPF;
else
return VC4_SCALING_TPZ;
@@ -394,15 +394,10 @@ static int vc4_plane_setup_clipping_and_
vc4_state->offsets[i] = bo->dma_addr + fb->offsets[i];
}
- /*
- * We don't support subpixel source positioning for scaling,
- * but fractional coordinates can be generated by clipping
- * so just round for now
- */
- vc4_state->src_x = DIV_ROUND_CLOSEST(state->src.x1, 1 << 16);
- vc4_state->src_y = DIV_ROUND_CLOSEST(state->src.y1, 1 << 16);
- vc4_state->src_w[0] = DIV_ROUND_CLOSEST(state->src.x2, 1 << 16) - vc4_state->src_x;
- vc4_state->src_h[0] = DIV_ROUND_CLOSEST(state->src.y2, 1 << 16) - vc4_state->src_y;
+ vc4_state->src_x = state->src.x1;
+ vc4_state->src_y = state->src.y1;
+ vc4_state->src_w[0] = state->src.x2 - vc4_state->src_x;
+ vc4_state->src_h[0] = state->src.y2 - vc4_state->src_y;
vc4_state->crtc_x = state->dst.x1;
vc4_state->crtc_y = state->dst.y1;
@@ -455,7 +450,7 @@ static void vc4_write_tpz(struct vc4_pla
{
u32 scale, recip;
- scale = (1 << 16) * src / dst;
+ scale = src / dst;
/* The specs note that while the reciprocal would be defined
* as (1<<32)/scale, ~0 is close enough.
@@ -501,7 +496,7 @@ static u32 vc4_lbm_size(struct drm_plane
if (vc4_state->x_scaling[0] == VC4_SCALING_TPZ)
pix_per_line = vc4_state->crtc_w;
else
- pix_per_line = vc4_state->src_w[0];
+ pix_per_line = vc4_state->src_w[0] >> 16;
if (!vc4_state->is_yuv) {
if (vc4_state->y_scaling[0] == VC4_SCALING_TPZ)
@@ -592,7 +587,8 @@ static void vc4_plane_calc_load(struct d
for (i = 0; i < fb->format->num_planes; i++) {
/* Even if the bandwidth/plane required for a single frame is
*
- * vc4_state->src_w[i] * vc4_state->src_h[i] * cpp * vrefresh
+ * (vc4_state->src_w[i] >> 16) * (vc4_state->src_h[i] >> 16) *
+ * cpp * vrefresh
*
* when downscaling, we have to read more pixels per line in
* the time frame reserved for a single line, so the bandwidth
@@ -601,11 +597,11 @@ static void vc4_plane_calc_load(struct d
* load by this number. We're likely over-estimating the read
* demand, but that's better than under-estimating it.
*/
- vscale_factor = DIV_ROUND_UP(vc4_state->src_h[i],
+ vscale_factor = DIV_ROUND_UP(vc4_state->src_h[i] >> 16,
vc4_state->crtc_h);
- vc4_state->membus_load += vc4_state->src_w[i] *
- vc4_state->src_h[i] * vscale_factor *
- fb->format->cpp[i];
+ vc4_state->membus_load += (vc4_state->src_w[i] >> 16) *
+ (vc4_state->src_h[i] >> 16) *
+ vscale_factor * fb->format->cpp[i];
vc4_state->hvs_load += vc4_state->crtc_h * vc4_state->crtc_w;
}
@@ -758,7 +754,8 @@ static int vc4_plane_mode_set(struct drm
bool mix_plane_alpha;
bool covers_screen;
u32 scl0, scl1, pitch0;
- u32 tiling, src_y;
+ u32 tiling, src_x, src_y;
+ u32 width, height;
u32 hvs_format = format->hvs;
unsigned int rotation;
int ret, i;
@@ -770,6 +767,9 @@ static int vc4_plane_mode_set(struct drm
if (ret)
return ret;
+ width = vc4_state->src_w[0] >> 16;
+ height = vc4_state->src_h[0] >> 16;
+
/* SCL1 is used for Cb/Cr scaling of planar formats. For RGB
* and 4:4:4, scl1 should be set to scl0 so both channels of
* the scaler do the same thing. For YUV, the Y plane needs
@@ -790,9 +790,11 @@ static int vc4_plane_mode_set(struct drm
DRM_MODE_REFLECT_Y);
/* We must point to the last line when Y reflection is enabled. */
- src_y = vc4_state->src_y;
+ src_y = vc4_state->src_y >> 16;
if (rotation & DRM_MODE_REFLECT_Y)
- src_y += vc4_state->src_h[0] - 1;
+ src_y += height - 1;
+
+ src_x = vc4_state->src_x >> 16;
switch (base_format_mod) {
case DRM_FORMAT_MOD_LINEAR:
@@ -807,7 +809,7 @@ static int vc4_plane_mode_set(struct drm
(i ? v_subsample : 1) *
fb->pitches[i];
- vc4_state->offsets[i] += vc4_state->src_x /
+ vc4_state->offsets[i] += src_x /
(i ? h_subsample : 1) *
fb->format->cpp[i];
}
@@ -830,7 +832,7 @@ static int vc4_plane_mode_set(struct drm
* pitch * tile_h == tile_size * tiles_per_row
*/
u32 tiles_w = fb->pitches[0] >> (tile_size_shift - tile_h_shift);
- u32 tiles_l = vc4_state->src_x >> tile_w_shift;
+ u32 tiles_l = src_x >> tile_w_shift;
u32 tiles_r = tiles_w - tiles_l;
u32 tiles_t = src_y >> tile_h_shift;
/* Intra-tile offsets, which modify the base address (the
@@ -840,7 +842,7 @@ static int vc4_plane_mode_set(struct drm
u32 tile_y = (src_y >> 4) & 1;
u32 subtile_y = (src_y >> 2) & 3;
u32 utile_y = src_y & 3;
- u32 x_off = vc4_state->src_x & tile_w_mask;
+ u32 x_off = src_x & tile_w_mask;
u32 y_off = src_y & tile_h_mask;
/* When Y reflection is requested we must set the
@@ -936,7 +938,7 @@ static int vc4_plane_mode_set(struct drm
* of the 12-pixels in that 128-bit word is the
* first pixel to be used
*/
- u32 remaining_pixels = vc4_state->src_x % 96;
+ u32 remaining_pixels = src_x % 96;
u32 aligned = remaining_pixels / 12;
u32 last_bits = remaining_pixels % 12;
@@ -958,12 +960,12 @@ static int vc4_plane_mode_set(struct drm
return -EINVAL;
}
pix_per_tile = tile_w / fb->format->cpp[0];
- x_off = (vc4_state->src_x % pix_per_tile) /
+ x_off = (src_x % pix_per_tile) /
(i ? h_subsample : 1) *
fb->format->cpp[i];
}
- tile = vc4_state->src_x / pix_per_tile;
+ tile = src_x / pix_per_tile;
vc4_state->offsets[i] += param * tile_w * tile;
vc4_state->offsets[i] += src_y /
@@ -1024,10 +1026,8 @@ static int vc4_plane_mode_set(struct drm
vc4_dlist_write(vc4_state,
(mix_plane_alpha ? SCALER_POS2_ALPHA_MIX : 0) |
vc4_hvs4_get_alpha_blend_mode(state) |
- VC4_SET_FIELD(vc4_state->src_w[0],
- SCALER_POS2_WIDTH) |
- VC4_SET_FIELD(vc4_state->src_h[0],
- SCALER_POS2_HEIGHT));
+ VC4_SET_FIELD(width, SCALER_POS2_WIDTH) |
+ VC4_SET_FIELD(height, SCALER_POS2_HEIGHT));
/* Position Word 3: Context. Written by the HVS. */
vc4_dlist_write(vc4_state, 0xc0c0c0c0);
@@ -1085,10 +1085,8 @@ static int vc4_plane_mode_set(struct drm
/* Position Word 2: Source Image Size */
vc4_state->pos2_offset = vc4_state->dlist_count;
vc4_dlist_write(vc4_state,
- VC4_SET_FIELD(vc4_state->src_w[0],
- SCALER5_POS2_WIDTH) |
- VC4_SET_FIELD(vc4_state->src_h[0],
- SCALER5_POS2_HEIGHT));
+ VC4_SET_FIELD(width, SCALER5_POS2_WIDTH) |
+ VC4_SET_FIELD(height, SCALER5_POS2_HEIGHT));
/* Position Word 3: Context. Written by the HVS. */
vc4_dlist_write(vc4_state, 0xc0c0c0c0);

View file

@ -0,0 +1,104 @@
From 530def8213913d0726bd2084b9f868af6b4dfabd Mon Sep 17 00:00:00 2001
From: Dom Cobley <popcornmix@gmail.com>
Date: Fri, 9 Apr 2021 15:00:40 +0100
Subject: [PATCH] vc4/drm: Handle fractional coordinates using the phase field
Signed-off-by: Dom Cobley <popcornmix@gmail.com>
---
drivers/gpu/drm/vc4/vc4_plane.c | 61 ++++++++++++++++++++++++++++++---
1 file changed, 56 insertions(+), 5 deletions(-)
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -464,14 +464,47 @@ static void vc4_write_tpz(struct vc4_pla
VC4_SET_FIELD(recip, SCALER_TPZ1_RECIP));
}
-static void vc4_write_ppf(struct vc4_plane_state *vc4_state, u32 src, u32 dst)
+/* phase magnitude bits */
+#define PHASE_BITS 6
+
+static void vc4_write_ppf(struct vc4_plane_state *vc4_state, u32 src, u32 dst, u32 xy, int channel)
{
- u32 scale = (1 << 16) * src / dst;
+ u32 scale = src / dst;
+ s32 offset, offset2;
+ s32 phase;
+
+ /* Start the phase at 1/2 pixel from the 1st pixel at src_x.
+ 1/4 pixel for YUV. */
+ if (channel) {
+ /* the phase is relative to scale_src->x, so shift it for display list's x value */
+ offset = (xy & 0x1ffff) >> (16 - PHASE_BITS) >> 1;
+ offset += -(1 << PHASE_BITS >> 2);
+ } else {
+ /* the phase is relative to scale_src->x, so shift it for display list's x value */
+ offset = (xy & 0xffff) >> (16 - PHASE_BITS);
+ offset += -(1 << PHASE_BITS >> 1);
+
+ /* This is a kludge to make sure the scaling factors are consitent with YUV's luma scaling.
+ we lose 1bit precision because of this. */
+ scale &= ~1;
+ }
+
+ /* There may be a also small error introduced by precision of scale.
+ Add half of that as a compromise */
+ offset2 = src - dst * scale;
+ offset2 >>= 16 - PHASE_BITS;
+ phase = offset + (offset2 >> 1);
+
+ /* Ensure +ve values don't touch the sign bit, then truncate negative values */
+ if (phase >= 1 << PHASE_BITS)
+ phase = (1 << PHASE_BITS) - 1;
+
+ phase &= SCALER_PPF_IPHASE_MASK;
vc4_dlist_write(vc4_state,
SCALER_PPF_AGC |
VC4_SET_FIELD(scale, SCALER_PPF_SCALE) |
- VC4_SET_FIELD(0, SCALER_PPF_IPHASE));
+ VC4_SET_FIELD(phase, SCALER_PPF_IPHASE));
}
static u32 vc4_lbm_size(struct drm_plane_state *state)
@@ -530,13 +563,13 @@ static void vc4_write_scaling_parameters
/* Ch0 H-PPF Word 0: Scaling Parameters */
if (vc4_state->x_scaling[channel] == VC4_SCALING_PPF) {
vc4_write_ppf(vc4_state,
- vc4_state->src_w[channel], vc4_state->crtc_w);
+ vc4_state->src_w[channel], vc4_state->crtc_w, vc4_state->src_x, channel);
}
/* Ch0 V-PPF Words 0-1: Scaling Parameters, Context */
if (vc4_state->y_scaling[channel] == VC4_SCALING_PPF) {
vc4_write_ppf(vc4_state,
- vc4_state->src_h[channel], vc4_state->crtc_h);
+ vc4_state->src_h[channel], vc4_state->crtc_h, vc4_state->src_y, channel);
vc4_dlist_write(vc4_state, 0xc0c0c0c0);
}
@@ -984,6 +1017,24 @@ static int vc4_plane_mode_set(struct drm
return -EINVAL;
}
+ /* fetch an extra pixel if we don't actually line up with the left edge. */
+ if ((vc4_state->src_x & 0xffff) && vc4_state->src_x < (state->fb->width << 16))
+ width++;
+
+ /* same for the right side */
+ if (((vc4_state->src_x + vc4_state->src_w[0]) & 0xffff) &&
+ vc4_state->src_x + vc4_state->src_w[0] < (state->fb->width << 16))
+ width++;
+
+ /* now for the top */
+ if ((vc4_state->src_y & 0xffff) && vc4_state->src_y < (state->fb->height << 16))
+ height++;
+
+ /* and the bottom */
+ if (((vc4_state->src_y + vc4_state->src_h[0]) & 0xffff) &&
+ vc4_state->src_y + vc4_state->src_h[0] < (state->fb->height << 16))
+ height++;
+
/* Don't waste cycles mixing with plane alpha if the set alpha
* is opaque or there is no per-pixel alpha information.
* In any case we use the alpha property value as the fixed alpha.

View file

@ -0,0 +1,170 @@
From 1772d6d383fe550ec9c8f7fa2526a114e036e3a9 Mon Sep 17 00:00:00 2001
From: Dom Cobley <popcornmix@gmail.com>
Date: Wed, 26 Jan 2022 15:58:13 +0000
Subject: [PATCH] drm: Add chroma siting properties
Signed-off-by: Dom Cobley <popcornmix@gmail.com>
---
drivers/gpu/drm/drm_atomic_state_helper.c | 14 +++++++++
drivers/gpu/drm/drm_atomic_uapi.c | 8 +++++
drivers/gpu/drm/drm_color_mgmt.c | 36 +++++++++++++++++++++++
include/drm/drm_color_mgmt.h | 3 ++
include/drm/drm_plane.h | 36 +++++++++++++++++++++++
5 files changed, 97 insertions(+)
--- a/drivers/gpu/drm/drm_atomic_state_helper.c
+++ b/drivers/gpu/drm/drm_atomic_state_helper.c
@@ -267,6 +267,20 @@ void __drm_atomic_helper_plane_state_res
plane_state->color_range = val;
}
+ if (plane->chroma_siting_h_property) {
+ if (!drm_object_property_get_default_value(&plane->base,
+ plane->chroma_siting_h_property,
+ &val))
+ plane_state->chroma_siting_h = val;
+ }
+
+ if (plane->chroma_siting_v_property) {
+ if (!drm_object_property_get_default_value(&plane->base,
+ plane->chroma_siting_v_property,
+ &val))
+ plane_state->chroma_siting_v = val;
+ }
+
if (plane->zpos_property) {
if (!drm_object_property_get_default_value(&plane->base,
plane->zpos_property,
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -562,6 +562,10 @@ static int drm_atomic_plane_set_property
state->color_encoding = val;
} else if (property == plane->color_range_property) {
state->color_range = val;
+ } else if (property == plane->chroma_siting_h_property) {
+ state->chroma_siting_h = val;
+ } else if (property == plane->chroma_siting_v_property) {
+ state->chroma_siting_v = val;
} else if (property == config->prop_fb_damage_clips) {
ret = drm_atomic_replace_property_blob_from_id(dev,
&state->fb_damage_clips,
@@ -628,6 +632,10 @@ drm_atomic_plane_get_property(struct drm
*val = state->color_encoding;
} else if (property == plane->color_range_property) {
*val = state->color_range;
+ } else if (property == plane->chroma_siting_h_property) {
+ *val = state->chroma_siting_h;
+ } else if (property == plane->chroma_siting_v_property) {
+ *val = state->chroma_siting_v;
} else if (property == config->prop_fb_damage_clips) {
*val = (state->fb_damage_clips) ?
state->fb_damage_clips->base.id : 0;
--- a/drivers/gpu/drm/drm_color_mgmt.c
+++ b/drivers/gpu/drm/drm_color_mgmt.c
@@ -591,6 +591,42 @@ int drm_plane_create_color_properties(st
EXPORT_SYMBOL(drm_plane_create_color_properties);
/**
+ * drm_plane_create_chroma_siting_properties - chroma siting related plane properties
+ * @plane: plane object
+ *
+ * Create and attach plane specific CHROMA_SITING
+ * properties to @plane.
+ */
+int drm_plane_create_chroma_siting_properties(struct drm_plane *plane,
+ int32_t default_chroma_siting_h,
+ int32_t default_chroma_siting_v)
+{
+ struct drm_device *dev = plane->dev;
+ struct drm_property *prop;
+
+ prop = drm_property_create_range(dev, 0, "CHROMA_SITING_H",
+ 0, 1<<16);
+ if (!prop)
+ return -ENOMEM;
+ plane->chroma_siting_h_property = prop;
+ drm_object_attach_property(&plane->base, prop, default_chroma_siting_h);
+
+ prop = drm_property_create_range(dev, 0, "CHROMA_SITING_V",
+ 0, 1<<16);
+ if (!prop)
+ return -ENOMEM;
+ plane->chroma_siting_v_property = prop;
+ drm_object_attach_property(&plane->base, prop, default_chroma_siting_v);
+
+ if (plane->state) {
+ plane->state->chroma_siting_h = default_chroma_siting_h;
+ plane->state->chroma_siting_v = default_chroma_siting_v;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(drm_plane_create_chroma_siting_properties);
+
+/**
* drm_color_lut_check - check validity of lookup table
* @lut: property blob containing LUT to check
* @tests: bitmask of tests to run
--- a/include/drm/drm_color_mgmt.h
+++ b/include/drm/drm_color_mgmt.h
@@ -93,6 +93,9 @@ int drm_plane_create_color_properties(st
enum drm_color_encoding default_encoding,
enum drm_color_range default_range);
+int drm_plane_create_chroma_siting_properties(struct drm_plane *plane,
+ int32_t default_chroma_siting_h, int32_t default_chroma_siting_v);
+
/**
* enum drm_color_lut_tests - hw-specific LUT tests to perform
*
--- a/include/drm/drm_plane.h
+++ b/include/drm/drm_plane.h
@@ -178,6 +178,24 @@ struct drm_plane_state {
enum drm_color_range color_range;
/**
+ * @chroma_siting_h:
+ *
+ * Location of chroma samples horizontally compared to luma
+ * 0 means chroma is sited with left luma
+ * 0x8000 is interstitial. 0x10000 is sited with right luma
+ */
+ int32_t chroma_siting_h;
+
+ /**
+ * @chroma_siting_v:
+ *
+ * Location of chroma samples vertically compared to luma
+ * 0 means chroma is sited with top luma
+ * 0x8000 is interstitial. 0x10000 is sited with bottom luma
+ */
+ int32_t chroma_siting_v;
+
+ /**
* @fb_damage_clips:
*
* Blob representing damage (area in plane framebuffer that changed
@@ -748,6 +766,24 @@ struct drm_plane {
* scaling.
*/
struct drm_property *scaling_filter_property;
+
+ /**
+ * @chroma_siting_h_property:
+ *
+ * Optional "CHROMA_SITING_H" property for specifying
+ * chroma siting for YUV formats.
+ * See drm_plane_create_chroma_siting_properties().
+ */
+ struct drm_property *chroma_siting_h_property;
+
+ /**
+ * @chroma_siting_v_property:
+ *
+ * Optional "CHROMA_SITING_V" property for specifying
+ * chroma siting for YUV formats.
+ * See drm_plane_create_chroma_siting_properties().
+ */
+ struct drm_property *chroma_siting_v_property;
};
#define obj_to_plane(x) container_of(x, struct drm_plane, base)

View file

@ -0,0 +1,60 @@
From df674e66baf169f020b7d22450295df9bf16f007 Mon Sep 17 00:00:00 2001
From: Dom Cobley <popcornmix@gmail.com>
Date: Thu, 27 Jan 2022 15:32:04 +0000
Subject: [PATCH] vc4/drm:plane: Make use of chroma siting parameter
Signed-off-by: Dom Cobley <popcornmix@gmail.com>
---
drivers/gpu/drm/vc4/vc4_plane.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -467,17 +467,18 @@ static void vc4_write_tpz(struct vc4_pla
/* phase magnitude bits */
#define PHASE_BITS 6
-static void vc4_write_ppf(struct vc4_plane_state *vc4_state, u32 src, u32 dst, u32 xy, int channel)
+static void vc4_write_ppf(struct vc4_plane_state *vc4_state, u32 src, u32 dst, u32 xy, int channel, int chroma_offset)
{
u32 scale = src / dst;
s32 offset, offset2;
s32 phase;
/* Start the phase at 1/2 pixel from the 1st pixel at src_x.
- 1/4 pixel for YUV. */
+ 1/4 pixel for YUV, plus the offset for chroma siting */
if (channel) {
/* the phase is relative to scale_src->x, so shift it for display list's x value */
offset = (xy & 0x1ffff) >> (16 - PHASE_BITS) >> 1;
+ offset -= chroma_offset >> (17 - PHASE_BITS);
offset += -(1 << PHASE_BITS >> 2);
} else {
/* the phase is relative to scale_src->x, so shift it for display list's x value */
@@ -563,13 +564,15 @@ static void vc4_write_scaling_parameters
/* Ch0 H-PPF Word 0: Scaling Parameters */
if (vc4_state->x_scaling[channel] == VC4_SCALING_PPF) {
vc4_write_ppf(vc4_state,
- vc4_state->src_w[channel], vc4_state->crtc_w, vc4_state->src_x, channel);
+ vc4_state->src_w[channel], vc4_state->crtc_w, vc4_state->src_x, channel,
+ state->chroma_siting_h);
}
/* Ch0 V-PPF Words 0-1: Scaling Parameters, Context */
if (vc4_state->y_scaling[channel] == VC4_SCALING_PPF) {
vc4_write_ppf(vc4_state,
- vc4_state->src_h[channel], vc4_state->crtc_h, vc4_state->src_y, channel);
+ vc4_state->src_h[channel], vc4_state->crtc_h, vc4_state->src_y, channel,
+ state->chroma_siting_v);
vc4_dlist_write(vc4_state, 0xc0c0c0c0);
}
@@ -1649,6 +1652,8 @@ struct drm_plane *vc4_plane_init(struct
DRM_COLOR_YCBCR_BT709,
DRM_COLOR_YCBCR_LIMITED_RANGE);
+ drm_plane_create_chroma_siting_properties(plane, 0, 0);
+
if (type == DRM_PLANE_TYPE_PRIMARY)
drm_plane_create_zpos_immutable_property(plane, 0);

View file

@ -0,0 +1,57 @@
From 9d5169f533e9da2b3aac09b3c4e7cc35afa9d8bf Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Fri, 1 Apr 2022 11:31:38 +0100
Subject: [PATCH] drm/vc4: Force trigger of dlist update on margins change
When the margins are changed, the dlist needs to be regenerated
with the changed updated dest regions for each of the planes.
Setting the zpos_changed flag is sufficient to trigger that
without doing a full modeset, therefore set it should the
margins be changed.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/vc4/vc4_crtc.c | 14 ++++++++++----
drivers/gpu/drm/vc4/vc4_drv.h | 7 +------
2 files changed, 11 insertions(+), 10 deletions(-)
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -757,10 +757,16 @@ static int vc4_crtc_atomic_check(struct
if (conn_state->crtc != crtc)
continue;
- vc4_state->margins.left = conn_state->tv.margins.left;
- vc4_state->margins.right = conn_state->tv.margins.right;
- vc4_state->margins.top = conn_state->tv.margins.top;
- vc4_state->margins.bottom = conn_state->tv.margins.bottom;
+ if (memcmp(&vc4_state->margins, &conn_state->tv.margins,
+ sizeof(vc4_state->margins))) {
+ memcpy(&vc4_state->margins, &conn_state->tv.margins,
+ sizeof(vc4_state->margins));
+
+ /* Need to force the dlist entries for all planes to be
+ * updated so that the dest rectangles are changed.
+ */
+ crtc_state->zpos_changed = true;
+ }
break;
}
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -581,12 +581,7 @@ struct vc4_crtc_state {
bool txp_armed;
unsigned int assigned_channel;
- struct {
- unsigned int left;
- unsigned int right;
- unsigned int top;
- unsigned int bottom;
- } margins;
+ struct drm_connector_tv_margins margins;
unsigned long hvs_load;

View file

@ -0,0 +1,121 @@
From 713e11c488cb9066e0c52c1d454773c495ba718f Mon Sep 17 00:00:00 2001
From: Daniel Vetter <daniel.vetter@ffwll.ch>
Date: Fri, 23 Oct 2020 14:39:23 +0200
Subject: [PATCH] drm/atomic-helpers: remove legacy_cursor_update hacks
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The stuff never really worked, and leads to lots of fun because it
out-of-order frees atomic states. Which upsets KASAN, among other
things.
For async updates we now have a more solid solution with the
->atomic_async_check and ->atomic_async_commit hooks. Support for that
for msm and vc4 landed. nouveau and i915 have their own commit
routines, doing something similar.
For everyone else it's probably better to remove the use-after-free
bug, and encourage folks to use the async support instead. The
affected drivers which register a legacy cursor plane and don't either
use the new async stuff or their own commit routine are: amdgpu,
atmel, mediatek, qxl, rockchip, sti, sun4i, tegra, virtio, and vmwgfx.
Inspired by an amdgpu bug report.
v2: Drop RFC, I think with amdgpu converted over to use
atomic_async_check/commit done in
commit 674e78acae0dfb4beb56132e41cbae5b60f7d662
Author: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Date: Wed Dec 5 14:59:07 2018 -0500
drm/amd/display: Add fast path for cursor plane updates
we don't have any driver anymore where we have userspace expecting
solid legacy cursor support _and_ they are using the atomic helpers in
their fully glory. So we can retire this.
v3: Paper over msm and i915 regression. The complete_all is the only
thing missing afaict.
v4: Rebased on recent kernel, added extra link for vc4 bug.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=199425
Link: https://lore.kernel.org/all/20220221134155.125447-9-maxime@cerno.tech/
Cc: mikita.lipski@amd.com
Cc: Michel Dänzer <michel@daenzer.net>
Cc: harry.wentland@amd.com
Cc: Rob Clark <robdclark@gmail.com>
Cc: "Kazlauskas, Nicholas" <nicholas.kazlauskas@amd.com>
Tested-by: Maxime Ripard <maxime@cerno.tech>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
drivers/gpu/drm/drm_atomic_helper.c | 13 -------------
drivers/gpu/drm/i915/display/intel_display.c | 13 +++++++++++++
drivers/gpu/drm/msm/msm_atomic.c | 2 ++
3 files changed, 15 insertions(+), 13 deletions(-)
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1626,13 +1626,6 @@ drm_atomic_helper_wait_for_vblanks(struc
int i, ret;
unsigned int crtc_mask = 0;
- /*
- * Legacy cursor ioctls are completely unsynced, and userspace
- * relies on that (by doing tons of cursor updates).
- */
- if (old_state->legacy_cursor_update)
- return;
-
for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
if (!new_crtc_state->active)
continue;
@@ -2282,12 +2275,6 @@ int drm_atomic_helper_setup_commit(struc
complete_all(&commit->flip_done);
continue;
}
-
- /* Legacy cursor updates are fully unsynced. */
- if (state->legacy_cursor_update) {
- complete_all(&commit->flip_done);
- continue;
- }
if (!new_crtc_state->event) {
commit->event = kzalloc(sizeof(*commit->event),
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -7743,6 +7743,19 @@ static int intel_atomic_commit(struct dr
state->base.legacy_cursor_update = false;
}
+ /*
+ * FIXME: Cut over to (async) commit helpers instead of hand-rolling
+ * everything.
+ */
+ if (state->base.legacy_cursor_update) {
+ struct intel_crtc_state *new_crtc_state;
+ struct intel_crtc *crtc;
+ int i;
+
+ for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i)
+ complete_all(&new_crtc_state->uapi.commit->flip_done);
+ }
+
ret = intel_atomic_prepare_commit(state);
if (ret) {
drm_dbg_atomic(&dev_priv->drm,
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -222,6 +222,8 @@ void msm_atomic_commit_tail(struct drm_a
/* async updates are limited to single-crtc updates: */
WARN_ON(crtc_mask != drm_crtc_mask(async_crtc));
+ complete_all(&async_crtc->state->commit->flip_done);
+
/*
* Start timer if we don't already have an update pending
* on this crtc:

View file

@ -0,0 +1,33 @@
From 8fd080d355a9af07751c2080151347132c8ad1f2 Mon Sep 17 00:00:00 2001
From: Dom Cobley <popcornmix@gmail.com>
Date: Thu, 5 May 2022 18:50:04 +0100
Subject: [PATCH] drm/vc4_hdmi: Force a modeset when Broadcast RGB setting
changes
Without this the change is not visible until the next modeset
Signed-off-by: Dom Cobley <popcornmix@gmail.com>
---
drivers/gpu/drm/vc4/vc4_hdmi.c | 3 +++
1 file changed, 3 insertions(+)
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -536,14 +536,17 @@ static int vc4_hdmi_connector_atomic_che
{
struct drm_connector_state *old_state =
drm_atomic_get_old_connector_state(state, connector);
+ struct vc4_hdmi_connector_state *old_vc4_state = conn_state_to_vc4_hdmi_conn_state(old_state);
struct drm_connector_state *new_state =
drm_atomic_get_new_connector_state(state, connector);
+ struct vc4_hdmi_connector_state *new_vc4_state = conn_state_to_vc4_hdmi_conn_state(new_state);
struct drm_crtc *crtc = new_state->crtc;
if (!crtc)
return 0;
if (old_state->colorspace != new_state->colorspace ||
+ old_vc4_state->broadcast_rgb != new_vc4_state->broadcast_rgb ||
!drm_connector_atomic_hdr_metadata_equal(old_state, new_state)) {
struct drm_crtc_state *crtc_state;

View file

@ -0,0 +1,59 @@
From 34b66f9e18412ee70ff12b1030df625d7adf5a51 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Fri, 1 Apr 2022 17:10:37 +0100
Subject: [PATCH] drm/atomic: If margins are updated, update all planes.
Margins may be implemented by scaling the planes, but as there
is no way of intercepting the set_property for a standard property,
and all planes are checked in drm_atomic_check_only before the
connectors, there's now way to add the planes into the state
from the driver.
If the margin properties change, add all corresponding planes to
the state.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/drm_atomic_uapi.c | 11 +++++++++++
1 file changed, 11 insertions(+)
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -679,6 +679,7 @@ static int drm_atomic_connector_set_prop
{
struct drm_device *dev = connector->dev;
struct drm_mode_config *config = &dev->mode_config;
+ bool margins_updated = false;
bool replaced = false;
int ret;
@@ -698,12 +699,16 @@ static int drm_atomic_connector_set_prop
state->tv.subconnector = val;
} else if (property == config->tv_left_margin_property) {
state->tv.margins.left = val;
+ margins_updated = true;
} else if (property == config->tv_right_margin_property) {
state->tv.margins.right = val;
+ margins_updated = true;
} else if (property == config->tv_top_margin_property) {
state->tv.margins.top = val;
+ margins_updated = true;
} else if (property == config->tv_bottom_margin_property) {
state->tv.margins.bottom = val;
+ margins_updated = true;
} else if (property == config->tv_mode_property) {
state->tv.mode = val;
} else if (property == config->tv_brightness_property) {
@@ -784,6 +789,12 @@ static int drm_atomic_connector_set_prop
return -EINVAL;
}
+ if (margins_updated && state->crtc) {
+ ret = drm_atomic_add_affected_planes(state->state, state->crtc);
+
+ return ret;
+ }
+
return 0;
}

View file

@ -0,0 +1,27 @@
From ee4cb8b3a707633e0f4aa547779c6f860cc61b18 Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime@cerno.tech>
Date: Mon, 6 Dec 2021 16:32:10 +0100
Subject: [PATCH] drm/vc4: hvs: Ignore atomic_flush if we're disabled
atomic_flush will be called for each CRTC even if they aren't enabled.
The whole code we have there will thus run without a properly affected
channel, which can then result in all sorts of weird behaviour.
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
drivers/gpu/drm/vc4/vc4_hvs.c | 3 +++
1 file changed, 3 insertions(+)
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -778,6 +778,9 @@ void vc4_hvs_atomic_flush(struct drm_crt
return;
}
+ if (vc4_state->assigned_channel == VC4_HVS_CHANNEL_DISABLED)
+ return;
+
if (debug_dump_regs) {
DRM_INFO("CRTC %d HVS before:\n", drm_crtc_index(crtc));
vc4_hvs_dump_state(hvs);

View file

@ -0,0 +1,118 @@
From 078bf356a2677a2bfb078aac5ac275e81c31d583 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Fri, 3 Jun 2022 16:49:09 +0100
Subject: [PATCH] drm: vc4: 0 is a valid value for pixel_order_hvs5, so fix
conditionals
vc4_plane_mode_set for HVS5 was using pixel_order unless pixel_order_hvs5
was non-zero, except 0 is a valid value for the pixel_order.
Specify pixel_order_hvs5 for all formats and remove the conditional.
Reported-by: vrazzer <teamvraz@pipmail.net>
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/vc4/vc4_plane.c | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -65,11 +65,13 @@ static const struct hvs_format {
.drm = DRM_FORMAT_RGB565,
.hvs = HVS_PIXEL_FORMAT_RGB565,
.pixel_order = HVS_PIXEL_ORDER_XRGB,
+ .pixel_order_hvs5 = HVS_PIXEL_ORDER_XRGB,
},
{
.drm = DRM_FORMAT_BGR565,
.hvs = HVS_PIXEL_FORMAT_RGB565,
.pixel_order = HVS_PIXEL_ORDER_XBGR,
+ .pixel_order_hvs5 = HVS_PIXEL_ORDER_XBGR,
},
{
.drm = DRM_FORMAT_ARGB1555,
@@ -87,56 +89,67 @@ static const struct hvs_format {
.drm = DRM_FORMAT_RGB888,
.hvs = HVS_PIXEL_FORMAT_RGB888,
.pixel_order = HVS_PIXEL_ORDER_XRGB,
+ .pixel_order_hvs5 = HVS_PIXEL_ORDER_XRGB,
},
{
.drm = DRM_FORMAT_BGR888,
.hvs = HVS_PIXEL_FORMAT_RGB888,
.pixel_order = HVS_PIXEL_ORDER_XBGR,
+ .pixel_order_hvs5 = HVS_PIXEL_ORDER_XBGR,
},
{
.drm = DRM_FORMAT_YUV422,
.hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_3PLANE,
.pixel_order = HVS_PIXEL_ORDER_XYCBCR,
+ .pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCBCR,
},
{
.drm = DRM_FORMAT_YVU422,
.hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_3PLANE,
.pixel_order = HVS_PIXEL_ORDER_XYCRCB,
+ .pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCRCB,
},
{
.drm = DRM_FORMAT_YUV420,
.hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_3PLANE,
.pixel_order = HVS_PIXEL_ORDER_XYCBCR,
+ .pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCBCR,
},
{
.drm = DRM_FORMAT_YVU420,
.hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_3PLANE,
.pixel_order = HVS_PIXEL_ORDER_XYCRCB,
+ .pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCRCB,
},
{
.drm = DRM_FORMAT_NV12,
.hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_2PLANE,
.pixel_order = HVS_PIXEL_ORDER_XYCBCR,
+ .pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCBCR,
},
{
.drm = DRM_FORMAT_NV21,
.hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_2PLANE,
.pixel_order = HVS_PIXEL_ORDER_XYCRCB,
+ .pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCRCB,
},
{
.drm = DRM_FORMAT_NV16,
.hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_2PLANE,
.pixel_order = HVS_PIXEL_ORDER_XYCBCR,
+ .pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCBCR,
},
{
.drm = DRM_FORMAT_NV61,
.hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_2PLANE,
.pixel_order = HVS_PIXEL_ORDER_XYCRCB,
+ .pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCRCB,
},
{
.drm = DRM_FORMAT_P030,
.hvs = HVS_PIXEL_FORMAT_YCBCR_10BIT,
.pixel_order = HVS_PIXEL_ORDER_XYCBCR,
+ .pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCBCR,
.hvs5_only = true,
},
{
@@ -1087,15 +1100,10 @@ static int vc4_plane_mode_set(struct drm
vc4_dlist_write(vc4_state, 0xc0c0c0c0);
} else {
- u32 hvs_pixel_order = format->pixel_order;
-
- if (format->pixel_order_hvs5)
- hvs_pixel_order = format->pixel_order_hvs5;
-
/* Control word */
vc4_dlist_write(vc4_state,
SCALER_CTL0_VALID |
- (hvs_pixel_order << SCALER_CTL0_ORDER_SHIFT) |
+ (format->pixel_order_hvs5 << SCALER_CTL0_ORDER_SHIFT) |
(hvs_format << SCALER_CTL0_PIXEL_FORMAT_SHIFT) |
VC4_SET_FIELD(tiling, SCALER_CTL0_TILING) |
(vc4_state->is_unity ?

View file

@ -0,0 +1,54 @@
From aae9a991d857f49d28bd4b102bf2d41a9b941c21 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Mon, 6 Jun 2022 12:23:28 +0100
Subject: [PATCH] drm: vc4: Omit pixel_order from the hvs_format for hvs5 only
formats
pixel_order is used for the earlier versions of the HVS, so is
redundant on the 10:10:10:2 and 10bit YUV formats that are only
supported on HVS5.
Remove the assignment from the table to avoid confusion.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/vc4/vc4_plane.c | 5 -----
1 file changed, 5 deletions(-)
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -148,35 +148,30 @@ static const struct hvs_format {
{
.drm = DRM_FORMAT_P030,
.hvs = HVS_PIXEL_FORMAT_YCBCR_10BIT,
- .pixel_order = HVS_PIXEL_ORDER_XYCBCR,
.pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCBCR,
.hvs5_only = true,
},
{
.drm = DRM_FORMAT_XRGB2101010,
.hvs = HVS_PIXEL_FORMAT_RGBA1010102,
- .pixel_order = HVS_PIXEL_ORDER_ABGR,
.pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB,
.hvs5_only = true,
},
{
.drm = DRM_FORMAT_ARGB2101010,
.hvs = HVS_PIXEL_FORMAT_RGBA1010102,
- .pixel_order = HVS_PIXEL_ORDER_ABGR,
.pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB,
.hvs5_only = true,
},
{
.drm = DRM_FORMAT_ABGR2101010,
.hvs = HVS_PIXEL_FORMAT_RGBA1010102,
- .pixel_order = HVS_PIXEL_ORDER_ARGB,
.pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR,
.hvs5_only = true,
},
{
.drm = DRM_FORMAT_XBGR2101010,
.hvs = HVS_PIXEL_FORMAT_RGBA1010102,
- .pixel_order = HVS_PIXEL_ORDER_ARGB,
.pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR,
.hvs5_only = true,
},

View file

@ -0,0 +1,104 @@
From 0ced8286b5b6e49895dcaf4e25de2aef1df8073c Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Fri, 3 Jun 2022 16:57:04 +0100
Subject: [PATCH] drm: vc4: Add 3:3:2 and 4:4:4:4 RGB/RGBX/RGBA formats
The hardware supports the 332 8bpp and 4:4:4:4 16bpp formats,
but the table of supported formats didn't include them.
Add them in.
In theory they are supported for T-format as well as linear,
but without a way to test them just add them as linear for now.
Suggested-by: vrazzer <teamvraz@pipmail.net>
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/vc4/vc4_plane.c | 70 +++++++++++++++++++++++++++++++++
1 file changed, 70 insertions(+)
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -175,6 +175,66 @@ static const struct hvs_format {
.pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR,
.hvs5_only = true,
},
+ {
+ .drm = DRM_FORMAT_RGB332,
+ .hvs = HVS_PIXEL_FORMAT_RGB332,
+ .pixel_order = HVS_PIXEL_ORDER_ARGB,
+ .pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB,
+ },
+ {
+ .drm = DRM_FORMAT_BGR233,
+ .hvs = HVS_PIXEL_FORMAT_RGB332,
+ .pixel_order = HVS_PIXEL_ORDER_ABGR,
+ .pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR,
+ },
+ {
+ .drm = DRM_FORMAT_XRGB4444,
+ .hvs = HVS_PIXEL_FORMAT_RGBA4444,
+ .pixel_order = HVS_PIXEL_ORDER_ABGR,
+ .pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB,
+ },
+ {
+ .drm = DRM_FORMAT_ARGB4444,
+ .hvs = HVS_PIXEL_FORMAT_RGBA4444,
+ .pixel_order = HVS_PIXEL_ORDER_ABGR,
+ .pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB,
+ },
+ {
+ .drm = DRM_FORMAT_XBGR4444,
+ .hvs = HVS_PIXEL_FORMAT_RGBA4444,
+ .pixel_order = HVS_PIXEL_ORDER_ARGB,
+ .pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR,
+ },
+ {
+ .drm = DRM_FORMAT_ABGR4444,
+ .hvs = HVS_PIXEL_FORMAT_RGBA4444,
+ .pixel_order = HVS_PIXEL_ORDER_ARGB,
+ .pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR,
+ },
+ {
+ .drm = DRM_FORMAT_BGRX4444,
+ .hvs = HVS_PIXEL_FORMAT_RGBA4444,
+ .pixel_order = HVS_PIXEL_ORDER_RGBA,
+ .pixel_order_hvs5 = HVS_PIXEL_ORDER_BGRA,
+ },
+ {
+ .drm = DRM_FORMAT_BGRA4444,
+ .hvs = HVS_PIXEL_FORMAT_RGBA4444,
+ .pixel_order = HVS_PIXEL_ORDER_RGBA,
+ .pixel_order_hvs5 = HVS_PIXEL_ORDER_BGRA,
+ },
+ {
+ .drm = DRM_FORMAT_RGBX4444,
+ .hvs = HVS_PIXEL_FORMAT_RGBA4444,
+ .pixel_order = HVS_PIXEL_ORDER_BGRA,
+ .pixel_order_hvs5 = HVS_PIXEL_ORDER_RGBA,
+ },
+ {
+ .drm = DRM_FORMAT_RGBA4444,
+ .hvs = HVS_PIXEL_FORMAT_RGBA4444,
+ .pixel_order = HVS_PIXEL_ORDER_BGRA,
+ .pixel_order_hvs5 = HVS_PIXEL_ORDER_RGBA,
+ },
};
static const struct hvs_format *vc4_get_hvs_format(u32 drm_format)
@@ -1575,6 +1635,16 @@ static bool vc4_format_mod_supported(str
case DRM_FORMAT_BGRX1010102:
case DRM_FORMAT_RGBA1010102:
case DRM_FORMAT_BGRA1010102:
+ case DRM_FORMAT_XRGB4444:
+ case DRM_FORMAT_ARGB4444:
+ case DRM_FORMAT_XBGR4444:
+ case DRM_FORMAT_ABGR4444:
+ case DRM_FORMAT_RGBX4444:
+ case DRM_FORMAT_RGBA4444:
+ case DRM_FORMAT_BGRX4444:
+ case DRM_FORMAT_BGRA4444:
+ case DRM_FORMAT_RGB332:
+ case DRM_FORMAT_BGR233:
case DRM_FORMAT_YUV422:
case DRM_FORMAT_YVU422:
case DRM_FORMAT_YUV420:

View file

@ -0,0 +1,36 @@
From 4f34c62b2e8672806287e789f126780cf7ecc93b Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Mon, 6 Jun 2022 14:53:56 +0100
Subject: [PATCH] drm: vc4: Add comments for which HVS_PIXEL_ORDER_xxx defines
apply
The HVS_PIXEL_ORDER_xxx defines apply to specific HVS_PIXEL_FORMAT_xxx
modes, so add comments to make this obvious.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/vc4/vc4_regs.h | 3 +++
1 file changed, 3 insertions(+)
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -870,16 +870,19 @@ enum hvs_pixel_format {
/* Note: the LSB is the rightmost character shown. Only valid for
* HVS_PIXEL_FORMAT_RGB8888, not RGB888.
*/
+/* For modes 332, 4444, 555, 5551, 6666, 8888, 10:10:10:2 */
#define HVS_PIXEL_ORDER_RGBA 0
#define HVS_PIXEL_ORDER_BGRA 1
#define HVS_PIXEL_ORDER_ARGB 2
#define HVS_PIXEL_ORDER_ABGR 3
+/* For modes 666 and 888 (4 & 5) */
#define HVS_PIXEL_ORDER_XBRG 0
#define HVS_PIXEL_ORDER_XRBG 1
#define HVS_PIXEL_ORDER_XRGB 2
#define HVS_PIXEL_ORDER_XBGR 3
+/* For YCbCr modes (8-12, and 17) */
#define HVS_PIXEL_ORDER_XYCBCR 0
#define HVS_PIXEL_ORDER_XYCRCB 1
#define HVS_PIXEL_ORDER_YXCBCR 2

View file

@ -0,0 +1,87 @@
From e8bb5f7a69eeb3493659a72a6fc003eabfc005b1 Mon Sep 17 00:00:00 2001
From: Phil Elwell <8911409+pelwell@users.noreply.github.com>
Date: Wed, 24 Aug 2022 11:14:40 +0100
Subject: [PATCH] drm/vc4: Add async update support for cursor planes
Now that cursors are implemented as regular planes, all cursor
movements result in atomic updates. As the firmware-kms driver
doesn't support asynchronous updates, these are synchronous, which
limits the update rate to the screen refresh rate. Xorg seems unaware
of this (or at least of the effect of this), because if the mouse is
configured with a higher update rate than the screen then continuous
mouse movement results in an increasing backlog of mouse events -
cue extreme lag.
Add minimal support for asynchronous updates - limited to cursor
planes - to eliminate the lag.
See: https://github.com/raspberrypi/linux/pull/4971
https://github.com/raspberrypi/linux/issues/4988
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
---
drivers/gpu/drm/vc4/vc4_firmware_kms.c | 46 ++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
@@ -675,6 +675,50 @@ static int vc4_plane_atomic_check(struct
return vc4_plane_to_mb(plane, &vc4_plane->mb, new_plane_state);
}
+static void vc4_plane_atomic_async_update(struct drm_plane *plane,
+ struct drm_atomic_state *state)
+{
+ struct drm_plane_state *new_plane_state =
+ drm_atomic_get_new_plane_state(state, plane);
+
+ swap(plane->state->fb, new_plane_state->fb);
+ plane->state->crtc_x = new_plane_state->crtc_x;
+ plane->state->crtc_y = new_plane_state->crtc_y;
+ plane->state->crtc_w = new_plane_state->crtc_w;
+ plane->state->crtc_h = new_plane_state->crtc_h;
+ plane->state->src_x = new_plane_state->src_x;
+ plane->state->src_y = new_plane_state->src_y;
+ plane->state->src_w = new_plane_state->src_w;
+ plane->state->src_h = new_plane_state->src_h;
+ plane->state->alpha = new_plane_state->alpha;
+ plane->state->pixel_blend_mode = new_plane_state->pixel_blend_mode;
+ plane->state->rotation = new_plane_state->rotation;
+ plane->state->zpos = new_plane_state->zpos;
+ plane->state->normalized_zpos = new_plane_state->normalized_zpos;
+ plane->state->color_encoding = new_plane_state->color_encoding;
+ plane->state->color_range = new_plane_state->color_range;
+ plane->state->src = new_plane_state->src;
+ plane->state->dst = new_plane_state->dst;
+ plane->state->visible = new_plane_state->visible;
+
+ vc4_plane_set_blank(plane, false);
+}
+
+static int vc4_plane_atomic_async_check(struct drm_plane *plane,
+ struct drm_atomic_state *state)
+{
+ struct drm_plane_state *new_plane_state =
+ drm_atomic_get_new_plane_state(state, plane);
+ int ret = -EINVAL;
+
+ if (plane->type == 2 &&
+ plane->state->fb &&
+ new_plane_state->crtc->state->active)
+ ret = 0;
+
+ return ret;
+}
+
/* Called during init to allocate the plane's atomic state. */
static void vc4_plane_reset(struct drm_plane *plane)
{
@@ -769,6 +813,8 @@ static const struct drm_plane_helper_fun
.atomic_check = vc4_plane_atomic_check,
.atomic_update = vc4_plane_atomic_update,
.atomic_disable = vc4_plane_atomic_disable,
+ .atomic_async_check = vc4_plane_atomic_async_check,
+ .atomic_async_update = vc4_plane_atomic_async_update,
};
static struct drm_plane *vc4_fkms_plane_init(struct drm_device *dev,

View file

@ -0,0 +1,96 @@
From 482f1cbc27b336c12cbea38360a580cc0c8a8e62 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Thu, 11 Aug 2022 13:49:16 +0100
Subject: [PATCH] drm/vc4: Configure the HVS COB allocations
The HVS Composite Output Buffer (COB) is the memory used to
generate the output pixel data.
Until now the vc4 driver has been relying on the firmware to
have set these to sensible values.
In testing triple screen support it has been noted that only
1 line was being assigned to HVS channel 2. Whilst that is fine
for the transposer (TXP), and indeed needed as only some pixels
have an alpha channel, it is insufficient to run a live display.
Split the COB more evenly between the 3 HVS channels.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Revert vc4_regs change
---
drivers/gpu/drm/vc4/vc4_hvs.c | 56 ++++++++++++++++++++++++++++++++++-
1 file changed, 55 insertions(+), 1 deletion(-)
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -1013,7 +1013,7 @@ static int vc4_hvs_bind(struct device *d
struct vc4_hvs *hvs = NULL;
int ret;
u32 dispctrl;
- u32 reg;
+ u32 reg, top;
hvs = drmm_kzalloc(drm, sizeof(*hvs), GFP_KERNEL);
if (!hvs)
@@ -1151,6 +1151,60 @@ static int vc4_hvs_bind(struct device *d
HVS_WRITE(SCALER_DISPCTRL, dispctrl);
+ /* Recompute Composite Output Buffer (COB) allocations for the displays
+ */
+ if (!vc4->is_vc5) {
+ /* The COB is 20736 pixels, or just over 10 lines at 2048 wide.
+ * The bottom 2048 pixels are full 32bpp RGBA (intended for the
+ * TXP composing RGBA to memory), whilst the remainder are only
+ * 24bpp RGB.
+ *
+ * Assign 3 lines to channels 1 & 2, and just over 4 lines to
+ * channel 0.
+ */
+ #define VC4_COB_SIZE 20736
+ #define VC4_COB_LINE_WIDTH 2048
+ #define VC4_COB_NUM_LINES 3
+ reg = 0;
+ top = VC4_COB_LINE_WIDTH * VC4_COB_NUM_LINES;
+ reg |= (top - 1) << 16;
+ HVS_WRITE(SCALER_DISPBASE2, reg);
+ reg = top;
+ top += VC4_COB_LINE_WIDTH * VC4_COB_NUM_LINES;
+ reg |= (top - 1) << 16;
+ HVS_WRITE(SCALER_DISPBASE1, reg);
+ reg = top;
+ top = VC4_COB_SIZE;
+ reg |= (top - 1) << 16;
+ HVS_WRITE(SCALER_DISPBASE0, reg);
+ } else {
+ /* The COB is 44416 pixels, or 10.8 lines at 4096 wide.
+ * The bottom 4096 pixels are full RGBA (intended for the TXP
+ * composing RGBA to memory), whilst the remainder are only
+ * RGB. Addressing is always pixel wide.
+ *
+ * Assign 3 lines of 4096 to channels 1 & 2, and just over 4
+ * lines. to channel 0.
+ */
+ #define VC5_COB_SIZE 44416
+ #define VC5_COB_LINE_WIDTH 4096
+ #define VC5_COB_NUM_LINES 3
+ reg = 0;
+ top = VC5_COB_LINE_WIDTH * VC5_COB_NUM_LINES;
+ reg |= top << 16;
+ HVS_WRITE(SCALER_DISPBASE2, reg);
+ top += 16;
+ reg = top;
+ top += VC5_COB_LINE_WIDTH * VC5_COB_NUM_LINES;
+ reg |= top << 16;
+ HVS_WRITE(SCALER_DISPBASE1, reg);
+ top += 16;
+ reg = top;
+ top = VC5_COB_SIZE;
+ reg |= top << 16;
+ HVS_WRITE(SCALER_DISPBASE0, reg);
+ }
+
ret = devm_request_irq(dev, platform_get_irq(pdev, 0),
vc4_hvs_irq_handler, 0, "vc4 hvs", drm);
if (ret)

View file

@ -0,0 +1,39 @@
From 87fed1718f9ce64127dea253c37a9f13ec987ee0 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Thu, 11 Aug 2022 13:59:34 +0100
Subject: [PATCH] drm/vc4: Set AXI panic modes for the HVS
The HVS can change AXI request mode based on how full the COB
FIFOs are.
Until now the vc4 driver has been relying on the firmware to
have set these to sensible values.
With HVS channel 2 now being used for live video, change the
panic mode for all channels to be explicitly set by the driver,
and the same for all channels.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/vc4/vc4_hvs.c | 11 +++++++++++
1 file changed, 11 insertions(+)
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -1149,6 +1149,17 @@ static int vc4_hvs_bind(struct device *d
dispctrl |= VC4_SET_FIELD(2, SCALER_DISPCTRL_PANIC1);
dispctrl |= VC4_SET_FIELD(2, SCALER_DISPCTRL_PANIC2);
+ /* Set AXI panic mode.
+ * VC4 panics when < 2 lines in FIFO.
+ * VC5 panics when less than 1 line in the FIFO.
+ */
+ dispctrl &= ~(SCALER_DISPCTRL_PANIC0_MASK |
+ SCALER_DISPCTRL_PANIC1_MASK |
+ SCALER_DISPCTRL_PANIC2_MASK);
+ dispctrl |= VC4_SET_FIELD(2, SCALER_DISPCTRL_PANIC0);
+ dispctrl |= VC4_SET_FIELD(2, SCALER_DISPCTRL_PANIC1);
+ dispctrl |= VC4_SET_FIELD(2, SCALER_DISPCTRL_PANIC2);
+
HVS_WRITE(SCALER_DISPCTRL, dispctrl);
/* Recompute Composite Output Buffer (COB) allocations for the displays

View file

@ -0,0 +1,25 @@
From 816a2693d6dd7058f96b0f8d089ec1ece8b6db14 Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime@cerno.tech>
Date: Mon, 11 Jul 2022 10:38:25 +0200
Subject: [PATCH] drm/vc4: hvs: Skip DebugFS Registration for FKMS
FKMS doesn't have an HVS and it's expected. Return from the debugfs init
function immediately if we're running with fkms.
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
drivers/gpu/drm/vc4/vc4_hvs.c | 3 +++
1 file changed, 3 insertions(+)
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -975,6 +975,9 @@ int vc4_hvs_debugfs_init(struct drm_mino
struct vc4_hvs *hvs = vc4->hvs;
int ret;
+ if (vc4->firmware_kms)
+ return 0;
+
if (!vc4->hvs)
return -ENODEV;

View file

@ -0,0 +1,39 @@
From e2339bd2c4fd484b8be3e2b662bfaf514834e3c7 Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime@cerno.tech>
Date: Mon, 15 Aug 2022 13:34:02 +0200
Subject: [PATCH] media: uapi: Add some RGB bus formats for VC4 DPI output
The VC4 DPI controller can output more RGB formats that aren't described
through a media bus format yet, so let's add them.
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
include/uapi/linux/media-bus-format.h | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
--- a/include/uapi/linux/media-bus-format.h
+++ b/include/uapi/linux/media-bus-format.h
@@ -34,19 +34,22 @@
#define MEDIA_BUS_FMT_FIXED 0x0001
-/* RGB - next is 0x1022 */
+/* RGB - next is 0x1025 */
#define MEDIA_BUS_FMT_RGB444_1X12 0x1016
#define MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE 0x1001
#define MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE 0x1002
#define MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE 0x1003
#define MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE 0x1004
#define MEDIA_BUS_FMT_RGB565_1X16 0x1017
+#define MEDIA_BUS_FMT_RGB565_1X24_CPADHI 0x1022
#define MEDIA_BUS_FMT_BGR565_2X8_BE 0x1005
#define MEDIA_BUS_FMT_BGR565_2X8_LE 0x1006
#define MEDIA_BUS_FMT_RGB565_2X8_BE 0x1007
#define MEDIA_BUS_FMT_RGB565_2X8_LE 0x1008
+#define MEDIA_BUS_FMT_BGR666_1X18 0x1023
#define MEDIA_BUS_FMT_RGB666_1X18 0x1009
#define MEDIA_BUS_FMT_RBG888_1X24 0x100e
+#define MEDIA_BUS_FMT_BGR666_1X24_CPADHI 0x1024
#define MEDIA_BUS_FMT_RGB666_1X24_CPADHI 0x1015
#define MEDIA_BUS_FMT_RGB666_1X7X3_SPWG 0x1010
#define MEDIA_BUS_FMT_BGR888_1X24 0x1013

View file

@ -0,0 +1,99 @@
From f4f85afe1641fc846b011dff80ef5c0b6b206258 Mon Sep 17 00:00:00 2001
From: Dom Cobley <popcornmix@gmail.com>
Date: Thu, 7 Apr 2022 18:23:07 +0100
Subject: [PATCH] raspberrypi-firmware: Update mailbox commands
Signed-off-by: Dom Cobley <popcornmix@gmail.com>
---
include/soc/bcm2835/raspberrypi-firmware.h | 28 +++++++++++++++++++++-
1 file changed, 27 insertions(+), 1 deletion(-)
--- a/include/soc/bcm2835/raspberrypi-firmware.h
+++ b/include/soc/bcm2835/raspberrypi-firmware.h
@@ -36,6 +36,8 @@ struct rpi_firmware_property_tag_header
enum rpi_firmware_property_tag {
RPI_FIRMWARE_PROPERTY_END = 0,
RPI_FIRMWARE_GET_FIRMWARE_REVISION = 0x00000001,
+ RPI_FIRMWARE_GET_FIRMWARE_VARIANT = 0x00000002,
+ RPI_FIRMWARE_GET_FIRMWARE_HASH = 0x00000003,
RPI_FIRMWARE_SET_CURSOR_INFO = 0x00008010,
RPI_FIRMWARE_SET_CURSOR_STATE = 0x00008011,
@@ -71,6 +73,7 @@ enum rpi_firmware_property_tag {
RPI_FIRMWARE_GET_DISPMANX_RESOURCE_MEM_HANDLE = 0x00030014,
RPI_FIRMWARE_GET_EDID_BLOCK = 0x00030020,
RPI_FIRMWARE_GET_CUSTOMER_OTP = 0x00030021,
+ RPI_FIRMWARE_GET_EDID_BLOCK_DISPLAY = 0x00030023,
RPI_FIRMWARE_GET_DOMAIN_STATE = 0x00030030,
RPI_FIRMWARE_GET_THROTTLED = 0x00030046,
RPI_FIRMWARE_GET_CLOCK_MEASURED = 0x00030047,
@@ -89,8 +92,11 @@ enum rpi_firmware_property_tag {
RPI_FIRMWARE_GET_PERIPH_REG = 0x00030045,
RPI_FIRMWARE_SET_PERIPH_REG = 0x00038045,
RPI_FIRMWARE_GET_POE_HAT_VAL = 0x00030049,
- RPI_FIRMWARE_SET_POE_HAT_VAL = 0x00030050,
+ RPI_FIRMWARE_SET_POE_HAT_VAL = 0x00038049,
+ RPI_FIRMWARE_SET_POE_HAT_VAL_OLD = 0x00030050,
RPI_FIRMWARE_NOTIFY_XHCI_RESET = 0x00030058,
+ RPI_FIRMWARE_GET_REBOOT_FLAGS = 0x00030064,
+ RPI_FIRMWARE_SET_REBOOT_FLAGS = 0x00038064,
RPI_FIRMWARE_NOTIFY_DISPLAY_DONE = 0x00030066,
/* Dispmanx TAGS */
@@ -105,9 +111,16 @@ enum rpi_firmware_property_tag {
RPI_FIRMWARE_FRAMEBUFFER_GET_VIRTUAL_OFFSET = 0x00040009,
RPI_FIRMWARE_FRAMEBUFFER_GET_OVERSCAN = 0x0004000a,
RPI_FIRMWARE_FRAMEBUFFER_GET_PALETTE = 0x0004000b,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_LAYER = 0x0004000c,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_TRANSFORM = 0x0004000d,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_VSYNC = 0x0004000e,
RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF = 0x0004000f,
RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF = 0x00040010,
RPI_FIRMWARE_FRAMEBUFFER_RELEASE = 0x00048001,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_ID = 0x00040016,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM = 0x00048013,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_NUM_DISPLAYS = 0x00040013,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_SETTINGS = 0x00040014,
RPI_FIRMWARE_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT = 0x00044003,
RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT = 0x00044004,
RPI_FIRMWARE_FRAMEBUFFER_TEST_DEPTH = 0x00044005,
@@ -116,26 +129,39 @@ enum rpi_firmware_property_tag {
RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_OFFSET = 0x00044009,
RPI_FIRMWARE_FRAMEBUFFER_TEST_OVERSCAN = 0x0004400a,
RPI_FIRMWARE_FRAMEBUFFER_TEST_PALETTE = 0x0004400b,
+ RPI_FIRMWARE_FRAMEBUFFER_TEST_LAYER = 0x0004400c,
+ RPI_FIRMWARE_FRAMEBUFFER_TEST_TRANSFORM = 0x0004400d,
RPI_FIRMWARE_FRAMEBUFFER_TEST_VSYNC = 0x0004400e,
RPI_FIRMWARE_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003,
RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004,
RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH = 0x00048005,
RPI_FIRMWARE_FRAMEBUFFER_SET_PIXEL_ORDER = 0x00048006,
RPI_FIRMWARE_FRAMEBUFFER_SET_ALPHA_MODE = 0x00048007,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH = 0x00048008,
RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009,
RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a,
RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE = 0x0004800b,
+
RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF = 0x0004801f,
RPI_FIRMWARE_FRAMEBUFFER_SET_GPIOVIRTBUF = 0x00048020,
RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC = 0x0004800e,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_LAYER = 0x0004800c,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_TRANSFORM = 0x0004800d,
RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f,
RPI_FIRMWARE_VCHIQ_INIT = 0x00048010,
+ RPI_FIRMWARE_SET_PLANE = 0x00048015,
+ RPI_FIRMWARE_GET_DISPLAY_TIMING = 0x00040017,
+ RPI_FIRMWARE_SET_TIMING = 0x00048017,
+ RPI_FIRMWARE_GET_DISPLAY_CFG = 0x00040018,
+ RPI_FIRMWARE_SET_DISPLAY_POWER = 0x00048019,
RPI_FIRMWARE_GET_COMMAND_LINE = 0x00050001,
RPI_FIRMWARE_GET_DMA_CHANNELS = 0x00060001,
};
+#define GET_DISPLAY_SETTINGS_PAYLOAD_SIZE 64
+
#if IS_ENABLED(CONFIG_RASPBERRYPI_FIRMWARE)
int rpi_firmware_property(struct rpi_firmware *fw,
u32 tag, void *data, size_t len);

View file

@ -0,0 +1,70 @@
From e8d0e03fcc00e871ecf963838d99b91b992252ea Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime@cerno.tech>
Date: Mon, 11 Jul 2022 15:58:36 +0200
Subject: [PATCH] clk: bcm: rpi: Create helper to retrieve private data
The RaspberryPi firmware clocks driver uses in several instances a
container_of to retrieve the struct raspberrypi_clk_data from a pointer
to struct clk_hw. Let's create a small function to avoid duplicating it
all over the place.
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
drivers/clk/bcm/clk-raspberrypi.c | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
--- a/drivers/clk/bcm/clk-raspberrypi.c
+++ b/drivers/clk/bcm/clk-raspberrypi.c
@@ -75,6 +75,12 @@ struct raspberrypi_clk_data {
struct raspberrypi_clk *rpi;
};
+static inline
+const struct raspberrypi_clk_data *clk_hw_to_data(const struct clk_hw *hw)
+{
+ return container_of(hw, struct raspberrypi_clk_data, hw);
+}
+
struct raspberrypi_clk_variant {
bool export;
char *clkdev;
@@ -187,8 +193,7 @@ static int raspberrypi_clock_property(st
static int raspberrypi_fw_is_prepared(struct clk_hw *hw)
{
- struct raspberrypi_clk_data *data =
- container_of(hw, struct raspberrypi_clk_data, hw);
+ const struct raspberrypi_clk_data *data = clk_hw_to_data(hw);
struct raspberrypi_clk *rpi = data->rpi;
u32 val = 0;
int ret;
@@ -205,8 +210,7 @@ static int raspberrypi_fw_is_prepared(st
static unsigned long raspberrypi_fw_get_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct raspberrypi_clk_data *data =
- container_of(hw, struct raspberrypi_clk_data, hw);
+ const struct raspberrypi_clk_data *data = clk_hw_to_data(hw);
struct raspberrypi_clk *rpi = data->rpi;
u32 val = 0;
int ret;
@@ -222,8 +226,7 @@ static unsigned long raspberrypi_fw_get_
static int raspberrypi_fw_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- struct raspberrypi_clk_data *data =
- container_of(hw, struct raspberrypi_clk_data, hw);
+ const struct raspberrypi_clk_data *data = clk_hw_to_data(hw);
struct raspberrypi_clk *rpi = data->rpi;
u32 _rate = rate;
int ret;
@@ -240,8 +243,7 @@ static int raspberrypi_fw_set_rate(struc
static int raspberrypi_fw_dumb_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
- struct raspberrypi_clk_data *data =
- container_of(hw, struct raspberrypi_clk_data, hw);
+ const struct raspberrypi_clk_data *data = clk_hw_to_data(hw);
struct raspberrypi_clk_variant *variant = data->variant;
/*

View file

@ -0,0 +1,24 @@
From 59af37c19b6ceb1caa4f8aa144d114c30667961b Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime@cerno.tech>
Date: Mon, 6 Jun 2022 11:02:16 +0200
Subject: [PATCH] arm64: setup: Fix build warning
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
arch/arm64/kernel/setup.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -222,9 +222,9 @@ static void __init request_standard_reso
size_t res_size;
kernel_code.start = __pa_symbol(_stext);
- kernel_code.end = __pa_symbol(__init_begin - 1);
+ kernel_code.end = __pa_symbol(__init_begin) - 1;
kernel_data.start = __pa_symbol(_sdata);
- kernel_data.end = __pa_symbol(_end - 1);
+ kernel_data.end = __pa_symbol(_end) - 1;
insert_resource(&iomem_resource, &kernel_code);
insert_resource(&iomem_resource, &kernel_data);

View file

@ -0,0 +1,22 @@
From e83914825e59198988203f5ed879a64f3557b280 Mon Sep 17 00:00:00 2001
From: Dom Cobley <popcornmix@gmail.com>
Date: Tue, 12 Apr 2022 20:07:20 +0100
Subject: [PATCH] clk-raspberrypi: Add ISP to exported clocks
Signed-off-by: Dom Cobley <popcornmix@gmail.com>
---
drivers/clk/bcm/clk-raspberrypi.c | 3 +++
1 file changed, 3 insertions(+)
--- a/drivers/clk/bcm/clk-raspberrypi.c
+++ b/drivers/clk/bcm/clk-raspberrypi.c
@@ -143,6 +143,9 @@ raspberrypi_clk_variants[RPI_FIRMWARE_NU
[RPI_FIRMWARE_HEVC_CLK_ID] = {
.export = true,
},
+ [RPI_FIRMWARE_ISP_CLK_ID] = {
+ .export = true,
+ },
[RPI_FIRMWARE_PIXEL_BVB_CLK_ID] = {
.export = true,
},

View file

@ -0,0 +1,45 @@
From ae2e43a22f1044d9a1d5ea1f9c23871a8a2e1ae8 Mon Sep 17 00:00:00 2001
From: Martin Sperl <kernel@martin.sperl.org>
Date: Fri, 2 Sep 2016 16:45:27 +0100
Subject: [PATCH] Register the clocks early during the boot process, so that
special/critical clocks can get enabled early on in the boot process avoiding
the risk of disabling a clock, pll_divider or pll when a claiming driver
fails to install propperly - maybe it needs to defer.
Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
---
drivers/clk/bcm/clk-bcm2835.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -2319,8 +2319,15 @@ static int bcm2835_clk_probe(struct plat
if (ret)
return ret;
- return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
+ ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
&cprman->onecell);
+ if (ret)
+ return ret;
+
+ /* note that we have registered all the clocks */
+ dev_dbg(dev, "registered %d clocks\n", asize);
+
+ return 0;
}
static const struct cprman_plat_data cprman_bcm2835_plat_data = {
@@ -2346,7 +2353,11 @@ static struct platform_driver bcm2835_cl
.probe = bcm2835_clk_probe,
};
-builtin_platform_driver(bcm2835_clk_driver);
+static int __init __bcm2835_clk_driver_init(void)
+{
+ return platform_driver_register(&bcm2835_clk_driver);
+}
+core_initcall(__bcm2835_clk_driver_init);
MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
MODULE_DESCRIPTION("BCM2835 clock driver");

View file

@ -0,0 +1,28 @@
From 2f4b354fedfd33cd996d261f66c887a87cbee641 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Mon, 13 Feb 2017 17:20:08 +0000
Subject: [PATCH] clk-bcm2835: Mark used PLLs and dividers CRITICAL
The VPU configures and relies on several PLLs and dividers. Mark all
enabled dividers and their PLLs as CRITICAL to prevent the kernel from
switching them off.
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
---
drivers/clk/bcm/clk-bcm2835.c | 5 +++++
1 file changed, 5 insertions(+)
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -1407,6 +1407,11 @@ bcm2835_register_pll_divider(struct bcm2
divider->div.hw.init = &init;
divider->div.table = NULL;
+ if (!(cprman_read(cprman, divider_data->cm_reg) & divider_data->hold_mask)) {
+ init.flags |= CLK_IS_CRITICAL;
+ divider->div.flags |= CLK_IS_CRITICAL;
+ }
+
divider->cprman = cprman;
divider->data = divider_data;

View file

@ -0,0 +1,118 @@
From 2bd63288dcd33f32b529ef073e9b716444846e48 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Mon, 13 Feb 2017 17:20:08 +0000
Subject: [PATCH] clk-bcm2835: Add claim-clocks property
The claim-clocks property can be used to prevent PLLs and dividers
from being marked as critical. It contains a vector of clock IDs,
as defined by dt-bindings/clock/bcm2835.h.
Use this mechanism to claim PLLD_DSI0, PLLD_DSI1, PLLH_AUX and
PLLH_PIX for the vc4_kms_v3d driver.
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
---
drivers/clk/bcm/clk-bcm2835.c | 43 +++++++++++++++++++++++++++++++++--
1 file changed, 41 insertions(+), 2 deletions(-)
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -1335,6 +1335,8 @@ static const struct clk_ops bcm2835_vpu_
.debug_init = bcm2835_clock_debug_init,
};
+static bool bcm2835_clk_is_claimed(const char *name);
+
static struct clk_hw *bcm2835_register_pll(struct bcm2835_cprman *cprman,
const void *data)
{
@@ -1352,6 +1354,9 @@ static struct clk_hw *bcm2835_register_p
init.ops = &bcm2835_pll_clk_ops;
init.flags = pll_data->flags | CLK_IGNORE_UNUSED;
+ if (!bcm2835_clk_is_claimed(pll_data->name))
+ init.flags |= CLK_IS_CRITICAL;
+
pll = kzalloc(sizeof(*pll), GFP_KERNEL);
if (!pll)
return NULL;
@@ -1408,8 +1413,10 @@ bcm2835_register_pll_divider(struct bcm2
divider->div.table = NULL;
if (!(cprman_read(cprman, divider_data->cm_reg) & divider_data->hold_mask)) {
- init.flags |= CLK_IS_CRITICAL;
- divider->div.flags |= CLK_IS_CRITICAL;
+ if (!bcm2835_clk_is_claimed(divider_data->source_pll))
+ init.flags |= CLK_IS_CRITICAL;
+ if (!bcm2835_clk_is_claimed(divider_data->name))
+ divider->div.flags |= CLK_IS_CRITICAL;
}
divider->cprman = cprman;
@@ -1466,6 +1473,15 @@ static struct clk_hw *bcm2835_register_c
init.flags = clock_data->flags | CLK_IGNORE_UNUSED;
/*
+ * Some GPIO clocks for ethernet/wifi PLLs are marked as
+ * critical (since some platforms use them), but if the
+ * firmware didn't have them turned on then they clearly
+ * aren't actually critical.
+ */
+ if ((cprman_read(cprman, clock_data->ctl_reg) & CM_ENABLE) == 0)
+ init.flags &= ~CLK_IS_CRITICAL;
+
+ /*
* Pass the CLK_SET_RATE_PARENT flag if we are allowed to propagate
* rate changes on at least of the parents.
*/
@@ -2245,6 +2261,8 @@ static const struct bcm2835_clk_desc clk
.ctl_reg = CM_PERIICTL),
};
+static bool bcm2835_clk_claimed[ARRAY_SIZE(clk_desc_array)];
+
/*
* Permanently take a reference on the parent of the SDRAM clock.
*
@@ -2264,6 +2282,19 @@ static int bcm2835_mark_sdc_parent_criti
return clk_prepare_enable(parent);
}
+static bool bcm2835_clk_is_claimed(const char *name)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(clk_desc_array); i++) {
+ const char *clk_name = *(const char **)(clk_desc_array[i].data);
+ if (!strcmp(name, clk_name))
+ return bcm2835_clk_claimed[i];
+ }
+
+ return false;
+}
+
static int bcm2835_clk_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -2273,6 +2304,7 @@ static int bcm2835_clk_probe(struct plat
const size_t asize = ARRAY_SIZE(clk_desc_array);
const struct cprman_plat_data *pdata;
size_t i;
+ u32 clk_id;
int ret;
pdata = of_device_get_match_data(&pdev->dev);
@@ -2291,6 +2323,13 @@ static int bcm2835_clk_probe(struct plat
if (IS_ERR(cprman->regs))
return PTR_ERR(cprman->regs);
+ memset(bcm2835_clk_claimed, 0, sizeof(bcm2835_clk_claimed));
+ for (i = 0;
+ !of_property_read_u32_index(pdev->dev.of_node, "claim-clocks",
+ i, &clk_id);
+ i++)
+ bcm2835_clk_claimed[clk_id]= true;
+
memcpy(cprman->real_parent_names, cprman_parent_names,
sizeof(cprman_parent_names));
of_clk_parent_fill(dev->of_node, cprman->real_parent_names,

View file

@ -0,0 +1,115 @@
From 34a1764a301c3a18ec016f4331ba104d7cd38f26 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Mon, 6 Mar 2017 09:06:18 +0000
Subject: [PATCH] clk-bcm2835: Read max core clock from firmware
The VPU is responsible for managing the core clock, usually under
direction from the bcm2835-cpufreq driver but not via the clk-bcm2835
driver. Since the core frequency can change without warning, it is
safer to report the maximum clock rate to users of the core clock -
I2C, SPI and the mini UART - to err on the safe side when calculating
clock divisors.
If the DT node for the clock driver includes a reference to the
firmware node, use the firmware API to query the maximum core clock
instead of reading the divider registers.
Prior to this patch, a "100KHz" I2C bus was sometimes clocked at about
160KHz. In particular, switching to the 4.9 kernel was likely to break
SenseHAT usage on a Pi3.
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
---
drivers/clk/bcm/clk-bcm2835.c | 39 ++++++++++++++++++++++++++++++++++-
1 file changed, 38 insertions(+), 1 deletion(-)
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -36,6 +36,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <dt-bindings/clock/bcm2835.h>
+#include <soc/bcm2835/raspberrypi-firmware.h>
#define CM_PASSWORD 0x5a000000
@@ -296,6 +297,8 @@
#define SOC_BCM2711 BIT(1)
#define SOC_ALL (SOC_BCM2835 | SOC_BCM2711)
+#define VCMSG_ID_CORE_CLOCK 4
+
/*
* Names of clocks used within the driver that need to be replaced
* with an external parent's name. This array is in the order that
@@ -314,6 +317,7 @@ static const char *const cprman_parent_n
struct bcm2835_cprman {
struct device *dev;
void __iomem *regs;
+ struct rpi_firmware *fw;
spinlock_t regs_lock; /* spinlock for all clocks */
unsigned int soc;
@@ -1039,6 +1043,30 @@ static unsigned long bcm2835_clock_get_r
return rate;
}
+static unsigned long bcm2835_clock_get_rate_vpu(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
+ struct bcm2835_cprman *cprman = clock->cprman;
+
+ if (cprman->fw) {
+ struct {
+ u32 id;
+ u32 val;
+ } packet;
+
+ packet.id = VCMSG_ID_CORE_CLOCK;
+ packet.val = 0;
+
+ if (!rpi_firmware_property(cprman->fw,
+ RPI_FIRMWARE_GET_MAX_CLOCK_RATE,
+ &packet, sizeof(packet)))
+ return packet.val;
+ }
+
+ return bcm2835_clock_get_rate(hw, parent_rate);
+}
+
static void bcm2835_clock_wait_busy(struct bcm2835_clock *clock)
{
struct bcm2835_cprman *cprman = clock->cprman;
@@ -1327,7 +1355,7 @@ static int bcm2835_vpu_clock_is_on(struc
*/
static const struct clk_ops bcm2835_vpu_clock_clk_ops = {
.is_prepared = bcm2835_vpu_clock_is_on,
- .recalc_rate = bcm2835_clock_get_rate,
+ .recalc_rate = bcm2835_clock_get_rate_vpu,
.set_rate = bcm2835_clock_set_rate,
.determine_rate = bcm2835_clock_determine_rate,
.set_parent = bcm2835_clock_set_parent,
@@ -2303,6 +2331,7 @@ static int bcm2835_clk_probe(struct plat
const struct bcm2835_clk_desc *desc;
const size_t asize = ARRAY_SIZE(clk_desc_array);
const struct cprman_plat_data *pdata;
+ struct device_node *fw_node;
size_t i;
u32 clk_id;
int ret;
@@ -2323,6 +2352,14 @@ static int bcm2835_clk_probe(struct plat
if (IS_ERR(cprman->regs))
return PTR_ERR(cprman->regs);
+ fw_node = of_parse_phandle(dev->of_node, "firmware", 0);
+ if (fw_node) {
+ struct rpi_firmware *fw = rpi_firmware_get(NULL);
+ if (!fw)
+ return -EPROBE_DEFER;
+ cprman->fw = fw;
+ }
+
memset(bcm2835_clk_claimed, 0, sizeof(bcm2835_clk_claimed));
for (i = 0;
!of_property_read_u32_index(pdev->dev.of_node, "claim-clocks",

View file

@ -0,0 +1,24 @@
From 06e0ba66373d40aa76f1a927b8228b66ecac07d4 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Thu, 24 Jan 2019 15:09:28 +0000
Subject: [PATCH] clk: clk-bcm2835: Use %zd when printing size_t
The debug text for how many clocks have been registered
uses "%d" with a size_t. Correct it to "%zd".
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
---
drivers/clk/bcm/clk-bcm2835.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -2406,7 +2406,7 @@ static int bcm2835_clk_probe(struct plat
return ret;
/* note that we have registered all the clocks */
- dev_dbg(dev, "registered %d clocks\n", asize);
+ dev_dbg(dev, "registered %zd clocks\n", asize);
return 0;
}

View file

@ -0,0 +1,38 @@
From 9c849cd78ee9d78443303af3b55cc3fc6318f31f Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Wed, 23 Jan 2019 16:11:50 +0000
Subject: [PATCH] clk-bcm2835: Don't wait for pllh lock
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
---
drivers/clk/bcm/clk-bcm2835.c | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -647,15 +647,17 @@ static int bcm2835_pll_on(struct clk_hw
spin_unlock(&cprman->regs_lock);
/* Wait for the PLL to lock. */
- timeout = ktime_add_ns(ktime_get(), LOCK_TIMEOUT_NS);
- while (!(cprman_read(cprman, CM_LOCK) & data->lock_mask)) {
- if (ktime_after(ktime_get(), timeout)) {
- dev_err(cprman->dev, "%s: couldn't lock PLL\n",
- clk_hw_get_name(hw));
- return -ETIMEDOUT;
- }
+ if (strcmp(data->name, "pllh")) {
+ timeout = ktime_add_ns(ktime_get(), LOCK_TIMEOUT_NS);
+ while (!(cprman_read(cprman, CM_LOCK) & data->lock_mask)) {
+ if (ktime_after(ktime_get(), timeout)) {
+ dev_err(cprman->dev, "%s: couldn't lock PLL\n",
+ clk_hw_get_name(hw));
+ return -ETIMEDOUT;
+ }
- cpu_relax();
+ cpu_relax();
+ }
}
cprman_write(cprman, data->a2w_ctrl_reg,

View file

@ -0,0 +1,53 @@
From c5a0182a6aec56695354cfe10bb5536a6a38c5f3 Mon Sep 17 00:00:00 2001
From: Eric Anholt <eric@anholt.net>
Date: Thu, 2 May 2019 15:11:05 -0700
Subject: [PATCH] clk: bcm2835: Add support for setting leaf clock rates while
running.
As long as you wait for !BUSY, you can do glitch-free updates of clock
rate while the clock is running.
Signed-off-by: Eric Anholt <eric@anholt.net>
---
drivers/clk/bcm/clk-bcm2835.c | 22 +++++++++++++---------
1 file changed, 13 insertions(+), 9 deletions(-)
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -1138,15 +1138,19 @@ static int bcm2835_clock_set_rate(struct
spin_lock(&cprman->regs_lock);
- /*
- * Setting up frac support
- *
- * In principle it is recommended to stop/start the clock first,
- * but as we set CLK_SET_RATE_GATE during registration of the
- * clock this requirement should be take care of by the
- * clk-framework.
+ ctl = cprman_read(cprman, data->ctl_reg);
+
+ /* If the clock is running, we have to pause clock generation while
+ * updating the control and div regs. This is glitchless (no clock
+ * signals generated faster than the rate) but each reg access is two
+ * OSC cycles so the clock will slow down for a moment.
*/
- ctl = cprman_read(cprman, data->ctl_reg) & ~CM_FRAC;
+ if (ctl & CM_ENABLE) {
+ cprman_write(cprman, data->ctl_reg, ctl & ~CM_ENABLE);
+ bcm2835_clock_wait_busy(clock);
+ }
+
+ ctl &= ~CM_FRAC;
ctl |= (div & CM_DIV_FRAC_MASK) ? CM_FRAC : 0;
cprman_write(cprman, data->ctl_reg, ctl);
@@ -1522,7 +1526,7 @@ static struct clk_hw *bcm2835_register_c
init.ops = &bcm2835_vpu_clock_clk_ops;
} else {
init.ops = &bcm2835_clock_clk_ops;
- init.flags |= CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
+ init.flags |= CLK_SET_PARENT_GATE;
/* If the clock wasn't actually enabled at boot, it's not
* critical.

View file

@ -0,0 +1,71 @@
From a9f709127c1a912517bd4e1160360bb4ab3e1498 Mon Sep 17 00:00:00 2001
From: Eric Anholt <eric@anholt.net>
Date: Thu, 2 May 2019 15:24:04 -0700
Subject: [PATCH] clk: bcm2835: Allow reparenting leaf clocks while they're
running.
This falls under the same "we can reprogram glitch-free as long as we
pause generation" rule as updating the div/frac fields. This can be
used for runtime reclocking of V3D to manage power leakage.
Signed-off-by: Eric Anholt <eric@anholt.net>
---
drivers/clk/bcm/clk-bcm2835.c | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -1127,8 +1127,10 @@ static int bcm2835_clock_on(struct clk_h
return 0;
}
-static int bcm2835_clock_set_rate(struct clk_hw *hw,
- unsigned long rate, unsigned long parent_rate)
+static int bcm2835_clock_set_rate_and_parent(struct clk_hw *hw,
+ unsigned long rate,
+ unsigned long parent_rate,
+ u8 parent)
{
struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
struct bcm2835_cprman *cprman = clock->cprman;
@@ -1150,6 +1152,11 @@ static int bcm2835_clock_set_rate(struct
bcm2835_clock_wait_busy(clock);
}
+ if (parent != 0xff) {
+ ctl &= ~(CM_SRC_MASK << CM_SRC_SHIFT);
+ ctl |= parent << CM_SRC_SHIFT;
+ }
+
ctl &= ~CM_FRAC;
ctl |= (div & CM_DIV_FRAC_MASK) ? CM_FRAC : 0;
cprman_write(cprman, data->ctl_reg, ctl);
@@ -1161,6 +1168,12 @@ static int bcm2835_clock_set_rate(struct
return 0;
}
+static int bcm2835_clock_set_rate(struct clk_hw *hw,
+ unsigned long rate, unsigned long parent_rate)
+{
+ return bcm2835_clock_set_rate_and_parent(hw, rate, parent_rate, 0xff);
+}
+
static bool
bcm2835_clk_is_pllc(struct clk_hw *hw)
{
@@ -1344,6 +1357,7 @@ static const struct clk_ops bcm2835_cloc
.unprepare = bcm2835_clock_off,
.recalc_rate = bcm2835_clock_get_rate,
.set_rate = bcm2835_clock_set_rate,
+ .set_rate_and_parent = bcm2835_clock_set_rate_and_parent,
.determine_rate = bcm2835_clock_determine_rate,
.set_parent = bcm2835_clock_set_parent,
.get_parent = bcm2835_clock_get_parent,
@@ -1526,7 +1540,6 @@ static struct clk_hw *bcm2835_register_c
init.ops = &bcm2835_vpu_clock_clk_ops;
} else {
init.ops = &bcm2835_clock_clk_ops;
- init.flags |= CLK_SET_PARENT_GATE;
/* If the clock wasn't actually enabled at boot, it's not
* critical.

View file

@ -0,0 +1,29 @@
From 1c9ad88925bb574d8623477c441d586d0756a91e Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Tue, 6 Aug 2019 15:23:14 +0100
Subject: [PATCH] clk-bcm2835: Avoid null pointer exception
clk_desc_array[BCM2835_PLLB] doesn't exist so we dereference null when iterating
Signed-off-by: popcornmix <popcornmix@gmail.com>
---
drivers/clk/bcm/clk-bcm2835.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -2334,9 +2334,11 @@ static bool bcm2835_clk_is_claimed(const
int i;
for (i = 0; i < ARRAY_SIZE(clk_desc_array); i++) {
- const char *clk_name = *(const char **)(clk_desc_array[i].data);
- if (!strcmp(name, clk_name))
- return bcm2835_clk_claimed[i];
+ if (clk_desc_array[i].data) {
+ const char *clk_name = *(const char **)(clk_desc_array[i].data);
+ if (!strcmp(name, clk_name))
+ return bcm2835_clk_claimed[i];
+ }
}
return false;

View file

@ -0,0 +1,58 @@
From bcca26f6e384cfb43bcdcf36873e85476de9fab1 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Tue, 3 Sep 2019 20:28:00 +0100
Subject: [PATCH] clk-bcm2835: Disable v3d clock
This is controlled by firmware, see clk-raspberrypi.c
Signed-off-by: popcornmix <popcornmix@gmail.com>
---
drivers/clk/bcm/clk-bcm2835.c | 30 ++++++++++++------------------
1 file changed, 12 insertions(+), 18 deletions(-)
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -1764,16 +1764,12 @@ static const struct bcm2835_clk_desc clk
.hold_mask = CM_PLLA_HOLDCORE,
.fixed_divider = 1,
.flags = CLK_SET_RATE_PARENT),
- [BCM2835_PLLA_PER] = REGISTER_PLL_DIV(
- SOC_ALL,
- .name = "plla_per",
- .source_pll = "plla",
- .cm_reg = CM_PLLA,
- .a2w_reg = A2W_PLLA_PER,
- .load_mask = CM_PLLA_LOADPER,
- .hold_mask = CM_PLLA_HOLDPER,
- .fixed_divider = 1,
- .flags = CLK_SET_RATE_PARENT),
+
+ /*
+ * PLLA_PER is used for gpu clocks. Controlled by firmware, see
+ * clk-raspberrypi.c.
+ */
+
[BCM2835_PLLA_DSI0] = REGISTER_PLL_DIV(
SOC_ALL,
.name = "plla_dsi0",
@@ -2074,14 +2070,12 @@ static const struct bcm2835_clk_desc clk
.int_bits = 6,
.frac_bits = 0,
.tcnt_mux = 3),
- [BCM2835_CLOCK_V3D] = REGISTER_VPU_CLK(
- SOC_ALL,
- .name = "v3d",
- .ctl_reg = CM_V3DCTL,
- .div_reg = CM_V3DDIV,
- .int_bits = 4,
- .frac_bits = 8,
- .tcnt_mux = 4),
+
+ /*
+ * CLOCK_V3D is used for v3d clock. Controlled by firmware, see
+ * clk-raspberrypi.c.
+ */
+
/*
* VPU clock. This doesn't have an enable bit, since it drives
* the bus for everything else, and is special so it doesn't need

View file

@ -0,0 +1,24 @@
From 83438d9e501ae9439b951f225d3d81bea7930568 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.com>
Date: Thu, 8 Jul 2021 09:37:10 +0100
Subject: [PATCH] clk: bcm2835: Pass DT node to rpi_firmware_get
The fw_node pointer has already been retrieved, and using it allows
us to remove a downstream patch to the firmware driver.
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
---
drivers/clk/bcm/clk-bcm2835.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -2369,7 +2369,7 @@ static int bcm2835_clk_probe(struct plat
fw_node = of_parse_phandle(dev->of_node, "firmware", 0);
if (fw_node) {
- struct rpi_firmware *fw = rpi_firmware_get(NULL);
+ struct rpi_firmware *fw = rpi_firmware_get(fw_node);
if (!fw)
return -EPROBE_DEFER;
cprman->fw = fw;

View file

@ -0,0 +1,34 @@
From 88c07badc7a952682f5914abeb0bb789015b67c6 Mon Sep 17 00:00:00 2001
From: Dom Cobley <popcornmix@gmail.com>
Date: Tue, 19 Oct 2021 14:14:55 +0100
Subject: [PATCH] clk-bcm2835: Remove VEC clock support
Signed-off-by: Dom Cobley <popcornmix@gmail.com>
---
drivers/clk/bcm/clk-bcm2835.c | 15 ---------------
1 file changed, 15 deletions(-)
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -2238,21 +2238,6 @@ static const struct bcm2835_clk_desc clk
.tcnt_mux = 28,
.round_up = true),
- /* TV encoder clock. Only operating frequency is 108Mhz. */
- [BCM2835_CLOCK_VEC] = REGISTER_PER_CLK(
- SOC_ALL,
- .name = "vec",
- .ctl_reg = CM_VECCTL,
- .div_reg = CM_VECDIV,
- .int_bits = 4,
- .frac_bits = 0,
- /*
- * Allow rate change propagation only on PLLH_AUX which is
- * assigned index 7 in the parent array.
- */
- .set_rate_parent = BIT(7),
- .tcnt_mux = 29),
-
/* dsi clocks */
[BCM2835_CLOCK_DSI0E] = REGISTER_PER_CLK(
SOC_ALL,

View file

@ -0,0 +1,99 @@
From 3f58295a84a9a9eb5c6aa06e7c0c93fe9959afe9 Mon Sep 17 00:00:00 2001
From: Dan Pasanen <dan.pasanen@gmail.com>
Date: Thu, 21 Sep 2017 09:55:42 -0500
Subject: [PATCH] arm: partially revert
702b94bff3c50542a6e4ab9a4f4cef093262fe65
* Re-expose some dmi APIs for use in VCSM
---
arch/arm/include/asm/cacheflush.h | 21 +++++++++++++++++++++
arch/arm/include/asm/glue-cache.h | 2 ++
arch/arm/mm/proc-macros.S | 2 ++
arch/arm/mm/proc-syms.c | 3 +++
4 files changed, 28 insertions(+)
--- a/arch/arm/include/asm/cacheflush.h
+++ b/arch/arm/include/asm/cacheflush.h
@@ -91,6 +91,21 @@
* DMA Cache Coherency
* ===================
*
+ * dma_inv_range(start, end)
+ *
+ * Invalidate (discard) the specified virtual address range.
+ * May not write back any entries. If 'start' or 'end'
+ * are not cache line aligned, those lines must be written
+ * back.
+ * - start - virtual start address
+ * - end - virtual end address
+ *
+ * dma_clean_range(start, end)
+ *
+ * Clean (write back) the specified virtual address range.
+ * - start - virtual start address
+ * - end - virtual end address
+ *
* dma_flush_range(start, end)
*
* Clean and invalidate the specified virtual address range.
@@ -112,6 +127,8 @@ struct cpu_cache_fns {
void (*dma_map_area)(const void *, size_t, int);
void (*dma_unmap_area)(const void *, size_t, int);
+ void (*dma_inv_range)(const void *, const void *);
+ void (*dma_clean_range)(const void *, const void *);
void (*dma_flush_range)(const void *, const void *);
} __no_randomize_layout;
@@ -137,6 +154,8 @@ extern struct cpu_cache_fns cpu_cache;
* is visible to DMA, or data written by DMA to system memory is
* visible to the CPU.
*/
+#define dmac_inv_range cpu_cache.dma_inv_range
+#define dmac_clean_range cpu_cache.dma_clean_range
#define dmac_flush_range cpu_cache.dma_flush_range
#else
@@ -156,6 +175,8 @@ extern void __cpuc_flush_dcache_area(voi
* is visible to DMA, or data written by DMA to system memory is
* visible to the CPU.
*/
+extern void dmac_inv_range(const void *, const void *);
+extern void dmac_clean_range(const void *, const void *);
extern void dmac_flush_range(const void *, const void *);
#endif
--- a/arch/arm/include/asm/glue-cache.h
+++ b/arch/arm/include/asm/glue-cache.h
@@ -155,6 +155,8 @@ static inline void nop_dma_unmap_area(co
#define __cpuc_coherent_user_range __glue(_CACHE,_coherent_user_range)
#define __cpuc_flush_dcache_area __glue(_CACHE,_flush_kern_dcache_area)
+#define dmac_inv_range __glue(_CACHE,_dma_inv_range)
+#define dmac_clean_range __glue(_CACHE,_dma_clean_range)
#define dmac_flush_range __glue(_CACHE,_dma_flush_range)
#endif
--- a/arch/arm/mm/proc-macros.S
+++ b/arch/arm/mm/proc-macros.S
@@ -333,6 +333,8 @@ ENTRY(\name\()_cache_fns)
.long \name\()_flush_kern_dcache_area
.long \name\()_dma_map_area
.long \name\()_dma_unmap_area
+ .long \name\()_dma_inv_range
+ .long \name\()_dma_clean_range
.long \name\()_dma_flush_range
.size \name\()_cache_fns, . - \name\()_cache_fns
.endm
--- a/arch/arm/mm/proc-syms.c
+++ b/arch/arm/mm/proc-syms.c
@@ -27,6 +27,9 @@ EXPORT_SYMBOL(__cpuc_flush_user_all);
EXPORT_SYMBOL(__cpuc_flush_user_range);
EXPORT_SYMBOL(__cpuc_coherent_kern_range);
EXPORT_SYMBOL(__cpuc_flush_dcache_area);
+EXPORT_SYMBOL(dmac_inv_range);
+EXPORT_SYMBOL(dmac_clean_range);
+EXPORT_SYMBOL(dmac_flush_range);
#else
EXPORT_SYMBOL(cpu_cache);
#endif

View file

@ -0,0 +1,53 @@
From 2d2b074c9a029ad9dfc1c62376a478be4d7b1c75 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Fri, 25 Aug 2017 19:18:13 +0100
Subject: [PATCH] cache: export clean and invalidate
hack: cache: Fix linker error
---
arch/arm/mm/cache-v6.S | 4 ++--
arch/arm/mm/cache-v7.S | 6 ++++--
2 files changed, 6 insertions(+), 4 deletions(-)
--- a/arch/arm/mm/cache-v6.S
+++ b/arch/arm/mm/cache-v6.S
@@ -198,7 +198,7 @@ ENTRY(v6_flush_kern_dcache_area)
* - start - virtual start address of region
* - end - virtual end address of region
*/
-v6_dma_inv_range:
+ENTRY(v6_dma_inv_range)
#ifdef CONFIG_DMA_CACHE_RWFO
ldrb r2, [r0] @ read for ownership
strb r2, [r0] @ write for ownership
@@ -243,7 +243,7 @@ v6_dma_inv_range:
* - start - virtual start address of region
* - end - virtual end address of region
*/
-v6_dma_clean_range:
+ENTRY(v6_dma_clean_range)
bic r0, r0, #D_CACHE_LINE_SIZE - 1
1:
#ifdef CONFIG_DMA_CACHE_RWFO
--- a/arch/arm/mm/cache-v7.S
+++ b/arch/arm/mm/cache-v7.S
@@ -359,7 +359,8 @@ ENDPROC(v7_flush_kern_dcache_area)
* - start - virtual start address of region
* - end - virtual end address of region
*/
-v7_dma_inv_range:
+ENTRY(b15_dma_inv_range)
+ENTRY(v7_dma_inv_range)
dcache_line_size r2, r3
sub r3, r2, #1
tst r0, r3
@@ -389,7 +390,8 @@ ENDPROC(v7_dma_inv_range)
* - start - virtual start address of region
* - end - virtual end address of region
*/
-v7_dma_clean_range:
+ENTRY(b15_dma_clean_range)
+ENTRY(v7_dma_clean_range)
dcache_line_size r2, r3
sub r3, r2, #1
bic r0, r0, r3

View file

@ -0,0 +1,32 @@
From 3f93e06e535477cdb96d8056f8309288744a3a8d Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.com>
Date: Mon, 20 Apr 2020 13:41:10 +0100
Subject: [PATCH] Revert "spi: spidev: Fix CS polarity if GPIO descriptors are
used"
This reverts commit 83b2a8fe43bda0c11981ad6afa5dd0104d78be28.
---
drivers/spi/spidev.c | 5 -----
1 file changed, 5 deletions(-)
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -414,7 +414,6 @@ spidev_ioctl(struct file *filp, unsigned
else
retval = get_user(tmp, (u32 __user *)arg);
if (retval == 0) {
- struct spi_controller *ctlr = spi->controller;
u32 save = spi->mode;
if (tmp & ~SPI_MODE_MASK) {
@@ -422,10 +421,6 @@ spidev_ioctl(struct file *filp, unsigned
break;
}
- if (ctlr->use_gpio_descriptors && ctlr->cs_gpiods &&
- ctlr->cs_gpiods[spi->chip_select])
- tmp |= SPI_CS_HIGH;
-
tmp |= spi->mode & ~SPI_MODE_MASK;
spi->mode = tmp & SPI_MODE_USER_MASK;
retval = spi_setup(spi);

View file

@ -0,0 +1,45 @@
From 6e0505463b9e5c402d9b7fb340c599537f9d1bb8 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.com>
Date: Mon, 1 Mar 2021 09:12:44 +0000
Subject: [PATCH] Revert "Bluetooth: Always request for user confirmation for
Just Works (LE SC)"
This reverts commit ffee202a78c2980688bc5d2f7d56480e69a5e0c9.
The commit "Bluetooth: Always request for user confirmation for Just
Works" prevents BLE devices pairing in (at least) the Raspberry Pi OS
GUI. After reverting it, pairing works again. Although this companion
commit ("... (LE SC)") has not been demonstrated to be problematic,
it follows the same logic and therefore could affect some use cases.
If another solution to the problem is found then this reversion will
be removed.
See: https://github.com/raspberrypi/linux/issues/4139
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
---
net/bluetooth/smp.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -2207,7 +2207,7 @@ mackey_and_ltk:
if (err)
return SMP_UNSPECIFIED;
- if (smp->method == REQ_OOB) {
+ if (smp->method == JUST_WORKS || smp->method == REQ_OOB) {
if (hcon->out) {
sc_dhkey_check(smp);
SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
@@ -2222,9 +2222,6 @@ mackey_and_ltk:
confirm_hint = 0;
confirm:
- if (smp->method == JUST_WORKS)
- confirm_hint = 1;
-
err = mgmt_user_confirm_request(hcon->hdev, &hcon->dst, hcon->type,
hcon->dst_type, passkey, confirm_hint);
if (err)

View file

@ -0,0 +1,43 @@
From a7def069d38b0f6b4304d6019c99e364ee1ad297 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.com>
Date: Mon, 1 Mar 2021 09:14:35 +0000
Subject: [PATCH] Revert "Bluetooth: Always request for user confirmation for
Just Works"
This reverts commit 92516cd97fd4d8ad5b1421a0d51771044f453a5f.
Thi commit "Bluetooth: Always request for user confirmation for Just
Works" prevents BLE devices pairing in (at least) the Raspberry Pi OS
GUI. After reverting it, pairing works again.
If another solution to the problem is found then this reversion will
be removed.
See: https://github.com/raspberrypi/linux/issues/4139
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
---
net/bluetooth/smp.c | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -883,16 +883,9 @@ static int tk_request(struct l2cap_conn
hcon->io_capability == HCI_IO_NO_INPUT_OUTPUT)
smp->method = JUST_WORKS;
- /* If Just Works, Continue with Zero TK and ask user-space for
- * confirmation */
+ /* If Just Works, Continue with Zero TK */
if (smp->method == JUST_WORKS) {
- ret = mgmt_user_confirm_request(hcon->hdev, &hcon->dst,
- hcon->type,
- hcon->dst_type,
- passkey, 1);
- if (ret)
- return ret;
- set_bit(SMP_FLAG_WAIT_USER, &smp->flags);
+ set_bit(SMP_FLAG_TK_VALID, &smp->flags);
return 0;
}

View file

@ -0,0 +1,28 @@
From c0ef0339d77fc9f5919ac06b9b961289f5c865cc Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.com>
Date: Mon, 7 Mar 2022 16:18:55 +0000
Subject: [PATCH] Revert "net: bcmgenet: Request APD, DLL disable and IDDQ-SR"
This reverts commit c3a4c69360ab43560f212eed326c9d8bde35b14c, which
broke rebooting when network booting.
See: https://github.com/raspberrypi/rpi-eeprom/issues/417
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
---
drivers/net/ethernet/broadcom/genet/bcmmii.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
--- a/drivers/net/ethernet/broadcom/genet/bcmmii.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c
@@ -290,9 +290,7 @@ int bcmgenet_mii_probe(struct net_device
struct device_node *dn = kdev->of_node;
phy_interface_t phy_iface = priv->phy_interface;
struct phy_device *phydev;
- u32 phy_flags = PHY_BRCM_AUTO_PWRDWN_ENABLE |
- PHY_BRCM_DIS_TXCRXC_NOENRGY |
- PHY_BRCM_IDDQ_SUSPEND;
+ u32 phy_flags = 0;
int ret;
/* Communicate the integrated PHY revision */

View file

@ -0,0 +1,47 @@
From 5811c0719511310ea778259dc83dffd1ee0e3e1c Mon Sep 17 00:00:00 2001
From: Steve Glendinning <steve.glendinning@smsc.com>
Date: Thu, 19 Feb 2015 18:47:12 +0000
Subject: [PATCH] smsx95xx: fix crimes against truesize
smsc95xx is adjusting truesize when it shouldn't, and following a recent patch from Eric this is now triggering warnings.
This patch stops smsc95xx from changing truesize.
Signed-off-by: Steve Glendinning <steve.glendinning@smsc.com>
---
drivers/net/usb/smsc95xx.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -79,6 +79,10 @@ static bool turbo_mode = true;
module_param(turbo_mode, bool, 0644);
MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction");
+static bool truesize_mode = false;
+module_param(truesize_mode, bool, 0644);
+MODULE_PARM_DESC(truesize_mode, "Report larger truesize value");
+
static int __must_check smsc95xx_read_reg(struct usbnet *dev, u32 index,
u32 *data)
{
@@ -1870,7 +1874,8 @@ static int smsc95xx_rx_fixup(struct usbn
if (dev->net->features & NETIF_F_RXCSUM)
smsc95xx_rx_csum_offload(skb);
skb_trim(skb, skb->len - 4); /* remove fcs */
- skb->truesize = size + sizeof(struct sk_buff);
+ if (truesize_mode)
+ skb->truesize = size + sizeof(struct sk_buff);
return 1;
}
@@ -1888,7 +1893,8 @@ static int smsc95xx_rx_fixup(struct usbn
if (dev->net->features & NETIF_F_RXCSUM)
smsc95xx_rx_csum_offload(ax_skb);
skb_trim(ax_skb, ax_skb->len - 4); /* remove fcs */
- ax_skb->truesize = size + sizeof(struct sk_buff);
+ if (truesize_mode)
+ ax_skb->truesize = size + sizeof(struct sk_buff);
usbnet_skb_return(dev, ax_skb);
}

View file

@ -0,0 +1,43 @@
From a9b5e24cb96753cbc74090246239e83ba53569da Mon Sep 17 00:00:00 2001
From: Sam Nazarko <email@samnazarko.co.uk>
Date: Fri, 1 Apr 2016 17:27:21 +0100
Subject: [PATCH] smsc95xx: Experimental: Enable turbo_mode and packetsize=2560
by default
See: http://forum.kodi.tv/showthread.php?tid=285288
---
drivers/net/usb/smsc95xx.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -83,6 +83,10 @@ static bool truesize_mode = false;
module_param(truesize_mode, bool, 0644);
MODULE_PARM_DESC(truesize_mode, "Report larger truesize value");
+static int packetsize = 2560;
+module_param(packetsize, int, 0644);
+MODULE_PARM_DESC(packetsize, "Override the RX URB packet size");
+
static int __must_check smsc95xx_read_reg(struct usbnet *dev, u32 index,
u32 *data)
{
@@ -936,13 +940,13 @@ static int smsc95xx_reset(struct usbnet
if (!turbo_mode) {
burst_cap = 0;
- dev->rx_urb_size = MAX_SINGLE_PACKET_SIZE;
+ dev->rx_urb_size = packetsize ? packetsize : MAX_SINGLE_PACKET_SIZE;
} else if (dev->udev->speed == USB_SPEED_HIGH) {
- burst_cap = DEFAULT_HS_BURST_CAP_SIZE / HS_USB_PKT_SIZE;
- dev->rx_urb_size = DEFAULT_HS_BURST_CAP_SIZE;
+ dev->rx_urb_size = packetsize ? packetsize : DEFAULT_HS_BURST_CAP_SIZE;
+ burst_cap = dev->rx_urb_size / HS_USB_PKT_SIZE;
} else {
- burst_cap = DEFAULT_FS_BURST_CAP_SIZE / FS_USB_PKT_SIZE;
- dev->rx_urb_size = DEFAULT_FS_BURST_CAP_SIZE;
+ dev->rx_urb_size = packetsize ? packetsize : DEFAULT_FS_BURST_CAP_SIZE;
+ burst_cap = dev->rx_urb_size / FS_USB_PKT_SIZE;
}
netif_dbg(dev, ifup, dev->net, "rx_urb_size=%ld\n",

View file

@ -0,0 +1,99 @@
From 429531c0dc5f4e495658320b45a5164c6668a533 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Tue, 26 Mar 2013 17:26:38 +0000
Subject: [PATCH] Allow mac address to be set in smsc95xx
Signed-off-by: popcornmix <popcornmix@gmail.com>
SQUASH: smsc95xx: Use dev_mod_addr to set MAC addr
Since adeef3e32146 ("net: constify netdev->dev_addr") it has been
illegal to write to the dev_addr MAC address field. Later commits
have added explicit checks that it hasn't been modified by nefarious
means. The dev_addr_mod helper function is the accepted way to change
the dev_addr field, so use it.
Squash with 96c1def63ee1 ("Allow mac address to be set in smsc95xx").
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
---
drivers/net/usb/smsc95xx.c | 54 ++++++++++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -87,6 +87,10 @@ static int packetsize = 2560;
module_param(packetsize, int, 0644);
MODULE_PARM_DESC(packetsize, "Override the RX URB packet size");
+static char *macaddr = ":";
+module_param(macaddr, charp, 0);
+MODULE_PARM_DESC(macaddr, "MAC address");
+
static int __must_check smsc95xx_read_reg(struct usbnet *dev, u32 index,
u32 *data)
{
@@ -809,6 +813,52 @@ static int smsc95xx_ioctl(struct net_dev
return phy_mii_ioctl(netdev->phydev, rq, cmd);
}
+/* Check the macaddr module parameter for a MAC address */
+static int smsc95xx_is_macaddr_param(struct usbnet *dev, struct net_device *nd)
+{
+ int i, j, got_num, num;
+ u8 mtbl[ETH_ALEN];
+
+ if (macaddr[0] == ':')
+ return 0;
+
+ i = 0;
+ j = 0;
+ num = 0;
+ got_num = 0;
+ while (j < ETH_ALEN) {
+ if (macaddr[i] && macaddr[i] != ':') {
+ got_num++;
+ if ('0' <= macaddr[i] && macaddr[i] <= '9')
+ num = num * 16 + macaddr[i] - '0';
+ else if ('A' <= macaddr[i] && macaddr[i] <= 'F')
+ num = num * 16 + 10 + macaddr[i] - 'A';
+ else if ('a' <= macaddr[i] && macaddr[i] <= 'f')
+ num = num * 16 + 10 + macaddr[i] - 'a';
+ else
+ break;
+ i++;
+ } else if (got_num == 2) {
+ mtbl[j++] = (u8) num;
+ num = 0;
+ got_num = 0;
+ i++;
+ } else {
+ break;
+ }
+ }
+
+ if (j == ETH_ALEN) {
+ netif_dbg(dev, ifup, dev->net, "Overriding MAC address with: "
+ "%02x:%02x:%02x:%02x:%02x:%02x\n", mtbl[0], mtbl[1], mtbl[2],
+ mtbl[3], mtbl[4], mtbl[5]);
+ dev_addr_mod(nd, 0, mtbl, ETH_ALEN);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
static void smsc95xx_init_mac_address(struct usbnet *dev)
{
u8 addr[ETH_ALEN];
@@ -832,6 +882,10 @@ static void smsc95xx_init_mac_address(st
}
}
+ /* Check module parameters */
+ if (smsc95xx_is_macaddr_param(dev, dev->net))
+ return;
+
/* no useful static MAC address found. generate a random one */
eth_hw_addr_random(dev->net);
netif_dbg(dev, ifup, dev->net, "MAC address set to eth_random_addr\n");

View file

@ -0,0 +1,85 @@
From b2670b95c0cbe7b6ba038a7615725d87ad59af4f Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Mon, 27 Nov 2017 17:14:54 +0000
Subject: [PATCH] cgroup: Disable cgroup "memory" by default
Some Raspberry Pis have limited RAM and most users won't use the
cgroup memory support so it is disabled by default. Enable with:
cgroup_enable=memory
See: https://github.com/raspberrypi/linux/issues/1950
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
---
kernel/cgroup/cgroup.c | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -6061,6 +6061,9 @@ int __init cgroup_init_early(void)
return 0;
}
+static u16 cgroup_enable_mask __initdata;
+static int __init cgroup_disable(char *str);
+
/**
* cgroup_init - cgroup initialization
*
@@ -6094,6 +6097,12 @@ int __init cgroup_init(void)
cgroup_unlock();
+ /*
+ * Apply an implicit disable, knowing that an explicit enable will
+ * prevent if from doing anything.
+ */
+ cgroup_disable("memory");
+
for_each_subsys(ss, ssid) {
if (ss->early_init) {
struct cgroup_subsys_state *css =
@@ -6734,6 +6743,10 @@ static int __init cgroup_disable(char *s
strcmp(token, ss->legacy_name))
continue;
+ /* An explicit cgroup_enable overrides a disable */
+ if (cgroup_enable_mask & (1 << i))
+ continue;
+
static_branch_disable(cgroup_subsys_enabled_key[i]);
pr_info("Disabling %s control group subsystem\n",
ss->name);
@@ -6752,6 +6765,31 @@ static int __init cgroup_disable(char *s
}
__setup("cgroup_disable=", cgroup_disable);
+static int __init cgroup_enable(char *str)
+{
+ struct cgroup_subsys *ss;
+ char *token;
+ int i;
+
+ while ((token = strsep(&str, ",")) != NULL) {
+ if (!*token)
+ continue;
+
+ for_each_subsys(ss, i) {
+ if (strcmp(token, ss->name) &&
+ strcmp(token, ss->legacy_name))
+ continue;
+
+ cgroup_enable_mask |= 1 << i;
+ static_branch_enable(cgroup_subsys_enabled_key[i]);
+ pr_info("Enabling %s control group subsystem\n",
+ ss->name);
+ }
+ }
+ return 1;
+}
+__setup("cgroup_enable=", cgroup_enable);
+
void __init __weak enable_debug_cgroup(void) { }
static int __init enable_cgroup_debug(char *str)

View file

@ -0,0 +1,27 @@
From 600eecf6486e7bd0f752863800296f99fe6ab05a Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Fri, 13 Mar 2015 12:43:36 +0000
Subject: [PATCH] Protect __release_resource against resources without parents
Without this patch, removing a device tree overlay can crash here.
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
---
kernel/resource.c | 6 ++++++
1 file changed, 6 insertions(+)
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -200,6 +200,12 @@ static int __release_resource(struct res
{
struct resource *tmp, **p, *chd;
+ if (!old->parent) {
+ WARN(old->sibling, "sibling but no parent");
+ if (old->sibling)
+ return -EINVAL;
+ return 0;
+ }
p = &old->parent->child;
for (;;) {
tmp = *p;

View file

@ -0,0 +1,24 @@
From b22008959b2e03d2946e0e7e825cdda079baebb4 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Thu, 9 Feb 2017 14:33:30 +0000
Subject: [PATCH] irq-bcm2836: Avoid "Invalid trigger warning"
Initialise the level for each IRQ to avoid a warning from the
arm arch timer code.
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
---
drivers/irqchip/irq-bcm2836.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/irqchip/irq-bcm2836.c
+++ b/drivers/irqchip/irq-bcm2836.c
@@ -128,7 +128,7 @@ static int bcm2836_map(struct irq_domain
irq_set_percpu_devid(irq);
irq_domain_set_info(d, irq, hw, chip, d->host_data,
handle_percpu_devid_irq, NULL, NULL);
- irq_set_status_flags(irq, IRQ_NOAUTOEN);
+ irq_set_status_flags(irq, IRQ_NOAUTOEN | IRQ_TYPE_LEVEL_LOW);
return 0;
}

View file

@ -0,0 +1,127 @@
From 94d16d548bce05e1c330842f3e6ba9370d522b05 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
Date: Fri, 12 Jun 2015 19:01:05 +0200
Subject: [PATCH] irqchip: bcm2835: Add FIQ support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Add a duplicate irq range with an offset on the hwirq's so the
driver can detect that enable_fiq() is used.
Tested with downstream dwc_otg USB controller driver.
Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
Reviewed-by: Eric Anholt <eric@anholt.net>
Acked-by: Stephen Warren <swarren@wwwdotorg.org>
---
arch/arm/mach-bcm/Kconfig | 1 +
drivers/irqchip/irq-bcm2835.c | 51 +++++++++++++++++++++++++++++++----
2 files changed, 47 insertions(+), 5 deletions(-)
--- a/arch/arm/mach-bcm/Kconfig
+++ b/arch/arm/mach-bcm/Kconfig
@@ -159,6 +159,7 @@ config ARCH_BCM2835
select ARM_TIMER_SP804
select HAVE_ARM_ARCH_TIMER if ARCH_MULTI_V7
select BCM2835_TIMER
+ select FIQ
select PINCTRL
select PINCTRL_BCM2835
select MFD_CORE
--- a/drivers/irqchip/irq-bcm2835.c
+++ b/drivers/irqchip/irq-bcm2835.c
@@ -45,7 +45,7 @@
#include <asm/exception.h>
/* Put the bank and irq (32 bits) into the hwirq */
-#define MAKE_HWIRQ(b, n) ((b << 5) | (n))
+#define MAKE_HWIRQ(b, n) (((b) << 5) | (n))
#define HWIRQ_BANK(i) (i >> 5)
#define HWIRQ_BIT(i) BIT(i & 0x1f)
@@ -62,9 +62,13 @@
#define REG_FIQ_CONTROL 0x0c
#define FIQ_CONTROL_ENABLE BIT(7)
+#define REG_FIQ_ENABLE FIQ_CONTROL_ENABLE
+#define REG_FIQ_DISABLE 0
#define NR_BANKS 3
#define IRQS_PER_BANK 32
+#define NUMBER_IRQS MAKE_HWIRQ(NR_BANKS, 0)
+#define FIQ_START (NR_IRQS_BANK0 + MAKE_HWIRQ(NR_BANKS - 1, 0))
static const int reg_pending[] __initconst = { 0x00, 0x04, 0x08 };
static const int reg_enable[] __initconst = { 0x18, 0x10, 0x14 };
@@ -89,14 +93,38 @@ static void __exception_irq_entry bcm283
struct pt_regs *regs);
static void bcm2836_chained_handle_irq(struct irq_desc *desc);
+static inline unsigned int hwirq_to_fiq(unsigned long hwirq)
+{
+ hwirq -= NUMBER_IRQS;
+ /*
+ * The hwirq numbering used in this driver is:
+ * BASE (0-7) GPU1 (32-63) GPU2 (64-95).
+ * This differ from the one used in the FIQ register:
+ * GPU1 (0-31) GPU2 (32-63) BASE (64-71)
+ */
+ if (hwirq >= 32)
+ return hwirq - 32;
+
+ return hwirq + 64;
+}
+
static void armctrl_mask_irq(struct irq_data *d)
{
- writel_relaxed(HWIRQ_BIT(d->hwirq), intc.disable[HWIRQ_BANK(d->hwirq)]);
+ if (d->hwirq >= NUMBER_IRQS)
+ writel_relaxed(REG_FIQ_DISABLE, intc.base + REG_FIQ_CONTROL);
+ else
+ writel_relaxed(HWIRQ_BIT(d->hwirq),
+ intc.disable[HWIRQ_BANK(d->hwirq)]);
}
static void armctrl_unmask_irq(struct irq_data *d)
{
- writel_relaxed(HWIRQ_BIT(d->hwirq), intc.enable[HWIRQ_BANK(d->hwirq)]);
+ if (d->hwirq >= NUMBER_IRQS)
+ writel_relaxed(REG_FIQ_ENABLE | hwirq_to_fiq(d->hwirq),
+ intc.base + REG_FIQ_CONTROL);
+ else
+ writel_relaxed(HWIRQ_BIT(d->hwirq),
+ intc.enable[HWIRQ_BANK(d->hwirq)]);
}
static struct irq_chip armctrl_chip = {
@@ -142,8 +170,9 @@ static int __init armctrl_of_init(struct
if (!base)
panic("%pOF: unable to map IC registers\n", node);
- intc.domain = irq_domain_add_linear(node, MAKE_HWIRQ(NR_BANKS, 0),
- &armctrl_ops, NULL);
+ intc.base = base;
+ intc.domain = irq_domain_add_linear(node, NUMBER_IRQS * 2,
+ &armctrl_ops, NULL);
if (!intc.domain)
panic("%pOF: unable to create IRQ domain\n", node);
@@ -186,6 +215,18 @@ static int __init armctrl_of_init(struct
set_handle_irq(bcm2835_handle_irq);
}
+ /* Make a duplicate irq range which is used to enable FIQ */
+ for (b = 0; b < NR_BANKS; b++) {
+ for (i = 0; i < bank_irqs[b]; i++) {
+ irq = irq_create_mapping(intc.domain,
+ MAKE_HWIRQ(b, i) + NUMBER_IRQS);
+ BUG_ON(irq <= 0);
+ irq_set_chip(irq, &armctrl_chip);
+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+ }
+ }
+ init_FIQ(FIQ_START);
+
return 0;
}

View file

@ -0,0 +1,99 @@
From b4e8413bf340d2b79e72fc002872a92a93433c75 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
Date: Fri, 23 Oct 2015 16:26:55 +0200
Subject: [PATCH] irqchip: irq-bcm2835: Add 2836 FIQ support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
drivers/irqchip/irq-bcm2835.c | 43 +++++++++++++++++++++++++++++++++--
1 file changed, 41 insertions(+), 2 deletions(-)
--- a/drivers/irqchip/irq-bcm2835.c
+++ b/drivers/irqchip/irq-bcm2835.c
@@ -41,8 +41,11 @@
#include <linux/of_irq.h>
#include <linux/irqchip.h>
#include <linux/irqdomain.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
#include <asm/exception.h>
+#include <asm/mach/irq.h>
/* Put the bank and irq (32 bits) into the hwirq */
#define MAKE_HWIRQ(b, n) (((b) << 5) | (n))
@@ -60,6 +63,9 @@
#define BANK0_VALID_MASK (BANK0_HWIRQ_MASK | BANK1_HWIRQ | BANK2_HWIRQ \
| SHORTCUT1_MASK | SHORTCUT2_MASK)
+#undef ARM_LOCAL_GPU_INT_ROUTING
+#define ARM_LOCAL_GPU_INT_ROUTING 0x0c
+
#define REG_FIQ_CONTROL 0x0c
#define FIQ_CONTROL_ENABLE BIT(7)
#define REG_FIQ_ENABLE FIQ_CONTROL_ENABLE
@@ -86,6 +92,7 @@ struct armctrl_ic {
void __iomem *enable[NR_BANKS];
void __iomem *disable[NR_BANKS];
struct irq_domain *domain;
+ struct regmap *local_regmap;
};
static struct armctrl_ic intc __read_mostly;
@@ -119,12 +126,35 @@ static void armctrl_mask_irq(struct irq_
static void armctrl_unmask_irq(struct irq_data *d)
{
- if (d->hwirq >= NUMBER_IRQS)
+ if (d->hwirq >= NUMBER_IRQS) {
+ if (num_online_cpus() > 1) {
+ unsigned int data;
+ int ret;
+
+ if (!intc.local_regmap) {
+ pr_err("FIQ is disabled due to missing regmap\n");
+ return;
+ }
+
+ ret = regmap_read(intc.local_regmap,
+ ARM_LOCAL_GPU_INT_ROUTING, &data);
+ if (ret) {
+ pr_err("Failed to read int routing %d\n", ret);
+ return;
+ }
+
+ data &= ~0xc;
+ data |= (1 << 2);
+ regmap_write(intc.local_regmap,
+ ARM_LOCAL_GPU_INT_ROUTING, data);
+ }
+
writel_relaxed(REG_FIQ_ENABLE | hwirq_to_fiq(d->hwirq),
intc.base + REG_FIQ_CONTROL);
- else
+ } else {
writel_relaxed(HWIRQ_BIT(d->hwirq),
intc.enable[HWIRQ_BANK(d->hwirq)]);
+ }
}
static struct irq_chip armctrl_chip = {
@@ -215,6 +245,15 @@ static int __init armctrl_of_init(struct
set_handle_irq(bcm2835_handle_irq);
}
+ if (is_2836) {
+ intc.local_regmap =
+ syscon_regmap_lookup_by_compatible("brcm,bcm2836-arm-local");
+ if (IS_ERR(intc.local_regmap)) {
+ pr_err("Failed to get local register map. FIQ is disabled for cpus > 1\n");
+ intc.local_regmap = NULL;
+ }
+ }
+
/* Make a duplicate irq range which is used to enable FIQ */
for (b = 0; b < NR_BANKS; b++) {
for (i = 0; i < bank_irqs[b]; i++) {

View file

@ -0,0 +1,24 @@
From 3e8d60e56b3274521715183e76ce6d9c326537b2 Mon Sep 17 00:00:00 2001
From: Dom Cobley <popcornmix@gmail.com>
Date: Mon, 24 Jan 2022 13:41:16 +0000
Subject: [PATCH] spi: spidev: Completely disable the spidev warning
An alternative strategy would be to use "rpi,spidev" instead, but that
would require many Raspberry Pi Device Tree changes.
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
---
drivers/spi/spidev.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -707,7 +707,7 @@ MODULE_DEVICE_TABLE(spi, spidev_spi_ids)
*/
static int spidev_of_check(struct device *dev)
{
- if (device_property_match_string(dev, "compatible", "spidev") < 0)
+ if (1 || device_property_match_string(dev, "compatible", "spidev") < 0)
return 0;
dev_err(dev, "spidev listed directly in DT is not supported\n");

View file

@ -0,0 +1,100 @@
From 3b7845accab532c7324e2ecd9dab278ade4af19d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
Date: Sat, 3 Oct 2015 22:22:55 +0200
Subject: [PATCH] dmaengine: bcm2835: Load driver early and support legacy API
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Load driver early since at least bcm2708_fb doesn't support deferred
probing and even if it did, we don't want the video driver deferred.
Support the legacy DMA API which is needed by bcm2708_fb.
Don't mask out channel 2.
Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
drivers/dma/Kconfig | 2 +-
drivers/dma/bcm2835-dma.c | 26 +++++++++++++++++++++++++-
2 files changed, 26 insertions(+), 2 deletions(-)
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -135,7 +135,7 @@ config BCM_SBA_RAID
config DMA_BCM2835
tristate "BCM2835 DMA engine support"
- depends on ARCH_BCM2835
+ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709
select DMA_ENGINE
select DMA_VIRTUAL_CHANNELS
--- a/drivers/dma/bcm2835-dma.c
+++ b/drivers/dma/bcm2835-dma.c
@@ -25,6 +25,7 @@
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/module.h>
+#include <linux/platform_data/dma-bcm2708.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/io.h>
@@ -36,6 +37,7 @@
#define BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED 14
#define BCM2835_DMA_CHAN_NAME_SIZE 8
+#define BCM2835_DMA_BULK_MASK BIT(0)
/**
* struct bcm2835_dmadev - BCM2835 DMA controller
@@ -906,6 +908,9 @@ static int bcm2835_dma_probe(struct plat
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
+ rc = bcm_dmaman_probe(pdev, base, BCM2835_DMA_BULK_MASK);
+ if (rc)
+ dev_err(&pdev->dev, "Failed to initialize the legacy API\n");
od->base = base;
@@ -951,6 +956,9 @@ static int bcm2835_dma_probe(struct plat
goto err_no_dma;
}
+ /* Channel 0 is used by the legacy API */
+ chans_available &= ~BCM2835_DMA_BULK_MASK;
+
/* get irqs for each channel that we support */
for (i = 0; i <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; i++) {
/* skip masked out channels */
@@ -1025,6 +1033,7 @@ static int bcm2835_dma_remove(struct pla
{
struct bcm2835_dmadev *od = platform_get_drvdata(pdev);
+ bcm_dmaman_remove(pdev);
dma_async_device_unregister(&od->ddev);
bcm2835_dma_free(od);
@@ -1040,7 +1049,22 @@ static struct platform_driver bcm2835_dm
},
};
-module_platform_driver(bcm2835_dma_driver);
+static int bcm2835_dma_init(void)
+{
+ return platform_driver_register(&bcm2835_dma_driver);
+}
+
+static void bcm2835_dma_exit(void)
+{
+ platform_driver_unregister(&bcm2835_dma_driver);
+}
+
+/*
+ * Load after serial driver (arch_initcall) so we see the messages if it fails,
+ * but before drivers (module_init) that need a DMA channel.
+ */
+subsys_initcall(bcm2835_dma_init);
+module_exit(bcm2835_dma_exit);
MODULE_ALIAS("platform:bcm2835-dma");
MODULE_DESCRIPTION("BCM2835 DMA engine driver");

View file

@ -0,0 +1,20 @@
From dfdd1db51e019b0960ce337e10ef854ac317282d Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Wed, 15 Jun 2016 16:48:41 +0100
Subject: [PATCH] rtc: Add SPI alias for pcf2123 driver
Without this alias, Device Tree won't cause the driver
to be loaded.
See: https://github.com/raspberrypi/linux/pull/1510
---
drivers/rtc/rtc-pcf2123.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/rtc/rtc-pcf2123.c
+++ b/drivers/rtc/rtc-pcf2123.c
@@ -474,3 +474,4 @@ module_spi_driver(pcf2123_driver);
MODULE_AUTHOR("Chris Verges <chrisv@cyberswitching.com>");
MODULE_DESCRIPTION("NXP PCF2123 RTC driver");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("spi:rtc-pcf2123");

View file

@ -0,0 +1,102 @@
From 16e876906575f53df3ac9bf8d0cea3a456d1a150 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
Date: Fri, 7 Oct 2016 16:50:59 +0200
Subject: [PATCH] watchdog: bcm2835: Support setting reboot partition
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The Raspberry Pi firmware looks at the RSTS register to know which
partition to boot from. The reboot syscall command
LINUX_REBOOT_CMD_RESTART2 supports passing in a string argument.
Add support for passing in a partition number 0..63 to boot from.
Partition 63 is a special partiton indicating halt.
If the partition doesn't exist, the firmware falls back to partition 0.
Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
drivers/watchdog/bcm2835_wdt.c | 49 +++++++++++++++++++---------------
1 file changed, 27 insertions(+), 22 deletions(-)
--- a/drivers/watchdog/bcm2835_wdt.c
+++ b/drivers/watchdog/bcm2835_wdt.c
@@ -32,13 +32,7 @@
#define PM_RSTC_WRCFG_SET 0x00000030
#define PM_RSTC_WRCFG_FULL_RESET 0x00000020
#define PM_RSTC_RESET 0x00000102
-
-/*
- * The Raspberry Pi firmware uses the RSTS register to know which partition
- * to boot from. The partition value is spread into bits 0, 2, 4, 6, 8, 10.
- * Partition 63 is a special partition used by the firmware to indicate halt.
- */
-#define PM_RSTS_RASPBERRYPI_HALT 0x555
+#define PM_RSTS_PARTITION_CLR 0xfffffaaa
#define SECS_TO_WDOG_TICKS(x) ((x) << 16)
#define WDOG_TICKS_TO_SECS(x) ((x) >> 16)
@@ -97,9 +91,24 @@ static unsigned int bcm2835_wdt_get_time
return WDOG_TICKS_TO_SECS(ret & PM_WDOG_TIME_SET);
}
-static void __bcm2835_restart(struct bcm2835_wdt *wdt)
+/*
+ * The Raspberry Pi firmware uses the RSTS register to know which partiton
+ * to boot from. The partiton value is spread into bits 0, 2, 4, 6, 8, 10.
+ * Partiton 63 is a special partition used by the firmware to indicate halt.
+ */
+
+static void __bcm2835_restart(struct bcm2835_wdt *wdt, u8 partition)
{
- u32 val;
+ u32 val, rsts;
+
+ rsts = (partition & BIT(0)) | ((partition & BIT(1)) << 1) |
+ ((partition & BIT(2)) << 2) | ((partition & BIT(3)) << 3) |
+ ((partition & BIT(4)) << 4) | ((partition & BIT(5)) << 5);
+
+ val = readl_relaxed(wdt->base + PM_RSTS);
+ val &= PM_RSTS_PARTITION_CLR;
+ val |= PM_PASSWORD | rsts;
+ writel_relaxed(val, wdt->base + PM_RSTS);
/* use a timeout of 10 ticks (~150us) */
writel_relaxed(10 | PM_PASSWORD, wdt->base + PM_WDOG);
@@ -117,7 +126,13 @@ static int bcm2835_restart(struct watchd
{
struct bcm2835_wdt *wdt = watchdog_get_drvdata(wdog);
- __bcm2835_restart(wdt);
+ unsigned long long val;
+ u8 partition = 0;
+
+ if (data && !kstrtoull(data, 0, &val) && val <= 63)
+ partition = val;
+
+ __bcm2835_restart(wdt, partition);
return 0;
}
@@ -152,19 +167,9 @@ static struct watchdog_device bcm2835_wd
static void bcm2835_power_off(void)
{
struct bcm2835_wdt *wdt = bcm2835_power_off_wdt;
- u32 val;
-
- /*
- * We set the watchdog hard reset bit here to distinguish this reset
- * from the normal (full) reset. bootcode.bin will not reboot after a
- * hard reset.
- */
- val = readl_relaxed(wdt->base + PM_RSTS);
- val |= PM_PASSWORD | PM_RSTS_RASPBERRYPI_HALT;
- writel_relaxed(val, wdt->base + PM_RSTS);
- /* Continue with normal reset mechanism */
- __bcm2835_restart(wdt);
+ /* Partition 63 tells the firmware that this is a halt */
+ __bcm2835_restart(wdt, 63);
}
static int bcm2835_wdt_probe(struct platform_device *pdev)

View file

@ -0,0 +1,23 @@
From 900d45ec28bcc58c12314555038b1a31f5add91e Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Tue, 5 Apr 2016 19:40:12 +0100
Subject: [PATCH] reboot: Use power off rather than busy spinning when halt is
requested
---
arch/arm/kernel/reboot.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
--- a/arch/arm/kernel/reboot.c
+++ b/arch/arm/kernel/reboot.c
@@ -102,9 +102,7 @@ void machine_shutdown(void)
*/
void machine_halt(void)
{
- local_irq_disable();
- smp_send_stop();
- while (1);
+ machine_power_off();
}
/*

Some files were not shown because too many files have changed in this diff Show more