diff --git a/config/kernel/linux-rk322x-current.config b/config/kernel/linux-rk322x-current.config index 27f995d64..fb2a2b1f4 100644 --- a/config/kernel/linux-rk322x-current.config +++ b/config/kernel/linux-rk322x-current.config @@ -1,16 +1,14 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 5.7.16 Kernel Configuration -# - -# -# Compiler: arm-none-linux-gnueabihf-gcc (GNU Toolchain for the A-profile Architecture 9.2-2019.12 (arm-9.10)) 9.2.1 20191025 +# Linux/arm 5.8.9 Kernel Configuration # +CONFIG_CC_VERSION_TEXT="arm-none-linux-gnueabihf-gcc (GNU Toolchain for the A-profile Architecture 9.2-2019.12 (arm-9.10)) 9.2.1 20191025" CONFIG_CC_IS_GCC=y CONFIG_GCC_VERSION=90201 CONFIG_LD_VERSION=233010000 CONFIG_CLANG_VERSION=0 CONFIG_CC_CAN_LINK=y +CONFIG_CC_CAN_LINK_STATIC=y CONFIG_CC_HAS_ASM_GOTO=y CONFIG_CC_HAS_ASM_INLINE=y CONFIG_IRQ_WORK=y @@ -34,12 +32,14 @@ CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_XZ is not set # CONFIG_KERNEL_LZO is not set # CONFIG_KERNEL_LZ4 is not set +CONFIG_DEFAULT_INIT="" CONFIG_DEFAULT_HOSTNAME="localhost" CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y CONFIG_POSIX_MQUEUE=y CONFIG_POSIX_MQUEUE_SYSCTL=y +# CONFIG_WATCH_QUEUE is not set CONFIG_CROSS_MEMORY_ATTACH=y CONFIG_USELIB=y CONFIG_AUDIT=y @@ -110,7 +110,9 @@ CONFIG_PREEMPT_RCU=y # CONFIG_RCU_EXPERT is not set CONFIG_SRCU=y CONFIG_TREE_SRCU=y +CONFIG_TASKS_RCU_GENERIC=y CONFIG_TASKS_RCU=y +CONFIG_TASKS_RUDE_RCU=y CONFIG_RCU_STALL_COMMON=y CONFIG_RCU_NEED_SEGCBLIST=y # end of RCU Subsystem @@ -133,7 +135,6 @@ CONFIG_CGROUPS=y CONFIG_PAGE_COUNTER=y CONFIG_MEMCG=y CONFIG_MEMCG_SWAP=y -CONFIG_MEMCG_SWAP_ENABLED=y CONFIG_MEMCG_KMEM=y CONFIG_BLK_CGROUP=y CONFIG_CGROUP_WRITEBACK=y @@ -318,6 +319,7 @@ CONFIG_ARCH_MULTI_V6_V7=y # CONFIG_ARCH_SIRF is not set # CONFIG_ARCH_QCOM is not set # CONFIG_ARCH_RDA is not set +# CONFIG_ARCH_REALTEK is not set # CONFIG_ARCH_REALVIEW is not set CONFIG_ARCH_ROCKCHIP=y # CONFIG_ARCH_S5PV210 is not set @@ -442,6 +444,9 @@ CONFIG_SCHED_HRTICK=y CONFIG_ARM_PATCH_IDIV=y CONFIG_AEABI=y # CONFIG_OABI_COMPAT is not set +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_HAVE_ARCH_PFN_VALID=y CONFIG_HIGHMEM=y # CONFIG_HIGHPTE is not set @@ -503,7 +508,6 @@ CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y # CONFIG_CPUFREQ_DT=m CONFIG_CPUFREQ_DT_PLATDEV=y -# CONFIG_QORIQ_CPUFREQ is not set # end of CPU Frequency scaling # @@ -577,10 +581,11 @@ CONFIG_ARCH_HIBERNATION_POSSIBLE=y # CONFIG_FIRMWARE_MEMMAP is not set # CONFIG_FW_CFG_SYSFS is not set # CONFIG_TRUSTED_FOUNDATIONS is not set -CONFIG_HAVE_ARM_SMCCC=y +# CONFIG_GOOGLE_FIRMWARE is not set CONFIG_ARM_PSCI_FW=y # CONFIG_ARM_PSCI_CHECKER is not set -# CONFIG_GOOGLE_FIRMWARE is not set +CONFIG_HAVE_ARM_SMCCC=y +CONFIG_HAVE_ARM_SMCCC_DISCOVERY=y # # Tegra firmware driver @@ -630,7 +635,6 @@ CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y CONFIG_ARCH_32BIT_OFF_T=y CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y CONFIG_HAVE_RSEQ=y -CONFIG_HAVE_CLK=y CONFIG_HAVE_HW_BREAKPOINT=y CONFIG_HAVE_PERF_REGS=y CONFIG_HAVE_PERF_USER_STACK_DUMP=y @@ -705,6 +709,7 @@ CONFIG_BLK_DEV_THROTTLING=y # CONFIG_BLK_CGROUP_IOCOST is not set CONFIG_BLK_DEBUG_FS=y # CONFIG_BLK_SED_OPAL is not set +# CONFIG_BLK_INLINE_ENCRYPTION is not set # # Partition Types @@ -774,6 +779,9 @@ CONFIG_COREDUMP=y # # Memory Management options # +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_SPARSEMEM_MANUAL is not set CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y CONFIG_ARCH_KEEP_MEMBLOCK=y @@ -809,7 +817,7 @@ CONFIG_ZPOOL=y CONFIG_ZBUD=y CONFIG_Z3FOLD=y CONFIG_ZSMALLOC=y -# CONFIG_PGTABLE_MAPPING is not set +# CONFIG_ZSMALLOC_PGTABLE_MAPPING is not set # CONFIG_ZSMALLOC_STAT is not set CONFIG_GENERIC_EARLY_IOREMAP=y CONFIG_IDLE_PAGE_TRACKING=y @@ -843,6 +851,8 @@ CONFIG_XFRM_USER=m # CONFIG_XFRM_SUB_POLICY is not set # CONFIG_XFRM_MIGRATE is not set # CONFIG_XFRM_STATISTICS is not set +CONFIG_XFRM_AH=m +CONFIG_XFRM_ESP=m CONFIG_XFRM_IPCOMP=m CONFIG_NET_KEY=m # CONFIG_NET_KEY_MIGRATE is not set @@ -913,6 +923,7 @@ CONFIG_IPV6_OPTIMISTIC_DAD=y CONFIG_INET6_AH=m CONFIG_INET6_ESP=m CONFIG_INET6_ESP_OFFLOAD=m +# CONFIG_INET6_ESPINTCP is not set CONFIG_INET6_IPCOMP=m CONFIG_IPV6_MIP6=m CONFIG_IPV6_ILA=m @@ -1342,6 +1353,7 @@ CONFIG_MRP=y CONFIG_BRIDGE=y CONFIG_BRIDGE_IGMP_SNOOPING=y CONFIG_BRIDGE_VLAN_FILTERING=y +# CONFIG_BRIDGE_MRP is not set CONFIG_HAVE_NET_DSA=y CONFIG_NET_DSA=m CONFIG_NET_DSA_TAG_8021Q=m @@ -1483,6 +1495,7 @@ CONFIG_NET_ACT_SKBMOD=m CONFIG_NET_ACT_IFE=m CONFIG_NET_ACT_TUNNEL_KEY=m # CONFIG_NET_ACT_CT is not set +# CONFIG_NET_ACT_GATE is not set CONFIG_NET_IFE_SKBMARK=m CONFIG_NET_IFE_SKBPRIO=m CONFIG_NET_IFE_SKBTCINDEX=m @@ -1513,6 +1526,7 @@ CONFIG_NET_NSH=m CONFIG_HSR=m CONFIG_NET_SWITCHDEV=y CONFIG_NET_L3_MASTER_DEV=y +# CONFIG_QRTR is not set # CONFIG_NET_NCSI is not set CONFIG_RPS=y CONFIG_RFS_ACCEL=y @@ -1599,8 +1613,10 @@ CONFIG_BT_HS=y CONFIG_BT_LE=y CONFIG_BT_6LOWPAN=m # CONFIG_BT_LEDS is not set -# CONFIG_BT_SELFTEST is not set +# CONFIG_BT_MSFTEXT is not set CONFIG_BT_DEBUGFS=y +# CONFIG_BT_SELFTEST is not set +# CONFIG_BT_FEATURE_DEBUG is not set # # Bluetooth device drivers @@ -1944,6 +1960,7 @@ CONFIG_DM_CRYPT=y CONFIG_DM_THIN_PROVISIONING=y # CONFIG_DM_CACHE is not set CONFIG_DM_WRITECACHE=m +# CONFIG_DM_EBS is not set # CONFIG_DM_ERA is not set CONFIG_DM_CLONE=m CONFIG_DM_MIRROR=y @@ -2094,6 +2111,7 @@ CONFIG_MDIO_BUS_MUX=m # CONFIG_MDIO_BUS_MUX_MMIOREG is not set CONFIG_MDIO_BUS_MUX_MULTIPLEXER=m # CONFIG_MDIO_HISI_FEMAC is not set +# CONFIG_MDIO_IPQ4019 is not set # CONFIG_MDIO_IPQ8064 is not set CONFIG_MDIO_MSCC_MIIM=m # CONFIG_MDIO_MVUSB is not set @@ -2115,6 +2133,7 @@ CONFIG_BCM7XXX_PHY=m # CONFIG_BCM87XX_PHY is not set CONFIG_BCM_NET_PHYLIB=m # CONFIG_BROADCOM_PHY is not set +# CONFIG_BCM54140_PHY is not set # CONFIG_BCM84881_PHY is not set # CONFIG_CICADA_PHY is not set # CONFIG_CORTINA_PHY is not set @@ -2289,6 +2308,8 @@ CONFIG_MT76x0_COMMON=m CONFIG_MT76x0U=m CONFIG_MT76x2_COMMON=m CONFIG_MT76x2U=m +CONFIG_MT7615_COMMON=m +CONFIG_MT7663U=m CONFIG_WLAN_VENDOR_RALINK=y CONFIG_RT2X00=y CONFIG_RT2500USB=y @@ -2471,6 +2492,7 @@ CONFIG_TOUCHSCREEN_ATMEL_MXT=y # CONFIG_TOUCHSCREEN_BU21013 is not set CONFIG_TOUCHSCREEN_BU21029=m # CONFIG_TOUCHSCREEN_CHIPONE_ICN8318 is not set +# CONFIG_TOUCHSCREEN_CY8CTMA140 is not set # CONFIG_TOUCHSCREEN_CY8CTMG110 is not set # CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set # CONFIG_TOUCHSCREEN_CYTTSP4_CORE is not set @@ -2547,10 +2569,8 @@ CONFIG_INPUT_MISC=y # CONFIG_INPUT_ATMEL_CAPTOUCH is not set # CONFIG_INPUT_BMA150 is not set # CONFIG_INPUT_E3X0_BUTTON is not set -# CONFIG_INPUT_MSM_VIBRATOR is not set CONFIG_INPUT_MAX77650_ONKEY=m # CONFIG_INPUT_MMA8450 is not set -# CONFIG_INPUT_GP2A is not set # CONFIG_INPUT_GPIO_BEEPER is not set # CONFIG_INPUT_GPIO_DECODER is not set CONFIG_INPUT_GPIO_VIBRA=m @@ -2570,6 +2590,7 @@ CONFIG_INPUT_UINPUT=y # CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set # CONFIG_INPUT_ADXL34X is not set # CONFIG_INPUT_IMS_PCU is not set +# CONFIG_INPUT_IQS269A is not set # CONFIG_INPUT_CMA3000 is not set # CONFIG_INPUT_DRV260X_HAPTICS is not set # CONFIG_INPUT_DRV2665_HAPTICS is not set @@ -2686,6 +2707,7 @@ CONFIG_HW_RANDOM=y # CONFIG_HW_RANDOM_TIMERIOMEM is not set CONFIG_HW_RANDOM_VIRTIO=m CONFIG_HW_RANDOM_OPTEE=m +# CONFIG_HW_RANDOM_CCTRNG is not set CONFIG_DEVMEM=y # CONFIG_DEVKMEM is not set # CONFIG_RAW_DRIVER is not set @@ -2798,6 +2820,7 @@ CONFIG_SPI_ROCKCHIP=y # CONFIG_SPI_XCOMM is not set # CONFIG_SPI_XILINX is not set # CONFIG_SPI_ZYNQMP_GQSPI is not set +# CONFIG_SPI_AMD is not set # # SPI Multiplexer support @@ -2811,6 +2834,7 @@ CONFIG_SPI_SPIDEV=y # CONFIG_SPI_LOOPBACK_TEST is not set # CONFIG_SPI_TLE62X0 is not set # CONFIG_SPI_SLAVE is not set +CONFIG_SPI_DYNAMIC=y # CONFIG_SPMI is not set # CONFIG_HSI is not set CONFIG_PPS=y @@ -2842,7 +2866,6 @@ CONFIG_PINMUX=y CONFIG_PINCONF=y CONFIG_GENERIC_PINCONF=y # CONFIG_DEBUG_PINCTRL is not set -# CONFIG_PINCTRL_AMD is not set # CONFIG_PINCTRL_MCP23S08 is not set CONFIG_PINCTRL_ROCKCHIP=y # CONFIG_PINCTRL_SINGLE is not set @@ -2851,7 +2874,6 @@ CONFIG_PINCTRL_ROCKCHIP=y # CONFIG_PINCTRL_RK805 is not set # CONFIG_PINCTRL_OCELOT is not set CONFIG_PINCTRL_MADERA=m -# CONFIG_PINCTRL_EQUILIBRIUM is not set CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y CONFIG_GPIOLIB=y CONFIG_GPIOLIB_FASTPATH_LIMIT=512 @@ -2923,6 +2945,7 @@ CONFIG_GPIO_MAX77650=m # # end of USB GPIO expanders +# CONFIG_GPIO_AGGREGATOR is not set # CONFIG_GPIO_MOCKUP is not set CONFIG_W1=m CONFIG_W1_CON=y @@ -2985,6 +3008,7 @@ CONFIG_POWER_SUPPLY_HWMON=y # CONFIG_TEST_POWER is not set # CONFIG_CHARGER_ADP5061 is not set # CONFIG_BATTERY_CPCAP is not set +# CONFIG_BATTERY_CW2015 is not set # CONFIG_BATTERY_DS2760 is not set # CONFIG_BATTERY_DS2780 is not set # CONFIG_BATTERY_DS2781 is not set @@ -3013,6 +3037,7 @@ CONFIG_CHARGER_GPIO=m # CONFIG_BATTERY_GAUGE_LTC2941 is not set # CONFIG_CHARGER_RT9455 is not set # CONFIG_CHARGER_UCS1002 is not set +# CONFIG_CHARGER_BD99954 is not set CONFIG_HWMON=y # CONFIG_HWMON_DEBUG_CHIP is not set @@ -3171,7 +3196,6 @@ CONFIG_CPU_FREQ_THERMAL=y # CONFIG_DEVFREQ_THERMAL is not set # CONFIG_THERMAL_EMULATION is not set CONFIG_THERMAL_MMIO=m -# CONFIG_QORIQ_THERMAL is not set CONFIG_ROCKCHIP_THERMAL=m # CONFIG_GENERIC_ADC_THERMAL is not set CONFIG_WATCHDOG=y @@ -3198,6 +3222,7 @@ CONFIG_SOFT_WATCHDOG=m # CONFIG_FTWDT010_WATCHDOG is not set CONFIG_DW_WATCHDOG=m # CONFIG_MAX63XX_WATCHDOG is not set +# CONFIG_ARM_SMC_WATCHDOG is not set # CONFIG_STPMIC1_WATCHDOG is not set # CONFIG_MEN_A21_WDT is not set @@ -3241,8 +3266,10 @@ CONFIG_MFD_MADERA_I2C=m # CONFIG_MFD_DA9063 is not set # CONFIG_MFD_DA9150 is not set # CONFIG_MFD_DLN2 is not set +# CONFIG_MFD_GATEWORKS_GSC is not set # CONFIG_MFD_MC13XXX_SPI is not set # CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_MFD_MP2629 is not set # CONFIG_MFD_HI6421_PMIC is not set # CONFIG_HTC_PASIC3 is not set # CONFIG_HTC_I2CPLD is not set @@ -3261,6 +3288,7 @@ CONFIG_MFD_MAX77650=m # CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_MAX8997 is not set # CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_MT6360 is not set # CONFIG_MFD_MT6397 is not set # CONFIG_MFD_MENF21BMC is not set # CONFIG_EZX_PCAP is not set @@ -3355,6 +3383,7 @@ CONFIG_REGULATOR_GPIO=y # CONFIG_REGULATOR_MAX8660 is not set # CONFIG_REGULATOR_MAX8952 is not set # CONFIG_REGULATOR_MAX8973 is not set +# CONFIG_REGULATOR_MAX77826 is not set # CONFIG_REGULATOR_MCP16502 is not set # CONFIG_REGULATOR_MP5416 is not set # CONFIG_REGULATOR_MP8859 is not set @@ -3379,8 +3408,6 @@ CONFIG_REGULATOR_RK808=y # CONFIG_REGULATOR_TPS6524X is not set CONFIG_REGULATOR_TPS6586X=y # CONFIG_REGULATOR_VCTRL is not set -CONFIG_CEC_CORE=y -CONFIG_CEC_NOTIFIER=y CONFIG_RC_CORE=y CONFIG_RC_MAP=y CONFIG_LIRC=y @@ -3415,44 +3442,76 @@ CONFIG_IR_GPIO_CIR=m # CONFIG_IR_SERIAL is not set # CONFIG_IR_SIR is not set # CONFIG_RC_XBOX_DVD is not set +CONFIG_CEC_CORE=y +CONFIG_CEC_NOTIFIER=y +# CONFIG_MEDIA_CEC_RC is not set +# CONFIG_MEDIA_CEC_SUPPORT is not set CONFIG_MEDIA_SUPPORT=y +CONFIG_MEDIA_SUPPORT_FILTER=y +# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set # -# Multimedia core support +# Media device types # CONFIG_MEDIA_CAMERA_SUPPORT=y CONFIG_MEDIA_ANALOG_TV_SUPPORT=y CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y CONFIG_MEDIA_RADIO_SUPPORT=y CONFIG_MEDIA_SDR_SUPPORT=y -# CONFIG_MEDIA_CEC_SUPPORT is not set -# CONFIG_MEDIA_CEC_RC is not set -CONFIG_MEDIA_CONTROLLER=y -CONFIG_MEDIA_CONTROLLER_DVB=y -CONFIG_MEDIA_CONTROLLER_REQUEST_API=y +CONFIG_MEDIA_PLATFORM_SUPPORT=y +# CONFIG_MEDIA_TEST_SUPPORT is not set +# end of Media device types + CONFIG_VIDEO_DEV=y -CONFIG_VIDEO_V4L2_SUBDEV_API=y +CONFIG_MEDIA_CONTROLLER=y +CONFIG_DVB_CORE=y + +# +# Video4Linux options +# CONFIG_VIDEO_V4L2=y CONFIG_VIDEO_V4L2_I2C=y +CONFIG_VIDEO_V4L2_SUBDEV_API=y # CONFIG_VIDEO_ADV_DEBUG is not set CONFIG_VIDEO_FIXED_MINOR_RANGES=y CONFIG_VIDEO_TUNER=m +CONFIG_V4L2_H264=m CONFIG_V4L2_MEM2MEM_DEV=m CONFIG_V4L2_FWNODE=m CONFIG_VIDEOBUF_GEN=m CONFIG_VIDEOBUF_VMALLOC=m -CONFIG_DVB_CORE=y +# end of Video4Linux options + +# +# Media controller options +# +CONFIG_MEDIA_CONTROLLER_DVB=y +CONFIG_MEDIA_CONTROLLER_REQUEST_API=y + +# +# Please notice that the enabled Media controller Request API is EXPERIMENTAL +# +# end of Media controller options + +# +# Digital TV options +# # CONFIG_DVB_MMAP is not set CONFIG_DVB_NET=y -CONFIG_TTPCI_EEPROM=m CONFIG_DVB_MAX_ADAPTERS=16 CONFIG_DVB_DYNAMIC_MINORS=y # CONFIG_DVB_DEMUX_SECTION_LOSS_LOG is not set # CONFIG_DVB_ULE_DEBUG is not set +# end of Digital TV options # # Media drivers # + +# +# Drivers filtered as selected at 'Filter media drivers' +# +CONFIG_TTPCI_EEPROM=m CONFIG_MEDIA_USB_SUPPORT=y # @@ -3610,32 +3669,6 @@ CONFIG_VIDEO_EM28XX_RC=m CONFIG_USB_AIRSPY=m CONFIG_USB_HACKRF=m CONFIG_USB_MSI2500=m -CONFIG_V4L_PLATFORM_DRIVERS=y -# CONFIG_VIDEO_CADENCE is not set -# CONFIG_VIDEO_ASPEED is not set -CONFIG_VIDEO_MUX=m -CONFIG_VIDEO_XILINX=m -CONFIG_VIDEO_XILINX_TPG=m -CONFIG_VIDEO_XILINX_VTC=m -CONFIG_V4L_MEM2MEM_DRIVERS=y -# CONFIG_VIDEO_MEM2MEM_DEINTERLACE is not set -# CONFIG_VIDEO_SH_VEU is not set -CONFIG_VIDEO_ROCKCHIP_RGA=m -CONFIG_V4L_TEST_DRIVERS=y -# CONFIG_VIDEO_VIMC is not set -CONFIG_VIDEO_VIVID=m -# CONFIG_VIDEO_VIVID_CEC is not set -CONFIG_VIDEO_VIVID_MAX_DEVS=64 -CONFIG_VIDEO_VIM2M=m -CONFIG_VIDEO_VICODEC=m -CONFIG_DVB_PLATFORM_DRIVERS=y -CONFIG_DVB_C8SECTPFE=m -# CONFIG_SDR_PLATFORM_DRIVERS is not set - -# -# Supported MMC/SDIO adapters -# -# CONFIG_SMS_SDIO_DRV is not set # CONFIG_RADIO_ADAPTERS is not set CONFIG_MEDIA_COMMON_OPTIONS=y @@ -3654,19 +3687,32 @@ CONFIG_VIDEOBUF2_DMA_SG=m CONFIG_DVB_B2C2_FLEXCOP=m CONFIG_SMS_SIANO_MDTV=m CONFIG_SMS_SIANO_RC=y -CONFIG_VIDEO_V4L2_TPG=m +CONFIG_V4L_PLATFORM_DRIVERS=y +# CONFIG_VIDEO_CADENCE is not set +# CONFIG_VIDEO_ASPEED is not set +CONFIG_VIDEO_MUX=m +CONFIG_VIDEO_XILINX=m +CONFIG_VIDEO_XILINX_TPG=m +CONFIG_VIDEO_XILINX_VTC=m +CONFIG_V4L_MEM2MEM_DRIVERS=y +# CONFIG_VIDEO_MEM2MEM_DEINTERLACE is not set +CONFIG_VIDEO_ROCKCHIP_RGA=m +CONFIG_DVB_PLATFORM_DRIVERS=y +CONFIG_DVB_C8SECTPFE=m +# CONFIG_SDR_PLATFORM_DRIVERS is not set # -# Media ancillary drivers (tuners, sensors, i2c, spi, frontends) +# MMC/SDIO DVB adapters +# +# CONFIG_SMS_SDIO_DRV is not set +# end of Media drivers + +# +# Media ancillary drivers # -# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set CONFIG_MEDIA_ATTACH=y CONFIG_VIDEO_IR_I2C=m -# -# I2C Encoders, decoders, sensors and other helper chips -# - # # Audio decoders, processors and mixers # @@ -3686,11 +3732,13 @@ CONFIG_VIDEO_WM8775=m # CONFIG_VIDEO_WM8739 is not set # CONFIG_VIDEO_VP27SMPX is not set # CONFIG_VIDEO_SONY_BTF_MPX is not set +# end of Audio decoders, processors and mixers # # RDS decoders # # CONFIG_VIDEO_SAA6588 is not set +# end of RDS decoders # # Video decoders @@ -3722,6 +3770,7 @@ CONFIG_VIDEO_SAA711X=m # # CONFIG_VIDEO_SAA717X is not set CONFIG_VIDEO_CX25840=m +# end of Video decoders # # Video encoders @@ -3736,6 +3785,35 @@ CONFIG_VIDEO_CX25840=m # CONFIG_VIDEO_AD9389B is not set # CONFIG_VIDEO_AK881X is not set # CONFIG_VIDEO_THS8200 is not set +# end of Video encoders + +# +# Video improvement chips +# +# CONFIG_VIDEO_UPD64031A is not set +# CONFIG_VIDEO_UPD64083 is not set +# end of Video improvement chips + +# +# Audio/Video compression chips +# +# CONFIG_VIDEO_SAA6752HS is not set +# end of Audio/Video compression chips + +# +# SDR tuner chips +# +# CONFIG_SDR_MAX2175 is not set +# end of SDR tuner chips + +# +# Miscellaneous helper chips +# +# CONFIG_VIDEO_THS7303 is not set +# CONFIG_VIDEO_M52790 is not set +# CONFIG_VIDEO_I2C is not set +# CONFIG_VIDEO_ST_MIPID02 is not set +# end of Miscellaneous helper chips # # Camera sensor devices @@ -3752,6 +3830,7 @@ CONFIG_VIDEO_CX25840=m # CONFIG_VIDEO_OV2659 is not set # CONFIG_VIDEO_OV2680 is not set # CONFIG_VIDEO_OV2685 is not set +# CONFIG_VIDEO_OV2740 is not set # CONFIG_VIDEO_OV5640 is not set # CONFIG_VIDEO_OV5645 is not set # CONFIG_VIDEO_OV5647 is not set @@ -3789,6 +3868,7 @@ CONFIG_VIDEO_CX25840=m # CONFIG_VIDEO_SMIAPP is not set # CONFIG_VIDEO_ET8EK8 is not set # CONFIG_VIDEO_S5C73M3 is not set +# end of Camera sensor devices # # Lens drivers @@ -3797,6 +3877,7 @@ CONFIG_VIDEO_CX25840=m # CONFIG_VIDEO_AK7375 is not set # CONFIG_VIDEO_DW9714 is not set # CONFIG_VIDEO_DW9807_VCM is not set +# end of Lens drivers # # Flash devices @@ -3804,31 +3885,7 @@ CONFIG_VIDEO_CX25840=m # CONFIG_VIDEO_ADP1653 is not set # CONFIG_VIDEO_LM3560 is not set # CONFIG_VIDEO_LM3646 is not set - -# -# Video improvement chips -# -# CONFIG_VIDEO_UPD64031A is not set -# CONFIG_VIDEO_UPD64083 is not set - -# -# Audio/Video compression chips -# -# CONFIG_VIDEO_SAA6752HS is not set - -# -# SDR tuner chips -# -# CONFIG_SDR_MAX2175 is not set - -# -# Miscellaneous helper chips -# -# CONFIG_VIDEO_THS7303 is not set -# CONFIG_VIDEO_M52790 is not set -# CONFIG_VIDEO_I2C is not set -# CONFIG_VIDEO_ST_MIPID02 is not set -# end of I2C Encoders, decoders, sensors and other helper chips +# end of Flash devices # # SPI helper chips @@ -4048,12 +4105,8 @@ CONFIG_DVB_AF9033=m # # CONFIG_DVB_CXD2099 is not set # CONFIG_DVB_SP2 is not set - -# -# Tools to develop new frontends -# -# CONFIG_DVB_DUMMY_FE is not set # end of Customise DVB Frontends +# end of Media ancillary drivers # # Graphics support @@ -4147,9 +4200,12 @@ CONFIG_DRM_PANEL_BRIDGE=y # Display Interface Bridges # # CONFIG_DRM_CDNS_DSI is not set +# CONFIG_DRM_CHRONTEL_CH7033 is not set CONFIG_DRM_DISPLAY_CONNECTOR=m +# CONFIG_DRM_ITE_IT66121 is not set # CONFIG_DRM_LVDS_CODEC is not set # CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW is not set +# CONFIG_DRM_NWL_MIPI_DSI is not set # CONFIG_DRM_NXP_PTN3460 is not set # CONFIG_DRM_PARADE_PS8622 is not set # CONFIG_DRM_PARADE_PS8640 is not set @@ -4435,6 +4491,7 @@ CONFIG_SND_SOC_MAX98090=m CONFIG_SND_SOC_MAX9867=m # CONFIG_SND_SOC_MAX98927 is not set # CONFIG_SND_SOC_MAX98373 is not set +# CONFIG_SND_SOC_MAX98390 is not set # CONFIG_SND_SOC_MAX9860 is not set # CONFIG_SND_SOC_MSM8916_WCD_DIGITAL is not set # CONFIG_SND_SOC_PCM1681 is not set @@ -4509,6 +4566,7 @@ CONFIG_SND_SOC_WM8904=m # CONFIG_SND_SOC_WM8974 is not set # CONFIG_SND_SOC_WM8978 is not set # CONFIG_SND_SOC_WM8985 is not set +# CONFIG_SND_SOC_ZL38060 is not set # CONFIG_SND_SOC_ZX_AUD96P22 is not set CONFIG_SND_SOC_MAX9759=m CONFIG_SND_SOC_MT6351=m @@ -4987,6 +5045,7 @@ CONFIG_LEDS_CLASS=y # LED drivers # # CONFIG_LEDS_AN30259A is not set +# CONFIG_LEDS_AW2013 is not set # CONFIG_LEDS_BCM6328 is not set # CONFIG_LEDS_BCM6358 is not set # CONFIG_LEDS_CPCAP is not set @@ -5223,7 +5282,6 @@ CONFIG_DMABUF_SELFTESTS=m CONFIG_VIRTIO=m # CONFIG_VIRTIO_MENU is not set # CONFIG_VDPA is not set -CONFIG_VHOST_DPN=y CONFIG_VHOST_MENU=y # CONFIG_VHOST_NET is not set # CONFIG_VHOST_CROSS_ENDIAN_LEGACY is not set @@ -5310,6 +5368,7 @@ CONFIG_88EU_AP_MODE=y CONFIG_STAGING_MEDIA=y CONFIG_VIDEO_HANTRO=m CONFIG_VIDEO_HANTRO_ROCKCHIP=y +CONFIG_VIDEO_ROCKCHIP_VDEC=m # # soc_camera sensor drivers @@ -5384,13 +5443,10 @@ CONFIG_HMS_PROFINET=m # CONFIG_MFD_CROS_EC is not set # CONFIG_CHROME_PLATFORMS is not set # CONFIG_MELLANOX_PLATFORM is not set +CONFIG_HAVE_CLK=y CONFIG_CLKDEV_LOOKUP=y CONFIG_HAVE_CLK_PREPARE=y CONFIG_COMMON_CLK=y - -# -# Common Clock Framework -# # CONFIG_CLK_HSDK is not set CONFIG_COMMON_CLK_MAX9485=m CONFIG_COMMON_CLK_RK808=y @@ -5407,8 +5463,6 @@ CONFIG_COMMON_CLK_SI544=m CONFIG_COMMON_CLK_VC5=m # CONFIG_COMMON_CLK_BD718XX is not set # CONFIG_COMMON_CLK_FIXED_MMIO is not set -# end of Common Clock Framework - # CONFIG_HWSPINLOCK is not set # @@ -5619,6 +5673,8 @@ CONFIG_AD7768_1=m # CONFIG_AD7923 is not set # CONFIG_AD7949 is not set # CONFIG_AD799X is not set +# CONFIG_AD9467 is not set +# CONFIG_ADI_AXI_ADC is not set # CONFIG_CC10001_ADC is not set # CONFIG_CPCAP_ADC is not set # CONFIG_ENVELOPE_DETECTOR is not set @@ -5632,6 +5688,7 @@ CONFIG_AD7768_1=m # CONFIG_MAX1027 is not set # CONFIG_MAX11100 is not set # CONFIG_MAX1118 is not set +# CONFIG_MAX1241 is not set # CONFIG_MAX1363 is not set # CONFIG_MAX9611 is not set # CONFIG_MCP320X is not set @@ -5674,6 +5731,7 @@ CONFIG_IIO_RESCALE=m # Chemical Sensors # # CONFIG_ATLAS_PH_SENSOR is not set +# CONFIG_ATLAS_EZO_SENSOR is not set CONFIG_BME680=m CONFIG_BME680_I2C=m CONFIG_BME680_SPI=m @@ -5811,6 +5869,7 @@ CONFIG_SI7020=m # # CONFIG_ADIS16400 is not set CONFIG_ADIS16460=m +# CONFIG_ADIS16475 is not set # CONFIG_ADIS16480 is not set # CONFIG_BMI160_I2C is not set # CONFIG_BMI160_SPI is not set @@ -5976,8 +6035,10 @@ CONFIG_MB1232=m # CONFIG_PING is not set # CONFIG_RFD77402 is not set # CONFIG_SRF04 is not set +# CONFIG_SX9310 is not set # CONFIG_SX9500 is not set # CONFIG_SRF08 is not set +# CONFIG_VCNL3020 is not set # CONFIG_VL53L0X_I2C is not set # end of Proximity and distance sensors @@ -6035,6 +6096,7 @@ CONFIG_GENERIC_PHY=y # CONFIG_PHY_CADENCE_TORRENT is not set # CONFIG_PHY_CADENCE_DPHY is not set # CONFIG_PHY_CADENCE_SIERRA is not set +# CONFIG_PHY_CADENCE_SALVO is not set # CONFIG_PHY_FSL_IMX8MQ_USB is not set # CONFIG_PHY_MIXEL_MIPI_DPHY is not set # CONFIG_PHY_PXA_28NM_HSIC is not set @@ -6051,7 +6113,6 @@ CONFIG_PHY_ROCKCHIP_INNO_USB2=y # CONFIG_PHY_ROCKCHIP_TYPEC is not set CONFIG_PHY_ROCKCHIP_USB=y # CONFIG_PHY_SAMSUNG_USB2 is not set -# CONFIG_PHY_INTEL_EMMC is not set # end of PHY Subsystem # CONFIG_POWERCAP is not set @@ -6114,7 +6175,7 @@ CONFIG_MUX_MMIO=m CONFIG_PM_OPP=y # CONFIG_SIOX is not set # CONFIG_SLIMBUS is not set -CONFIG_INTERCONNECT=m +# CONFIG_INTERCONNECT is not set # CONFIG_COUNTER is not set CONFIG_MOST=m # end of Device Drivers @@ -6307,27 +6368,10 @@ CONFIG_PSTORE_CONSOLE=y # CONFIG_PSTORE_PMSG is not set # CONFIG_PSTORE_FTRACE is not set CONFIG_PSTORE_RAM=y +# CONFIG_PSTORE_BLK is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set # CONFIG_EROFS_FS is not set -CONFIG_AUFS_FS=m -CONFIG_AUFS_BRANCH_MAX_127=y -# CONFIG_AUFS_BRANCH_MAX_511 is not set -# CONFIG_AUFS_BRANCH_MAX_1023 is not set -# CONFIG_AUFS_BRANCH_MAX_32767 is not set -CONFIG_AUFS_SBILIST=y -# CONFIG_AUFS_HNOTIFY is not set -# CONFIG_AUFS_EXPORT is not set -# CONFIG_AUFS_XATTR is not set -# CONFIG_AUFS_FHSM is not set -# CONFIG_AUFS_RDU is not set -# CONFIG_AUFS_DIRREN is not set -# CONFIG_AUFS_SHWH is not set -# CONFIG_AUFS_BR_RAMFS is not set -# CONFIG_AUFS_BR_FUSE is not set -CONFIG_AUFS_BR_HFSPLUS=y -CONFIG_AUFS_BDEV_LOOP=y -# CONFIG_AUFS_DEBUG is not set CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V2=y @@ -6448,7 +6492,6 @@ CONFIG_IO_WQ=y CONFIG_KEYS=y # CONFIG_KEYS_REQUEST_CACHE is not set # CONFIG_PERSISTENT_KEYRINGS is not set -# CONFIG_BIG_KEYS is not set # CONFIG_TRUSTED_KEYS is not set # CONFIG_ENCRYPTED_KEYS is not set # CONFIG_KEY_DH_OPERATIONS is not set @@ -6712,6 +6755,7 @@ CONFIG_BINARY_PRINTF=y # CONFIG_RAID6_PQ=y CONFIG_RAID6_PQ_BENCHMARK=y +CONFIG_LINEAR_RANGES=y CONFIG_PACKING=y CONFIG_BITREVERSE=y CONFIG_HAVE_ARCH_BITREVERSE=y @@ -6719,6 +6763,7 @@ CONFIG_GENERIC_STRNCPY_FROM_USER=y CONFIG_GENERIC_STRNLEN_USER=y CONFIG_GENERIC_NET_UTILS=y # CONFIG_CORDIC is not set +# CONFIG_PRIME_NUMBERS is not set CONFIG_RATIONAL=y CONFIG_GENERIC_PCI_IOMAP=y CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y @@ -6835,6 +6880,7 @@ CONFIG_CONSOLE_LOGLEVEL_QUIET=4 CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 # CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_DYNAMIC_DEBUG_CORE is not set CONFIG_SYMBOLIC_ERRNAME=y CONFIG_DEBUG_BUGVERBOSE=y # end of printk and dmesg options @@ -6880,6 +6926,7 @@ CONFIG_PAGE_EXTENSION=y # CONFIG_PAGE_POISONING is not set # CONFIG_DEBUG_PAGE_REF is not set # CONFIG_DEBUG_RODATA_TEST is not set +# CONFIG_DEBUG_WX is not set # CONFIG_DEBUG_OBJECTS is not set # CONFIG_SLUB_DEBUG_ON is not set # CONFIG_SLUB_STATS is not set @@ -6894,6 +6941,7 @@ CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y # CONFIG_DEBUG_PER_CPU_MAPS is not set # CONFIG_DEBUG_HIGHMEM is not set CONFIG_CC_HAS_KASAN_GENERIC=y +CONFIG_CC_HAS_WORKING_NOSANITIZE_ADDRESS=y CONFIG_KASAN_STACK=1 # end of Memory Debugging @@ -6996,7 +7044,6 @@ CONFIG_DYNAMIC_FTRACE=y CONFIG_DYNAMIC_FTRACE_WITH_REGS=y # CONFIG_FUNCTION_PROFILER is not set # CONFIG_STACK_TRACER is not set -# CONFIG_PREEMPTIRQ_EVENTS is not set # CONFIG_IRQSOFF_TRACER is not set # CONFIG_PREEMPT_TRACER is not set # CONFIG_SCHED_TRACER is not set @@ -7009,6 +7056,7 @@ CONFIG_BRANCH_PROFILE_NONE=y CONFIG_BLK_DEV_IO_TRACE=y # CONFIG_UPROBE_EVENTS is not set CONFIG_FTRACE_MCOUNT_RECORD=y +# CONFIG_SYNTH_EVENTS is not set # CONFIG_TRACE_EVENT_INJECT is not set # CONFIG_TRACEPOINT_BENCHMARK is not set # CONFIG_RING_BUFFER_BENCHMARK is not set @@ -7025,7 +7073,6 @@ CONFIG_STRICT_DEVMEM=y # arm Debugging # # CONFIG_ARM_PTDUMP_DEBUGFS is not set -# CONFIG_DEBUG_WX is not set CONFIG_UNWINDER_FRAME_POINTER=y # CONFIG_DEBUG_USER is not set # CONFIG_DEBUG_LL is not set diff --git a/config/kernel/linux-rk322x-dev.config b/config/kernel/linux-rk322x-dev.config index 1ad9cfcd9..fb2a2b1f4 100644 --- a/config/kernel/linux-rk322x-dev.config +++ b/config/kernel/linux-rk322x-dev.config @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 5.8.2 Kernel Configuration +# Linux/arm 5.8.9 Kernel Configuration # CONFIG_CC_VERSION_TEXT="arm-none-linux-gnueabihf-gcc (GNU Toolchain for the A-profile Architecture 9.2-2019.12 (arm-9.10)) 9.2.1 20191025" CONFIG_CC_IS_GCC=y @@ -2834,6 +2834,7 @@ CONFIG_SPI_SPIDEV=y # CONFIG_SPI_LOOPBACK_TEST is not set # CONFIG_SPI_TLE62X0 is not set # CONFIG_SPI_SLAVE is not set +CONFIG_SPI_DYNAMIC=y # CONFIG_SPMI is not set # CONFIG_HSI is not set CONFIG_PPS=y @@ -4201,6 +4202,7 @@ CONFIG_DRM_PANEL_BRIDGE=y # CONFIG_DRM_CDNS_DSI is not set # CONFIG_DRM_CHRONTEL_CH7033 is not set CONFIG_DRM_DISPLAY_CONNECTOR=m +# CONFIG_DRM_ITE_IT66121 is not set # CONFIG_DRM_LVDS_CODEC is not set # CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW is not set # CONFIG_DRM_NWL_MIPI_DSI is not set @@ -5445,6 +5447,7 @@ CONFIG_HAVE_CLK=y CONFIG_CLKDEV_LOOKUP=y CONFIG_HAVE_CLK_PREPARE=y CONFIG_COMMON_CLK=y +# CONFIG_CLK_HSDK is not set CONFIG_COMMON_CLK_MAX9485=m CONFIG_COMMON_CLK_RK808=y # CONFIG_COMMON_CLK_SI5341 is not set diff --git a/config/kernel/linux-rk322x-legacy.config b/config/kernel/linux-rk322x-legacy.config index b0dd4685f..278adc0a4 100644 --- a/config/kernel/linux-rk322x-legacy.config +++ b/config/kernel/linux-rk322x-legacy.config @@ -1925,6 +1925,10 @@ CONFIG_MVL88W8977=m # CONFIG_SSV6051=m # CONFIG_WL_TI is not set +CONFIG_RTL8822BU=m +CONFIG_RTL8821CU=m +CONFIG_88XXAU=m +CONFIG_RTL8192EU=m CONFIG_ZD1211RW=m # CONFIG_ZD1211RW_DEBUG is not set CONFIG_MWIFIEX=y @@ -2814,8 +2818,9 @@ CONFIG_MEDIA_CAMERA_SUPPORT=y CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y # CONFIG_MEDIA_RADIO_SUPPORT is not set # CONFIG_MEDIA_SDR_SUPPORT is not set -# CONFIG_MEDIA_RC_SUPPORT is not set +CONFIG_MEDIA_RC_SUPPORT=y CONFIG_MEDIA_CEC_SUPPORT=y +CONFIG_MEDIA_CEC_RC=y CONFIG_MEDIA_CONTROLLER=y CONFIG_VIDEO_DEV=y CONFIG_VIDEO_V4L2_SUBDEV_API=y @@ -2840,6 +2845,33 @@ CONFIG_DVB_MAX_ADAPTERS=8 # # Media drivers # +CONFIG_RC_CORE=y +CONFIG_RC_MAP=y +# CONFIG_LIRC is not set +CONFIG_RC_DECODERS=y +CONFIG_IR_NEC_DECODER=y +CONFIG_IR_RC5_DECODER=y +CONFIG_IR_RC6_DECODER=y +CONFIG_IR_JVC_DECODER=y +CONFIG_IR_SONY_DECODER=y +CONFIG_IR_SANYO_DECODER=y +CONFIG_IR_SHARP_DECODER=y +CONFIG_IR_MCE_KBD_DECODER=y +CONFIG_IR_XMP_DECODER=y +# CONFIG_IR_IMON_DECODER is not set +CONFIG_RC_DEVICES=y +# CONFIG_RC_ATI_REMOTE is not set +# CONFIG_IR_HIX5HD2 is not set +# CONFIG_IR_IMON is not set +# CONFIG_IR_MCEUSB is not set +# CONFIG_IR_REDRAT3 is not set +# CONFIG_IR_STREAMZAP is not set +# CONFIG_IR_IGORPLUGUSB is not set +# CONFIG_IR_IGUANA is not set +# CONFIG_IR_TTUSBIR is not set +# CONFIG_RC_LOOPBACK is not set +CONFIG_IR_GPIO_CIR=m +# CONFIG_IR_SERIAL is not set CONFIG_MEDIA_USB_SUPPORT=y # @@ -2861,10 +2893,14 @@ CONFIG_USB_VIDEO_CLASS=y # CONFIG_VIDEO_AU0828=m CONFIG_VIDEO_AU0828_V4L2=y +# CONFIG_VIDEO_AU0828_RC is not set +# CONFIG_VIDEO_CX231XX is not set +# CONFIG_VIDEO_TM6000 is not set # # Digital TV USB devices # +# CONFIG_DVB_USB is not set CONFIG_DVB_USB_V2=y CONFIG_DVB_USB_AF9015=m CONFIG_DVB_USB_AF9035=m @@ -2874,6 +2910,7 @@ CONFIG_DVB_USB_AZ6007=m CONFIG_DVB_USB_CE6230=m CONFIG_DVB_USB_EC168=m CONFIG_DVB_USB_GL861=m +# CONFIG_DVB_USB_LME2510 is not set CONFIG_DVB_USB_MXL111SF=m CONFIG_DVB_USB_RTL28XXU=m CONFIG_DVB_USB_DVBSKY=m @@ -2926,6 +2963,7 @@ CONFIG_DVB_B2C2_FLEXCOP=m # # CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set CONFIG_MEDIA_ATTACH=y +CONFIG_VIDEO_IR_I2C=y # # I2C Encoders, decoders, sensors and other helper chips @@ -3801,6 +3839,7 @@ CONFIG_HID_PICOLCD=m CONFIG_HID_PICOLCD_FB=y CONFIG_HID_PICOLCD_BACKLIGHT=y CONFIG_HID_PICOLCD_LEDS=y +# CONFIG_HID_PICOLCD_CIR is not set CONFIG_HID_PLANTRONICS=m CONFIG_HID_PRIMAX=m CONFIG_HID_ROCCAT=m diff --git a/config/sources/families/rk322x.conf b/config/sources/families/rk322x.conf index 91c6cf472..df304d3df 100644 --- a/config/sources/families/rk322x.conf +++ b/config/sources/families/rk322x.conf @@ -3,7 +3,7 @@ BOOTENV_FILE='rk322x.txt' OVERLAY_PREFIX='rk322x' UBOOT_TARGET_MAP="all u-boot.itb;;u-boot-rk322x-with-spl.bin" BOOTDELAY=0 -BOOTBRANCH='tag:v2020.04' +BOOTBRANCH='tag:v2020.07' ARCH=armhf SERIALCON=ttyS2 @@ -19,7 +19,7 @@ case $BRANCH in current) - KERNELBRANCH='branch:linux-5.7.y' + KERNELBRANCH='branch:linux-5.8.y' AUFS=no ;; @@ -57,7 +57,7 @@ uboot_custom_postprocess() # tools/mkimage -n rk322x -T rksd -d tpl/u-boot-tpl.bin u-boot-rk322x-with-spl.bin # - tools/mkimage -n rk322x -T rksd -d $SRC/packages/blobs/rockchip/rk322x_ddr2_300_ddr3_600_v1.09.bin u-boot-rk322x-with-spl.bin + tools/mkimage -n rk322x -T rksd -d $SRC/packages/blobs/rockchip/rk322x_ddr3_600MHz_ddr2_330MHz_v1.10.bin u-boot-rk322x-with-spl.bin cat spl/u-boot-spl.bin >> u-boot-rk322x-with-spl.bin dd if=u-boot.itb of=u-boot-rk322x-with-spl.bin seek=$((0x200 - 0x40)) conv=notrunc @@ -97,13 +97,9 @@ family_tweaks_bsp() cp $SRC/packages/bsp/rockchip/asound.conf $destination/etc/ cp $SRC/packages/bsp/rockchip/89-pulseaudio-usb.rules $destination/etc/udev/rules.d - # For rk322x boards copy ssv6051 wifi firmware files to /etc/firmware - # We don't want to copy it into /lib/firmware to not interfere with armbian - # firmware deb package, so for now put them in a separate position - mkdir -p $destination/etc/firmware - cp $SRC/packages/blobs/ssv6051/ssv6051-wifi.cfg $destination/etc/firmware - cp $SRC/packages/blobs/ssv6051/ssv6051-sw.bin $destination/etc/firmware - echo "options ssv6051 stacfgpath=/etc/firmware/ssv6051-wifi.cfg cfgfirmwarepath=/etc/firmware/" > $destination/etc/modprobe.d/ssv6051.conf + # esp8089 wifi driver modprobe default configuration options + mkdir -p $destination/etc/modprobe.d + cp $SRC/packages/bsp/rk322x/esp8089.conf $destination/etc/modprobe.d/esp8089.conf # Board selection script install -m 755 $SRC/packages/bsp/rk322x/rk322x-config $destination/usr/local/bin diff --git a/packages/blobs/rockchip/rk322x_ddr3_600MHz_ddr2_330MHz_v1.10.bin b/packages/blobs/rockchip/rk322x_ddr3_600MHz_ddr2_330MHz_v1.10.bin new file mode 100644 index 000000000..fbc4e34b7 Binary files /dev/null and b/packages/blobs/rockchip/rk322x_ddr3_600MHz_ddr2_330MHz_v1.10.bin differ diff --git a/packages/blobs/rockchip/rk322x_tee.bin b/packages/blobs/rockchip/rk322x_tee.bin index 70efbcaa0..4f076e44a 100644 Binary files a/packages/blobs/rockchip/rk322x_tee.bin and b/packages/blobs/rockchip/rk322x_tee.bin differ diff --git a/packages/blobs/ssv6051/ssv6051-sw.bin b/packages/blobs/ssv6051/ssv6051-sw.bin deleted file mode 100644 index 8ca0a3726..000000000 Binary files a/packages/blobs/ssv6051/ssv6051-sw.bin and /dev/null differ diff --git a/packages/blobs/ssv6051/ssv6051-wifi.cfg b/packages/blobs/ssv6051/ssv6051-wifi.cfg deleted file mode 100644 index c072960f6..000000000 --- a/packages/blobs/ssv6051/ssv6051-wifi.cfg +++ /dev/null @@ -1,91 +0,0 @@ -############################################################ -# ROCKCHIP RK3X28 & RK322X -# WIFI-CONFIGURATION -################################################## - -################################################## -# Firmware setting -# Priority.1 insmod parameter "cfgfirmwarepath" -# Priority.2 firmware_path -# Priority.3 default firmware -################################################## -firmware_path = /vendor/etc/firmware/ - -############################################################ -# MAC address -# -# Priority 1. From wifi.cfg [ hw_mac & hw_mac_2 ] -# -# Priority 2. From e-fuse[ON/OFF switch by wifi.cfg] -# -# Priority 3. From insert module parameter -# -# Priority 4. From external file path -# path only support some special charater "_" ":" "/" "." "-" -# -# Priority 5. Default[Software mode] -# -# 0. => 00:33:33:33:33:33 -# 1. => Always random -# 2. => First random and write to file[Default path mac_output_path] -# -############################################################ -ignore_efuse_mac = 0 -#mac_address_path = /xxxx/xxxx -mac_address_mode = 2 -mac_output_path = /data/wifimac - -################################################## -# Hardware setting -# -#volt regulator(DCDC-0 LDO-1) -# -################################################## -xtal_clock = 24 -volt_regulator = 1 - -################################################## -# Default channel after wifi on -# value range: [1 ~ 14] -################################################## -def_chan = 6 -################################################## -# Hardware Capability Settings: -################################################## -hw_cap_ht = on -hw_cap_gf = off -hw_cap_2ghz = on -hw_cap_5ghz = off -hw_cap_security = on -hw_cap_sgi_20 = on -hw_cap_sgi_40 = off -hw_cap_ap = on -hw_cap_p2p = on -hw_cap_ampdu_rx = on -hw_cap_ampdu_tx = on -use_wpa2_only = 1 -################################################## -# TX power level setting [0-14] -# The larger the number the smaller the TX power -# 0 - The maximum power -# 1 level = -0.5db -# -# 6051Z .. 4 or 4 -# 6051Q .. 2 or 5 -# 6051P .. 0 or 0 -# -################################################## -#wifi_tx_gain_level_b = 2 -#wifi_tx_gain_level_gn = 5 -################################################ -# Signal strength control -# rssi control -#rssi_ctl = 10 - - -################################################## -# Import extenal configuration(UP to 64 groups) -# example: -# register = CE010010:91919191 -# register = 00CC0010:00091919 -################################################## diff --git a/packages/bsp/rk322x/40-serverflags.conf b/packages/bsp/rk322x/40-serverflags.conf index e40e146a0..735a8a141 100644 --- a/packages/bsp/rk322x/40-serverflags.conf +++ b/packages/bsp/rk322x/40-serverflags.conf @@ -1,10 +1,13 @@ Section "ServerFlags" - Option "AutoAddGPU" "off" + Option "AutoAddGPU" "off" + Option "Debug" "dmabuf_capable" EndSection -Section "Device" - Identifier "meson" - Driver "modesetting" - Option "kmsdev" "/dev/dri/card0" +Section "OutputClass" + Identifier "Lima" + Driver "modesetting" + MatchDriver "rockchip" + Option "AccelMethod" "none" + Option "PrimaryGPU" "true" EndSection diff --git a/packages/bsp/rk322x/esp8089.conf b/packages/bsp/rk322x/esp8089.conf new file mode 100644 index 000000000..c43b297c2 --- /dev/null +++ b/packages/bsp/rk322x/esp8089.conf @@ -0,0 +1 @@ +options esp8089 crystal_26M_en=0 diff --git a/patch/kernel/rk322x-current/01-linux-0001-rockchip-from-5.9.patch b/patch/kernel/rk322x-current/01-linux-0001-rockchip-from-5.9.patch new file mode 100644 index 000000000..d8845599b --- /dev/null +++ b/patch/kernel/rk322x-current/01-linux-0001-rockchip-from-5.9.patch @@ -0,0 +1,3987 @@ +From df792eba98fd6a729c254623ea28968f642efd1e Mon Sep 17 00:00:00 2001 +From: Tobias Schramm +Date: Thu, 28 May 2020 19:25:50 +0200 +Subject: [PATCH] arm64: dts: rockchip: add fuel gauge to Pinebook Pro dts + +This commit adds cw2015 fuel gauge and battery to the Pinebook Pro dts. + +Signed-off-by: Tobias Schramm +Link: https://lore.kernel.org/r/20200528172550.2324722-2-t.schramm@manjaro.org +Signed-off-by: Heiko Stuebner +(cherry picked from commit c7c4d698cd2882c4d095aeed43bbad6fc990e998) +--- + .../boot/dts/rockchip/rk3399-pinebook-pro.dts | 25 +++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts +index cb0245d2226d..8f5b2df01560 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts +@@ -28,6 +28,13 @@ backlight: edp-backlight { + pwms = <&pwm0 0 740740 0>; + }; + ++ bat: battery { ++ compatible = "simple-battery"; ++ charge-full-design-microamp-hours = <9800000>; ++ voltage-max-design-microvolt = <4350000>; ++ voltage-min-design-microvolt = <3000000>; ++ }; ++ + edp_panel: edp-panel { + compatible = "boe,nv140fhmn49"; + backlight = <&backlight>; +@@ -741,6 +748,24 @@ usbc_dp: endpoint { + }; + }; + }; ++ ++ cw2015@62 { ++ compatible = "cellwise,cw2015"; ++ reg = <0x62>; ++ cellwise,battery-profile = /bits/ 8 < ++ 0x17 0x67 0x80 0x73 0x6E 0x6C 0x6B 0x63 ++ 0x77 0x51 0x5C 0x58 0x50 0x4C 0x48 0x36 ++ 0x15 0x0C 0x0C 0x19 0x5B 0x7D 0x6F 0x69 ++ 0x69 0x5B 0x0C 0x29 0x20 0x40 0x52 0x59 ++ 0x57 0x56 0x54 0x4F 0x3B 0x1F 0x7F 0x17 ++ 0x06 0x1A 0x30 0x5A 0x85 0x93 0x96 0x2D ++ 0x48 0x77 0x9C 0xB3 0x80 0x52 0x94 0xCB ++ 0x2F 0x00 0x64 0xA5 0xB5 0x11 0xF0 0x11 ++ >; ++ cellwise,monitor-interval-ms = <5000>; ++ monitored-battery = <&bat>; ++ power-supplies = <&mains_charger>, <&fusb0>; ++ }; + }; + + &i2s1 { + +From 279f038076d9ccc8a78c938eaf8008ff626ccb10 Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Sun, 14 Jun 2020 14:29:51 +0000 +Subject: [PATCH] arm64: dts: rockchip: set rockpro64 usbc dr_mode as host + +The usb-c port on the rockpro64 does not detect devices reliably when in otg mode. +Setting the mode to "host" allows the port to work reliably. +This aligns with the pinebook-pro configuration. + +Signed-off-by: Peter Geis +Link: https://lore.kernel.org/r/20200614142950.1120694-1-pgwipeout@gmail.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit 75152d66315521a48c4997305f4e01c5f139e160) +--- + arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi +index 6788ab28f89a..3456ee97c288 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi +@@ -795,7 +795,7 @@ &usbdrd3_0 { + + &usbdrd_dwc3_0 { + status = "okay"; +- dr_mode = "otg"; ++ dr_mode = "host"; + }; + + &usbdrd3_1 { + +From f739ccdaa19eac37af51d49e2d56e84b0bf62bfa Mon Sep 17 00:00:00 2001 +From: Johan Jonker +Date: Sun, 24 May 2020 18:06:36 +0200 +Subject: [PATCH] arm64: dts: rockchip: rename label and nodename pinctrl + subnodes that end with gpio + +A test with the command below gives for example this error: + +arch/arm64/boot/dts/rockchip/rk3326-odroid-go2.dt.yaml: +tsadc: tsadc-otp-gpio: +{'phandle': [[90]], 'rockchip,pins': [[0, 6, 0, 123]]} +is not of type 'array' + +'gpio' is a sort of reserved nodename and should not be used +for pinctrl in combination with 'rockchip,pins', so change +nodes that end with 'gpio' to end with 'pin' or 'pins'. + +make ARCH=arm64 dtbs_check +DT_SCHEMA_FILES=~/.local/lib/python3.5/site-packages/ +dtschema/schemas/gpio/gpio.yaml + +Signed-off-by: Johan Jonker +Link: https://lore.kernel.org/r/20200524160636.16547-2-jbx6244@gmail.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit 2bc65fef4fe424f5f8295175f1b42f8b94c6df01) +--- + arch/arm64/boot/dts/rockchip/px30.dtsi | 6 +- + arch/arm64/boot/dts/rockchip/rk3308.dtsi | 6 +- + arch/arm64/boot/dts/rockchip/rk3328-evb.dts | 2 +- + .../arm64/boot/dts/rockchip/rk3328-roc-cc.dts | 2 +- + .../arm64/boot/dts/rockchip/rk3328-rock64.dts | 2 +- + arch/arm64/boot/dts/rockchip/rk3328.dtsi | 24 +++--- + .../boot/dts/rockchip/rk3368-lion-haikou.dts | 2 +- + arch/arm64/boot/dts/rockchip/rk3368.dtsi | 6 +- + .../boot/dts/rockchip/rk3399-firefly.dts | 4 +- + .../boot/dts/rockchip/rk3399-gru-scarlet.dtsi | 2 +- + arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 4 +- + .../boot/dts/rockchip/rk3399-hugsun-x99.dts | 8 +- + .../boot/dts/rockchip/rk3399-leez-p710.dts | 8 +- + .../boot/dts/rockchip/rk3399-pinebook-pro.dts | 74 +++++++++---------- + .../boot/dts/rockchip/rk3399-roc-pc.dtsi | 8 +- + .../boot/dts/rockchip/rk3399-rock-pi-4.dts | 8 +- + .../boot/dts/rockchip/rk3399-rock960.dtsi | 4 +- + .../boot/dts/rockchip/rk3399-rockpro64.dtsi | 8 +- + .../boot/dts/rockchip/rk3399-sapphire.dtsi | 4 +- + arch/arm64/boot/dts/rockchip/rk3399.dtsi | 6 +- + 20 files changed, 94 insertions(+), 94 deletions(-) + +diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi +index a6b8427156d5..e9bb2b97ae55 100644 +--- a/arch/arm64/boot/dts/rockchip/px30.dtsi ++++ b/arch/arm64/boot/dts/rockchip/px30.dtsi +@@ -733,9 +733,9 @@ tsadc: tsadc@ff280000 { + rockchip,grf = <&grf>; + rockchip,hw-tshut-temp = <120000>; + pinctrl-names = "init", "default", "sleep"; +- pinctrl-0 = <&tsadc_otp_gpio>; ++ pinctrl-0 = <&tsadc_otp_pin>; + pinctrl-1 = <&tsadc_otp_out>; +- pinctrl-2 = <&tsadc_otp_gpio>; ++ pinctrl-2 = <&tsadc_otp_pin>; + #thermal-sensor-cells = <1>; + status = "disabled"; + }; +@@ -1373,7 +1373,7 @@ i2c3_xfer: i2c3-xfer { + }; + + tsadc { +- tsadc_otp_gpio: tsadc-otp-gpio { ++ tsadc_otp_pin: tsadc-otp-pin { + rockchip,pins = + <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3308.dtsi b/arch/arm64/boot/dts/rockchip/rk3308.dtsi +index ac7f694079d0..ba1c71568164 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3308.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3308.dtsi +@@ -1629,7 +1629,7 @@ spi2_mosi: spi2-mosi { + }; + + tsadc { +- tsadc_otp_gpio: tsadc-otp-gpio { ++ tsadc_otp_pin: tsadc-otp-pin { + rockchip,pins = + <0 RK_PB2 0 &pcfg_pull_none>; + }; +@@ -1657,7 +1657,7 @@ uart0_rts: uart0-rts { + <2 RK_PA3 1 &pcfg_pull_none>; + }; + +- uart0_rts_gpio: uart0-rts-gpio { ++ uart0_rts_pin: uart0-rts-pin { + rockchip,pins = + <2 RK_PA3 0 &pcfg_pull_none>; + }; +@@ -1730,7 +1730,7 @@ uart4_rts: uart4-rts { + <4 RK_PA7 1 &pcfg_pull_none>; + }; + +- uart4_rts_gpio: uart4-rts-gpio { ++ uart4_rts_pin: uart4-rts-pin { + rockchip,pins = + <4 RK_PA7 0 &pcfg_pull_none>; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3328-evb.dts b/arch/arm64/boot/dts/rockchip/rk3328-evb.dts +index ac29c2744d08..1969dab84138 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3328-evb.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3328-evb.dts +@@ -41,7 +41,7 @@ vcc_sd: sdmmc-regulator { + compatible = "regulator-fixed"; + gpio = <&gpio0 30 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; +- pinctrl-0 = <&sdmmc0m1_gpio>; ++ pinctrl-0 = <&sdmmc0m1_pin>; + regulator-name = "vcc_sd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; +diff --git a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts +index 34db48c274e5..b70ffb1c6a63 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts +@@ -34,7 +34,7 @@ vcc_sd: sdmmc-regulator { + compatible = "regulator-fixed"; + gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; +- pinctrl-0 = <&sdmmc0m1_gpio>; ++ pinctrl-0 = <&sdmmc0m1_pin>; + regulator-boot-on; + regulator-name = "vcc_sd"; + regulator-min-microvolt = <3300000>; +diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts +index 6e09c223ed57..86cfb5c50a94 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts +@@ -25,7 +25,7 @@ vcc_sd: sdmmc-regulator { + compatible = "regulator-fixed"; + gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; +- pinctrl-0 = <&sdmmc0m1_gpio>; ++ pinctrl-0 = <&sdmmc0m1_pin>; + regulator-name = "vcc_sd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; +diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +index d399883d4b75..72e655020560 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +@@ -552,9 +552,9 @@ tsadc: tsadc@ff250000 { + clocks = <&cru SCLK_TSADC>, <&cru PCLK_TSADC>; + clock-names = "tsadc", "apb_pclk"; + pinctrl-names = "init", "default", "sleep"; +- pinctrl-0 = <&otp_gpio>; ++ pinctrl-0 = <&otp_pin>; + pinctrl-1 = <&otp_out>; +- pinctrl-2 = <&otp_gpio>; ++ pinctrl-2 = <&otp_pin>; + resets = <&cru SRST_TSADC>; + reset-names = "tsadc-apb"; + rockchip,grf = <&grf>; +@@ -1154,7 +1154,7 @@ i2c3_xfer: i2c3-xfer { + rockchip,pins = <0 RK_PA5 2 &pcfg_pull_none>, + <0 RK_PA6 2 &pcfg_pull_none>; + }; +- i2c3_gpio: i2c3-gpio { ++ i2c3_pins: i2c3-pins { + rockchip,pins = + <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>, + <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; +@@ -1225,7 +1225,7 @@ pdmm0_fsync_sleep: pdmm0-fsync-sleep { + }; + + tsadc { +- otp_gpio: otp-gpio { ++ otp_pin: otp-pin { + rockchip,pins = <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + +@@ -1248,7 +1248,7 @@ uart0_rts: uart0-rts { + rockchip,pins = <1 RK_PB2 1 &pcfg_pull_none>; + }; + +- uart0_rts_gpio: uart0-rts-gpio { ++ uart0_rts_pin: uart0-rts-pin { + rockchip,pins = <1 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +@@ -1267,7 +1267,7 @@ uart1_rts: uart1-rts { + rockchip,pins = <3 RK_PA5 4 &pcfg_pull_none>; + }; + +- uart1_rts_gpio: uart1-rts-gpio { ++ uart1_rts_pin: uart1-rts-pin { + rockchip,pins = <3 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +@@ -1493,7 +1493,7 @@ sdmmc0m0_pwren: sdmmc0m0-pwren { + rockchip,pins = <2 RK_PA7 1 &pcfg_pull_up_4ma>; + }; + +- sdmmc0m0_gpio: sdmmc0m0-gpio { ++ sdmmc0m0_pin: sdmmc0m0-pin { + rockchip,pins = <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up_4ma>; + }; + }; +@@ -1503,7 +1503,7 @@ sdmmc0m1_pwren: sdmmc0m1-pwren { + rockchip,pins = <0 RK_PD6 3 &pcfg_pull_up_4ma>; + }; + +- sdmmc0m1_gpio: sdmmc0m1-gpio { ++ sdmmc0m1_pin: sdmmc0m1-pin { + rockchip,pins = <0 RK_PD6 RK_FUNC_GPIO &pcfg_pull_up_4ma>; + }; + }; +@@ -1536,7 +1536,7 @@ sdmmc0_bus4: sdmmc0-bus4 { + <1 RK_PA3 1 &pcfg_pull_up_8ma>; + }; + +- sdmmc0_gpio: sdmmc0-gpio { ++ sdmmc0_pins: sdmmc0-pins { + rockchip,pins = + <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up_4ma>, + <1 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up_4ma>, +@@ -1578,7 +1578,7 @@ sdmmc0ext_bus4: sdmmc0ext-bus4 { + <3 RK_PA7 3 &pcfg_pull_up_4ma>; + }; + +- sdmmc0ext_gpio: sdmmc0ext-gpio { ++ sdmmc0ext_pins: sdmmc0ext-pins { + rockchip,pins = + <3 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up_4ma>, + <3 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up_4ma>, +@@ -1623,7 +1623,7 @@ sdmmc1_bus4: sdmmc1-bus4 { + <1 RK_PC1 1 &pcfg_pull_up_8ma>; + }; + +- sdmmc1_gpio: sdmmc1-gpio { ++ sdmmc1_pins: sdmmc1-pins { + rockchip,pins = + <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up_4ma>, + <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up_4ma>, +@@ -1817,7 +1817,7 @@ tsadc_pin { + tsadc_int: tsadc-int { + rockchip,pins = <2 RK_PB5 2 &pcfg_pull_none>; + }; +- tsadc_gpio: tsadc-gpio { ++ tsadc_pin: tsadc-pin { + rockchip,pins = <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3368-lion-haikou.dts b/arch/arm64/boot/dts/rockchip/rk3368-lion-haikou.dts +index cbde279ae81d..dbd2caba322f 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3368-lion-haikou.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3368-lion-haikou.dts +@@ -125,7 +125,7 @@ led_sd_haikou: led-sd-gpio { + }; + + sdmmc { +- sdmmc_cd_gpio: sdmmc-cd-gpio { ++ sdmmc_cd_pin: sdmmc-cd-pin { + rockchip,pins = + <2 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3368.dtsi b/arch/arm64/boot/dts/rockchip/rk3368.dtsi +index 1ebb0eef42da..5d25a9d04051 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3368.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3368.dtsi +@@ -483,9 +483,9 @@ tsadc: tsadc@ff280000 { + resets = <&cru SRST_TSADC>; + reset-names = "tsadc-apb"; + pinctrl-names = "init", "default", "sleep"; +- pinctrl-0 = <&otp_gpio>; ++ pinctrl-0 = <&otp_pin>; + pinctrl-1 = <&otp_out>; +- pinctrl-2 = <&otp_gpio>; ++ pinctrl-2 = <&otp_pin>; + #thermal-sensor-cells = <1>; + rockchip,hw-tshut-temp = <95000>; + status = "disabled"; +@@ -1145,7 +1145,7 @@ spi2_tx: spi2-tx { + }; + + tsadc { +- otp_gpio: otp-gpio { ++ otp_pin: otp-pin { + rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts b/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts +index 20b5599f5e78..6db18808b9c5 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts +@@ -589,11 +589,11 @@ pcie_3g_drv: pcie-3g-drv { + }; + + pmic { +- vsel1_gpio: vsel1-gpio { ++ vsel1_pin: vsel1-pin { + rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_down>; + }; + +- vsel2_gpio: vsel2-gpio { ++ vsel2_pin: vsel2-pin { + rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru-scarlet.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru-scarlet.dtsi +index 4373ed732af7..60cd1c18cd4e 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-gru-scarlet.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399-gru-scarlet.dtsi +@@ -499,7 +499,7 @@ &i2s0_8ch_bus { + }; + + /* there is no external pull up, so need to set this pin pull up */ +-&sdmmc_cd_gpio { ++&sdmmc_cd_pin { + rockchip,pins = <1 RK_PB3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi +index 2f3997740068..32dcaf210085 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi +@@ -516,7 +516,7 @@ &sdmmc { + * configured as SDMMC and not JTAG. + */ + pinctrl-names = "default"; +- pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_cd_gpio ++ pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_cd_pin + &sdmmc_bus4>; + + bus-width = <4>; +@@ -767,7 +767,7 @@ sdmmc_cd: sdmmc-cd { + }; + + /* This is where we actually hook up CD; has external pull */ +- sdmmc_cd_gpio: sdmmc-cd-gpio { ++ sdmmc_cd_pin: sdmmc-cd-pin { + rockchip,pins = <4 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dts b/arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dts +index bf87fa32d3b1..341d074ed996 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dts +@@ -205,7 +205,7 @@ vdd_cpu_b: syr827@40 { + compatible = "silergy,syr827"; + reg = <0x40>; + regulator-compatible = "fan53555-reg"; +- pinctrl-0 = <&vsel1_gpio>; ++ pinctrl-0 = <&vsel1_pin>; + regulator-name = "vdd_cpu_b"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; +@@ -223,7 +223,7 @@ vdd_gpu: syr828@41 { + compatible = "silergy,syr828"; + reg = <0x41>; + regulator-compatible = "fan53555-reg"; +- pinctrl-0 = <&vsel2_gpio>; ++ pinctrl-0 = <&vsel2_pin>; + regulator-name = "vdd_gpu"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; +@@ -521,12 +521,12 @@ pmic_int_l: pmic-int-l { + <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + +- vsel1_gpio: vsel1-gpio { ++ vsel1_pin: vsel1-pin { + rockchip,pins = + <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>; + }; + +- vsel2_gpio: vsel2-gpio { ++ vsel2_pin: vsel2-pin { + rockchip,pins = + <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-leez-p710.dts b/arch/arm64/boot/dts/rockchip/rk3399-leez-p710.dts +index 73be38a53796..1fa80ac15464 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-leez-p710.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399-leez-p710.dts +@@ -341,7 +341,7 @@ vdd_cpu_b: regulator@40 { + reg = <0x40>; + fcs,suspend-voltage-selector = <1>; + pinctrl-names = "default"; +- pinctrl-0 = <&vsel1_gpio>; ++ pinctrl-0 = <&vsel1_pin>; + regulator-name = "vdd_cpu_b"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; +@@ -360,7 +360,7 @@ vdd_gpu: regulator@41 { + reg = <0x41>; + fcs,suspend-voltage-selector = <1>; + pinctrl-names = "default"; +- pinctrl-0 = <&vsel2_gpio>; ++ pinctrl-0 = <&vsel2_pin>; + regulator-name = "vdd_gpu"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; +@@ -447,11 +447,11 @@ pmic_int_l: pmic-int-l { + rockchip,pins = <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + +- vsel1_gpio: vsel1-gpio { ++ vsel1_pin: vsel1-pin { + rockchip,pins = <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>; + }; + +- vsel2_gpio: vsel2-gpio { ++ vsel2_pin: vsel2-pin { + rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts +index 8f5b2df01560..06d48338c836 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts +@@ -40,7 +40,7 @@ edp_panel: edp-panel { + backlight = <&backlight>; + enable-gpios = <&gpio1 RK_PA0 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; +- pinctrl-0 = <&panel_en_gpio>; ++ pinctrl-0 = <&panel_en_pin>; + power-supply = <&vcc3v3_panel>; + + ports { +@@ -67,7 +67,7 @@ panel_in_edp: endpoint@0 { + gpio-key-lid { + compatible = "gpio-keys"; + pinctrl-names = "default"; +- pinctrl-0 = <&lidbtn_gpio>; ++ pinctrl-0 = <&lidbtn_pin>; + + lid { + debounce-interval = <20>; +@@ -83,7 +83,7 @@ lid { + gpio-key-power { + compatible = "gpio-keys"; + pinctrl-names = "default"; +- pinctrl-0 = <&pwrbtn_gpio>; ++ pinctrl-0 = <&pwrbtn_pin>; + + power { + debounce-interval = <20>; +@@ -124,7 +124,7 @@ sdio_pwrseq: sdio-pwrseq { + clocks = <&rk808 1>; + clock-names = "ext_clock"; + pinctrl-names = "default"; +- pinctrl-0 = <&wifi_enable_h_gpio>; ++ pinctrl-0 = <&wifi_enable_h_pin>; + post-power-on-delay-ms = <100>; + power-off-delay-us = <500000>; + +@@ -136,7 +136,7 @@ sdio_pwrseq: sdio-pwrseq { + es8316-sound { + compatible = "simple-audio-card"; + pinctrl-names = "default"; +- pinctrl-0 = <&hp_det_gpio>; ++ pinctrl-0 = <&hp_det_pin>; + simple-audio-card,name = "rockchip,es8316-codec"; + simple-audio-card,format = "i2s"; + simple-audio-card,mclk-fs = <256>; +@@ -220,7 +220,7 @@ vcc5v0_usb: pa_5v: vcc5v0-usb-regulator { + enable-active-high; + gpio = <&gpio1 RK_PB5 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; +- pinctrl-0 = <&pwr_5v_gpio>; ++ pinctrl-0 = <&pwr_5v_pin>; + regulator-name = "vcc5v0_usb"; + regulator-always-on; + regulator-min-microvolt = <5000000>; +@@ -277,7 +277,7 @@ vcc3v0_sd: vcc3v0-sd { + enable-active-high; + gpio = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; +- pinctrl-0 = <&sdmmc0_pwr_h_gpio>; ++ pinctrl-0 = <&sdmmc0_pwr_h_pin>; + regulator-name = "vcc3v0_sd"; + regulator-always-on; + regulator-min-microvolt = <3000000>; +@@ -295,7 +295,7 @@ vcc3v3_panel: vcc3v3-panel { + enable-active-high; + gpio = <&gpio1 RK_PC6 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; +- pinctrl-0 = <&lcdvcc_en_gpio>; ++ pinctrl-0 = <&lcdvcc_en_pin>; + regulator-name = "vcc3v3_panel"; + regulator-always-on; + regulator-min-microvolt = <3300000>; +@@ -324,7 +324,7 @@ vcc5v0_otg: vcc5v0-otg { + enable-active-high; + gpio = <&gpio4 RK_PD2 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; +- pinctrl-0 = <&vcc5v0_host_en_gpio>; ++ pinctrl-0 = <&vcc5v0_host_en_pin>; + regulator-name = "vcc5v0_otg"; + regulator-always-on; + regulator-min-microvolt = <5000000>; +@@ -343,7 +343,7 @@ vbus_5vout: vbus_typec: vbus-5vout { + enable-active-high; + gpio = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; +- pinctrl-0 = <&vcc5v0_typec0_en_gpio>; ++ pinctrl-0 = <&vcc5v0_typec0_en_pin>; + regulator-name = "vbus_5vout"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; +@@ -375,7 +375,7 @@ mains_charger: dc-charger { + + /* Also triggered by USB charger */ + pinctrl-names = "default"; +- pinctrl-0 = <&dc_det_gpio>; ++ pinctrl-0 = <&dc_det_pin>; + }; + }; + +@@ -454,7 +454,7 @@ rk808: pmic@1b { + interrupt-parent = <&gpio3>; + interrupts = <10 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; +- pinctrl-0 = <&pmic_int_l_gpio>; ++ pinctrl-0 = <&pmic_int_l_pin>; + rockchip,system-power-controller; + wakeup-source; + +@@ -634,7 +634,7 @@ vdd_cpu_b: regulator@40 { + reg = <0x40>; + fcs,suspend-voltage-selector = <1>; + pinctrl-names = "default"; +- pinctrl-0 = <&vsel1_gpio>; ++ pinctrl-0 = <&vsel1_pin>; + regulator-name = "vdd_cpu_b"; + regulator-always-on; + regulator-boot-on; +@@ -653,7 +653,7 @@ vdd_gpu: regulator@41 { + reg = <0x41>; + fcs,suspend-voltage-selector = <1>; + pinctrl-names = "default"; +- pinctrl-0 = <&vsel2_gpio>; ++ pinctrl-0 = <&vsel2_pin>; + regulator-name = "vdd_gpu"; + regulator-always-on; + regulator-boot-on; +@@ -700,7 +700,7 @@ fusb0: fusb30x@22 { + interrupt-parent = <&gpio1>; + interrupts = ; + pinctrl-names = "default"; +- pinctrl-0 = <&fusb0_int_gpio>; ++ pinctrl-0 = <&fusb0_int_pin>; + vbus-supply = <&vbus_typec>; + + connector { +@@ -770,7 +770,7 @@ cw2015@62 { + + &i2s1 { + pinctrl-names = "default"; +- pinctrl-0 = <&i2s_8ch_mclk_gpio>, <&i2s1_2ch_bus>; ++ pinctrl-0 = <&i2s_8ch_mclk_pin>, <&i2s1_2ch_bus>; + rockchip,capture-channels = <8>; + rockchip,playback-channels = <8>; + status = "okay"; +@@ -802,49 +802,49 @@ &pcie0 { + + &pinctrl { + buttons { +- pwrbtn_gpio: pwrbtn-gpio { ++ pwrbtn_pin: pwrbtn-pin { + rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + +- lidbtn_gpio: lidbtn-gpio { ++ lidbtn_pin: lidbtn-pin { + rockchip,pins = <1 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + dc-charger { +- dc_det_gpio: dc-det-gpio { ++ dc_det_pin: dc-det-pin { + rockchip,pins = <4 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + es8316 { +- hp_det_gpio: hp-det-gpio { ++ hp_det_pin: hp-det-pin { + rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + fusb302x { +- fusb0_int_gpio: fusb0-int-gpio { ++ fusb0_int_pin: fusb0-int-pin { + rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + i2s1 { +- i2s_8ch_mclk_gpio: i2s-8ch-mclk-gpio { ++ i2s_8ch_mclk_pin: i2s-8ch-mclk-pin { + rockchip,pins = <4 RK_PA0 1 &pcfg_pull_none>; + }; + }; + + lcd-panel { +- lcdvcc_en_gpio: lcdvcc-en-gpio { ++ lcdvcc_en_pin: lcdvcc-en-pin { + rockchip,pins = <1 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + +- panel_en_gpio: panel-en-gpio { ++ panel_en_pin: panel-en-pin { + rockchip,pins = <1 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + +- lcd_panel_reset_gpio: lcd-panel-reset-gpio { ++ lcd_panel_reset_pin: lcd-panel-reset-pin { + rockchip,pins = <4 RK_PD6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +@@ -860,58 +860,58 @@ slp_led_pin: slp-led-pin { + }; + + pmic { +- pmic_int_l_gpio: pmic-int-l-gpio { ++ pmic_int_l_pin: pmic-int-l-pin { + rockchip,pins = <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + +- vsel1_gpio: vsel1-gpio { ++ vsel1_pin: vsel1-pin { + rockchip,pins = <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>; + }; + +- vsel2_gpio: vsel2-gpio { ++ vsel2_pin: vsel2-pin { + rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + sdcard { +- sdmmc0_pwr_h_gpio: sdmmc0-pwr-h-gpio { ++ sdmmc0_pwr_h_pin: sdmmc0-pwr-h-pin { + rockchip,pins = <0 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + }; + + sdio-pwrseq { +- wifi_enable_h_gpio: wifi-enable-h-gpio { ++ wifi_enable_h_pin: wifi-enable-h-pin { + rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + usb-typec { +- vcc5v0_typec0_en_gpio: vcc5v0-typec0-en-gpio { ++ vcc5v0_typec0_en_pin: vcc5v0-typec0-en-pin { + rockchip,pins = <1 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + usb2 { +- pwr_5v_gpio: pwr-5v-gpio { ++ pwr_5v_pin: pwr-5v-pin { + rockchip,pins = <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + +- vcc5v0_host_en_gpio: vcc5v0-host-en-gpio { ++ vcc5v0_host_en_pin: vcc5v0-host-en-pin { + rockchip,pins = <4 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + wireless-bluetooth { +- bt_wake_gpio: bt-wake-gpio { ++ bt_wake_pin: bt-wake-pin { + rockchip,pins = <2 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + +- bt_host_wake_gpio: bt-host-wake-gpio { ++ bt_host_wake_pin: bt-host-wake-pin { + rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + +- bt_reset_gpio: bt-reset-gpio { ++ bt_reset_pin: bt-reset-pin { + rockchip,pins = <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +@@ -1059,7 +1059,7 @@ bluetooth { + host-wakeup-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_HIGH>; + max-speed = <1500000>; + pinctrl-names = "default"; +- pinctrl-0 = <&bt_host_wake_gpio &bt_wake_gpio &bt_reset_gpio>; ++ pinctrl-0 = <&bt_host_wake_pin &bt_wake_pin &bt_reset_pin>; + shutdown-gpios = <&gpio0 RK_PB1 GPIO_ACTIVE_HIGH>; + vbat-supply = <&wifi_bat>; + vddio-supply = <&vcc_wl>; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi +index 9f225e9c3d54..59b89d6ccdef 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi +@@ -456,7 +456,7 @@ vdd_cpu_b: regulator@40 { + reg = <0x40>; + fcs,suspend-voltage-selector = <1>; + pinctrl-names = "default"; +- pinctrl-0 = <&vsel1_gpio>; ++ pinctrl-0 = <&vsel1_pin>; + regulator-name = "vdd_cpu_b"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; +@@ -475,7 +475,7 @@ vdd_gpu: regulator@41 { + reg = <0x41>; + fcs,suspend-voltage-selector = <1>; + pinctrl-names = "default"; +- pinctrl-0 = <&vsel2_gpio>; ++ pinctrl-0 = <&vsel2_pin>; + regulator-name = "vdd_gpu"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; +@@ -609,11 +609,11 @@ yellow_led_gpio: yellow_led-gpio { + }; + + pmic { +- vsel1_gpio: vsel1-gpio { ++ vsel1_pin: vsel1-pin { + rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_down>; + }; + +- vsel2_gpio: vsel2-gpio { ++ vsel2_pin: vsel2-pin { + rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts +index 3923ec01ef66..60f98a3e19d8 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts +@@ -390,7 +390,7 @@ vdd_cpu_b: regulator@40 { + reg = <0x40>; + fcs,suspend-voltage-selector = <1>; + pinctrl-names = "default"; +- pinctrl-0 = <&vsel1_gpio>; ++ pinctrl-0 = <&vsel1_pin>; + regulator-name = "vdd_cpu_b"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; +@@ -409,7 +409,7 @@ vdd_gpu: regulator@41 { + reg = <0x41>; + fcs,suspend-voltage-selector = <1>; + pinctrl-names = "default"; +- pinctrl-0 = <&vsel2_gpio>; ++ pinctrl-0 = <&vsel2_pin>; + regulator-name = "vdd_gpu"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; +@@ -532,11 +532,11 @@ pmic_int_l: pmic-int-l { + rockchip,pins = <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + +- vsel1_gpio: vsel1-gpio { ++ vsel1_pin: vsel1-pin { + rockchip,pins = <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>; + }; + +- vsel2_gpio: vsel2-gpio { ++ vsel2_pin: vsel2-pin { + rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi +index ba7c75c9f2a1..5e3ac589bc54 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi +@@ -470,12 +470,12 @@ pmic_int_l: pmic-int-l { + <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + +- vsel1_gpio: vsel1-gpio { ++ vsel1_pin: vsel1-pin { + rockchip,pins = + <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>; + }; + +- vsel2_gpio: vsel2-gpio { ++ vsel2_pin: vsel2-pin { + rockchip,pins = + <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi +index 3456ee97c288..c84cad16118a 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi +@@ -445,7 +445,7 @@ vdd_cpu_b: regulator@40 { + reg = <0x40>; + fcs,suspend-voltage-selector = <1>; + pinctrl-names = "default"; +- pinctrl-0 = <&vsel1_gpio>; ++ pinctrl-0 = <&vsel1_pin>; + regulator-name = "vdd_cpu_b"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; +@@ -464,7 +464,7 @@ vdd_gpu: regulator@41 { + reg = <0x41>; + fcs,suspend-voltage-selector = <1>; + pinctrl-names = "default"; +- pinctrl-0 = <&vsel2_gpio>; ++ pinctrl-0 = <&vsel2_pin>; + regulator-name = "vdd_gpu"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; +@@ -612,11 +612,11 @@ pmic_int_l: pmic-int-l { + rockchip,pins = <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + +- vsel1_gpio: vsel1-gpio { ++ vsel1_pin: vsel1-pin { + rockchip,pins = <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>; + }; + +- vsel2_gpio: vsel2-gpio { ++ vsel2_pin: vsel2-pin { + rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi +index 1bc1579674e5..701a567d7638 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi +@@ -481,11 +481,11 @@ pmic_int_l: pmic-int-l { + <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + +- vsel1_gpio: vsel1-gpio { ++ vsel1_pin: vsel1-pin { + rockchip,pins = <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>; + }; + +- vsel2_gpio: vsel2-gpio { ++ vsel2_pin: vsel2-pin { + rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi +index 2581e9cc7a1d..781b5c2cdb4d 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi +@@ -845,9 +845,9 @@ tsadc: tsadc@ff260000 { + rockchip,grf = <&grf>; + rockchip,hw-tshut-temp = <95000>; + pinctrl-names = "init", "default", "sleep"; +- pinctrl-0 = <&otp_gpio>; ++ pinctrl-0 = <&otp_pin>; + pinctrl-1 = <&otp_out>; +- pinctrl-2 = <&otp_gpio>; ++ pinctrl-2 = <&otp_pin>; + #thermal-sensor-cells = <1>; + status = "disabled"; + }; +@@ -2485,7 +2485,7 @@ test_clkout2: test-clkout2 { + }; + + tsadc { +- otp_gpio: otp-gpio { ++ otp_pin: otp-pin { + rockchip,pins = <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + +From b73a18f9f69f893cb7ae0155770d4eac8cc9874f Mon Sep 17 00:00:00 2001 +From: Johan Jonker +Date: Fri, 22 May 2020 17:46:57 +0200 +Subject: [PATCH] arm64: dts: rockchip: rename and label gpio-led subnodes part + 2 + +Current dts files with 'gpio-led' nodes were manually verified. +In order to automate this process leds-gpio.txt +has been converted to yaml. With this conversion a check +for pattern properties was added. In part 2 rename and label +gpio-led subnodes that passed the regex, but still don't have +the preferred form. Any pin subnode that ends with '-gpio' +in the pinctrl node generates a warning. + +Fix with help of the following rules: + +1: Add nodename in the preferred form. + +2: Always add a label that ends with '_led' to prevent conflicts + with other labels such as 'power' and 'mmc' + +3: If leds need pinctrl add a label that ends with '_led_pin' + also to prevent conflicts with other labels. + +patternProperties: + # The first form is preferred, but fall back to just 'led' + # anywhere in the node name to at least catch some child nodes. + "(^led-[0-9a-f]$|led)": + +make ARCH=arm64 dtbs_check +DT_SCHEMA_FILES=Documentation/devicetree/bindings/leds/ +leds-gpio.yaml + +make ARCH=arm64 dtbs_check +DT_SCHEMA_FILES=~/.local/lib/python3.5/site-packages/dtschema/ +schemas/gpio/gpio.yaml + +Signed-off-by: Johan Jonker +Link: https://lore.kernel.org/r/20200522154657.9472-1-jbx6244@gmail.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit 6dd5e12c0b9bba40b3947ac1a9fd2f992585b5c6) +--- + .../arm64/boot/dts/rockchip/rk3368-lion-haikou.dts | 6 +++--- + arch/arm64/boot/dts/rockchip/rk3368-lion.dtsi | 8 ++++---- + .../boot/dts/rockchip/rk3399-khadas-edge.dtsi | 10 +++++----- + arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi | 6 +++--- + .../arm64/boot/dts/rockchip/rk3399-puma-haikou.dts | 6 +++--- + arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi | 6 +++--- + arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi | 14 +++++++------- + arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi | 10 +++++----- + 8 files changed, 33 insertions(+), 33 deletions(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3368-lion-haikou.dts b/arch/arm64/boot/dts/rockchip/rk3368-lion-haikou.dts +index dbd2caba322f..7fcb1eacea8a 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3368-lion-haikou.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3368-lion-haikou.dts +@@ -25,9 +25,9 @@ eeprom: eeprom@50 { + }; + + leds { +- pinctrl-0 = <&led_pins_module>, <&led_sd_haikou>; ++ pinctrl-0 = <&module_led_pins>, <&sd_card_led_pin>; + +- sd-card-led { ++ sd_card_led: led-3 { + label = "sd_card_led"; + gpios = <&gpio0 RK_PD2 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "mmc0"; +@@ -118,7 +118,7 @@ haikou_pin_hog: haikou-pin-hog { + }; + + leds { +- led_sd_haikou: led-sd-gpio { ++ sd_card_led_pin: sd-card-led-pin { + rockchip,pins = + <0 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3368-lion.dtsi b/arch/arm64/boot/dts/rockchip/rk3368-lion.dtsi +index 216aafd90e7f..24d28be4736c 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3368-lion.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3368-lion.dtsi +@@ -76,16 +76,16 @@ i2c@1 { + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; +- pinctrl-0 = <&led_pins_module>; ++ pinctrl-0 = <&module_led_pins>; + +- module_led1 { ++ module_led1: led-1 { + label = "module_led1"; + gpios = <&gpio2 RK_PB5 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + panic-indicator; + }; + +- module_led2 { ++ module_led2: led-2 { + label = "module_led2"; + gpios = <&gpio3 RK_PA3 GPIO_ACTIVE_HIGH>; + default-state = "off"; +@@ -270,7 +270,7 @@ &i2c2 { + + &pinctrl { + leds { +- led_pins_module: led-module-gpio { ++ module_led_pins: module-led-pins { + rockchip,pins = + <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>, + <3 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-khadas-edge.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-khadas-edge.dtsi +index e87a04477440..e36837c04dc7 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-khadas-edge.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399-khadas-edge.dtsi +@@ -141,15 +141,15 @@ power { + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; +- pinctrl-0 = <&sys_led_gpio>, <&user_led_gpio>; ++ pinctrl-0 = <&sys_led_pin>, <&user_led_pin>; + +- sys-led { ++ sys_led: led-0 { + label = "sys_led"; + linux,default-trigger = "heartbeat"; + gpios = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>; + }; + +- user-led { ++ user_led: led-1 { + label = "user_led"; + default-state = "off"; + gpios = <&gpio4 RK_PD0 GPIO_ACTIVE_HIGH>; +@@ -586,11 +586,11 @@ pwrbtn: pwrbtn { + }; + + leds { +- sys_led_gpio: sys_led-gpio { ++ sys_led_pin: sys-led-pin { + rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + +- user_led_gpio: user_led-gpio { ++ user_led_pin: user-led-pin { + rockchip,pins = <4 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi +index 1d246c2caa3c..76a8b40a93c6 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi +@@ -117,9 +117,9 @@ power { + leds: gpio-leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; +- pinctrl-0 = <&leds_gpio>; ++ pinctrl-0 = <&status_led_pin>; + +- status { ++ status_led: led-0 { + gpios = <&gpio0 RK_PB5 GPIO_ACTIVE_HIGH>; + label = "status_led"; + linux,default-trigger = "heartbeat"; +@@ -520,7 +520,7 @@ fusb0_int: fusb0-int { + }; + + gpio-leds { +- leds_gpio: leds-gpio { ++ status_led_pin: status-led-pin { + rockchip,pins = <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts b/arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts +index d80d6b726820..a8d363568fd6 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts +@@ -15,9 +15,9 @@ chosen { + }; + + leds { +- pinctrl-0 = <&led_pin_module>, <&led_sd_haikou>; ++ pinctrl-0 = <&module_led_pin>, <&sd_card_led_pin>; + +- sd-card-led { ++ sd_card_led: led-1 { + label = "sd_card_led"; + gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "mmc0"; +@@ -179,7 +179,7 @@ haikou_pin_hog: haikou-pin-hog { + }; + + leds { +- led_sd_haikou: led-sd-gpio { ++ sd_card_led_pin: sd-card-led-pin { + rockchip,pins = + <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi +index 72c06abd27ea..4660416c8f38 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi +@@ -11,9 +11,9 @@ / { + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; +- pinctrl-0 = <&led_pin_module>; ++ pinctrl-0 = <&module_led_pin>; + +- module-led { ++ module_led: led-0 { + label = "module_led"; + gpios = <&gpio2 RK_PD1 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; +@@ -450,7 +450,7 @@ i2c8_xfer_a: i2c8-xfer { + }; + + leds { +- led_pin_module: led-module-gpio { ++ module_led_pin: module-led-pin { + rockchip,pins = + <2 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi +index 59b89d6ccdef..b85ec31cd283 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi +@@ -61,23 +61,23 @@ power { + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; +- pinctrl-0 = <&work_led_gpio>, <&diy_led_gpio>, <&yellow_led_gpio>; ++ pinctrl-0 = <&work_led_pin>, <&diy_led_pin>, <&yellow_led_pin>; + +- work-led { ++ work_led: led-0 { + label = "green:work"; + gpios = <&gpio2 RK_PD3 GPIO_ACTIVE_HIGH>; + default-state = "on"; + linux,default-trigger = "heartbeat"; + }; + +- diy-led { ++ diy_led: led-1 { + label = "red:diy"; + gpios = <&gpio0 RK_PB5 GPIO_ACTIVE_HIGH>; + default-state = "off"; + linux,default-trigger = "mmc1"; + }; + +- yellow-led { ++ yellow_led: led-2 { + label = "yellow:yellow-led"; + gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; + default-state = "off"; +@@ -595,15 +595,15 @@ lcd_panel_reset: lcd-panel-reset { + }; + + leds { +- diy_led_gpio: diy_led-gpio { ++ diy_led_pin: diy-led-pin { + rockchip,pins = <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + +- work_led_gpio: work_led-gpio { ++ work_led_pin: work-led-pin { + rockchip,pins = <2 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + +- yellow_led_gpio: yellow_led-gpio { ++ yellow_led_pin: yellow-led-pin { + rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi +index c84cad16118a..6e553ff47534 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi +@@ -39,15 +39,15 @@ power { + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; +- pinctrl-0 = <&work_led_gpio>, <&diy_led_gpio>; ++ pinctrl-0 = <&work_led_pin>, <&diy_led_pin>; + +- work-led { ++ work_led: led-0 { + label = "work"; + default-state = "on"; + gpios = <&gpio0 RK_PB3 GPIO_ACTIVE_HIGH>; + }; + +- diy-led { ++ diy_led: led-1 { + label = "diy"; + default-state = "off"; + gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; +@@ -588,11 +588,11 @@ fusb0_int: fusb0-int { + }; + + leds { +- work_led_gpio: work_led-gpio { ++ work_led_pin: work-led-pin { + rockchip,pins = <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + +- diy_led_gpio: diy_led-gpio { ++ diy_led_pin: diy-led-pin { + rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + +From c40071fd1c70da63fdd7cc308114b34623d7eb91 Mon Sep 17 00:00:00 2001 +From: Johan Jonker +Date: Sun, 24 May 2020 18:06:35 +0200 +Subject: [PATCH] ARM: dts: rockchip: rename label and nodename pinctrl + subnodes that end with gpio + +A test with the command below gives for example this error: + +arch/arm/boot/dts/rk3288-tinker.dt.yaml: tsadc: otp-gpio: +{'phandle': [[54]], 'rockchip,pins': [[0, 10, 0, 118]]} +is not of type 'array' + +'gpio' is a sort of reserved nodename and should not be used +for pinctrl in combination with 'rockchip,pins', so change +nodes that end with 'gpio' to end with 'pin' or 'pins'. + +make ARCH=arm dtbs_check +DT_SCHEMA_FILES=~/.local/lib/python3.5/site-packages/ +dtschema/schemas/gpio/gpio.yaml + +Signed-off-by: Johan Jonker +Link: https://lore.kernel.org/r/20200524160636.16547-1-jbx6244@gmail.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit fff987e7328951f7d6fb2d0545de8635ceafa89f) +--- + arch/arm/boot/dts/rk322x.dtsi | 6 +++--- + arch/arm/boot/dts/rk3288-veyron-jaq.dts | 2 +- + arch/arm/boot/dts/rk3288-veyron-jerry.dts | 2 +- + arch/arm/boot/dts/rk3288-veyron-mighty.dts | 6 +++--- + arch/arm/boot/dts/rk3288-veyron-minnie.dts | 2 +- + arch/arm/boot/dts/rk3288-veyron-pinky.dts | 6 +++--- + arch/arm/boot/dts/rk3288-veyron-sdmmc.dtsi | 2 +- + arch/arm/boot/dts/rk3288-veyron-speedy.dts | 2 +- + arch/arm/boot/dts/rk3288.dtsi | 6 +++--- + arch/arm/boot/dts/rv1108.dtsi | 12 ++++++------ + 10 files changed, 23 insertions(+), 23 deletions(-) + +diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi +index b0fd92befdeb..3236abb0aba9 100644 +--- a/arch/arm/boot/dts/rk322x.dtsi ++++ b/arch/arm/boot/dts/rk322x.dtsi +@@ -520,9 +520,9 @@ tsadc: tsadc@11150000 { + resets = <&cru SRST_TSADC>; + reset-names = "tsadc-apb"; + pinctrl-names = "init", "default", "sleep"; +- pinctrl-0 = <&otp_gpio>; ++ pinctrl-0 = <&otp_pin>; + pinctrl-1 = <&otp_out>; +- pinctrl-2 = <&otp_gpio>; ++ pinctrl-2 = <&otp_pin>; + #thermal-sensor-cells = <0>; + rockchip,hw-tshut-temp = <95000>; + status = "disabled"; +@@ -1111,7 +1111,7 @@ spdif_tx: spdif-tx { + }; + + tsadc { +- otp_gpio: otp-gpio { ++ otp_pin: otp-pin { + rockchip,pins = <0 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + +diff --git a/arch/arm/boot/dts/rk3288-veyron-jaq.dts b/arch/arm/boot/dts/rk3288-veyron-jaq.dts +index 171ba6185b6d..8efba9deae3c 100644 +--- a/arch/arm/boot/dts/rk3288-veyron-jaq.dts ++++ b/arch/arm/boot/dts/rk3288-veyron-jaq.dts +@@ -47,7 +47,7 @@ regulator-state-mem { + &sdmmc { + disable-wp; + pinctrl-names = "default"; +- pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd_disabled &sdmmc_cd_gpio ++ pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd_disabled &sdmmc_cd_pin + &sdmmc_bus4>; + }; + +diff --git a/arch/arm/boot/dts/rk3288-veyron-jerry.dts b/arch/arm/boot/dts/rk3288-veyron-jerry.dts +index 66f00d28801a..2c916c50dda5 100644 +--- a/arch/arm/boot/dts/rk3288-veyron-jerry.dts ++++ b/arch/arm/boot/dts/rk3288-veyron-jerry.dts +@@ -192,7 +192,7 @@ mwifiex: wifi@1 { + &sdmmc { + disable-wp; + pinctrl-names = "default"; +- pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd_disabled &sdmmc_cd_gpio ++ pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd_disabled &sdmmc_cd_pin + &sdmmc_bus4>; + }; + +diff --git a/arch/arm/boot/dts/rk3288-veyron-mighty.dts b/arch/arm/boot/dts/rk3288-veyron-mighty.dts +index 27fbc07476d2..fa695a88f236 100644 +--- a/arch/arm/boot/dts/rk3288-veyron-mighty.dts ++++ b/arch/arm/boot/dts/rk3288-veyron-mighty.dts +@@ -18,8 +18,8 @@ / { + }; + + &sdmmc { +- pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd_disabled &sdmmc_cd_gpio +- &sdmmc_wp_gpio &sdmmc_bus4>; ++ pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd_disabled &sdmmc_cd_pin ++ &sdmmc_wp_pin &sdmmc_bus4>; + wp-gpios = <&gpio7 10 GPIO_ACTIVE_HIGH>; + + /delete-property/ disable-wp; +@@ -27,7 +27,7 @@ &sdmmc { + + &pinctrl { + sdmmc { +- sdmmc_wp_gpio: sdmmc-wp-gpio { ++ sdmmc_wp_pin: sdmmc-wp-pin { + rockchip,pins = <7 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +diff --git a/arch/arm/boot/dts/rk3288-veyron-minnie.dts b/arch/arm/boot/dts/rk3288-veyron-minnie.dts +index 383fad1a88a1..f8b69e0a16a0 100644 +--- a/arch/arm/boot/dts/rk3288-veyron-minnie.dts ++++ b/arch/arm/boot/dts/rk3288-veyron-minnie.dts +@@ -114,7 +114,7 @@ regulator-state-mem { + &sdmmc { + disable-wp; + pinctrl-names = "default"; +- pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd_disabled &sdmmc_cd_gpio ++ pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd_disabled &sdmmc_cd_pin + &sdmmc_bus4>; + }; + +diff --git a/arch/arm/boot/dts/rk3288-veyron-pinky.dts b/arch/arm/boot/dts/rk3288-veyron-pinky.dts +index 71e6629cc208..4e9fdb0f722d 100644 +--- a/arch/arm/boot/dts/rk3288-veyron-pinky.dts ++++ b/arch/arm/boot/dts/rk3288-veyron-pinky.dts +@@ -105,7 +105,7 @@ emmc_reset: emmc-reset { + }; + + sdmmc { +- sdmmc_wp_gpio: sdmmc-wp-gpio { ++ sdmmc_wp_pin: sdmmc-wp-pin { + rockchip,pins = <7 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +@@ -126,8 +126,8 @@ regulator-state-mem { + + &sdmmc { + pinctrl-names = "default"; +- pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd_disabled &sdmmc_cd_gpio +- &sdmmc_wp_gpio &sdmmc_bus4>; ++ pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd_disabled &sdmmc_cd_pin ++ &sdmmc_wp_pin &sdmmc_bus4>; + wp-gpios = <&gpio7 RK_PB2 GPIO_ACTIVE_HIGH>; + }; + +diff --git a/arch/arm/boot/dts/rk3288-veyron-sdmmc.dtsi b/arch/arm/boot/dts/rk3288-veyron-sdmmc.dtsi +index fe950f9863e8..27fb06ce907e 100644 +--- a/arch/arm/boot/dts/rk3288-veyron-sdmmc.dtsi ++++ b/arch/arm/boot/dts/rk3288-veyron-sdmmc.dtsi +@@ -41,7 +41,7 @@ sdmmc_cd_disabled: sdmmc-cd-disabled { + }; + + /* This is where we actually hook up CD */ +- sdmmc_cd_gpio: sdmmc-cd-gpio { ++ sdmmc_cd_pin: sdmmc-cd-pin { + rockchip,pins = <7 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +diff --git a/arch/arm/boot/dts/rk3288-veyron-speedy.dts b/arch/arm/boot/dts/rk3288-veyron-speedy.dts +index e354c61a45e7..4a3ea934d03e 100644 +--- a/arch/arm/boot/dts/rk3288-veyron-speedy.dts ++++ b/arch/arm/boot/dts/rk3288-veyron-speedy.dts +@@ -54,7 +54,7 @@ &rk808 { + &sdmmc { + disable-wp; + pinctrl-names = "default"; +- pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd_disabled &sdmmc_cd_gpio ++ pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd_disabled &sdmmc_cd_pin + &sdmmc_bus4>; + }; + +diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi +index 2e1edd85f04a..84d59469035e 100644 +--- a/arch/arm/boot/dts/rk3288.dtsi ++++ b/arch/arm/boot/dts/rk3288.dtsi +@@ -574,9 +574,9 @@ tsadc: tsadc@ff280000 { + resets = <&cru SRST_TSADC>; + reset-names = "tsadc-apb"; + pinctrl-names = "init", "default", "sleep"; +- pinctrl-0 = <&otp_gpio>; ++ pinctrl-0 = <&otp_pin>; + pinctrl-1 = <&otp_out>; +- pinctrl-2 = <&otp_gpio>; ++ pinctrl-2 = <&otp_pin>; + #thermal-sensor-cells = <1>; + rockchip,grf = <&grf>; + rockchip,hw-tshut-temp = <95000>; +@@ -1929,7 +1929,7 @@ uart4_rts: uart4-rts { + }; + + tsadc { +- otp_gpio: otp-gpio { ++ otp_pin: otp-pin { + rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + +diff --git a/arch/arm/boot/dts/rv1108.dtsi b/arch/arm/boot/dts/rv1108.dtsi +index f9cfe2c80791..a5d130bd0547 100644 +--- a/arch/arm/boot/dts/rv1108.dtsi ++++ b/arch/arm/boot/dts/rv1108.dtsi +@@ -351,9 +351,9 @@ tsadc: tsadc@10370000 { + clocks = <&cru SCLK_TSADC>, <&cru PCLK_TSADC>; + clock-names = "tsadc", "apb_pclk"; + pinctrl-names = "init", "default", "sleep"; +- pinctrl-0 = <&otp_gpio>; ++ pinctrl-0 = <&otp_pin>; + pinctrl-1 = <&otp_out>; +- pinctrl-2 = <&otp_gpio>; ++ pinctrl-2 = <&otp_pin>; + resets = <&cru SRST_TSADC>; + reset-names = "tsadc-apb"; + rockchip,hw-tshut-temp = <120000>; +@@ -728,7 +728,7 @@ i2c2m1_xfer: i2c2m1-xfer { + <0 RK_PC6 3 &pcfg_pull_none>; + }; + +- i2c2m1_gpio: i2c2m1-gpio { ++ i2c2m1_pins: i2c2m1-pins { + rockchip,pins = <0 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>, + <0 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; + }; +@@ -740,7 +740,7 @@ i2c2m05v_xfer: i2c2m05v-xfer { + <1 RK_PD4 2 &pcfg_pull_none>; + }; + +- i2c2m05v_gpio: i2c2m05v-gpio { ++ i2c2m05v_pins: i2c2m05v-pins { + rockchip,pins = <1 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>, + <1 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>; + }; +@@ -867,7 +867,7 @@ otp_out: otp-out { + rockchip,pins = <0 RK_PB7 1 &pcfg_pull_none>; + }; + +- otp_gpio: otp-gpio { ++ otp_pin: otp-pin { + rockchip,pins = <0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +@@ -886,7 +886,7 @@ uart0_rts: uart0-rts { + rockchip,pins = <3 RK_PA3 1 &pcfg_pull_none>; + }; + +- uart0_rts_gpio: uart0-rts-gpio { ++ uart0_rts_pin: uart0-rts-pin { + rockchip,pins = <3 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + +From c07b527960a7909caa8adb15247362f2319f1653 Mon Sep 17 00:00:00 2001 +From: Abhishek Pandit-Subedi +Date: Fri, 12 Jun 2020 13:02:48 -0700 +Subject: [PATCH] ARM: dts: rockchip: Add marvell BT irq config + +Veyron Jaq and Mighty both use the Marvel 8897 WiFi+BT chip. Add wakeup +and pinctrl block to devicetree so the btmrvl driver can correctly +configure the wakeup interrupt. + +Signed-off-by: Abhishek Pandit-Subedi +Reviewed-by: Douglas Anderson +Link: https://lore.kernel.org/r/20200612130219.v2.1.I66864be898aa835ccb66b6cd5220d0b082338a81@changeid +Signed-off-by: Heiko Stuebner +(cherry picked from commit 6c2b99a2e7a073575b4ee91abf7d16470991c1f4) +--- + arch/arm/boot/dts/rk3288-veyron-jaq.dts | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/arch/arm/boot/dts/rk3288-veyron-jaq.dts b/arch/arm/boot/dts/rk3288-veyron-jaq.dts +index 8efba9deae3c..af77ab20586d 100644 +--- a/arch/arm/boot/dts/rk3288-veyron-jaq.dts ++++ b/arch/arm/boot/dts/rk3288-veyron-jaq.dts +@@ -44,6 +44,21 @@ regulator-state-mem { + }; + }; + ++&sdio0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ btmrvl: btmrvl@2 { ++ compatible = "marvell,sd8897-bt"; ++ reg = <2>; ++ interrupt-parent = <&gpio4>; ++ interrupts = ; ++ marvell,wakeup-pin = /bits/ 16 <13>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bt_host_wake_l>; ++ }; ++}; ++ + &sdmmc { + disable-wp; + pinctrl-names = "default"; + +From f0ee8fdc42d8bb5a2cb126df71302324fb23866b Mon Sep 17 00:00:00 2001 +From: Sugar Zhang +Date: Thu, 4 Jun 2020 09:36:38 +0800 +Subject: [PATCH] dmaengine: pl330: Make sure the debug is idle before doing + DMAGO + +According to the datasheet of pl330: + +Example 2-1 Using DMAGO with the debug instruction registers + +1. Create a program for the DMA channel +2. Store the program in a region of system memory +3. Poll the DBGSTATUS Register to ensure that the debug is idle +4. Write to the DBGINST0 Register +5. Write to the DBGINST1 Register +6. Write zero to the DBGCMD Register + +so, we should make sure the debug is idle before step 4/5/6, not +only step 6. if not, there maybe a risk that fail to write DBGINST0/1. + +Signed-off-by: Sugar Zhang +Link: https://lore.kernel.org/r/1591234598-78919-1-git-send-email-sugar.zhang@rock-chips.com +Signed-off-by: Vinod Koul +(cherry picked from commit d12ea5591eddf625b7707c018b72e46e8674c3c2) +--- + drivers/dma/pl330.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index 88b884cbb7c1..6a158eef6b8a 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -885,6 +885,12 @@ static inline void _execute_DBGINSN(struct pl330_thread *thrd, + void __iomem *regs = thrd->dmac->base; + u32 val; + ++ /* If timed out due to halted state-machine */ ++ if (_until_dmac_idle(thrd)) { ++ dev_err(thrd->dmac->ddma.dev, "DMAC halted!\n"); ++ return; ++ } ++ + val = (insn[0] << 16) | (insn[1] << 24); + if (!as_manager) { + val |= (1 << 0); +@@ -895,12 +901,6 @@ static inline void _execute_DBGINSN(struct pl330_thread *thrd, + val = le32_to_cpu(*((__le32 *)&insn[2])); + writel(val, regs + DBGINST1); + +- /* If timed out due to halted state-machine */ +- if (_until_dmac_idle(thrd)) { +- dev_err(thrd->dmac->ddma.dev, "DMAC halted!\n"); +- return; +- } +- + /* Get going */ + writel(0, regs + DBGCMD); + } + +From e5214dd97994bfdb32dcae94e03f18a794c43947 Mon Sep 17 00:00:00 2001 +From: Shunqian Zheng +Date: Fri, 3 Apr 2020 13:15:37 -0300 +Subject: [PATCH] arm64: dts: rockchip: add rx0 mipi-phy for rk3399 + +Designware MIPI D-PHY, used for ISP0 in rk3399. + +Verified with: +make ARCH=arm64 dtbs_check DT_SCHEMA_FILES=Documentation/devicetree/bindings/phy/rockchip-mipi-dphy-rx0.yaml + +Signed-off-by: Shunqian Zheng +Signed-off-by: Jacob Chen +Signed-off-by: Helen Koike +Link: https://lore.kernel.org/r/20200403161538.1375908-9-helen.koike@collabora.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit e4bfde13e323f9ee5f2f38aa5cac0676dd656f8e) +--- + arch/arm64/boot/dts/rockchip/rk3399.dtsi | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi +index 781b5c2cdb4d..f2ef0d8ba54b 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi +@@ -1397,6 +1397,17 @@ io_domains: io-domains { + status = "disabled"; + }; + ++ mipi_dphy_rx0: mipi-dphy-rx0 { ++ compatible = "rockchip,rk3399-mipi-dphy-rx0"; ++ clocks = <&cru SCLK_MIPIDPHY_REF>, ++ <&cru SCLK_DPHY_RX0_CFG>, ++ <&cru PCLK_VIO_GRF>; ++ clock-names = "dphy-ref", "dphy-cfg", "grf"; ++ power-domains = <&power RK3399_PD_VIO>; ++ #phy-cells = <0>; ++ status = "disabled"; ++ }; ++ + u2phy0: usb2-phy@e450 { + compatible = "rockchip,rk3399-usb2phy"; + reg = <0xe450 0x10>; + +From d2266424a494804c6709ea8231fc44e1ca376138 Mon Sep 17 00:00:00 2001 +From: Pierre-Louis Bossart +Date: Tue, 7 Jul 2020 14:06:10 -0500 +Subject: [PATCH] ASoC: codecs: es8316: fix 'defined but not used' warning + +Fix W=1 warning + +sound/soc/codecs/es8316.c:842:36: warning: 'es8316_acpi_match' defined +but not used [-Wunused-const-variable=] + 842 | static const struct acpi_device_id es8316_acpi_match[] = { + | ^~~~~~~~~~~~~~~~~ + +Signed-off-by: Pierre-Louis Bossart +Link: https://lore.kernel.org/r/20200707190612.97799-12-pierre-louis.bossart@linux.intel.com +Signed-off-by: Mark Brown +(cherry picked from commit 07ac670981fc5932ca3799ce7d96431d80afce0e) +--- + sound/soc/codecs/es8316.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c +index 36eef1fb3d18..70af35c5f727 100644 +--- a/sound/soc/codecs/es8316.c ++++ b/sound/soc/codecs/es8316.c +@@ -839,11 +839,13 @@ static const struct of_device_id es8316_of_match[] = { + }; + MODULE_DEVICE_TABLE(of, es8316_of_match); + ++#ifdef CONFIG_ACPI + static const struct acpi_device_id es8316_acpi_match[] = { + {"ESSX8316", 0}, + {}, + }; + MODULE_DEVICE_TABLE(acpi, es8316_acpi_match); ++#endif + + static struct i2c_driver es8316_i2c_driver = { + .driver = { + +From 2a38a809f8b033a5ddae29b81fb1209a897689f5 Mon Sep 17 00:00:00 2001 +From: Vinod Koul +Date: Wed, 8 Jul 2020 18:58:07 +0530 +Subject: [PATCH] phy: rockchip-typec: use correct format for structure + description + +We get warning with W=1 build: +drivers/phy/rockchip/phy-rockchip-typec.c:360: warning: cannot +understand function prototype: 'struct rockchip_usb3phy_port_cfg ' + +The 'struct rockchip_usb3phy_port_cfg ' is commented properly but uses +wrong format, so fix that up + +Link: https://lore.kernel.org/r/20200708132809.265967-4-vkoul@kernel.org +Signed-off-by: Vinod Koul +(cherry picked from commit 72fbf95f36218ec2a901e0eb7c3aa0bea6f1f396) +--- + drivers/phy/rockchip/phy-rockchip-typec.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c b/drivers/phy/rockchip/phy-rockchip-typec.c +index 24563160197f..70a31251b202 100644 +--- a/drivers/phy/rockchip/phy-rockchip-typec.c ++++ b/drivers/phy/rockchip/phy-rockchip-typec.c +@@ -347,7 +347,7 @@ struct usb3phy_reg { + }; + + /** +- * struct rockchip_usb3phy_port_cfg: usb3-phy port configuration. ++ * struct rockchip_usb3phy_port_cfg - usb3-phy port configuration. + * @reg: the base address for usb3-phy config. + * @typec_conn_dir: the register of type-c connector direction. + * @usb3tousb2_en: the register of type-c force usb2 to usb2 enable. + +From 4210b54dbec5ef3259494989feab48ffde364bb2 Mon Sep 17 00:00:00 2001 +From: Sugar Zhang +Date: Mon, 13 Jul 2020 18:26:00 +0800 +Subject: [PATCH] ASoC: rockchip: spdif: Handle clk by pm runtime + +This patch handle the clk by pm runtime mechanism to simplify +the clk management. + +Signed-off-by: Sugar Zhang +Link: https://lore.kernel.org/r/1594635960-67855-1-git-send-email-sugar.zhang@rock-chips.com +Signed-off-by: Mark Brown +(cherry picked from commit f50d67f9eff62f8078fe6e98ede3f4fb1defc361) +--- + sound/soc/rockchip/rockchip_spdif.c | 59 +++++++++-------------------- + 1 file changed, 17 insertions(+), 42 deletions(-) + +diff --git a/sound/soc/rockchip/rockchip_spdif.c b/sound/soc/rockchip/rockchip_spdif.c +index 6635145a26c4..674810851fbc 100644 +--- a/sound/soc/rockchip/rockchip_spdif.c ++++ b/sound/soc/rockchip/rockchip_spdif.c +@@ -306,44 +306,22 @@ static int rk_spdif_probe(struct platform_device *pdev) + return -ENOMEM; + + spdif->hclk = devm_clk_get(&pdev->dev, "hclk"); +- if (IS_ERR(spdif->hclk)) { +- dev_err(&pdev->dev, "Can't retrieve rk_spdif bus clock\n"); ++ if (IS_ERR(spdif->hclk)) + return PTR_ERR(spdif->hclk); +- } +- ret = clk_prepare_enable(spdif->hclk); +- if (ret) { +- dev_err(spdif->dev, "hclock enable failed %d\n", ret); +- return ret; +- } + + spdif->mclk = devm_clk_get(&pdev->dev, "mclk"); +- if (IS_ERR(spdif->mclk)) { +- dev_err(&pdev->dev, "Can't retrieve rk_spdif master clock\n"); +- ret = PTR_ERR(spdif->mclk); +- goto err_disable_hclk; +- } +- +- ret = clk_prepare_enable(spdif->mclk); +- if (ret) { +- dev_err(spdif->dev, "clock enable failed %d\n", ret); +- goto err_disable_clocks; +- } ++ if (IS_ERR(spdif->mclk)) ++ return PTR_ERR(spdif->mclk); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + regs = devm_ioremap_resource(&pdev->dev, res); +- if (IS_ERR(regs)) { +- ret = PTR_ERR(regs); +- goto err_disable_clocks; +- } ++ if (IS_ERR(regs)) ++ return PTR_ERR(regs); + + spdif->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "hclk", regs, + &rk_spdif_regmap_config); +- if (IS_ERR(spdif->regmap)) { +- dev_err(&pdev->dev, +- "Failed to initialise managed register map\n"); +- ret = PTR_ERR(spdif->regmap); +- goto err_disable_clocks; +- } ++ if (IS_ERR(spdif->regmap)) ++ return PTR_ERR(spdif->regmap); + + spdif->playback_dma_data.addr = res->start + SPDIF_SMPDR; + spdif->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; +@@ -352,47 +330,44 @@ static int rk_spdif_probe(struct platform_device *pdev) + spdif->dev = &pdev->dev; + dev_set_drvdata(&pdev->dev, spdif); + +- pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); +- pm_request_idle(&pdev->dev); ++ if (!pm_runtime_enabled(&pdev->dev)) { ++ ret = rk_spdif_runtime_resume(&pdev->dev); ++ if (ret) ++ goto err_pm_runtime; ++ } + + ret = devm_snd_soc_register_component(&pdev->dev, + &rk_spdif_component, + &rk_spdif_dai, 1); + if (ret) { + dev_err(&pdev->dev, "Could not register DAI\n"); +- goto err_pm_runtime; ++ goto err_pm_suspend; + } + + ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); + if (ret) { + dev_err(&pdev->dev, "Could not register PCM\n"); +- goto err_pm_runtime; ++ goto err_pm_suspend; + } + + return 0; + ++err_pm_suspend: ++ if (!pm_runtime_status_suspended(&pdev->dev)) ++ rk_spdif_runtime_suspend(&pdev->dev); + err_pm_runtime: + pm_runtime_disable(&pdev->dev); +-err_disable_clocks: +- clk_disable_unprepare(spdif->mclk); +-err_disable_hclk: +- clk_disable_unprepare(spdif->hclk); + + return ret; + } + + static int rk_spdif_remove(struct platform_device *pdev) + { +- struct rk_spdif_dev *spdif = dev_get_drvdata(&pdev->dev); +- + pm_runtime_disable(&pdev->dev); + if (!pm_runtime_status_suspended(&pdev->dev)) + rk_spdif_runtime_suspend(&pdev->dev); + +- clk_disable_unprepare(spdif->mclk); +- clk_disable_unprepare(spdif->hclk); +- + return 0; + } + + +From 6af0776af231629c2331f81faa2fdb311cf3ed44 Mon Sep 17 00:00:00 2001 +From: Katsuhiro Suzuki +Date: Tue, 14 Jul 2020 16:32:47 +0900 +Subject: [PATCH] ASoC: convert rk3328 codec binding to yaml + +This patch converts Rockchip rk3328 audio codec binding to DT schema. +And adds description about "mclk" clock and fixes some errors in +original example. + +Signed-off-by: Katsuhiro Suzuki +Reviewed-by: Rob Herring +Link: https://lore.kernel.org/r/20200714073247.172859-1-katsuhiro@katsuster.net +Signed-off-by: Mark Brown +(cherry picked from commit 3f6597ad2f9ed8ed89dbd2a9ec0b0c892774f9d2) +--- + .../bindings/sound/rockchip,rk3328-codec.txt | 28 -------- + .../bindings/sound/rockchip,rk3328-codec.yaml | 69 +++++++++++++++++++ + 2 files changed, 69 insertions(+), 28 deletions(-) + delete mode 100644 Documentation/devicetree/bindings/sound/rockchip,rk3328-codec.txt + create mode 100644 Documentation/devicetree/bindings/sound/rockchip,rk3328-codec.yaml + +diff --git a/Documentation/devicetree/bindings/sound/rockchip,rk3328-codec.txt b/Documentation/devicetree/bindings/sound/rockchip,rk3328-codec.txt +deleted file mode 100644 +index 1ecd75d2032a..000000000000 +--- a/Documentation/devicetree/bindings/sound/rockchip,rk3328-codec.txt ++++ /dev/null +@@ -1,28 +0,0 @@ +-* Rockchip Rk3328 internal codec +- +-Required properties: +- +-- compatible: "rockchip,rk3328-codec" +-- reg: physical base address of the controller and length of memory mapped +- region. +-- rockchip,grf: the phandle of the syscon node for GRF register. +-- clocks: a list of phandle + clock-specifer pairs, one for each entry in clock-names. +-- clock-names: should be "pclk". +-- spk-depop-time-ms: speak depop time msec. +- +-Optional properties: +- +-- mute-gpios: GPIO specifier for external line driver control (typically the +- dedicated GPIO_MUTE pin) +- +-Example for rk3328 internal codec: +- +-codec: codec@ff410000 { +- compatible = "rockchip,rk3328-codec"; +- reg = <0x0 0xff410000 0x0 0x1000>; +- rockchip,grf = <&grf>; +- clocks = <&cru PCLK_ACODEC>; +- clock-names = "pclk"; +- mute-gpios = <&grf_gpio 0 GPIO_ACTIVE_LOW>; +- spk-depop-time-ms = 100; +-}; +diff --git a/Documentation/devicetree/bindings/sound/rockchip,rk3328-codec.yaml b/Documentation/devicetree/bindings/sound/rockchip,rk3328-codec.yaml +new file mode 100644 +index 000000000000..5b85ad5e4834 +--- /dev/null ++++ b/Documentation/devicetree/bindings/sound/rockchip,rk3328-codec.yaml +@@ -0,0 +1,69 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/sound/rockchip,rk3328-codec.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Rockchip rk3328 internal codec ++ ++maintainers: ++ - Heiko Stuebner ++ ++properties: ++ compatible: ++ const: rockchip,rk3328-codec ++ ++ reg: ++ maxItems: 1 ++ ++ clocks: ++ items: ++ - description: clock for audio codec ++ - description: clock for I2S master clock ++ ++ clock-names: ++ items: ++ - const: pclk ++ - const: mclk ++ ++ rockchip,grf: ++ $ref: /schemas/types.yaml#/definitions/phandle ++ description: ++ The phandle of the syscon node for the GRF register. ++ ++ spk-depop-time-ms: ++ default: 200 ++ description: ++ Speaker depop time in msec. ++ ++ mute-gpios: ++ maxItems: 1 ++ description: ++ GPIO specifier for external line driver control (typically the ++ dedicated GPIO_MUTE pin) ++ ++ "#sound-dai-cells": ++ const: 0 ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ - clock-names ++ - rockchip,grf ++ - "#sound-dai-cells" ++ ++examples: ++ - | ++ #include ++ #include ++ codec: codec@ff410000 { ++ compatible = "rockchip,rk3328-codec"; ++ reg = <0xff410000 0x1000>; ++ clocks = <&cru PCLK_ACODECPHY>, <&cru SCLK_I2S1>; ++ clock-names = "pclk", "mclk"; ++ rockchip,grf = <&grf>; ++ mute-gpios = <&grf_gpio 0 GPIO_ACTIVE_LOW>; ++ spk-depop-time-ms = <100>; ++ #sound-dai-cells = <0>; ++ }; + +From 6917bb6287536dbdd26511d0ba6e6b82bc0f5d86 Mon Sep 17 00:00:00 2001 +From: Sugar Zhang +Date: Mon, 29 Jun 2020 22:05:42 +0800 +Subject: [PATCH] dmaengine: pl330: Remove the burst limit for quirk + 'NO-FLUSHP' + +There is no reason to limit the performance on the 'NO-FLUSHP' SoCs, +because 'FLUSHP' instruction is broken on these platforms, so remove +the limit to improve the efficiency. + +Signed-off-by: Sugar Zhang +Link: https://lore.kernel.org/r/1593439555-68130-2-git-send-email-sugar.zhang@rock-chips.com +Signed-off-by: Vinod Koul +(cherry picked from commit 05611a93b8ffa3fe7d2eb43dd6c11e37ead5908a) +--- + drivers/dma/pl330.c | 10 ++-------- + 1 file changed, 2 insertions(+), 8 deletions(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index 6a158eef6b8a..7686292bc1db 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -1183,9 +1183,6 @@ static inline int _ldst_peripheral(struct pl330_dmac *pl330, + { + int off = 0; + +- if (pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP) +- cond = BURST; +- + /* + * do FLUSHP at beginning to clear any stale dma requests before the + * first WFP. +@@ -2221,9 +2218,7 @@ static bool pl330_prep_slave_fifo(struct dma_pl330_chan *pch, + + static int fixup_burst_len(int max_burst_len, int quirks) + { +- if (quirks & PL330_QUIRK_BROKEN_NO_FLUSHP) +- return 1; +- else if (max_burst_len > PL330_MAX_BURST) ++ if (max_burst_len > PL330_MAX_BURST) + return PL330_MAX_BURST; + else if (max_burst_len < 1) + return 1; +@@ -3128,8 +3123,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) + pd->dst_addr_widths = PL330_DMA_BUSWIDTHS; + pd->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); + pd->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; +- pd->max_burst = ((pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP) ? +- 1 : PL330_MAX_BURST); ++ pd->max_burst = PL330_MAX_BURST; + + ret = dma_async_device_register(pd); + if (ret) { + +From cb00fa158b947abf47ce2f256139a849b3bc8f2e Mon Sep 17 00:00:00 2001 +From: Sugar Zhang +Date: Mon, 29 Jun 2020 22:05:43 +0800 +Subject: [PATCH] dmaengine: pl330: Improve transfer efficiency for the dregs + +Only the unaligned burst transfers have the dregs. +so, still use BURST transfer with a reduced size +for better performance. + +Signed-off-by: Sugar Zhang +Link: https://lore.kernel.org/r/1593439555-68130-3-git-send-email-sugar.zhang@rock-chips.com +Signed-off-by: Vinod Koul +(cherry picked from commit 3e7f0bd872087bf4653eeee9a83050f91baae907) +--- + drivers/dma/pl330.c | 32 +++++++++++++++++++++----------- + 1 file changed, 21 insertions(+), 11 deletions(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index 7686292bc1db..f1f0176c6c05 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -1228,8 +1228,9 @@ static int _bursts(struct pl330_dmac *pl330, unsigned dry_run, u8 buf[], + } + + /* +- * transfer dregs with single transfers to peripheral, or a reduced size burst +- * for mem-to-mem. ++ * only the unaligned burst transfers have the dregs. ++ * so, still transfer dregs with a reduced size burst ++ * for mem-to-mem, mem-to-dev or dev-to-mem. + */ + static int _dregs(struct pl330_dmac *pl330, unsigned int dry_run, u8 buf[], + const struct _xfer_spec *pxs, int transfer_length) +@@ -1240,22 +1241,31 @@ static int _dregs(struct pl330_dmac *pl330, unsigned int dry_run, u8 buf[], + if (transfer_length == 0) + return off; + ++ /* ++ * dregs_len = (total bytes - BURST_TO_BYTE(bursts, ccr)) / ++ * BRST_SIZE(ccr) ++ * the dregs len must be smaller than burst len, ++ * so, for higher efficiency, we can modify CCR ++ * to use a reduced size burst len for the dregs. ++ */ ++ dregs_ccr = pxs->ccr; ++ dregs_ccr &= ~((0xf << CC_SRCBRSTLEN_SHFT) | ++ (0xf << CC_DSTBRSTLEN_SHFT)); ++ dregs_ccr |= (((transfer_length - 1) & 0xf) << ++ CC_SRCBRSTLEN_SHFT); ++ dregs_ccr |= (((transfer_length - 1) & 0xf) << ++ CC_DSTBRSTLEN_SHFT); ++ + switch (pxs->desc->rqtype) { + case DMA_MEM_TO_DEV: + /* fall through */ + case DMA_DEV_TO_MEM: +- off += _ldst_peripheral(pl330, dry_run, &buf[off], pxs, +- transfer_length, SINGLE); ++ off += _emit_MOV(dry_run, &buf[off], CCR, dregs_ccr); ++ off += _ldst_peripheral(pl330, dry_run, &buf[off], pxs, 1, ++ BURST); + break; + + case DMA_MEM_TO_MEM: +- dregs_ccr = pxs->ccr; +- dregs_ccr &= ~((0xf << CC_SRCBRSTLEN_SHFT) | +- (0xf << CC_DSTBRSTLEN_SHFT)); +- dregs_ccr |= (((transfer_length - 1) & 0xf) << +- CC_SRCBRSTLEN_SHFT); +- dregs_ccr |= (((transfer_length - 1) & 0xf) << +- CC_DSTBRSTLEN_SHFT); + off += _emit_MOV(dry_run, &buf[off], CCR, dregs_ccr); + off += _ldst_memtomem(dry_run, &buf[off], pxs, 1); + break; + +From 73de2b83dab82d5b7ad55360f14b1aa35e55eb8f Mon Sep 17 00:00:00 2001 +From: Sugar Zhang +Date: Mon, 29 Jun 2020 22:05:45 +0800 +Subject: [PATCH] dmaengine: pl330: Add quirk 'arm,pl330-periph-burst' + +This patch adds the qurik to use burst transfers only +for pl330 controller, even for request with a length of 1. + +Although, the correct way should be: if the peripheral request +length is 1, the peripheral should use SINGLE request, and then +notify the dmac using SINGLE mode by src/dst_maxburst with 1. + +For example, on the Rockchip SoCs, all the peripherals can use +SINGLE or BURST request by setting GRF registers. it is possible +that if these peripheral drivers are used only for Rockchip SoCs. +Unfortunately, it's not, such as dw uart, which is used so widely, +and we can't set src/dst_maxburst according to the SoCs' specific +to compatible with all the other SoCs. + +So, for convenience, all the peripherals are set as BURST request +by default on the Rockchip SoCs. even for request with a length of 1. +the current pl330 driver will perform SINGLE transfer if the client's +maxburst is 1, which still should be working according to chapter 2.6.6 +of datasheet which describe how DMAC performs SINGLE transfers for +a BURST request. Unfortunately, it's broken on the Rockchip SoCs, +which support only matching transfers, such as BURST transfer for +BURST request, SINGLE transfer for SINGLE request. + +Finally, we add the quirk to specify pl330 to use burst transfers only. + +Signed-off-by: Sugar Zhang +Link: https://lore.kernel.org/r/1593439555-68130-5-git-send-email-sugar.zhang@rock-chips.com +Signed-off-by: Vinod Koul +(cherry picked from commit 5fb9e3a3423313fe6169d5069e471bfdab6e0b79) +--- + drivers/dma/pl330.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index f1f0176c6c05..3be8d462eab4 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -33,7 +33,8 @@ + #define PL330_MAX_PERI 32 + #define PL330_MAX_BURST 16 + +-#define PL330_QUIRK_BROKEN_NO_FLUSHP BIT(0) ++#define PL330_QUIRK_BROKEN_NO_FLUSHP BIT(0) ++#define PL330_QUIRK_PERIPH_BURST BIT(1) + + enum pl330_cachectrl { + CCTRL0, /* Noncacheable and nonbufferable */ +@@ -509,6 +510,10 @@ static struct pl330_of_quirks { + { + .quirk = "arm,pl330-broken-no-flushp", + .id = PL330_QUIRK_BROKEN_NO_FLUSHP, ++ }, ++ { ++ .quirk = "arm,pl330-periph-burst", ++ .id = PL330_QUIRK_PERIPH_BURST, + } + }; + +@@ -1206,6 +1211,9 @@ static int _bursts(struct pl330_dmac *pl330, unsigned dry_run, u8 buf[], + int off = 0; + enum pl330_cond cond = BRST_LEN(pxs->ccr) > 1 ? BURST : SINGLE; + ++ if (pl330->quirks & PL330_QUIRK_PERIPH_BURST) ++ cond = BURST; ++ + switch (pxs->desc->rqtype) { + case DMA_MEM_TO_DEV: + /* fall through */ + +From e02c5f202e532c3107f055ff4938852675c9effd Mon Sep 17 00:00:00 2001 +From: Lee Jones +Date: Tue, 14 Jul 2020 12:15:34 +0100 +Subject: [PATCH] dmaengine: pl330: Demote obvious misuse of kerneldoc to + standard comment block + +No 'struct' title is provided. Nor are any attribute descriptions. + +Fixes the following W=1 kernel build warning(s): + + drivers/dma/pl330.c:295: warning: cannot understand function prototype: 'struct pl330_reqcfg ' + +Signed-off-by: Lee Jones +Cc: Philipp Zabel +Cc: Jaswinder Singh +Link: https://lore.kernel.org/r/20200714111546.1755231-6-lee.jones@linaro.org +Signed-off-by: Vinod Koul +(cherry picked from commit f9e036df575d8efce6fd469acd9df3148c2adf6e) +--- + drivers/dma/pl330.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index 3be8d462eab4..2c508ee672b9 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -285,7 +285,7 @@ struct pl330_config { + u32 irq_ns; + }; + +-/** ++/* + * Request Configuration. + * The PL330 core does not modify this and uses the last + * working configuration if the request doesn't provide any. + +From 90e0dc93ec0461e912927d1667f31be40a277954 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto +Date: Thu, 9 Jul 2020 10:55:36 +0900 +Subject: [PATCH] ASoC: hdmi-codec: return -ENOTSUPP for digital_mute + +snd_soc_dai_digital_mute() will return -ENOTSUPP if driver doesn't +support mute. +In hdmi-codec case, hdmi_codec_digital_mute() will be used for it, +and each driver has .digital_mute() callback. +hdmi_codec_digital_mute() want to return -ENOTSUPP to follow it. + +Signed-off-by: Kuninori Morimoto +Link: https://lore.kernel.org/r/87fta1xxjc.wl-kuninori.morimoto.gx@renesas.com +Signed-off-by: Mark Brown +(cherry picked from commit e07e49c0d1e3693facf588142c4cbde45904b3f8) +--- + sound/soc/codecs/hdmi-codec.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c +index f005751da2cc..926ab447a96b 100644 +--- a/sound/soc/codecs/hdmi-codec.c ++++ b/sound/soc/codecs/hdmi-codec.c +@@ -566,7 +566,7 @@ static int hdmi_codec_digital_mute(struct snd_soc_dai *dai, int mute) + return hcp->hcd.ops->digital_mute(dai->dev->parent, + hcp->hcd.data, mute); + +- return 0; ++ return -ENOTSUPP; + } + + static const struct snd_soc_dai_ops hdmi_codec_i2s_dai_ops = { + +From f7c70c0be79698095f473dc90a266d98a4a5d12d Mon Sep 17 00:00:00 2001 +From: Johan Jonker +Date: Wed, 15 Jul 2020 09:09:54 +0200 +Subject: [PATCH] arm64: dts: rockchip: remove bus-width from mmc nodes in px30 + dts files + +'bus-width' has been added to px30.dtsi mmc nodes, so now it can be +removed from the dts files that include it. + +Signed-off-by: Johan Jonker +Link: https://lore.kernel.org/r/20200715070954.1992-1-jbx6244@gmail.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit e7e46a1f6b755248058db531b1cff3b0cc580650) +--- + arch/arm64/boot/dts/rockchip/px30-evb.dts | 3 --- + arch/arm64/boot/dts/rockchip/rk3326-odroid-go2.dts | 1 - + 2 files changed, 4 deletions(-) + +diff --git a/arch/arm64/boot/dts/rockchip/px30-evb.dts b/arch/arm64/boot/dts/rockchip/px30-evb.dts +index 0a680257d9c2..5fe905fae9a8 100644 +--- a/arch/arm64/boot/dts/rockchip/px30-evb.dts ++++ b/arch/arm64/boot/dts/rockchip/px30-evb.dts +@@ -145,7 +145,6 @@ &dsi_dphy { + }; + + &emmc { +- bus-width = <8>; + cap-mmc-highspeed; + mmc-hs200-1_8v; + non-removable; +@@ -499,7 +498,6 @@ &saradc { + }; + + &sdmmc { +- bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + card-detect-delay = <800>; +@@ -513,7 +511,6 @@ &sdmmc { + }; + + &sdio { +- bus-width = <4>; + cap-sd-highspeed; + keep-power-in-suspend; + non-removable; +diff --git a/arch/arm64/boot/dts/rockchip/rk3326-odroid-go2.dts b/arch/arm64/boot/dts/rockchip/rk3326-odroid-go2.dts +index b3a8f936578f..35bd6b904b9c 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3326-odroid-go2.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3326-odroid-go2.dts +@@ -445,7 +445,6 @@ &saradc { + }; + + &sdmmc { +- bus-width = <4>; + cap-sd-highspeed; + card-detect-delay = <200>; + cd-gpios = <&gpio0 RK_PA3 GPIO_ACTIVE_LOW>; /*[> CD GPIO <]*/ + +From 3abee17c54e34c806bacab0a257b88ea3d75ab80 Mon Sep 17 00:00:00 2001 +From: Sugar Zhang +Date: Mon, 29 Jun 2020 22:12:11 +0800 +Subject: [PATCH] arm64: dts: rockchip: Add 'arm,pl330-periph-burst' for dmac + +This patch Add the quirk to specify to use burst transfer +for better compatible and higher performance. + +Signed-off-by: Sugar Zhang + +Link: https://lore.kernel.org/r/1593439935-68540-1-git-send-email-sugar.zhang@rock-chips.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit 505af9184ec0a0222bb883486137fac32731e01d) +--- + arch/arm64/boot/dts/rockchip/px30.dtsi | 1 + + arch/arm64/boot/dts/rockchip/rk3308.dtsi | 2 ++ + arch/arm64/boot/dts/rockchip/rk3328.dtsi | 1 + + arch/arm64/boot/dts/rockchip/rk3368.dtsi | 2 ++ + arch/arm64/boot/dts/rockchip/rk3399.dtsi | 2 ++ + 5 files changed, 8 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi +index e9bb2b97ae55..2695ea8cda14 100644 +--- a/arch/arm64/boot/dts/rockchip/px30.dtsi ++++ b/arch/arm64/boot/dts/rockchip/px30.dtsi +@@ -714,6 +714,7 @@ dmac: dmac@ff240000 { + reg = <0x0 0xff240000 0x0 0x4000>; + interrupts = , + ; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMAC>; + clock-names = "apb_pclk"; + #dma-cells = <1>; +diff --git a/arch/arm64/boot/dts/rockchip/rk3308.dtsi b/arch/arm64/boot/dts/rockchip/rk3308.dtsi +index ba1c71568164..e8b754d415d8 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3308.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3308.dtsi +@@ -524,6 +524,7 @@ dmac0: dma-controller@ff2c0000 { + reg = <0x0 0xff2c0000 0x0 0x4000>; + interrupts = , + ; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMAC0>; + clock-names = "apb_pclk"; + #dma-cells = <1>; +@@ -534,6 +535,7 @@ dmac1: dma-controller@ff2d0000 { + reg = <0x0 0xff2d0000 0x0 0x4000>; + interrupts = , + ; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMAC1>; + clock-names = "apb_pclk"; + #dma-cells = <1>; +diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +index 72e655020560..bbdb19a3e85d 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +@@ -153,6 +153,7 @@ dmac: dmac@ff1f0000 { + reg = <0x0 0xff1f0000 0x0 0x4000>; + interrupts = , + ; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMAC>; + clock-names = "apb_pclk"; + #dma-cells = <1>; +diff --git a/arch/arm64/boot/dts/rockchip/rk3368.dtsi b/arch/arm64/boot/dts/rockchip/rk3368.dtsi +index 5d25a9d04051..3746f23dc3df 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3368.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3368.dtsi +@@ -149,6 +149,7 @@ dmac_peri: dma-controller@ff250000 { + ; + #dma-cells = <1>; + arm,pl330-broken-no-flushp; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMAC_PERI>; + clock-names = "apb_pclk"; + }; +@@ -160,6 +161,7 @@ dmac_bus: dma-controller@ff600000 { + ; + #dma-cells = <1>; + arm,pl330-broken-no-flushp; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMAC_BUS>; + clock-names = "apb_pclk"; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi +index f2ef0d8ba54b..ada724b12f01 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi +@@ -209,6 +209,7 @@ dmac_bus: dma-controller@ff6d0000 { + interrupts = , + ; + #dma-cells = <1>; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMAC0_PERILP>; + clock-names = "apb_pclk"; + }; +@@ -219,6 +220,7 @@ dmac_peri: dma-controller@ff6e0000 { + interrupts = , + ; + #dma-cells = <1>; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMAC1_PERILP>; + clock-names = "apb_pclk"; + }; + +From 932b4a4d3d1ea833e2ac81c122879e4671ee2429 Mon Sep 17 00:00:00 2001 +From: Sugar Zhang +Date: Mon, 29 Jun 2020 22:10:57 +0800 +Subject: [PATCH] ARM: dts: rockchip: Add 'arm,pl330-periph-burst' for dmac + +This patch Add the quirk to specify to use burst transfer +for better compatible and higher performance. + +Signed-off-by: Sugar Zhang + +Link: https://lore.kernel.org/r/1593439866-68459-1-git-send-email-sugar.zhang@rock-chips.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit fb082df317823463eaf09ac88de19fb3319e4f58) +--- + arch/arm/boot/dts/rk3036.dtsi | 1 + + arch/arm/boot/dts/rk322x.dtsi | 1 + + arch/arm/boot/dts/rk3288.dtsi | 3 +++ + arch/arm/boot/dts/rk3xxx.dtsi | 3 +++ + arch/arm/boot/dts/rv1108.dtsi | 1 + + 5 files changed, 9 insertions(+) + +diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi +index d9a0c9a29b68..093567022386 100644 +--- a/arch/arm/boot/dts/rk3036.dtsi ++++ b/arch/arm/boot/dts/rk3036.dtsi +@@ -67,6 +67,7 @@ pdma: pdma@20078000 { + ; + #dma-cells = <1>; + arm,pl330-broken-no-flushp; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMAC2>; + clock-names = "apb_pclk"; + }; +diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi +index 3236abb0aba9..48e6e8d44a1a 100644 +--- a/arch/arm/boot/dts/rk322x.dtsi ++++ b/arch/arm/boot/dts/rk322x.dtsi +@@ -107,6 +107,7 @@ pdma: pdma@110f0000 { + interrupts = , + ; + #dma-cells = <1>; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMAC>; + clock-names = "apb_pclk"; + }; +diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi +index 84d59469035e..9fa11b9f4522 100644 +--- a/arch/arm/boot/dts/rk3288.dtsi ++++ b/arch/arm/boot/dts/rk3288.dtsi +@@ -167,6 +167,7 @@ dmac_peri: dma-controller@ff250000 { + ; + #dma-cells = <1>; + arm,pl330-broken-no-flushp; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMAC2>; + clock-names = "apb_pclk"; + }; +@@ -178,6 +179,7 @@ dmac_bus_ns: dma-controller@ff600000 { + ; + #dma-cells = <1>; + arm,pl330-broken-no-flushp; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMAC1>; + clock-names = "apb_pclk"; + status = "disabled"; +@@ -190,6 +192,7 @@ dmac_bus_s: dma-controller@ffb20000 { + ; + #dma-cells = <1>; + arm,pl330-broken-no-flushp; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMAC1>; + clock-names = "apb_pclk"; + }; +diff --git a/arch/arm/boot/dts/rk3xxx.dtsi b/arch/arm/boot/dts/rk3xxx.dtsi +index d929b60517ab..859a7477909f 100644 +--- a/arch/arm/boot/dts/rk3xxx.dtsi ++++ b/arch/arm/boot/dts/rk3xxx.dtsi +@@ -45,6 +45,7 @@ dmac1_s: dma-controller@20018000 { + ; + #dma-cells = <1>; + arm,pl330-broken-no-flushp; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMA1>; + clock-names = "apb_pclk"; + }; +@@ -56,6 +57,7 @@ dmac1_ns: dma-controller@2001c000 { + ; + #dma-cells = <1>; + arm,pl330-broken-no-flushp; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMA1>; + clock-names = "apb_pclk"; + status = "disabled"; +@@ -68,6 +70,7 @@ dmac2: dma-controller@20078000 { + ; + #dma-cells = <1>; + arm,pl330-broken-no-flushp; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMA2>; + clock-names = "apb_pclk"; + }; +diff --git a/arch/arm/boot/dts/rv1108.dtsi b/arch/arm/boot/dts/rv1108.dtsi +index a5d130bd0547..a1a08cb9364e 100644 +--- a/arch/arm/boot/dts/rv1108.dtsi ++++ b/arch/arm/boot/dts/rv1108.dtsi +@@ -97,6 +97,7 @@ pdma: pdma@102a0000 { + interrupts = ; + #dma-cells = <1>; + arm,pl330-broken-no-flushp; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMAC>; + clock-names = "apb_pclk"; + }; + +From ea1abccee16e018a29011224d0e7b5392d818e70 Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Wed, 15 Jul 2020 14:04:12 +0530 +Subject: [PATCH] ARM: dts: rockchip: dalang-carrier: Move i2c nodes into SOM + +I2C nodes and associated slave devices defined in Carrier board +are specific to rk3399pro vmrac SOM. + +So, move them into SOM dtsi. + +Signed-off-by: Jagan Teki +Link: https://lore.kernel.org/r/20200715083418.112003-2-jagan@amarulasolutions.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit c2f343510d99ab53b46bdfeb184cb48f622e6943) +--- + .../dts/rockchip-radxa-dalang-carrier.dtsi | 32 ------------------- + .../dts/rockchip/rk3399pro-vmarc-som.dtsi | 29 +++++++++++++++++ + 2 files changed, 29 insertions(+), 32 deletions(-) + +diff --git a/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi b/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi +index df3712aedf8a..176b53b8e41a 100644 +--- a/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi ++++ b/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi +@@ -17,29 +17,6 @@ &gmac { + status = "okay"; + }; + +-&i2c1 { +- status = "okay"; +- i2c-scl-rising-time-ns = <140>; +- i2c-scl-falling-time-ns = <30>; +-}; +- +-&i2c2 { +- status = "okay"; +- clock-frequency = <400000>; +- +- hym8563: hym8563@51 { +- compatible = "haoyu,hym8563"; +- reg = <0x51>; +- #clock-cells = <0>; +- clock-frequency = <32768>; +- clock-output-names = "hym8563"; +- pinctrl-names = "default"; +- pinctrl-0 = <&hym8563_int>; +- interrupt-parent = <&gpio4>; +- interrupts = <30 IRQ_TYPE_LEVEL_LOW>; +- }; +-}; +- + &pwm0 { + status = "okay"; + }; +@@ -70,12 +47,3 @@ &uart0 { + &uart2 { + status = "okay"; + }; +- +-&pinctrl { +- hym8563 { +- hym8563_int: hym8563-int { +- rockchip,pins = +- <4 RK_PD6 0 &pcfg_pull_up>; +- }; +- }; +-}; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi b/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi +index 0a516334f15f..e11538171e67 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi +@@ -297,6 +297,29 @@ regulator-state-mem { + }; + }; + ++&i2c1 { ++ i2c-scl-falling-time-ns = <30>; ++ i2c-scl-rising-time-ns = <140>; ++ status = "okay"; ++}; ++ ++&i2c2 { ++ clock-frequency = <400000>; ++ status = "okay"; ++ ++ hym8563: hym8563@51 { ++ compatible = "haoyu,hym8563"; ++ reg = <0x51>; ++ #clock-cells = <0>; ++ clock-frequency = <32768>; ++ clock-output-names = "hym8563"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&hym8563_int>; ++ interrupt-parent = <&gpio4>; ++ interrupts = ; ++ }; ++}; ++ + &io_domains { + status = "okay"; + bt656-supply = <&vcca_1v8>; +@@ -324,6 +347,12 @@ &tsadc { + }; + + &pinctrl { ++ hym8563 { ++ hym8563_int: hym8563-int { ++ rockchip,pins = <4 RK_PD6 0 &pcfg_pull_up>; ++ }; ++ }; ++ + pmic { + pmic_int_l: pmic-int-l { + rockchip,pins = + +From 2e13dc44e6d147dad03cc7f4024ec9152f329fa9 Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Wed, 15 Jul 2020 14:04:13 +0530 +Subject: [PATCH] arm64: dts: rk3399pro: vmarc-som: Fix sorting nodes, + properties + +Fix node, properties sorting on RockPI N10 board dts(i) files. + +Signed-off-by: Jagan Teki +Link: https://lore.kernel.org/r/20200715083418.112003-3-jagan@amarulasolutions.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit 3047b384a74090f09b994298eb5c40986275233a) +--- + .../dts/rockchip/rk3399pro-rock-pi-n10.dts | 2 +- + .../dts/rockchip/rk3399pro-vmarc-som.dtsi | 35 +++++++++---------- + 2 files changed, 18 insertions(+), 19 deletions(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3399pro-rock-pi-n10.dts b/arch/arm64/boot/dts/rockchip/rk3399pro-rock-pi-n10.dts +index a1783e7f769a..539f4005386d 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399pro-rock-pi-n10.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399pro-rock-pi-n10.dts +@@ -8,8 +8,8 @@ + /dts-v1/; + #include "rk3399.dtsi" + #include "rk3399-opp.dtsi" +-#include "rk3399pro-vmarc-som.dtsi" + #include ++#include "rk3399pro-vmarc-som.dtsi" + + / { + model = "Radxa ROCK Pi N10"; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi b/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi +index e11538171e67..121a430d6a70 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi +@@ -76,8 +76,8 @@ &gmac { + + &i2c0 { + clock-frequency = <400000>; +- i2c-scl-rising-time-ns = <180>; + i2c-scl-falling-time-ns = <30>; ++ i2c-scl-rising-time-ns = <180>; + status = "okay"; + + rk809: pmic@20 { +@@ -323,8 +323,22 @@ hym8563: hym8563@51 { + &io_domains { + status = "okay"; + bt656-supply = <&vcca_1v8>; +- sdmmc-supply = <&vccio_sd>; + gpio1830-supply = <&vccio_3v0>; ++ sdmmc-supply = <&vccio_sd>; ++}; ++ ++&pinctrl { ++ hym8563 { ++ hym8563_int: hym8563-int { ++ rockchip,pins = <4 RK_PD6 0 &pcfg_pull_up>; ++ }; ++ }; ++ ++ pmic { ++ pmic_int_l: pmic-int-l { ++ rockchip,pins = <1 RK_PC2 0 &pcfg_pull_up>; ++ }; ++ }; + }; + + &pmu_io_domains { +@@ -341,22 +355,7 @@ &sdhci { + }; + + &tsadc { +- status = "okay"; + rockchip,hw-tshut-mode = <1>; + rockchip,hw-tshut-polarity = <1>; +-}; +- +-&pinctrl { +- hym8563 { +- hym8563_int: hym8563-int { +- rockchip,pins = <4 RK_PD6 0 &pcfg_pull_up>; +- }; +- }; +- +- pmic { +- pmic_int_l: pmic-int-l { +- rockchip,pins = +- <1 RK_PC2 0 &pcfg_pull_up>; +- }; +- }; ++ status = "okay"; + }; + +From 4617f4569e155d9512cdfa8defdea925cd30b9e4 Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Wed, 15 Jul 2020 14:04:14 +0530 +Subject: [PATCH] arm64: dts: rk3399pro: vmarc-som: Move supply regulators into + Carrier + +Supply regulators are common across different variants of vmarc SOM's +since the Type C power controller IC is part of the carrier board. + +So, move the supply regulators into carrier board dtsi. + +Signed-off-by: Jagan Teki +Link: https://lore.kernel.org/r/20200715083418.112003-4-jagan@amarulasolutions.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit 4a3ca113c0f3a2ce33e51fc6a48a121b2d707d4f) +--- + .../dts/rockchip-radxa-dalang-carrier.dtsi | 19 +++++++++++++++++++ + .../dts/rockchip/rk3399pro-vmarc-som.dtsi | 19 ------------------- + 2 files changed, 19 insertions(+), 19 deletions(-) + +diff --git a/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi b/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi +index 176b53b8e41a..00b200a62263 100644 +--- a/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi ++++ b/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi +@@ -11,6 +11,25 @@ / { + chosen { + stdout-path = "serial2:1500000n8"; + }; ++ ++ vcc12v_dcin: vcc12v-dcin-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc12v_dcin"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <12000000>; ++ regulator-max-microvolt = <12000000>; ++ }; ++ ++ vcc5v0_sys: vcc5v0-sys-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc5v0_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc12v_dcin>; ++ }; + }; + + &gmac { +diff --git a/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi b/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi +index 121a430d6a70..d8fa8127d9dc 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi +@@ -18,25 +18,6 @@ clkin_gmac: external-gmac-clock { + clock-output-names = "clkin_gmac"; + #clock-cells = <0>; + }; +- +- vcc12v_dcin: vcc12v-dcin-regulator { +- compatible = "regulator-fixed"; +- regulator-name = "vcc12v_dcin"; +- regulator-always-on; +- regulator-boot-on; +- regulator-min-microvolt = <12000000>; +- regulator-max-microvolt = <12000000>; +- }; +- +- vcc5v0_sys: vcc5v0-sys-regulator { +- compatible = "regulator-fixed"; +- regulator-name = "vcc5v0_sys"; +- regulator-always-on; +- regulator-boot-on; +- regulator-min-microvolt = <5000000>; +- regulator-max-microvolt = <5000000>; +- vin-supply = <&vcc12v_dcin>; +- }; + }; + + &cpu_l0 { + +From 772d02fccf2734a12aaaf22398aa70986a2868c7 Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Wed, 15 Jul 2020 14:04:15 +0530 +Subject: [PATCH] arm64: dts: rk3399pro: vmarc-som: Move common properties into + Carrier + +Some of gmac, sdmmc node properties are common across rk3288 and +rk3399pro SOM's so move them into Carrier dtsi. + +Chosen node is specific to rk3399pro configure SBC, so move it into +RockPI N10 dts. + +Signed-off-by: Jagan Teki +Link: https://lore.kernel.org/r/20200715083418.112003-5-jagan@amarulasolutions.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit a66bd94d0eac017e4846658750acaca2937555bb) +--- + .../dts/rockchip-radxa-dalang-carrier.dtsi | 18 ++++++++++++---- + .../dts/rockchip/rk3399pro-rock-pi-n10.dts | 4 ++++ + .../dts/rockchip/rk3399pro-vmarc-som.dtsi | 21 +++++-------------- + 3 files changed, 23 insertions(+), 20 deletions(-) + +diff --git a/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi b/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi +index 00b200a62263..450e5bb5af0b 100644 +--- a/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi ++++ b/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi +@@ -8,8 +8,11 @@ + #include + + / { +- chosen { +- stdout-path = "serial2:1500000n8"; ++ clkin_gmac: external-gmac-clock { ++ compatible = "fixed-clock"; ++ clock-frequency = <125000000>; ++ clock-output-names = "clkin_gmac"; ++ #clock-cells = <0>; + }; + + vcc12v_dcin: vcc12v-dcin-regulator { +@@ -33,6 +36,15 @@ vcc5v0_sys: vcc5v0-sys-regulator { + }; + + &gmac { ++ assigned-clock-parents = <&clkin_gmac>; ++ clock_in_out = "input"; ++ phy-mode = "rgmii"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&rgmii_pins>; ++ snps,reset-active-low; ++ snps,reset-delays-us = <0 10000 50000>; ++ tx_delay = <0x28>; ++ rx_delay = <0x11>; + status = "okay"; + }; + +@@ -48,10 +60,8 @@ &sdmmc { + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; +- cd-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>; + disable-wp; + vqmmc-supply = <&vccio_sd>; +- max-frequency = <150000000>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_bus4>; + status = "okay"; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399pro-rock-pi-n10.dts b/arch/arm64/boot/dts/rockchip/rk3399pro-rock-pi-n10.dts +index 539f4005386d..369de5dc0ebd 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399pro-rock-pi-n10.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399pro-rock-pi-n10.dts +@@ -15,4 +15,8 @@ / { + model = "Radxa ROCK Pi N10"; + compatible = "radxa,rockpi-n10", "vamrs,rk3399pro-vmarc-som", + "rockchip,rk3399pro"; ++ ++ chosen { ++ stdout-path = "serial2:1500000n8"; ++ }; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi b/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi +index d8fa8127d9dc..37ed95d5f7e9 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi +@@ -11,13 +11,6 @@ + + / { + compatible = "vamrs,rk3399pro-vmarc-som", "rockchip,rk3399pro"; +- +- clkin_gmac: external-gmac-clock { +- compatible = "fixed-clock"; +- clock-frequency = <125000000>; +- clock-output-names = "clkin_gmac"; +- #clock-cells = <0>; +- }; + }; + + &cpu_l0 { +@@ -42,17 +35,8 @@ &emmc_phy { + + &gmac { + assigned-clocks = <&cru SCLK_RMII_SRC>; +- assigned-clock-parents = <&clkin_gmac>; +- clock_in_out = "input"; + phy-supply = <&vcc_lan>; +- phy-mode = "rgmii"; +- pinctrl-names = "default"; +- pinctrl-0 = <&rgmii_pins>; + snps,reset-gpio = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; +- snps,reset-active-low; +- snps,reset-delays-us = <0 10000 50000>; +- tx_delay = <0x28>; +- rx_delay = <0x11>; + }; + + &i2c0 { +@@ -335,6 +319,11 @@ &sdhci { + status = "okay"; + }; + ++&sdmmc { ++ cd-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>; ++ max-frequency = <150000000>; ++}; ++ + &tsadc { + rockchip,hw-tshut-mode = <1>; + rockchip,hw-tshut-polarity = <1>; + +From 916191ead33a0ce0baec3a3cadb386c12d9a1b99 Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Wed, 15 Jul 2020 14:04:16 +0530 +Subject: [PATCH] dt-bindings: arm: rockchip: Add Rock Pi N8 binding + +Rock Pi N8 is a Rockchip RK3288 based SBC, which has +- VMARC RK3288 SOM (as per SMARC standard) from Vamrs. +- Compatible carrier board from Radxa. + +VMARC RK3288 SOM need to mount on top of dalang carrier +board for making Rock PI N8 SBC. + +Add dt-bindings for it. + +Signed-off-by: Jagan Teki +Reviewed-by: Rob Herring +Link: https://lore.kernel.org/r/20200715083418.112003-6-jagan@amarulasolutions.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit 09ee4794270f0010c6397163f033f883f5bff1aa) +--- + Documentation/devicetree/bindings/arm/rockchip.yaml | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/Documentation/devicetree/bindings/arm/rockchip.yaml b/Documentation/devicetree/bindings/arm/rockchip.yaml +index d4a4045092df..db2e35796795 100644 +--- a/Documentation/devicetree/bindings/arm/rockchip.yaml ++++ b/Documentation/devicetree/bindings/arm/rockchip.yaml +@@ -435,6 +435,12 @@ properties: + - const: radxa,rockpi4 + - const: rockchip,rk3399 + ++ - description: Radxa ROCK Pi N8 ++ items: ++ - const: radxa,rockpi-n8 ++ - const: vamrs,rk3288-vmarc-som ++ - const: rockchip,rk3288 ++ + - description: Radxa ROCK Pi N10 + items: + - const: radxa,rockpi-n10 + +From 2a5e46160a746adc9a7b9b952e2000060d6da48a Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Wed, 15 Jul 2020 14:04:17 +0530 +Subject: [PATCH] ARM: dts: rockchip: Add VMARC RK3288 SOM initial support + +VMARC RK3288 SOM is a standard SMARC SOM design with +Rockchip RK3288 SoC, which is designed by Vamrs. + +Specification: +- Rockchip RK3288 +- PMIC: RK808 +- eMMC: 16GB/32GB/64GB +- SD slot +- 2xUSB-2.0, 1xUSB3.0 +- USB-C for power supply +- Ethernet +- HDMI, MIPI-DSI/CSI, eDP + +Add initial support for VMARC RK3288 SOM, this would use +with associated carrier board. + +Signed-off-by: Jagan Teki +Link: https://lore.kernel.org/r/20200715083418.112003-7-jagan@amarulasolutions.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit b8c564d4fa76b1314a10585eea8e97b8c621a77a) +--- + arch/arm/boot/dts/rk3288-vmarc-som.dtsi | 270 ++++++++++++++++++++++++ + 1 file changed, 270 insertions(+) + create mode 100644 arch/arm/boot/dts/rk3288-vmarc-som.dtsi + +diff --git a/arch/arm/boot/dts/rk3288-vmarc-som.dtsi b/arch/arm/boot/dts/rk3288-vmarc-som.dtsi +new file mode 100644 +index 000000000000..cd61b6230f0d +--- /dev/null ++++ b/arch/arm/boot/dts/rk3288-vmarc-som.dtsi +@@ -0,0 +1,270 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd ++ * Copyright (c) 2019 Vamrs Limited ++ * Copyright (c) 2019 Amarula Solutions(India) ++ */ ++ ++#include ++#include ++ ++/ { ++ compatible = "vamrs,rk3288-vmarc-som", "rockchip,rk3288"; ++ ++ vccio_flash: vccio-flash-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vccio_flash"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ vin-supply = <&vcc_io>; ++ }; ++}; ++ ++&emmc { ++ bus-width = <8>; ++ cap-mmc-highspeed; ++ disable-wp; ++ non-removable; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_pwr &emmc_bus8>; ++ vmmc-supply = <&vcc_io>; ++ vqmmc-supply = <&vccio_flash>; ++ status = "okay"; ++}; ++ ++&gmac { ++ assigned-clocks = <&cru SCLK_MAC>; ++ phy-supply = <&vcc_io>; ++ snps,reset-gpio = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>; ++}; ++ ++&i2c0 { ++ clock-frequency = <400000>; ++ status = "okay"; ++ ++ rk808: pmic@1b { ++ compatible = "rockchip,rk808"; ++ reg = <0x1b>; ++ interrupt-parent = <&gpio0>; ++ interrupts = ; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_int &global_pwroff>; ++ rockchip,system-power-controller; ++ wakeup-source; ++ #clock-cells = <1>; ++ clock-output-names = "rk808-clkout1", "rk808-clkout2"; ++ ++ vcc1-supply = <&vcc5v0_sys>; ++ vcc2-supply = <&vcc5v0_sys>; ++ vcc3-supply = <&vcc5v0_sys>; ++ vcc4-supply = <&vcc5v0_sys>; ++ vcc6-supply = <&vcc5v0_sys>; ++ vcc7-supply = <&vcc5v0_sys>; ++ vcc8-supply = <&vcc_io>; ++ vcc9-supply = <&vcc_io>; ++ vcc10-supply = <&vcc5v0_sys>; ++ vcc11-supply = <&vcc5v0_sys>; ++ vcc12-supply = <&vcc_io>; ++ vddio-supply = <&vcc_io>; ++ ++ regulators { ++ vdd_cpu: DCDC_REG1 { ++ regulator-name = "vdd_arm"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <1400000>; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_gpu: DCDC_REG2 { ++ regulator-name = "vdd_gpu"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <1250000>; ++ regulator-ramp-delay = <6000>; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_ddr: DCDC_REG3 { ++ regulator-name = "vcc_ddr"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vcc_io: DCDC_REG4 { ++ regulator-name = "vcc_io"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vcc_tp: LDO_REG1 { ++ regulator-name = "vcc_tp"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcca_codec: LDO_REG2 { ++ regulator-name = "vcca_codec"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vdd_10: LDO_REG3 { ++ regulator-name = "vdd_10"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1000000>; ++ regulator-max-microvolt = <1000000>; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1000000>; ++ }; ++ }; ++ ++ vcc_wl: LDO_REG4 { ++ regulator-name = "vcc_wl"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vccio_sd: LDO_REG5 { ++ regulator-name = "vccio_sd"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vdd10_lcd: LDO_REG6 { ++ regulator-name = "vdd10_lcd"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1000000>; ++ regulator-max-microvolt = <1000000>; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_18: LDO_REG7 { ++ regulator-name = "vcc_18"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcc18_lcd: LDO_REG8 { ++ regulator-name = "vcc18_lcd"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_sd: SWITCH_REG1 { ++ regulator-name = "vcc_sd"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_lcd: SWITCH_REG2 { ++ regulator-name = "vcc_lcd"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&io_domains { ++ bb-supply = <&vcc_io>; ++ flash0-supply = <&vccio_flash>; ++ gpio1830-supply = <&vcc_18>; ++ gpio30-supply = <&vcc_io>; ++ sdcard-supply = <&vccio_sd>; ++ status = "okay"; ++}; ++ ++&pinctrl { ++ pcfg_pull_none_drv_8ma: pcfg-pull-none-drv-8ma { ++ drive-strength = <8>; ++ }; ++ ++ pcfg_pull_up_drv_8ma: pcfg-pull-up-drv-8ma { ++ bias-pull-up; ++ drive-strength = <8>; ++ }; ++ ++ pmic { ++ pmic_int: pmic-int { ++ rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ sdmmc { ++ sdmmc_bus4: sdmmc-bus4 { ++ rockchip,pins = ++ <6 RK_PC0 1 &pcfg_pull_up_drv_8ma>, ++ <6 RK_PC1 1 &pcfg_pull_up_drv_8ma>, ++ <6 RK_PC2 1 &pcfg_pull_up_drv_8ma>, ++ <6 RK_PC3 1 &pcfg_pull_up_drv_8ma>; ++ }; ++ ++ sdmmc_clk: sdmmc-clk { ++ rockchip,pins = <6 RK_PC4 1 &pcfg_pull_none_drv_8ma>; ++ }; ++ ++ sdmmc_cmd: sdmmc-cmd { ++ rockchip,pins = <6 RK_PC5 1 &pcfg_pull_up_drv_8ma>; ++ }; ++ }; ++}; + +From 10ff584a4e12d06e7f041b37f806bd6ffac91f94 Mon Sep 17 00:00:00 2001 +From: Michael Trimarchi +Date: Tue, 7 Jul 2020 12:12:14 +0200 +Subject: [PATCH] ARM: dts: rockchip: Fix VBUS on rk3288-vyasa + +Connect the voltage regulator of vbus to the otg connector. +Depending on the current mode this is enabled (in "host" mode") +or disabled (in "peripheral" mode). The regulator must be updated +if the controller is configured in "otg" mode and the status changes +between "host" and "peripheral". + +Signed-off-by: Michael Trimarchi +Link: https://lore.kernel.org/r/20200707101214.2301768-1-michael@amarulasolutions.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit 719646b76a41b8a482f8701825b635e9710ab329) +--- + arch/arm/boot/dts/rk3288-vyasa.dts | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/arch/arm/boot/dts/rk3288-vyasa.dts b/arch/arm/boot/dts/rk3288-vyasa.dts +index 385dd59393e1..1a20854a1317 100644 +--- a/arch/arm/boot/dts/rk3288-vyasa.dts ++++ b/arch/arm/boot/dts/rk3288-vyasa.dts +@@ -99,8 +99,6 @@ vusb1_5v: vusb1-5v { + pinctrl-0 = <&otg_vbus_drv>; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; +- regulator-always-on; +- regulator-boot-on; + vin-supply = <&vsus_5v>; + }; + +@@ -416,6 +414,7 @@ &usb_host1 { + }; + + &usb_otg { ++ vbus-supply = <&vusb1_5v>; + status = "okay"; + }; + + +From 8635890fdcf41e911c4e3dd5213f3ff891513cab Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Mon, 20 Jul 2020 16:28:46 +0530 +Subject: [PATCH] ARM: dts: rockchip: Add usb host0 ohci node for rk3288 + +rk3288 and rk3288w have a usb host0 ohci controller. + +Although rk3288 ohci doesn't actually work on hardware, but +rk3288w ohci can work well. + +So add usb host0 ohci node in rk3288 dtsi and boards +can then enable it if supported. + +Signed-off-by: Jagan Teki +Cc: William Wu +Link: https://lore.kernel.org/r/20200720105846.367776-1-jagan@amarulasolutions.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit 82540defdd9cfc491f564ffb8d01911966636bc7) +--- + arch/arm/boot/dts/rk3288.dtsi | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi +index 9fa11b9f4522..68d5a58cfe88 100644 +--- a/arch/arm/boot/dts/rk3288.dtsi ++++ b/arch/arm/boot/dts/rk3288.dtsi +@@ -616,7 +616,16 @@ usb_host0_ehci: usb@ff500000 { + status = "disabled"; + }; + +- /* NOTE: ohci@ff520000 doesn't actually work on hardware */ ++ /* NOTE: doesn't work on RK3288, but was fixed on RK3288W */ ++ usb_host0_ohci: usb@ff520000 { ++ compatible = "generic-ohci"; ++ reg = <0x0 0xff520000 0x0 0x100>; ++ interrupts = ; ++ clocks = <&cru HCLK_USBHOST0>; ++ phys = <&usbphy1>; ++ phy-names = "usb"; ++ status = "disabled"; ++ }; + + usb_host1: usb@ff540000 { + compatible = "rockchip,rk3288-usb", "rockchip,rk3066-usb", + +From cb343a78f51f82997bce9de813c1035f15010e38 Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Mon, 20 Jul 2020 16:32:28 +0530 +Subject: [PATCH] ARM: dts: rockchip: Add USB for RockPI N8/N10 + +Radxa dalang carrier board has 2x USB 2.0 and 1x USB 3.0 +ports. + +This patch adds support to enable all these USB ports for +N10 and N8 combinations SBCs. + +Note that the USB 3.0 port on RockPI N8 combination works +as USB 2.0 OTG since it is driven from RK3288. + +Signed-off-by: Jagan Teki +Link: https://lore.kernel.org/r/20200720110230.367985-1-jagan@amarulasolutions.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit 417b188a985d3557b0ecb5623b27bd9843f03aec) +--- + arch/arm/boot/dts/rk3288-vmarc-som.dtsi | 42 ++++++++++ + .../dts/rockchip-radxa-dalang-carrier.dtsi | 18 +++++ + .../dts/rockchip/rk3399pro-vmarc-som.dtsi | 78 +++++++++++++++++++ + 3 files changed, 138 insertions(+) + +diff --git a/arch/arm/boot/dts/rk3288-vmarc-som.dtsi b/arch/arm/boot/dts/rk3288-vmarc-som.dtsi +index cd61b6230f0d..78164d117248 100644 +--- a/arch/arm/boot/dts/rk3288-vmarc-som.dtsi ++++ b/arch/arm/boot/dts/rk3288-vmarc-som.dtsi +@@ -267,4 +267,46 @@ sdmmc_cmd: sdmmc-cmd { + rockchip,pins = <6 RK_PC5 1 &pcfg_pull_up_drv_8ma>; + }; + }; ++ ++ vbus_host { ++ usb1_en_oc: usb1-en-oc { ++ rockchip,pins = <0 RK_PC1 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ vbus_typec { ++ usb0_en_oc: usb0-en-oc { ++ rockchip,pins = <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++}; ++ ++&usbphy { ++ status = "okay"; ++}; ++ ++&usb_host0_ehci { ++ status = "okay"; ++}; ++ ++&usb_host0_ohci { ++ status = "okay"; ++}; ++ ++&usb_host1 { ++ status = "okay"; ++}; ++ ++&usb_otg { ++ status = "okay"; ++}; ++ ++&vbus_host { ++ enable-active-high; ++ gpio = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>; /* USB1_EN_OC# */ ++}; ++ ++&vbus_typec { ++ enable-active-high; ++ gpio = <&gpio0 RK_PB5 GPIO_ACTIVE_HIGH>; /* USB0_EN_OC# */ + }; +diff --git a/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi b/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi +index 450e5bb5af0b..d2b6ead148a2 100644 +--- a/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi ++++ b/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi +@@ -33,6 +33,24 @@ vcc5v0_sys: vcc5v0-sys-regulator { + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc12v_dcin>; + }; ++ ++ vbus_host: vbus-host { ++ compatible = "regulator-fixed"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usb1_en_oc>; ++ regulator-name = "vbus_host"; /* HOST-5V */ ++ regulator-always-on; ++ vin-supply = <&vcc5v0_sys>; ++ }; ++ ++ vbus_typec: vbus-typec { ++ compatible = "regulator-fixed"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usb0_en_oc>; ++ regulator-name = "vbus_typec"; ++ regulator-always-on; ++ vin-supply = <&vcc5v0_sys>; ++ }; + }; + + &gmac { +diff --git a/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi b/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi +index 37ed95d5f7e9..111d6cf9a4e6 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi +@@ -304,6 +304,18 @@ pmic_int_l: pmic-int-l { + rockchip,pins = <1 RK_PC2 0 &pcfg_pull_up>; + }; + }; ++ ++ vbus_host { ++ usb1_en_oc: usb1-en-oc { ++ rockchip,pins = <4 RK_PD1 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ vbus_typec { ++ usb0_en_oc: usb0-en-oc { ++ rockchip,pins = <4 RK_PD2 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; + }; + + &pmu_io_domains { +@@ -324,8 +336,74 @@ &sdmmc { + max-frequency = <150000000>; + }; + ++&tcphy0 { ++ status = "okay"; ++}; ++ + &tsadc { + rockchip,hw-tshut-mode = <1>; + rockchip,hw-tshut-polarity = <1>; + status = "okay"; + }; ++ ++&u2phy0 { ++ status = "okay"; ++ ++ u2phy0_otg: otg-port { ++ phy-supply = <&vbus_typec>; ++ status = "okay"; ++ }; ++ ++ u2phy0_host: host-port { ++ phy-supply = <&vbus_host>; ++ status = "okay"; ++ }; ++}; ++ ++ ++&u2phy1 { ++ status = "okay"; ++ ++ u2phy1_host: host-port { ++ phy-supply = <&vbus_host>; ++ status = "okay"; ++ }; ++}; ++ ++&usb_host0_ehci { ++ status = "okay"; ++}; ++ ++&usb_host0_ohci { ++ status = "okay"; ++}; ++ ++&usb_host1_ehci { ++ status = "okay"; ++}; ++ ++&usb_host1_ohci { ++ status = "okay"; ++}; ++ ++&usbdrd3_0 { ++ status = "okay"; ++}; ++ ++&usbdrd_dwc3_0 { ++ status = "okay"; ++}; ++ ++&vbus_host { ++ enable-active-high; ++ gpio = <&gpio4 RK_PD1 GPIO_ACTIVE_HIGH>; /* USB1_EN_OC# */ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usb1_en_oc>; ++}; ++ ++&vbus_typec { ++ enable-active-high; ++ gpio = <&gpio4 RK_PD2 GPIO_ACTIVE_HIGH>; /* USB0_EN_OC# */ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usb0_en_oc>; ++}; + +From 3137628a7366f1fc30748b59254d6b25c2c86efd Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Mon, 20 Jul 2020 16:32:29 +0530 +Subject: [PATCH] ARM: dts: rockchip: Add HDMI out for RockPI N8/N10 + +This patch adds support to enable HDMI out for +N10 and N8 combinations SBCs. + +Signed-off-by: Jagan Teki +Signed-off-by: Suniel Mahesh +Link: https://lore.kernel.org/r/20200720110230.367985-2-jagan@amarulasolutions.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit d0cb2f30e7c033f0a8bbe98ec73dbc1db4788942) +--- + arch/arm/boot/dts/rk3288-vmarc-som.dtsi | 10 ++++++++++ + .../dts/rockchip-radxa-dalang-carrier.dtsi | 20 +++++++++++++++++++ + .../dts/rockchip/rk3399pro-vmarc-som.dtsi | 12 +++++++++++ + 3 files changed, 42 insertions(+) + +diff --git a/arch/arm/boot/dts/rk3288-vmarc-som.dtsi b/arch/arm/boot/dts/rk3288-vmarc-som.dtsi +index 78164d117248..4a373f5aa600 100644 +--- a/arch/arm/boot/dts/rk3288-vmarc-som.dtsi ++++ b/arch/arm/boot/dts/rk3288-vmarc-som.dtsi +@@ -38,6 +38,12 @@ &gmac { + snps,reset-gpio = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>; + }; + ++&hdmi { ++ ddc-i2c-bus = <&i2c5>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&hdmi_cec_c0>; ++}; ++ + &i2c0 { + clock-frequency = <400000>; + status = "okay"; +@@ -225,6 +231,10 @@ regulator-state-mem { + }; + }; + ++&i2c5 { ++ status = "okay"; ++}; ++ + &io_domains { + bb-supply = <&vcc_io>; + flash0-supply = <&vccio_flash>; +diff --git a/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi b/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi +index d2b6ead148a2..26b53eac4706 100644 +--- a/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi ++++ b/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi +@@ -66,6 +66,10 @@ &gmac { + status = "okay"; + }; + ++&hdmi { ++ status = "okay"; ++}; ++ + &pwm0 { + status = "okay"; + }; +@@ -94,3 +98,19 @@ &uart0 { + &uart2 { + status = "okay"; + }; ++ ++&vopb { ++ status = "okay"; ++}; ++ ++&vopb_mmu { ++ status = "okay"; ++}; ++ ++&vopl { ++ status = "okay"; ++}; ++ ++&vopl_mmu { ++ status = "okay"; ++}; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi b/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi +index 111d6cf9a4e6..ebccc4a153a2 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi +@@ -39,6 +39,12 @@ &gmac { + snps,reset-gpio = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + }; + ++&hdmi { ++ ddc-i2c-bus = <&i2c3>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&hdmi_cec>; ++}; ++ + &i2c0 { + clock-frequency = <400000>; + i2c-scl-falling-time-ns = <30>; +@@ -285,6 +291,12 @@ hym8563: hym8563@51 { + }; + }; + ++&i2c3 { ++ i2c-scl-rising-time-ns = <450>; ++ i2c-scl-falling-time-ns = <15>; ++ status = "okay"; ++}; ++ + &io_domains { + status = "okay"; + bt656-supply = <&vcca_1v8>; + +From 0d5ba09fbbd6b8a5d9fc7df9d3f760842549c07f Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Mon, 20 Jul 2020 16:32:30 +0530 +Subject: [PATCH] arm64: dts: rockchip: Add PCIe for RockPI N10 + +This patch adds support to enable PCIe for RockPI N10. + +Signed-off-by: Jagan Teki +Link: https://lore.kernel.org/r/20200720110230.367985-3-jagan@amarulasolutions.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit 93ca8ac2e8fcea6feb02a40edd2334144b62fc6e) +--- + .../dts/rockchip/rk3399pro-vmarc-som.dtsi | 40 ++++++++++++++++++- + 1 file changed, 38 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi b/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi +index ebccc4a153a2..5d087be04af8 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi +@@ -11,6 +11,18 @@ + + / { + compatible = "vamrs,rk3399pro-vmarc-som", "rockchip,rk3399pro"; ++ ++ vcc3v3_pcie: vcc-pcie-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio4 RK_PD4 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pcie_pwr>; ++ regulator-name = "vcc3v3_pcie"; ++ regulator-always-on; ++ regulator-boot-on; ++ vin-supply = <&vcc5v0_sys>; ++ }; + }; + + &cpu_l0 { +@@ -142,7 +154,8 @@ vcca_0v9: LDO_REG1 { + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + regulator-state-mem { +- regulator-off-in-suspend; ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <900000>; + }; + }; + +@@ -177,7 +190,8 @@ vcca_1v8: LDO_REG4 { + regulator-min-microvolt = <1850000>; + regulator-max-microvolt = <1850000>; + regulator-state-mem { +- regulator-off-in-suspend; ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1850000>; + }; + }; + +@@ -304,6 +318,22 @@ &io_domains { + sdmmc-supply = <&vccio_sd>; + }; + ++&pcie_phy { ++ status = "okay"; ++}; ++ ++&pcie0 { ++ ep-gpios = <&gpio0 RK_PB4 GPIO_ACTIVE_HIGH>; ++ max-link-speed = <2>; ++ num-lanes = <4>; ++ pinctrl-0 = <&pcie_clkreqnb_cpm>; ++ pinctrl-names = "default"; ++ vpcie0v9-supply = <&vcca_0v9>; /* VCC_0V9_S0 */ ++ vpcie1v8-supply = <&vcca_1v8>; /* VCC_1V8_S0 */ ++ vpcie3v3-supply = <&vcc3v3_pcie>; ++ status = "okay"; ++}; ++ + &pinctrl { + hym8563 { + hym8563_int: hym8563-int { +@@ -311,6 +341,12 @@ hym8563_int: hym8563-int { + }; + }; + ++ pcie { ++ pcie_pwr: pcie-pwr { ++ rockchip,pins = <4 RK_PD4 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ + pmic { + pmic_int_l: pmic-int-l { + rockchip,pins = <1 RK_PC2 0 &pcfg_pull_up>; + +From ec258d2b9150088af58b6935bbf3c6c3618ea8f7 Mon Sep 17 00:00:00 2001 +From: Katsuhiro Suzuki +Date: Sat, 25 Jul 2020 00:59:33 +0900 +Subject: [PATCH] ASoC: convert Everest ES8316 binding to yaml + +This patch converts Everest Semiconductor ES8316 low power audio +CODEC binding to DT schema. + +Signed-off-by: Katsuhiro Suzuki +Reviewed-by: Rob Herring +Link: https://lore.kernel.org/r/20200724155933.1040501-1-katsuhiro@katsuster.net +Signed-off-by: Mark Brown +(cherry picked from commit 92e67a9c4f206dc9c859c405e67448a8be59ac5d) +--- + .../bindings/sound/everest,es8316.txt | 23 --------- + .../bindings/sound/everest,es8316.yaml | 50 +++++++++++++++++++ + 2 files changed, 50 insertions(+), 23 deletions(-) + delete mode 100644 Documentation/devicetree/bindings/sound/everest,es8316.txt + create mode 100644 Documentation/devicetree/bindings/sound/everest,es8316.yaml + +diff --git a/Documentation/devicetree/bindings/sound/everest,es8316.txt b/Documentation/devicetree/bindings/sound/everest,es8316.txt +deleted file mode 100644 +index 1bf03c5f2af4..000000000000 +--- a/Documentation/devicetree/bindings/sound/everest,es8316.txt ++++ /dev/null +@@ -1,23 +0,0 @@ +-Everest ES8316 audio CODEC +- +-This device supports both I2C and SPI. +- +-Required properties: +- +- - compatible : should be "everest,es8316" +- - reg : the I2C address of the device for I2C +- +-Optional properties: +- +- - clocks : a list of phandle, should contain entries for clock-names +- - clock-names : should include as follows: +- "mclk" : master clock (MCLK) of the device +- +-Example: +- +-es8316: codec@11 { +- compatible = "everest,es8316"; +- reg = <0x11>; +- clocks = <&clks 10>; +- clock-names = "mclk"; +-}; +diff --git a/Documentation/devicetree/bindings/sound/everest,es8316.yaml b/Documentation/devicetree/bindings/sound/everest,es8316.yaml +new file mode 100644 +index 000000000000..3b752bba748b +--- /dev/null ++++ b/Documentation/devicetree/bindings/sound/everest,es8316.yaml +@@ -0,0 +1,50 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/sound/everest,es8316.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Everest ES8316 audio CODEC ++ ++maintainers: ++ - Daniel Drake ++ - Katsuhiro Suzuki ++ ++properties: ++ compatible: ++ const: everest,es8316 ++ ++ reg: ++ maxItems: 1 ++ ++ clocks: ++ items: ++ - description: clock for master clock (MCLK) ++ ++ clock-names: ++ items: ++ - const: mclk ++ ++ "#sound-dai-cells": ++ const: 0 ++ ++required: ++ - compatible ++ - reg ++ - "#sound-dai-cells" ++ ++additionalProperties: false ++ ++examples: ++ - | ++ i2c0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ es8316: codec@11 { ++ compatible = "everest,es8316"; ++ reg = <0x11>; ++ clocks = <&clks 10>; ++ clock-names = "mclk"; ++ #sound-dai-cells = <0>; ++ }; ++ }; + +From f5b60a176251d6e0d1716bbe62a5697a80d38089 Mon Sep 17 00:00:00 2001 +From: Alper Nebi Yasak +Date: Tue, 21 Jul 2020 21:27:10 +0300 +Subject: [PATCH] ASoC: rk3399_gru_sound: Add DAPM pins, kcontrols for jack + detection + +PulseAudio (and perhaps other userspace utilities) can not detect any +jack for rk3399_gru_sound as the driver doesn't expose related Jack +kcontrols. + +This patch adds two DAPM pins to the headset jack, where the +snd_soc_card_jack_new() call automatically creates "Headphones Jack" and +"Headset Mic Jack" kcontrols from them. + +With an appropriate ALSA UCM config specifying JackControl fields for +the "Headphones" and "Headset" (mic) devices, PulseAudio can detect +plug/unplug events for both of them after this patch. + +Signed-off-by: Alper Nebi Yasak +Link: https://lore.kernel.org/r/20200721182709.6895-1-alpernebiyasak@gmail.com +Signed-off-by: Mark Brown +(cherry picked from commit d0508b4f16049a658d68a7c276ba08296c5a76bc) +--- + sound/soc/rockchip/rk3399_gru_sound.c | 17 ++++++++++++++++- + 1 file changed, 16 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/rockchip/rk3399_gru_sound.c b/sound/soc/rockchip/rk3399_gru_sound.c +index 9539b0d024fe..3e45179638ca 100644 +--- a/sound/soc/rockchip/rk3399_gru_sound.c ++++ b/sound/soc/rockchip/rk3399_gru_sound.c +@@ -32,6 +32,19 @@ static unsigned int dmic_wakeup_delay; + + static struct snd_soc_jack rockchip_sound_jack; + ++/* Headset jack detection DAPM pins */ ++static struct snd_soc_jack_pin rockchip_sound_jack_pins[] = { ++ { ++ .pin = "Headphones", ++ .mask = SND_JACK_HEADPHONE, ++ }, ++ { ++ .pin = "Headset Mic", ++ .mask = SND_JACK_MICROPHONE, ++ }, ++ ++}; ++ + static const struct snd_soc_dapm_widget rockchip_dapm_widgets[] = { + SND_SOC_DAPM_HP("Headphones", NULL), + SND_SOC_DAPM_SPK("Speakers", NULL), +@@ -176,7 +189,9 @@ static int rockchip_sound_da7219_init(struct snd_soc_pcm_runtime *rtd) + SND_JACK_HEADSET | SND_JACK_LINEOUT | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3, +- &rockchip_sound_jack, NULL, 0); ++ &rockchip_sound_jack, ++ rockchip_sound_jack_pins, ++ ARRAY_SIZE(rockchip_sound_jack_pins)); + + if (ret) { + dev_err(rtd->card->dev, "New Headset Jack failed! (%d)\n", ret); diff --git a/patch/kernel/rk322x-current/01-linux-0002-rockchip-from-next.patch b/patch/kernel/rk322x-current/01-linux-0002-rockchip-from-next.patch new file mode 100644 index 000000000..a20e585c6 --- /dev/null +++ b/patch/kernel/rk322x-current/01-linux-0002-rockchip-from-next.patch @@ -0,0 +1,434 @@ +From 9d29c5e2f20a44575a5a0e483319682d62daa4b3 Mon Sep 17 00:00:00 2001 +From: Heiko Stuebner +Date: Wed, 29 Jan 2020 17:38:19 +0100 +Subject: [PATCH] clk: rockchip: convert rk3399 pll type to use + readl_relaxed_poll_timeout + +Instead of open coding the polling of the lock status, use the handy +readl_relaxed_poll_timeout for this. As the pll locking is normally +blazingly fast and we don't want to incur additional delays, we're +not doing any sleeps similar to for example the imx clk-pllv4 +and define a very safe but still short timeout of 1ms. + +Suggested-by: Stephen Boyd +Signed-off-by: Heiko Stuebner +Reviewed-by: Stephen Boyd +Link: https://lore.kernel.org/r/20200129163821.1547295-1-heiko@sntech.de +(cherry picked from commit bf4237a188f872e535de8cbfc7903c1387b83b01) +--- + drivers/clk/rockchip/clk-pll.c | 23 ++++++++++++----------- + 1 file changed, 12 insertions(+), 11 deletions(-) + +diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c +index 10560d963baf..28b04aad31ad 100644 +--- a/drivers/clk/rockchip/clk-pll.c ++++ b/drivers/clk/rockchip/clk-pll.c +@@ -589,19 +589,20 @@ static const struct clk_ops rockchip_rk3066_pll_clk_ops = { + static int rockchip_rk3399_pll_wait_lock(struct rockchip_clk_pll *pll) + { + u32 pllcon; +- int delay = 24000000; ++ int ret; + +- /* poll check the lock status in rk3399 xPLLCON2 */ +- while (delay > 0) { +- pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(2)); +- if (pllcon & RK3399_PLLCON2_LOCK_STATUS) +- return 0; ++ /* ++ * Lock time typical 250, max 500 input clock cycles @24MHz ++ * So define a very safe maximum of 1000us, meaning 24000 cycles. ++ */ ++ ret = readl_relaxed_poll_timeout(pll->reg_base + RK3399_PLLCON(2), ++ pllcon, ++ pllcon & RK3399_PLLCON2_LOCK_STATUS, ++ 0, 1000); ++ if (ret) ++ pr_err("%s: timeout waiting for pll to lock\n", __func__); + +- delay--; +- } +- +- pr_err("%s: timeout waiting for pll to lock\n", __func__); +- return -ETIMEDOUT; ++ return ret; + } + + static void rockchip_rk3399_pll_get_params(struct rockchip_clk_pll *pll, + +From afe54d66a661ce9d99250431f1371e46f9b6d8a5 Mon Sep 17 00:00:00 2001 +From: Heiko Stuebner +Date: Wed, 29 Jan 2020 17:38:20 +0100 +Subject: [PATCH] clk: rockchip: convert basic pll lock_wait to use + regmap_read_poll_timeout + +Instead of open coding the polling of the lock status, use the +handy regmap_read_poll_timeout for this. As the pll locking is +normally blazingly fast and we don't want to incur additional +delays, we're not doing any sleeps similar to for example the imx +clk-pllv4 and define a very safe but still short timeout of 1ms. + +Suggested-by: Stephen Boyd +Signed-off-by: Heiko Stuebner +Reviewed-by: Stephen Boyd +Link: https://lore.kernel.org/r/20200129163821.1547295-2-heiko@sntech.de +(cherry picked from commit 3507df1a4615113ae6509e0f14f6546f0d1c84b4) +--- + drivers/clk/rockchip/clk-pll.c | 21 ++++++--------------- + 1 file changed, 6 insertions(+), 15 deletions(-) + +diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c +index 28b04aad31ad..945f8b2cacc1 100644 +--- a/drivers/clk/rockchip/clk-pll.c ++++ b/drivers/clk/rockchip/clk-pll.c +@@ -86,23 +86,14 @@ static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll) + { + struct regmap *grf = pll->ctx->grf; + unsigned int val; +- int delay = 24000000, ret; +- +- while (delay > 0) { +- ret = regmap_read(grf, pll->lock_offset, &val); +- if (ret) { +- pr_err("%s: failed to read pll lock status: %d\n", +- __func__, ret); +- return ret; +- } ++ int ret; + +- if (val & BIT(pll->lock_shift)) +- return 0; +- delay--; +- } ++ ret = regmap_read_poll_timeout(grf, pll->lock_offset, val, ++ val & BIT(pll->lock_shift), 0, 1000); ++ if (ret) ++ pr_err("%s: timeout waiting for pll to lock\n", __func__); + +- pr_err("%s: timeout waiting for pll to lock\n", __func__); +- return -ETIMEDOUT; ++ return ret; + } + + /** + +From 9a37c781854b2cc475aced9045ba8c35b6838f3a Mon Sep 17 00:00:00 2001 +From: Heiko Stuebner +Date: Wed, 29 Jan 2020 17:38:21 +0100 +Subject: [PATCH] clk: rockchip: convert rk3036 pll type to use internal lock + status + +The rk3036 pll type exposes its lock status in both its pllcon registers +as well as the General Register Files. To remove one dependency convert +it to the "internal" lock status, similar to how rk3399 handles it. + +Signed-off-by: Heiko Stuebner +Reviewed-by: Stephen Boyd +Link: https://lore.kernel.org/r/20200129163821.1547295-3-heiko@sntech.de +(cherry picked from commit 7f6ffbb885d147557bdca471c37b7b1204005798) +--- + drivers/clk/rockchip/clk-pll.c | 26 +++++++++++++++++++++++--- + 1 file changed, 23 insertions(+), 3 deletions(-) + +diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c +index 945f8b2cacc1..4c6c9167ef50 100644 +--- a/drivers/clk/rockchip/clk-pll.c ++++ b/drivers/clk/rockchip/clk-pll.c +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + #include + #include + #include "clk.h" +@@ -109,12 +110,31 @@ static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll) + #define RK3036_PLLCON1_REFDIV_SHIFT 0 + #define RK3036_PLLCON1_POSTDIV2_MASK 0x7 + #define RK3036_PLLCON1_POSTDIV2_SHIFT 6 ++#define RK3036_PLLCON1_LOCK_STATUS BIT(10) + #define RK3036_PLLCON1_DSMPD_MASK 0x1 + #define RK3036_PLLCON1_DSMPD_SHIFT 12 ++#define RK3036_PLLCON1_PWRDOWN BIT(13) + #define RK3036_PLLCON2_FRAC_MASK 0xffffff + #define RK3036_PLLCON2_FRAC_SHIFT 0 + +-#define RK3036_PLLCON1_PWRDOWN (1 << 13) ++static int rockchip_rk3036_pll_wait_lock(struct rockchip_clk_pll *pll) ++{ ++ u32 pllcon; ++ int ret; ++ ++ /* ++ * Lock time typical 250, max 500 input clock cycles @24MHz ++ * So define a very safe maximum of 1000us, meaning 24000 cycles. ++ */ ++ ret = readl_relaxed_poll_timeout(pll->reg_base + RK3036_PLLCON(1), ++ pllcon, ++ pllcon & RK3036_PLLCON1_LOCK_STATUS, ++ 0, 1000); ++ if (ret) ++ pr_err("%s: timeout waiting for pll to lock\n", __func__); ++ ++ return ret; ++} + + static void rockchip_rk3036_pll_get_params(struct rockchip_clk_pll *pll, + struct rockchip_pll_rate_table *rate) +@@ -212,7 +232,7 @@ static int rockchip_rk3036_pll_set_params(struct rockchip_clk_pll *pll, + writel_relaxed(pllcon, pll->reg_base + RK3036_PLLCON(2)); + + /* wait for the pll to lock */ +- ret = rockchip_pll_wait_lock(pll); ++ ret = rockchip_rk3036_pll_wait_lock(pll); + if (ret) { + pr_warn("%s: pll update unsuccessful, trying to restore old params\n", + __func__); +@@ -251,7 +271,7 @@ static int rockchip_rk3036_pll_enable(struct clk_hw *hw) + + writel(HIWORD_UPDATE(0, RK3036_PLLCON1_PWRDOWN, 0), + pll->reg_base + RK3036_PLLCON(1)); +- rockchip_pll_wait_lock(pll); ++ rockchip_rk3036_pll_wait_lock(pll); + + return 0; + } + +From 4e8605e139b42a4b239339fc54016ef2d0704908 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Myl=C3=A8ne=20Josserand?= +Date: Tue, 2 Jun 2020 10:06:43 +0200 +Subject: [PATCH] clk: rockchip: Handle clock tree for rk3288w variant +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The revision rk3288w has a different clock tree about "hclk_vio" +clock, according to the BSP kernel code. + +This patch handles this difference by detecting which device-tree +we are using. If it is a "rockchip,rk3288-cru", let's register +the clock tree as it was before. If the device-tree node is +"rockchip,rk3288w-cru", we will apply the difference with this +version of this SoC. + +Noticed that this new device-tree compatible must be handled in +bootloader such as u-boot. + +Signed-off-by: Mylène Josserand +Link: https://lore.kernel.org/r/20200602080644.11333-2-mylene.josserand@collabora.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit 1627f683636df70fb25358b0a7b39a24e8fce5bf) +--- + drivers/clk/rockchip/clk-rk3288.c | 20 ++++++++++++++++++-- + 1 file changed, 18 insertions(+), 2 deletions(-) + +diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c +index cc2a177bbdbf..204976e2d0cb 100644 +--- a/drivers/clk/rockchip/clk-rk3288.c ++++ b/drivers/clk/rockchip/clk-rk3288.c +@@ -425,8 +425,6 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { + COMPOSITE(0, "aclk_vio0", mux_pll_src_cpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, + RK3288_CLKSEL_CON(31), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK3288_CLKGATE_CON(3), 0, GFLAGS), +- DIV(0, "hclk_vio", "aclk_vio0", 0, +- RK3288_CLKSEL_CON(28), 8, 5, DFLAGS), + COMPOSITE(0, "aclk_vio1", mux_pll_src_cpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, + RK3288_CLKSEL_CON(31), 14, 2, MFLAGS, 8, 5, DFLAGS, + RK3288_CLKGATE_CON(3), 2, GFLAGS), +@@ -819,6 +817,16 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { + INVERTER(0, "pclk_isp", "pclk_isp_in", RK3288_CLKSEL_CON(29), 3, IFLAGS), + }; + ++static struct rockchip_clk_branch rk3288w_hclkvio_branch[] __initdata = { ++ DIV(0, "hclk_vio", "aclk_vio1", 0, ++ RK3288_CLKSEL_CON(28), 8, 5, DFLAGS), ++}; ++ ++static struct rockchip_clk_branch rk3288_hclkvio_branch[] __initdata = { ++ DIV(0, "hclk_vio", "aclk_vio0", 0, ++ RK3288_CLKSEL_CON(28), 8, 5, DFLAGS), ++}; ++ + static const char *const rk3288_critical_clocks[] __initconst = { + "aclk_cpu", + "aclk_peri", +@@ -936,6 +944,14 @@ static void __init rk3288_clk_init(struct device_node *np) + RK3288_GRF_SOC_STATUS1); + rockchip_clk_register_branches(ctx, rk3288_clk_branches, + ARRAY_SIZE(rk3288_clk_branches)); ++ ++ if (of_device_is_compatible(np, "rockchip,rk3288w-cru")) ++ rockchip_clk_register_branches(ctx, rk3288w_hclkvio_branch, ++ ARRAY_SIZE(rk3288w_hclkvio_branch)); ++ else ++ rockchip_clk_register_branches(ctx, rk3288_hclkvio_branch, ++ ARRAY_SIZE(rk3288_hclkvio_branch)); ++ + rockchip_clk_protect_critical(rk3288_critical_clocks, + ARRAY_SIZE(rk3288_critical_clocks)); + + +From cac2ef41ac59ff839b73fea934e8ffd161d406f2 Mon Sep 17 00:00:00 2001 +From: Heiko Stuebner +Date: Fri, 3 Jul 2020 17:49:48 +0200 +Subject: [PATCH] clk: rockchip: use separate compatibles for rk3288w-cru + +Commit 1627f683636d ("clk: rockchip: Handle clock tree for rk3288w variant") +added the check for rk3288w-specific clock-tree changes but in turn would +require a double-compatible due to re-using the main rockchip,rk3288-cru +compatible as entry point. + +The binding change actually describes the compatibles as one or the other +so adapt the code accordingly and add a real second entry-point for the +clock controller. + +Signed-off-by: Heiko Stuebner +Reviewed-by: Ezequiel Garcia +Reviewed-by: Jagan Teki +Tested-by: Jagan Teki # rock-pi-n8 +Link: https://lore.kernel.org/r/20200703154948.260369-1-heiko@sntech.de +(cherry picked from commit 0a7f99aad259d223ce69c03e792c7e2bfcf8c2c6) +--- + drivers/clk/rockchip/clk-rk3288.c | 21 +++++++++++++++++++-- + 1 file changed, 19 insertions(+), 2 deletions(-) + +diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c +index 204976e2d0cb..93c794695c46 100644 +--- a/drivers/clk/rockchip/clk-rk3288.c ++++ b/drivers/clk/rockchip/clk-rk3288.c +@@ -15,6 +15,11 @@ + #define RK3288_GRF_SOC_CON(x) (0x244 + x * 4) + #define RK3288_GRF_SOC_STATUS1 0x284 + ++enum rk3288_variant { ++ RK3288_CRU, ++ RK3288W_CRU, ++}; ++ + enum rk3288_plls { + apll, dpll, cpll, gpll, npll, + }; +@@ -922,7 +927,8 @@ static struct syscore_ops rk3288_clk_syscore_ops = { + .resume = rk3288_clk_resume, + }; + +-static void __init rk3288_clk_init(struct device_node *np) ++static void __init rk3288_common_init(struct device_node *np, ++ enum rk3288_variant soc) + { + struct rockchip_clk_provider *ctx; + +@@ -945,7 +951,7 @@ static void __init rk3288_clk_init(struct device_node *np) + rockchip_clk_register_branches(ctx, rk3288_clk_branches, + ARRAY_SIZE(rk3288_clk_branches)); + +- if (of_device_is_compatible(np, "rockchip,rk3288w-cru")) ++ if (soc == RK3288W_CRU) + rockchip_clk_register_branches(ctx, rk3288w_hclkvio_branch, + ARRAY_SIZE(rk3288w_hclkvio_branch)); + else +@@ -970,4 +976,15 @@ static void __init rk3288_clk_init(struct device_node *np) + + rockchip_clk_of_add_provider(np, ctx); + } ++ ++static void __init rk3288_clk_init(struct device_node *np) ++{ ++ rk3288_common_init(np, RK3288_CRU); ++} + CLK_OF_DECLARE(rk3288_cru, "rockchip,rk3288-cru", rk3288_clk_init); ++ ++static void __init rk3288w_clk_init(struct device_node *np) ++{ ++ rk3288_common_init(np, RK3288W_CRU); ++} ++CLK_OF_DECLARE(rk3288w_cru, "rockchip,rk3288w-cru", rk3288w_clk_init); + +From b80ef30ce22bba6a4bdf9f0aaa9376b6fea24249 Mon Sep 17 00:00:00 2001 +From: Robin Murphy +Date: Thu, 18 Jun 2020 18:56:29 +0100 +Subject: [PATCH] clk: rockchip: Revert "fix wrong mmc sample phase shift for + rk3328" + +This reverts commit 82f4b67f018c88a7cc9337f0067ed3d6ec352648. + +According to a subsequent revert in the vendor kernel, the original +change was based on unclear documentation and was in fact incorrect. + +Emprically, my board's HS200 eMMC at 200MHZ apparently gets lucky with a +phase where this had no impact, but limiting max-frequency to 150MHz to +match the nominal capability of the I/O pins made it virtually unusable, +constantly throwing errors and retuning. With this revert, it starts +behaving perfectly at 150MHz too. + +Fixes: 82f4b67f018c ("clk: rockchip: fix wrong mmc sample phase shift for rk3328") +Signed-off-by: Robin Murphy +Reviewed-by: Shawn Lin +Link: https://lore.kernel.org/r/c80eb52e34c03f817586b6b7912fbd4e31be9079.1589475794.git.robin.murphy@arm.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit 465931e70881476a210d44705102ef8b6ee6cdb0) +--- + drivers/clk/rockchip/clk-rk3328.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/clk/rockchip/clk-rk3328.c b/drivers/clk/rockchip/clk-rk3328.c +index c186a1985bf4..2429b7c2a8b3 100644 +--- a/drivers/clk/rockchip/clk-rk3328.c ++++ b/drivers/clk/rockchip/clk-rk3328.c +@@ -808,22 +808,22 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = { + MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "clk_sdmmc", + RK3328_SDMMC_CON0, 1), + MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "clk_sdmmc", +- RK3328_SDMMC_CON1, 0), ++ RK3328_SDMMC_CON1, 1), + + MMC(SCLK_SDIO_DRV, "sdio_drv", "clk_sdio", + RK3328_SDIO_CON0, 1), + MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "clk_sdio", +- RK3328_SDIO_CON1, 0), ++ RK3328_SDIO_CON1, 1), + + MMC(SCLK_EMMC_DRV, "emmc_drv", "clk_emmc", + RK3328_EMMC_CON0, 1), + MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "clk_emmc", +- RK3328_EMMC_CON1, 0), ++ RK3328_EMMC_CON1, 1), + + MMC(SCLK_SDMMC_EXT_DRV, "sdmmc_ext_drv", "clk_sdmmc_ext", + RK3328_SDMMC_EXT_CON0, 1), + MMC(SCLK_SDMMC_EXT_SAMPLE, "sdmmc_ext_sample", "clk_sdmmc_ext", +- RK3328_SDMMC_EXT_CON1, 0), ++ RK3328_SDMMC_EXT_CON1, 1), + }; + + static const char *const rk3328_critical_clocks[] __initconst = { + +From 21710a18bfba0cf0993a1ef700f03f540d2648ed Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Wed, 22 Jul 2020 18:18:20 +0200 +Subject: [PATCH] clk: rockchip: add sclk_mac_lbtest to rk3188_critical_clocks + +Since the loopbacktest clock is not exported and is not touched in the +driver, it has to be added to rk3188_critical_clocks to be protected from +being disabled and in order to get the emac working. + +Signed-off-by: Alex Bee +Link: https://lore.kernel.org/r/20200722161820.5316-1-knaerzche@gmail.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit ef990bcad58cf1d13c5a49191a2c2342eb8d6709) +--- + drivers/clk/rockchip/clk-rk3188.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c +index 77aebfb1d6d5..730020fcc7fe 100644 +--- a/drivers/clk/rockchip/clk-rk3188.c ++++ b/drivers/clk/rockchip/clk-rk3188.c +@@ -751,6 +751,7 @@ static const char *const rk3188_critical_clocks[] __initconst = { + "pclk_peri", + "hclk_cpubus", + "hclk_vio_bus", ++ "sclk_mac_lbtest", + }; + + static struct rockchip_clk_provider *__init rk3188_common_clk_init(struct device_node *np) diff --git a/patch/kernel/rk322x-current/01-linux-0003-rockchip-from-list.patch.disabled b/patch/kernel/rk322x-current/01-linux-0003-rockchip-from-list.patch.disabled deleted file mode 100644 index 179cc5018..000000000 --- a/patch/kernel/rk322x-current/01-linux-0003-rockchip-from-list.patch.disabled +++ /dev/null @@ -1,2372 +0,0 @@ -diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile -index aaa1bf81d00d..c903112fc0c1 100644 ---- a/drivers/media/rc/keymaps/Makefile -+++ b/drivers/media/rc/keymaps/Makefile -@@ -79,6 +79,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ - rc-npgtech.o \ - rc-odroid.o \ - rc-pctv-sedna.o \ -+ rc-pine64.o \ - rc-pinnacle-color.o \ - rc-pinnacle-grey.o \ - rc-pinnacle-pctv-hd.o \ -diff --git a/drivers/media/rc/keymaps/rc-pine64.c b/drivers/media/rc/keymaps/rc-pine64.c -new file mode 100644 -index 000000000000..94e5624f63f4 ---- /dev/null -+++ b/drivers/media/rc/keymaps/rc-pine64.c -@@ -0,0 +1,59 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+// Keytable for Pine64 IR Remote Controller -+// Copyright (c) 2017 Jonas Karlman -+ -+#include -+#include -+ -+static struct rc_map_table pine64[] = { -+ { 0x404000, KEY_NUMERIC_0 }, -+ { 0x404001, KEY_NUMERIC_1 }, -+ { 0x404002, KEY_NUMERIC_2 }, -+ { 0x404003, KEY_NUMERIC_3 }, -+ { 0x404004, KEY_NUMERIC_4 }, -+ { 0x404005, KEY_NUMERIC_5 }, -+ { 0x404006, KEY_NUMERIC_6 }, -+ { 0x404007, KEY_NUMERIC_7 }, -+ { 0x404008, KEY_NUMERIC_8 }, -+ { 0x404009, KEY_NUMERIC_9 }, -+ { 0x40400a, KEY_MUTE }, -+ { 0x40400b, KEY_UP }, -+ { 0x40400c, KEY_BACKSPACE }, -+ { 0x40400d, KEY_OK }, -+ { 0x40400e, KEY_DOWN }, -+ { 0x404010, KEY_LEFT }, -+ { 0x404011, KEY_RIGHT }, -+ { 0x404017, KEY_VOLUMEDOWN }, -+ { 0x404018, KEY_VOLUMEUP }, -+ { 0x40401a, KEY_HOME }, -+ { 0x40401d, KEY_MENU }, -+ { 0x40401f, KEY_WWW }, -+ { 0x404045, KEY_BACK }, -+ { 0x404047, KEY_CONTEXT_MENU }, -+ { 0x40404d, KEY_POWER }, -+}; -+ -+static struct rc_map_list pine64_map = { -+ .map = { -+ .scan = pine64, -+ .size = ARRAY_SIZE(pine64), -+ .rc_proto = RC_PROTO_NECX, -+ .name = RC_MAP_PINE64, -+ } -+}; -+ -+static int __init init_rc_map_pine64(void) -+{ -+ return rc_map_register(&pine64_map); -+} -+ -+static void __exit exit_rc_map_pine64(void) -+{ -+ rc_map_unregister(&pine64_map); -+} -+ -+module_init(init_rc_map_pine64) -+module_exit(exit_rc_map_pine64) -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Jonas Karlman"); -diff --git a/include/media/rc-map.h b/include/media/rc-map.h -index d22810dcd85c..bd1f4f4347d5 100644 ---- a/include/media/rc-map.h -+++ b/include/media/rc-map.h -@@ -233,6 +233,7 @@ struct rc_map *rc_map_get(const char *name); - #define RC_MAP_NPGTECH "rc-npgtech" - #define RC_MAP_ODROID "rc-odroid" - #define RC_MAP_PCTV_SEDNA "rc-pctv-sedna" -+#define RC_MAP_PINE64 "rc-pine64" - #define RC_MAP_PINNACLE_COLOR "rc-pinnacle-color" - #define RC_MAP_PINNACLE_GREY "rc-pinnacle-grey" - #define RC_MAP_PINNACLE_PCTV_HD "rc-pinnacle-pctv-hd" --- -2.17.1 - - -From 64be34f37bf89d457bc4352f8f8c663a30464a40 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Wed, 7 Aug 2019 15:11:23 +0000 -Subject: [PATCH] ASoC: hdmi-codec: reorder channel allocation list - -Wrong channel allocation is selected by hdmi_codec_get_ch_alloc_table_idx(). - -E.g when ELD reports FL|FR|LFE|FC|RL|RR or FL|FR|LFE|FC|RL|RR|RC|RLC|RRC - -ca_id 0x01 with speaker mask FL|FR|LFE gets selected instead of -ca_id 0x03 with speaker mask FL|FR|LFE|FC for 4 channels - -and - -ca_id 0x04 with speaker mask FL|FR|RC gets selected instead of -ca_id 0x0b with speaker mask FL|FR|LFE|FC|RL|RR for 6 channels - -Fix this by reorder the channel allocation list with -most specific speaker mask at the top. - -Signed-off-by: Jonas Karlman ---- - sound/soc/codecs/hdmi-codec.c | 115 ++++++++++++++++------------------ - 1 file changed, 53 insertions(+), 62 deletions(-) - -diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c -index f005751da2cc..437759e5f459 100644 ---- a/sound/soc/codecs/hdmi-codec.c -+++ b/sound/soc/codecs/hdmi-codec.c -@@ -189,84 +189,75 @@ static const struct snd_pcm_chmap_elem hdmi_codec_8ch_chmaps[] = { - /* - * hdmi_codec_channel_alloc: speaker configuration available for CEA - * -- * This is an ordered list that must match with hdmi_codec_8ch_chmaps struct -+ * This is an ordered list where ca_id must exist in hdmi_codec_8ch_chmaps - * The preceding ones have better chances to be selected by - * hdmi_codec_get_ch_alloc_table_idx(). - */ - static const struct hdmi_codec_cea_spk_alloc hdmi_codec_channel_alloc[] = { - { .ca_id = 0x00, .n_ch = 2, -- .mask = FL | FR}, -- /* 2.1 */ -- { .ca_id = 0x01, .n_ch = 4, -- .mask = FL | FR | LFE}, -- /* Dolby Surround */ -+ .mask = FL | FR }, -+ { .ca_id = 0x03, .n_ch = 4, -+ .mask = FL | FR | LFE | FC }, - { .ca_id = 0x02, .n_ch = 4, - .mask = FL | FR | FC }, -- /* surround51 */ -+ { .ca_id = 0x01, .n_ch = 4, -+ .mask = FL | FR | LFE }, - { .ca_id = 0x0b, .n_ch = 6, -- .mask = FL | FR | LFE | FC | RL | RR}, -- /* surround40 */ -- { .ca_id = 0x08, .n_ch = 6, -- .mask = FL | FR | RL | RR }, -- /* surround41 */ -- { .ca_id = 0x09, .n_ch = 6, -- .mask = FL | FR | LFE | RL | RR }, -- /* surround50 */ -+ .mask = FL | FR | LFE | FC | RL | RR }, - { .ca_id = 0x0a, .n_ch = 6, - .mask = FL | FR | FC | RL | RR }, -- /* 6.1 */ -- { .ca_id = 0x0f, .n_ch = 8, -- .mask = FL | FR | LFE | FC | RL | RR | RC }, -- /* surround71 */ -+ { .ca_id = 0x09, .n_ch = 6, -+ .mask = FL | FR | LFE | RL | RR }, -+ { .ca_id = 0x08, .n_ch = 6, -+ .mask = FL | FR | RL | RR }, -+ { .ca_id = 0x07, .n_ch = 6, -+ .mask = FL | FR | LFE | FC | RC }, -+ { .ca_id = 0x06, .n_ch = 6, -+ .mask = FL | FR | FC | RC }, -+ { .ca_id = 0x05, .n_ch = 6, -+ .mask = FL | FR | LFE | RC }, -+ { .ca_id = 0x04, .n_ch = 6, -+ .mask = FL | FR | RC }, - { .ca_id = 0x13, .n_ch = 8, - .mask = FL | FR | LFE | FC | RL | RR | RLC | RRC }, -- /* others */ -- { .ca_id = 0x03, .n_ch = 8, -- .mask = FL | FR | LFE | FC }, -- { .ca_id = 0x04, .n_ch = 8, -- .mask = FL | FR | RC}, -- { .ca_id = 0x05, .n_ch = 8, -- .mask = FL | FR | LFE | RC }, -- { .ca_id = 0x06, .n_ch = 8, -- .mask = FL | FR | FC | RC }, -- { .ca_id = 0x07, .n_ch = 8, -- .mask = FL | FR | LFE | FC | RC }, -- { .ca_id = 0x0c, .n_ch = 8, -- .mask = FL | FR | RC | RL | RR }, -- { .ca_id = 0x0d, .n_ch = 8, -- .mask = FL | FR | LFE | RL | RR | RC }, -- { .ca_id = 0x0e, .n_ch = 8, -- .mask = FL | FR | FC | RL | RR | RC }, -- { .ca_id = 0x10, .n_ch = 8, -- .mask = FL | FR | RL | RR | RLC | RRC }, -- { .ca_id = 0x11, .n_ch = 8, -- .mask = FL | FR | LFE | RL | RR | RLC | RRC }, -+ { .ca_id = 0x1f, .n_ch = 8, -+ .mask = FL | FR | LFE | FC | RL | RR | FLC | FRC }, - { .ca_id = 0x12, .n_ch = 8, - .mask = FL | FR | FC | RL | RR | RLC | RRC }, -- { .ca_id = 0x14, .n_ch = 8, -- .mask = FL | FR | FLC | FRC }, -- { .ca_id = 0x15, .n_ch = 8, -- .mask = FL | FR | LFE | FLC | FRC }, -- { .ca_id = 0x16, .n_ch = 8, -- .mask = FL | FR | FC | FLC | FRC }, -- { .ca_id = 0x17, .n_ch = 8, -- .mask = FL | FR | LFE | FC | FLC | FRC }, -- { .ca_id = 0x18, .n_ch = 8, -- .mask = FL | FR | RC | FLC | FRC }, -- { .ca_id = 0x19, .n_ch = 8, -- .mask = FL | FR | LFE | RC | FLC | FRC }, -- { .ca_id = 0x1a, .n_ch = 8, -- .mask = FL | FR | RC | FC | FLC | FRC }, -- { .ca_id = 0x1b, .n_ch = 8, -- .mask = FL | FR | LFE | RC | FC | FLC | FRC }, -- { .ca_id = 0x1c, .n_ch = 8, -- .mask = FL | FR | RL | RR | FLC | FRC }, -- { .ca_id = 0x1d, .n_ch = 8, -- .mask = FL | FR | LFE | RL | RR | FLC | FRC }, - { .ca_id = 0x1e, .n_ch = 8, - .mask = FL | FR | FC | RL | RR | FLC | FRC }, -- { .ca_id = 0x1f, .n_ch = 8, -- .mask = FL | FR | LFE | FC | RL | RR | FLC | FRC }, -+ { .ca_id = 0x11, .n_ch = 8, -+ .mask = FL | FR | LFE | RL | RR | RLC | RRC }, -+ { .ca_id = 0x1d, .n_ch = 8, -+ .mask = FL | FR | LFE | RL | RR | FLC | FRC }, -+ { .ca_id = 0x10, .n_ch = 8, -+ .mask = FL | FR | RL | RR | RLC | RRC }, -+ { .ca_id = 0x1c, .n_ch = 8, -+ .mask = FL | FR | RL | RR | FLC | FRC }, -+ { .ca_id = 0x0f, .n_ch = 8, -+ .mask = FL | FR | LFE | FC | RL | RR | RC }, -+ { .ca_id = 0x1b, .n_ch = 8, -+ .mask = FL | FR | LFE | RC | FC | FLC | FRC }, -+ { .ca_id = 0x0e, .n_ch = 8, -+ .mask = FL | FR | FC | RL | RR | RC }, -+ { .ca_id = 0x1a, .n_ch = 8, -+ .mask = FL | FR | RC | FC | FLC | FRC }, -+ { .ca_id = 0x0d, .n_ch = 8, -+ .mask = FL | FR | LFE | RL | RR | RC }, -+ { .ca_id = 0x19, .n_ch = 8, -+ .mask = FL | FR | LFE | RC | FLC | FRC }, -+ { .ca_id = 0x0c, .n_ch = 8, -+ .mask = FL | FR | RC | RL | RR }, -+ { .ca_id = 0x18, .n_ch = 8, -+ .mask = FL | FR | RC | FLC | FRC }, -+ { .ca_id = 0x17, .n_ch = 8, -+ .mask = FL | FR | LFE | FC | FLC | FRC }, -+ { .ca_id = 0x16, .n_ch = 8, -+ .mask = FL | FR | FC | FLC | FRC }, -+ { .ca_id = 0x15, .n_ch = 8, -+ .mask = FL | FR | LFE | FLC | FRC }, -+ { .ca_id = 0x14, .n_ch = 8, -+ .mask = FL | FR | FLC | FRC }, - }; - - struct hdmi_codec_priv { --- -2.17.1 - - -From 5e626ea314cb0b25dc7a58e72908b1f91e762dfc Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Tue, 1 Oct 2019 20:52:42 +0000 -Subject: [PATCH] media: cec-adap: add debounce support when setting an invalid - phys addr - -When EDID is refreshed, HDMI cable is unplugged/replugged or -an AVR is power cycled the CEC phys addr gets invalidated. - -This can cause some disruption of CEC communication when -adapter is being reconfigured. - -Add a debounce module option that can be used to debounce setting -an invalid phys addr. Default is not to use debouncing. - -Using a configured debounce of e.g. 5000 ms, cec reconfiguring -could be avoided when AVR was power cycled on my setup. - -Power off AVR (default cec.debounce=0): -[ 101.536866] cec-dw_hdmi: new physical address f.f.f.f -[ 102.495686] cec-dw_hdmi: new physical address 2.1.0.0 -[ 102.495913] cec-dw_hdmi: physical address: 2.1.0.0, claim 1 logical addresses -[ 102.628574] cec-dw_hdmi: config: la 1 pa 2.1.0.0 -[ 105.130115] cec-dw_hdmi: new physical address f.f.f.f -[ 106.979705] cec-dw_hdmi: new physical address 2.1.0.0 -[ 106.979872] cec-dw_hdmi: physical address: 2.1.0.0, claim 1 logical addresses -[ 107.112399] cec-dw_hdmi: config: la 1 pa 2.1.0.0 -[ 108.979408] cec-dw_hdmi: reported physical address 2.0.0.0 for logical address 5 -[ 109.205386] cec-dw_hdmi: reported physical address 2.0.0.0 for logical address 11 - -Power on AVR (default cec.debounce=0): -[ 158.398447] cec-dw_hdmi: new physical address f.f.f.f -[ 161.977714] cec-dw_hdmi: new physical address 2.1.0.0 -[ 161.978766] cec-dw_hdmi: physical address: 2.1.0.0, claim 1 logical addresses -[ 162.115624] cec-dw_hdmi: config: la 1 pa 2.1.0.0 -[ 162.402750] cec-dw_hdmi: new physical address f.f.f.f -[ 162.403389] cec-dw_hdmi: cec_transmit_msg_fh: adapter is unconfigured -[ 162.886757] cec-dw_hdmi: new physical address 2.1.0.0 -[ 162.886964] cec-dw_hdmi: physical address: 2.1.0.0, claim 1 logical addresses -[ 163.510725] cec-dw_hdmi: config: la 1 pa 2.1.0.0 -[ 173.034200] cec-dw_hdmi: message 10 89 02 05 timed out - -Power off AVR (cec.debounce=5000): -[ 251.720471] cec-dw_hdmi: reported physical address 2.0.0.0 for logical address 5 -[ 251.922432] cec-dw_hdmi: reported physical address 2.0.0.0 for logical address 11 - -Power on AVR (cec.debounce=5000): -[ 291.154262] cec-dw_hdmi: reported physical address 2.0.0.0 for logical address 5 -[ 291.296199] cec-dw_hdmi: reported physical address 2.0.0.0 for logical address 11 - -Signed-off-by: Jonas Karlman ---- - Documentation/media/uapi/cec/cec-intro.rst | 8 ++++++++ - drivers/media/cec/cec-adap.c | 9 ++++++++- - drivers/media/cec/cec-core.c | 18 ++++++++++++++++++ - drivers/media/cec/cec-priv.h | 1 + - include/media/cec.h | 2 ++ - 5 files changed, 37 insertions(+), 1 deletion(-) - -diff --git a/Documentation/media/uapi/cec/cec-intro.rst b/Documentation/media/uapi/cec/cec-intro.rst -index 05088fcefe81..9bfd11ef987b 100644 ---- a/Documentation/media/uapi/cec/cec-intro.rst -+++ b/Documentation/media/uapi/cec/cec-intro.rst -@@ -47,3 +47,11 @@ provides three tools to handle CEC: - determine how compliant the CEC implementation is. - - - cec-follower: emulates a CEC follower. -+ -+Debouncing -+---------- -+ -+The ``debounce_ms`` option is a module parameter that can be used to enabled -+debouncing of setting invalid physical address. -+ -+FIXME: Make a section "1.1 Debouncing" that explains this module option. -diff --git a/drivers/media/cec/cec-adap.c b/drivers/media/cec/cec-adap.c -index 6c95dc471d4c..c483e847db95 100644 ---- a/drivers/media/cec/cec-adap.c -+++ b/drivers/media/cec/cec-adap.c -@@ -1609,8 +1609,15 @@ void cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block) - if (IS_ERR_OR_NULL(adap)) - return; - -+ cancel_delayed_work_sync(&adap->debounce_work); -+ - mutex_lock(&adap->lock); -- __cec_s_phys_addr(adap, phys_addr, block); -+ if (cec_debounce_ms > 0 && !block && -+ phys_addr == CEC_PHYS_ADDR_INVALID && adap->phys_addr != phys_addr) -+ schedule_delayed_work(&adap->debounce_work, -+ msecs_to_jiffies(cec_debounce_ms)); -+ else -+ __cec_s_phys_addr(adap, phys_addr, block); - mutex_unlock(&adap->lock); - } - EXPORT_SYMBOL_GPL(cec_s_phys_addr); -diff --git a/drivers/media/cec/cec-core.c b/drivers/media/cec/cec-core.c -index 0c52e1bb3910..cd71d77c057c 100644 ---- a/drivers/media/cec/cec-core.c -+++ b/drivers/media/cec/cec-core.c -@@ -28,6 +28,10 @@ static bool debug_phys_addr; - module_param(debug_phys_addr, bool, 0644); - MODULE_PARM_DESC(debug_phys_addr, "add CEC_CAP_PHYS_ADDR if set"); - -+int cec_debounce_ms; -+module_param_named(debounce_ms, cec_debounce_ms, int, 0644); -+MODULE_PARM_DESC(debounce_ms, "invalid physical address debounce time in ms"); -+ - static dev_t cec_dev_t; - - /* Active devices */ -@@ -174,6 +178,8 @@ static void cec_devnode_unregister(struct cec_adapter *adap) - devnode->unregistered = true; - mutex_unlock(&devnode->lock); - -+ cancel_delayed_work_sync(&adap->debounce_work); -+ - mutex_lock(&adap->lock); - __cec_s_phys_addr(adap, CEC_PHYS_ADDR_INVALID, false); - __cec_s_log_addrs(adap, NULL, false); -@@ -232,6 +238,17 @@ static const struct file_operations cec_error_inj_fops = { - }; - #endif - -+static void cec_s_phys_addr_debounce(struct work_struct *work) -+{ -+ struct delayed_work *delayed_work = to_delayed_work(work); -+ struct cec_adapter *adap = -+ container_of(delayed_work, struct cec_adapter, debounce_work); -+ -+ mutex_lock(&adap->lock); -+ __cec_s_phys_addr(adap, CEC_PHYS_ADDR_INVALID, false); -+ mutex_unlock(&adap->lock); -+} -+ - struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, - void *priv, const char *name, u32 caps, - u8 available_las) -@@ -270,6 +287,7 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, - INIT_LIST_HEAD(&adap->transmit_queue); - INIT_LIST_HEAD(&adap->wait_queue); - init_waitqueue_head(&adap->kthread_waitq); -+ INIT_DELAYED_WORK(&adap->debounce_work, cec_s_phys_addr_debounce); - - /* adap->devnode initialization */ - INIT_LIST_HEAD(&adap->devnode.fhs); -diff --git a/drivers/media/cec/cec-priv.h b/drivers/media/cec/cec-priv.h -index 9bbd05053d42..d479dbd50528 100644 ---- a/drivers/media/cec/cec-priv.h -+++ b/drivers/media/cec/cec-priv.h -@@ -27,6 +27,7 @@ static inline bool msg_is_raw(const struct cec_msg *msg) - - /* cec-core.c */ - extern int cec_debug; -+extern int cec_debounce_ms; - int cec_get_device(struct cec_devnode *devnode); - void cec_put_device(struct cec_devnode *devnode); - -diff --git a/include/media/cec.h b/include/media/cec.h -index 972bc8cd4384..5befad3a6a0f 100644 ---- a/include/media/cec.h -+++ b/include/media/cec.h -@@ -164,6 +164,8 @@ struct cec_adapter { - wait_queue_head_t kthread_waitq; - wait_queue_head_t waitq; - -+ struct delayed_work debounce_work; -+ - const struct cec_adap_ops *ops; - void *priv; - u32 capabilities; --- -2.17.1 - - -From e7067ef6d71c5686c082f37f8e54454d499124a8 Mon Sep 17 00:00:00 2001 -From: Boris Brezillon -Date: Thu, 19 Dec 2019 11:11:48 +0100 -Subject: [PATCH] drm/bridge: Add a drm_bridge_state object - -One of the last remaining objects to not have its atomic state. - -This is being motivated by our attempt to support runtime bus-format -negotiation between elements of the bridge chain. -This patch just paves the road for such a feature by adding a new -drm_bridge_state object inheriting from drm_private_obj so we can -re-use some of the existing state initialization/tracking logic. - -Signed-off-by: Boris Brezillon -Reviewed-by: Neil Armstrong -Reviewed-by: Laurent Pinchart -Signed-off-by: Neil Armstrong ---- - drivers/gpu/drm/drm_atomic.c | 39 +++++++ - drivers/gpu/drm/drm_atomic_helper.c | 20 ++++ - drivers/gpu/drm/drm_bridge.c | 169 +++++++++++++++++++++++++++- - include/drm/drm_atomic.h | 3 + - include/drm/drm_bridge.h | 120 ++++++++++++++++++++ - 5 files changed, 345 insertions(+), 6 deletions(-) - -diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c -index d33691512a8e..bf1b9c37d515 100644 ---- a/drivers/gpu/drm/drm_atomic.c -+++ b/drivers/gpu/drm/drm_atomic.c -@@ -30,6 +30,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -1017,6 +1018,44 @@ static void drm_atomic_connector_print_state(struct drm_printer *p, - connector->funcs->atomic_print_state(p, state); - } - -+/** -+ * drm_atomic_add_encoder_bridges - add bridges attached to an encoder -+ * @state: atomic state -+ * @encoder: DRM encoder -+ * -+ * This function adds all bridges attached to @encoder. This is needed to add -+ * bridge states to @state and make them available when -+ * &bridge_funcs.atomic_{check,pre_enable,enable,disable_post_disable}() are -+ * called -+ * -+ * Returns: -+ * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK -+ * then the w/w mutex code has detected a deadlock and the entire atomic -+ * sequence must be restarted. All other errors are fatal. -+ */ -+int -+drm_atomic_add_encoder_bridges(struct drm_atomic_state *state, -+ struct drm_encoder *encoder) -+{ -+ struct drm_bridge_state *bridge_state; -+ struct drm_bridge *bridge; -+ -+ if (!encoder) -+ return 0; -+ -+ DRM_DEBUG_ATOMIC("Adding all bridges for [encoder:%d:%s] to %p\n", -+ encoder->base.id, encoder->name, state); -+ -+ drm_for_each_bridge_in_chain(encoder, bridge) { -+ bridge_state = drm_atomic_get_bridge_state(state, bridge); -+ if (IS_ERR(bridge_state)) -+ return PTR_ERR(bridge_state); -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL(drm_atomic_add_encoder_bridges); -+ - /** - * drm_atomic_add_affected_connectors - add connectors for CRTC - * @state: atomic state -diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c -index 4511c2e07bb9..ad8eae98d9e8 100644 ---- a/drivers/gpu/drm/drm_atomic_helper.c -+++ b/drivers/gpu/drm/drm_atomic_helper.c -@@ -730,6 +730,26 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, - return ret; - } - -+ /* -+ * Iterate over all connectors again, and add all affected bridges to -+ * the state. -+ */ -+ for_each_oldnew_connector_in_state(state, connector, -+ old_connector_state, -+ new_connector_state, i) { -+ struct drm_encoder *encoder; -+ -+ encoder = old_connector_state->best_encoder; -+ ret = drm_atomic_add_encoder_bridges(state, encoder); -+ if (ret) -+ return ret; -+ -+ encoder = new_connector_state->best_encoder; -+ ret = drm_atomic_add_encoder_bridges(state, encoder); -+ if (ret) -+ return ret; -+ } -+ - ret = mode_valid(state); - if (ret) - return ret; -diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c -index c2cf0c90fa26..a3921b45f044 100644 ---- a/drivers/gpu/drm/drm_bridge.c -+++ b/drivers/gpu/drm/drm_bridge.c -@@ -25,6 +25,7 @@ - #include - #include - -+#include - #include - #include - -@@ -89,6 +90,38 @@ void drm_bridge_remove(struct drm_bridge *bridge) - } - EXPORT_SYMBOL(drm_bridge_remove); - -+static struct drm_private_state * -+drm_bridge_atomic_duplicate_priv_state(struct drm_private_obj *obj) -+{ -+ struct drm_bridge *bridge = drm_priv_to_bridge(obj); -+ struct drm_bridge_state *state; -+ -+ if (bridge->funcs->atomic_duplicate_state) -+ state = bridge->funcs->atomic_duplicate_state(bridge); -+ else -+ state = drm_atomic_helper_bridge_duplicate_state(bridge); -+ -+ return state ? &state->base : NULL; -+} -+ -+static void -+drm_bridge_atomic_destroy_priv_state(struct drm_private_obj *obj, -+ struct drm_private_state *s) -+{ -+ struct drm_bridge_state *state = drm_priv_to_bridge_state(s); -+ struct drm_bridge *bridge = drm_priv_to_bridge(obj); -+ -+ if (bridge->funcs->atomic_destroy_state) -+ bridge->funcs->atomic_destroy_state(bridge, state); -+ else -+ drm_atomic_helper_bridge_destroy_state(bridge, state); -+} -+ -+static const struct drm_private_state_funcs drm_bridge_priv_state_funcs = { -+ .atomic_duplicate_state = drm_bridge_atomic_duplicate_priv_state, -+ .atomic_destroy_state = drm_bridge_atomic_destroy_priv_state, -+}; -+ - /** - * drm_bridge_attach - attach the bridge to an encoder's chain - * -@@ -114,6 +147,7 @@ EXPORT_SYMBOL(drm_bridge_remove); - int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge, - struct drm_bridge *previous) - { -+ struct drm_bridge_state *state; - int ret; - - if (!encoder || !bridge) -@@ -135,15 +169,35 @@ int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge, - - if (bridge->funcs->attach) { - ret = bridge->funcs->attach(bridge); -- if (ret < 0) { -- list_del(&bridge->chain_node); -- bridge->dev = NULL; -- bridge->encoder = NULL; -- return ret; -- } -+ if (ret < 0) -+ goto err_reset_bridge; -+ } -+ -+ if (bridge->funcs->atomic_reset) -+ state = bridge->funcs->atomic_reset(bridge); -+ else -+ state = drm_atomic_helper_bridge_reset(bridge); -+ -+ if (IS_ERR(state)) { -+ ret = PTR_ERR(state); -+ goto err_detach_bridge; - } - -+ drm_atomic_private_obj_init(bridge->dev, &bridge->base, -+ &state->base, -+ &drm_bridge_priv_state_funcs); -+ - return 0; -+ -+err_detach_bridge: -+ if (bridge->funcs->detach) -+ bridge->funcs->detach(bridge); -+ -+err_reset_bridge: -+ bridge->dev = NULL; -+ bridge->encoder = NULL; -+ list_del(&bridge->chain_node); -+ return ret; - } - EXPORT_SYMBOL(drm_bridge_attach); - -@@ -155,6 +209,8 @@ void drm_bridge_detach(struct drm_bridge *bridge) - if (WARN_ON(!bridge->dev)) - return; - -+ drm_atomic_private_obj_fini(&bridge->base); -+ - if (bridge->funcs->detach) - bridge->funcs->detach(bridge); - -@@ -516,6 +572,107 @@ void drm_atomic_bridge_chain_enable(struct drm_bridge *bridge, - } - EXPORT_SYMBOL(drm_atomic_bridge_chain_enable); - -+/** -+ * drm_atomic_helper_bridge_destroy_state() - Default destroy state helper -+ * @bridge: the bridge this state refers to -+ * @state: state object to destroy -+ * -+ * Just a simple kfree() for now. -+ */ -+void drm_atomic_helper_bridge_destroy_state(struct drm_bridge *bridge, -+ struct drm_bridge_state *state) -+{ -+ kfree(state); -+} -+EXPORT_SYMBOL(drm_atomic_helper_bridge_destroy_state); -+ -+/** -+ * __drm_atomic_helper_bridge_reset() - Initialize a bridge state to its -+ * default -+ * @bridge: the bridge this state is refers to -+ * @state: bridge state to initialize -+ * -+ * Initialize the bridge state to default values. This is meant to be* called -+ * by the bridge &drm_plane_funcs.reset hook for bridges that subclass the -+ * bridge state. -+ */ -+void __drm_atomic_helper_bridge_reset(struct drm_bridge *bridge, -+ struct drm_bridge_state *state) -+{ -+ memset(state, 0, sizeof(*state)); -+ state->bridge = bridge; -+} -+EXPORT_SYMBOL(__drm_atomic_helper_bridge_reset); -+ -+/** -+ * drm_atomic_helper_bridge_reset() - default &drm_plane_funcs.reset hook for -+ * bridges -+ * @bridge: the bridge to reset state on -+ * -+ * Resets the atomic state for @bridge by freeing the state pointer (which -+ * might be NULL, e.g. at driver load time) and allocating a new empty state -+ * object. -+ * -+ * RETURNS: -+ * A valid drm_bridge_state object in case of success, an ERR_PTR() -+ * giving the reaon of the failure otherwise. -+ */ -+struct drm_bridge_state * -+drm_atomic_helper_bridge_reset(struct drm_bridge *bridge) -+{ -+ struct drm_bridge_state *bridge_state; -+ -+ bridge_state = kzalloc(sizeof(*bridge_state), GFP_KERNEL); -+ if (!bridge_state) -+ return ERR_PTR(-ENOMEM); -+ -+ __drm_atomic_helper_bridge_reset(bridge, bridge_state); -+ return bridge_state; -+} -+EXPORT_SYMBOL(drm_atomic_helper_bridge_reset); -+ -+/** -+ * __drm_atomic_helper_bridge_duplicate_state() - Copy atomic bridge state -+ * @bridge: bridge object -+ * @state: atomic bridge state -+ * -+ * Copies atomic state from a bridge's current state and resets inferred values. -+ * This is useful for drivers that subclass the bridge state. -+ */ -+void __drm_atomic_helper_bridge_duplicate_state(struct drm_bridge *bridge, -+ struct drm_bridge_state *state) -+{ -+ __drm_atomic_helper_private_obj_duplicate_state(&bridge->base, -+ &state->base); -+ state->bridge = bridge; -+} -+EXPORT_SYMBOL(__drm_atomic_helper_bridge_duplicate_state); -+ -+/** -+ * drm_atomic_helper_duplicate_bridge_state() - Default duplicate state helper -+ * @bridge: bridge containing the state to duplicate -+ * -+ * Default implementation of &drm_bridge_funcs.atomic_duplicate(). -+ * -+ * RETURNS: -+ * a valid state object or NULL if the allocation fails. -+ */ -+struct drm_bridge_state * -+drm_atomic_helper_bridge_duplicate_state(struct drm_bridge *bridge) -+{ -+ struct drm_bridge_state *new; -+ -+ if (WARN_ON(!bridge->base.state)) -+ return NULL; -+ -+ new = kzalloc(sizeof(*new), GFP_KERNEL); -+ if (new) -+ __drm_atomic_helper_bridge_duplicate_state(bridge, new); -+ -+ return new; -+} -+EXPORT_SYMBOL(drm_atomic_helper_bridge_duplicate_state); -+ - #ifdef CONFIG_OF - /** - * of_drm_find_bridge - find the bridge corresponding to the device node in -diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h -index 951dfb15c27b..ccce65e14917 100644 ---- a/include/drm/drm_atomic.h -+++ b/include/drm/drm_atomic.h -@@ -669,6 +669,9 @@ __drm_atomic_get_current_plane_state(struct drm_atomic_state *state, - return plane->state; - } - -+int __must_check -+drm_atomic_add_encoder_bridges(struct drm_atomic_state *state, -+ struct drm_encoder *encoder); - int __must_check - drm_atomic_add_affected_connectors(struct drm_atomic_state *state, - struct drm_crtc *crtc); -diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h -index 694e153a7531..8a926c1a08db 100644 ---- a/include/drm/drm_bridge.h -+++ b/include/drm/drm_bridge.h -@@ -25,6 +25,8 @@ - - #include - #include -+ -+#include - #include - #include - #include -@@ -33,6 +35,23 @@ struct drm_bridge; - struct drm_bridge_timings; - struct drm_panel; - -+/** -+ * struct drm_bridge_state - Atomic bridge state object -+ * @base: inherit from &drm_private_state -+ * @bridge: the bridge this state refers to -+ */ -+struct drm_bridge_state { -+ struct drm_private_state base; -+ -+ struct drm_bridge *bridge; -+}; -+ -+static inline struct drm_bridge_state * -+drm_priv_to_bridge_state(struct drm_private_state *priv) -+{ -+ return container_of(priv, struct drm_bridge_state, base); -+} -+ - /** - * struct drm_bridge_funcs - drm_bridge control functions - */ -@@ -338,6 +357,49 @@ struct drm_bridge_funcs { - */ - void (*atomic_post_disable)(struct drm_bridge *bridge, - struct drm_atomic_state *old_state); -+ -+ /** -+ * @atomic_duplicate_state: -+ * -+ * Duplicate the current bridge state object (which is guaranteed to be -+ * non-NULL). -+ * -+ * The atomic_duplicate_state() is optional. When not implemented the -+ * core allocates a drm_bridge_state object and calls -+ * &__drm_atomic_helper_bridge_duplicate_state() to initialize it. -+ * -+ * RETURNS: -+ * A valid drm_bridge_state object or NULL if the allocation fails. -+ */ -+ struct drm_bridge_state *(*atomic_duplicate_state)(struct drm_bridge *bridge); -+ -+ /** -+ * @atomic_destroy_state: -+ * -+ * Destroy a bridge state object previously allocated by -+ * &drm_bridge_funcs.atomic_duplicate_state(). -+ * -+ * The atomic_destroy_state hook is optional. When not implemented the -+ * core calls kfree() on the state. -+ */ -+ void (*atomic_destroy_state)(struct drm_bridge *bridge, -+ struct drm_bridge_state *state); -+ -+ /** -+ * @atomic_reset: -+ * -+ * Reset the bridge to a predefined state (or retrieve its current -+ * state) and return a &drm_bridge_state object matching this state. -+ * This function is called at attach time. -+ * -+ * The atomic_reset hook is optional. When not implemented the core -+ * allocates a new state and calls &__drm_atomic_helper_bridge_reset(). -+ * -+ * RETURNS: -+ * A valid drm_bridge_state object in case of success, an ERR_PTR() -+ * giving the reason of the failure otherwise. -+ */ -+ struct drm_bridge_state *(*atomic_reset)(struct drm_bridge *bridge); - }; - - /** -@@ -380,6 +442,8 @@ struct drm_bridge_timings { - * struct drm_bridge - central DRM bridge control structure - */ - struct drm_bridge { -+ /** @base: inherit from &drm_private_object */ -+ struct drm_private_obj base; - /** @dev: DRM device this bridge belongs to */ - struct drm_device *dev; - /** @encoder: encoder to which this bridge is connected */ -@@ -404,6 +468,12 @@ struct drm_bridge { - void *driver_private; - }; - -+static inline struct drm_bridge * -+drm_priv_to_bridge(struct drm_private_obj *priv) -+{ -+ return container_of(priv, struct drm_bridge, base); -+} -+ - void drm_bridge_add(struct drm_bridge *bridge); - void drm_bridge_remove(struct drm_bridge *bridge); - struct drm_bridge *of_drm_find_bridge(struct device_node *np); -@@ -491,6 +561,56 @@ void drm_atomic_bridge_chain_pre_enable(struct drm_bridge *bridge, - void drm_atomic_bridge_chain_enable(struct drm_bridge *bridge, - struct drm_atomic_state *state); - -+void __drm_atomic_helper_bridge_reset(struct drm_bridge *bridge, -+ struct drm_bridge_state *state); -+void drm_atomic_helper_bridge_destroy_state(struct drm_bridge *bridge, -+ struct drm_bridge_state *state); -+struct drm_bridge_state * -+drm_atomic_helper_bridge_reset(struct drm_bridge *bridge); -+void __drm_atomic_helper_bridge_duplicate_state(struct drm_bridge *bridge, -+ struct drm_bridge_state *new); -+struct drm_bridge_state * -+drm_atomic_helper_bridge_duplicate_state(struct drm_bridge *bridge); -+ -+static inline struct drm_bridge_state * -+drm_atomic_get_bridge_state(struct drm_atomic_state *state, -+ struct drm_bridge *bridge) -+{ -+ struct drm_private_state *obj_state; -+ -+ obj_state = drm_atomic_get_private_obj_state(state, &bridge->base); -+ if (IS_ERR(obj_state)) -+ return ERR_CAST(obj_state); -+ -+ return drm_priv_to_bridge_state(obj_state); -+} -+ -+static inline struct drm_bridge_state * -+drm_atomic_get_old_bridge_state(struct drm_atomic_state *state, -+ struct drm_bridge *bridge) -+{ -+ struct drm_private_state *obj_state; -+ -+ obj_state = drm_atomic_get_old_private_obj_state(state, &bridge->base); -+ if (!obj_state) -+ return NULL; -+ -+ return drm_priv_to_bridge_state(obj_state); -+} -+ -+static inline struct drm_bridge_state * -+drm_atomic_get_new_bridge_state(struct drm_atomic_state *state, -+ struct drm_bridge *bridge) -+{ -+ struct drm_private_state *obj_state; -+ -+ obj_state = drm_atomic_get_new_private_obj_state(state, &bridge->base); -+ if (!obj_state) -+ return NULL; -+ -+ return drm_priv_to_bridge_state(obj_state); -+} -+ - #ifdef CONFIG_DRM_PANEL_BRIDGE - struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel); - struct drm_bridge *drm_panel_bridge_add_typed(struct drm_panel *panel, --- -2.17.1 - - -From 7b00bdecec40941c08461791cdc3ebfe766ffb15 Mon Sep 17 00:00:00 2001 -From: Boris Brezillon -Date: Thu, 19 Dec 2019 11:11:49 +0100 -Subject: [PATCH] drm/bridge: Patch atomic hooks to take a drm_bridge_state - -This way the drm_bridge_funcs interface is consistent with the rest of -the subsystem. - -The only driver implementing those hooks (analogix DP) is patched too. - -Signed-off-by: Boris Brezillon -Reviewed-by: Laurent Pinchart -Signed-off-by: Neil Armstrong ---- - .../drm/bridge/analogix/analogix_dp_core.c | 41 +++++++------ - drivers/gpu/drm/drm_bridge.c | 61 +++++++++++++++---- - include/drm/drm_bridge.h | 8 +-- - 3 files changed, 77 insertions(+), 33 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c -index 6effe532f820..6fab71985cd4 100644 ---- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c -+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c -@@ -1289,19 +1289,21 @@ struct drm_crtc *analogix_dp_get_new_crtc(struct analogix_dp_device *dp, - return conn_state->crtc; - } - --static void analogix_dp_bridge_atomic_pre_enable(struct drm_bridge *bridge, -- struct drm_atomic_state *state) -+static void -+analogix_dp_bridge_atomic_pre_enable(struct drm_bridge *bridge, -+ struct drm_bridge_state *old_bridge_state) - { -+ struct drm_atomic_state *old_state = old_bridge_state->base.state; - struct analogix_dp_device *dp = bridge->driver_private; - struct drm_crtc *crtc; - struct drm_crtc_state *old_crtc_state; - int ret; - -- crtc = analogix_dp_get_new_crtc(dp, state); -+ crtc = analogix_dp_get_new_crtc(dp, old_state); - if (!crtc) - return; - -- old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc); -+ old_crtc_state = drm_atomic_get_old_crtc_state(old_state, crtc); - /* Don't touch the panel if we're coming back from PSR */ - if (old_crtc_state && old_crtc_state->self_refresh_active) - return; -@@ -1366,20 +1368,22 @@ static int analogix_dp_set_bridge(struct analogix_dp_device *dp) - return ret; - } - --static void analogix_dp_bridge_atomic_enable(struct drm_bridge *bridge, -- struct drm_atomic_state *state) -+static void -+analogix_dp_bridge_atomic_enable(struct drm_bridge *bridge, -+ struct drm_bridge_state *old_bridge_state) - { -+ struct drm_atomic_state *old_state = old_bridge_state->base.state; - struct analogix_dp_device *dp = bridge->driver_private; - struct drm_crtc *crtc; - struct drm_crtc_state *old_crtc_state; - int timeout_loop = 0; - int ret; - -- crtc = analogix_dp_get_new_crtc(dp, state); -+ crtc = analogix_dp_get_new_crtc(dp, old_state); - if (!crtc) - return; - -- old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc); -+ old_crtc_state = drm_atomic_get_old_crtc_state(old_state, crtc); - /* Not a full enable, just disable PSR and continue */ - if (old_crtc_state && old_crtc_state->self_refresh_active) { - ret = analogix_dp_disable_psr(dp); -@@ -1440,18 +1444,20 @@ static void analogix_dp_bridge_disable(struct drm_bridge *bridge) - dp->dpms_mode = DRM_MODE_DPMS_OFF; - } - --static void analogix_dp_bridge_atomic_disable(struct drm_bridge *bridge, -- struct drm_atomic_state *state) -+static void -+analogix_dp_bridge_atomic_disable(struct drm_bridge *bridge, -+ struct drm_bridge_state *old_bridge_state) - { -+ struct drm_atomic_state *old_state = old_bridge_state->base.state; - struct analogix_dp_device *dp = bridge->driver_private; - struct drm_crtc *crtc; - struct drm_crtc_state *new_crtc_state = NULL; - -- crtc = analogix_dp_get_new_crtc(dp, state); -+ crtc = analogix_dp_get_new_crtc(dp, old_state); - if (!crtc) - goto out; - -- new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc); -+ new_crtc_state = drm_atomic_get_new_crtc_state(old_state, crtc); - if (!new_crtc_state) - goto out; - -@@ -1463,20 +1469,21 @@ static void analogix_dp_bridge_atomic_disable(struct drm_bridge *bridge, - analogix_dp_bridge_disable(bridge); - } - --static --void analogix_dp_bridge_atomic_post_disable(struct drm_bridge *bridge, -- struct drm_atomic_state *state) -+static void -+analogix_dp_bridge_atomic_post_disable(struct drm_bridge *bridge, -+ struct drm_bridge_state *old_bridge_state) - { -+ struct drm_atomic_state *old_state = old_bridge_state->base.state; - struct analogix_dp_device *dp = bridge->driver_private; - struct drm_crtc *crtc; - struct drm_crtc_state *new_crtc_state; - int ret; - -- crtc = analogix_dp_get_new_crtc(dp, state); -+ crtc = analogix_dp_get_new_crtc(dp, old_state); - if (!crtc) - return; - -- new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc); -+ new_crtc_state = drm_atomic_get_new_crtc_state(old_state, crtc); - if (!new_crtc_state || !new_crtc_state->self_refresh_active) - return; - -diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c -index a3921b45f044..6bdc4ab789c9 100644 ---- a/drivers/gpu/drm/drm_bridge.c -+++ b/drivers/gpu/drm/drm_bridge.c -@@ -465,10 +465,19 @@ void drm_atomic_bridge_chain_disable(struct drm_bridge *bridge, - - encoder = bridge->encoder; - list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) { -- if (iter->funcs->atomic_disable) -- iter->funcs->atomic_disable(iter, old_state); -- else if (iter->funcs->disable) -+ if (iter->funcs->atomic_disable) { -+ struct drm_bridge_state *old_bridge_state; -+ -+ old_bridge_state = -+ drm_atomic_get_old_bridge_state(old_state, -+ iter); -+ if (WARN_ON(!old_bridge_state)) -+ return; -+ -+ iter->funcs->atomic_disable(iter, old_bridge_state); -+ } else if (iter->funcs->disable) { - iter->funcs->disable(iter); -+ } - - if (iter == bridge) - break; -@@ -499,10 +508,20 @@ void drm_atomic_bridge_chain_post_disable(struct drm_bridge *bridge, - - encoder = bridge->encoder; - list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) { -- if (bridge->funcs->atomic_post_disable) -- bridge->funcs->atomic_post_disable(bridge, old_state); -- else if (bridge->funcs->post_disable) -+ if (bridge->funcs->atomic_post_disable) { -+ struct drm_bridge_state *old_bridge_state; -+ -+ old_bridge_state = -+ drm_atomic_get_old_bridge_state(old_state, -+ bridge); -+ if (WARN_ON(!old_bridge_state)) -+ return; -+ -+ bridge->funcs->atomic_post_disable(bridge, -+ old_bridge_state); -+ } else if (bridge->funcs->post_disable) { - bridge->funcs->post_disable(bridge); -+ } - } - } - EXPORT_SYMBOL(drm_atomic_bridge_chain_post_disable); -@@ -531,10 +550,19 @@ void drm_atomic_bridge_chain_pre_enable(struct drm_bridge *bridge, - - encoder = bridge->encoder; - list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) { -- if (iter->funcs->atomic_pre_enable) -- iter->funcs->atomic_pre_enable(iter, old_state); -- else if (iter->funcs->pre_enable) -+ if (iter->funcs->atomic_pre_enable) { -+ struct drm_bridge_state *old_bridge_state; -+ -+ old_bridge_state = -+ drm_atomic_get_old_bridge_state(old_state, -+ iter); -+ if (WARN_ON(!old_bridge_state)) -+ return; -+ -+ iter->funcs->atomic_pre_enable(iter, old_bridge_state); -+ } else if (iter->funcs->pre_enable) { - iter->funcs->pre_enable(iter); -+ } - - if (iter == bridge) - break; -@@ -564,10 +592,19 @@ void drm_atomic_bridge_chain_enable(struct drm_bridge *bridge, - - encoder = bridge->encoder; - list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) { -- if (bridge->funcs->atomic_enable) -- bridge->funcs->atomic_enable(bridge, old_state); -- else if (bridge->funcs->enable) -+ if (bridge->funcs->atomic_enable) { -+ struct drm_bridge_state *old_bridge_state; -+ -+ old_bridge_state = -+ drm_atomic_get_old_bridge_state(old_state, -+ bridge); -+ if (WARN_ON(!old_bridge_state)) -+ return; -+ -+ bridge->funcs->atomic_enable(bridge, old_bridge_state); -+ } else if (bridge->funcs->enable) { - bridge->funcs->enable(bridge); -+ } - } - } - EXPORT_SYMBOL(drm_atomic_bridge_chain_enable); -diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h -index 8a926c1a08db..0331e330635b 100644 ---- a/include/drm/drm_bridge.h -+++ b/include/drm/drm_bridge.h -@@ -282,7 +282,7 @@ struct drm_bridge_funcs { - * The @atomic_pre_enable callback is optional. - */ - void (*atomic_pre_enable)(struct drm_bridge *bridge, -- struct drm_atomic_state *old_state); -+ struct drm_bridge_state *old_bridge_state); - - /** - * @atomic_enable: -@@ -307,7 +307,7 @@ struct drm_bridge_funcs { - * The @atomic_enable callback is optional. - */ - void (*atomic_enable)(struct drm_bridge *bridge, -- struct drm_atomic_state *old_state); -+ struct drm_bridge_state *old_bridge_state); - /** - * @atomic_disable: - * -@@ -330,7 +330,7 @@ struct drm_bridge_funcs { - * The @atomic_disable callback is optional. - */ - void (*atomic_disable)(struct drm_bridge *bridge, -- struct drm_atomic_state *old_state); -+ struct drm_bridge_state *old_bridge_state); - - /** - * @atomic_post_disable: -@@ -356,7 +356,7 @@ struct drm_bridge_funcs { - * The @atomic_post_disable callback is optional. - */ - void (*atomic_post_disable)(struct drm_bridge *bridge, -- struct drm_atomic_state *old_state); -+ struct drm_bridge_state *old_bridge_state); - - /** - * @atomic_duplicate_state: --- -2.17.1 - - -From 7891bb247f22d65b57b84efb5cadaae13114236b Mon Sep 17 00:00:00 2001 -From: Boris Brezillon -Date: Thu, 19 Dec 2019 11:11:50 +0100 -Subject: [PATCH] drm/bridge: Add an ->atomic_check() hook - -So that bridge drivers have a way to check/reject an atomic operation. -The drm_atomic_bridge_chain_check() (which is just a wrapper around -the ->atomic_check() hook) is called in place of -drm_bridge_chain_mode_fixup() (when ->atomic_check() is not implemented, -the core falls back on ->mode_fixup(), so the behavior should stay -the same for existing bridge drivers). - -Signed-off-by: Boris Brezillon -Reviewed-by: Neil Armstrong -Reviewed-by: Laurent Pinchart -Signed-off-by: Neil Armstrong ---- - drivers/gpu/drm/drm_atomic_helper.c | 12 +++--- - drivers/gpu/drm/drm_bridge.c | 62 +++++++++++++++++++++++++++++ - include/drm/drm_bridge.h | 29 +++++++++++++- - 3 files changed, 96 insertions(+), 7 deletions(-) - -diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c -index ad8eae98d9e8..afe14f72a824 100644 ---- a/drivers/gpu/drm/drm_atomic_helper.c -+++ b/drivers/gpu/drm/drm_atomic_helper.c -@@ -437,12 +437,12 @@ mode_fixup(struct drm_atomic_state *state) - funcs = encoder->helper_private; - - bridge = drm_bridge_chain_get_first_bridge(encoder); -- ret = drm_bridge_chain_mode_fixup(bridge, -- &new_crtc_state->mode, -- &new_crtc_state->adjusted_mode); -- if (!ret) { -- DRM_DEBUG_ATOMIC("Bridge fixup failed\n"); -- return -EINVAL; -+ ret = drm_atomic_bridge_chain_check(bridge, -+ new_crtc_state, -+ new_conn_state); -+ if (ret) { -+ DRM_DEBUG_ATOMIC("Bridge atomic check failed\n"); -+ return ret; - } - - if (funcs && funcs->atomic_check) { -diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c -index 6bdc4ab789c9..442804598f60 100644 ---- a/drivers/gpu/drm/drm_bridge.c -+++ b/drivers/gpu/drm/drm_bridge.c -@@ -609,6 +609,68 @@ void drm_atomic_bridge_chain_enable(struct drm_bridge *bridge, - } - EXPORT_SYMBOL(drm_atomic_bridge_chain_enable); - -+static int drm_atomic_bridge_check(struct drm_bridge *bridge, -+ struct drm_crtc_state *crtc_state, -+ struct drm_connector_state *conn_state) -+{ -+ if (bridge->funcs->atomic_check) { -+ struct drm_bridge_state *bridge_state; -+ int ret; -+ -+ bridge_state = drm_atomic_get_new_bridge_state(crtc_state->state, -+ bridge); -+ if (WARN_ON(!bridge_state)) -+ return -EINVAL; -+ -+ ret = bridge->funcs->atomic_check(bridge, bridge_state, -+ crtc_state, conn_state); -+ if (ret) -+ return ret; -+ } else if (bridge->funcs->mode_fixup) { -+ if (!bridge->funcs->mode_fixup(bridge, &crtc_state->mode, -+ &crtc_state->adjusted_mode)) -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+/** -+ * drm_atomic_bridge_chain_check() - Do an atomic check on the bridge chain -+ * @bridge: bridge control structure -+ * @crtc_state: new CRTC state -+ * @conn_state: new connector state -+ * -+ * Calls &drm_bridge_funcs.atomic_check() (falls back on -+ * &drm_bridge_funcs.mode_fixup()) op for all the bridges in the encoder chain, -+ * starting from the last bridge to the first. These are called before calling -+ * &drm_encoder_helper_funcs.atomic_check() -+ * -+ * RETURNS: -+ * 0 on success, a negative error code on failure -+ */ -+int drm_atomic_bridge_chain_check(struct drm_bridge *bridge, -+ struct drm_crtc_state *crtc_state, -+ struct drm_connector_state *conn_state) -+{ -+ struct drm_encoder *encoder = bridge->encoder; -+ struct drm_bridge *iter; -+ -+ list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) { -+ int ret; -+ -+ ret = drm_atomic_bridge_check(iter, crtc_state, conn_state); -+ if (ret) -+ return ret; -+ -+ if (iter == bridge) -+ break; -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL(drm_atomic_bridge_chain_check); -+ - /** - * drm_atomic_helper_bridge_destroy_state() - Default destroy state helper - * @bridge: the bridge this state refers to -diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h -index 0331e330635b..269f0d1da339 100644 ---- a/include/drm/drm_bridge.h -+++ b/include/drm/drm_bridge.h -@@ -128,7 +128,9 @@ struct drm_bridge_funcs { - * this function passes all other callbacks must succeed for this - * configuration. - * -- * The @mode_fixup callback is optional. -+ * The mode_fixup callback is optional. &drm_bridge_funcs.mode_fixup() -+ * is not called when &drm_bridge_funcs.atomic_check() is implemented, -+ * so only one of them should be provided. - * - * NOTE: - * -@@ -385,6 +387,28 @@ struct drm_bridge_funcs { - void (*atomic_destroy_state)(struct drm_bridge *bridge, - struct drm_bridge_state *state); - -+ /** -+ * @atomic_check: -+ * -+ * This method is responsible for checking bridge state correctness. -+ * It can also check the state of the surrounding components in chain -+ * to make sure the whole pipeline can work properly. -+ * -+ * &drm_bridge_funcs.atomic_check() hooks are called in reverse -+ * order (from the last to the first bridge). -+ * -+ * This method is optional. &drm_bridge_funcs.mode_fixup() is not -+ * called when &drm_bridge_funcs.atomic_check() is implemented, so only -+ * one of them should be provided. -+ * -+ * RETURNS: -+ * zero if the check passed, a negative error code otherwise. -+ */ -+ int (*atomic_check)(struct drm_bridge *bridge, -+ struct drm_bridge_state *bridge_state, -+ struct drm_crtc_state *crtc_state, -+ struct drm_connector_state *conn_state); -+ - /** - * @atomic_reset: - * -@@ -552,6 +576,9 @@ void drm_bridge_chain_mode_set(struct drm_bridge *bridge, - void drm_bridge_chain_pre_enable(struct drm_bridge *bridge); - void drm_bridge_chain_enable(struct drm_bridge *bridge); - -+int drm_atomic_bridge_chain_check(struct drm_bridge *bridge, -+ struct drm_crtc_state *crtc_state, -+ struct drm_connector_state *conn_state); - void drm_atomic_bridge_chain_disable(struct drm_bridge *bridge, - struct drm_atomic_state *state); - void drm_atomic_bridge_chain_post_disable(struct drm_bridge *bridge, --- -2.17.1 - - -From 08c9023ffcdae0022fe84dac4e12efc6f989c6c8 Mon Sep 17 00:00:00 2001 -From: Boris Brezillon -Date: Thu, 19 Dec 2019 11:11:51 +0100 -Subject: [PATCH] drm/bridge: Add the necessary bits to support bus format - negotiation - -drm_bridge_state is extended to describe the input and output bus -configurations. These bus configurations are exposed through the -drm_bus_cfg struct which encodes the configuration of a physical -bus between two components in an output pipeline, usually between -two bridges, an encoder and a bridge, or a bridge and a connector. - -The bus configuration is stored in drm_bridge_state separately for -the input and output buses, as seen from the point of view of each -bridge. The bus configuration of a bridge output is usually identical -to the configuration of the next bridge's input, but may differ if -the signals are modified between the two bridges, for instance by an -inverter on the board. The input and output configurations of a -bridge may differ if the bridge modifies the signals internally, -for instance by performing format conversion, or*modifying signals -polarities. - -Bus format negotiation is automated by the core, drivers just have -to implement the ->atomic_get_{output,input}_bus_fmts() hooks if they -want to take part to this negotiation. Negotiation happens in reverse -order, starting from the last element of the chain (the one directly -connected to the display) up to the first element of the chain (the one -connected to the encoder). -During this negotiation all supported formats are tested until we find -one that works, meaning that the formats array should be in decreasing -preference order (assuming the driver has a preference order). - -Note that the bus format negotiation works even if some elements in the -chain don't implement the ->atomic_get_{output,input}_bus_fmts() hooks. -In that case, the core advertises only MEDIA_BUS_FMT_FIXED and lets -the previous bridge element decide what to do (most of the time, bridge -drivers will pick a default bus format or extract this piece of -information from somewhere else, like a FW property). - -Signed-off-by: Boris Brezillon -Signed-off-by: Neil Armstrong ---- - drivers/gpu/drm/drm_bridge.c | 267 ++++++++++++++++++++++++++++++++++- - include/drm/drm_bridge.h | 124 ++++++++++++++++ - 2 files changed, 390 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c -index 442804598f60..9cc4b0181f85 100644 ---- a/drivers/gpu/drm/drm_bridge.c -+++ b/drivers/gpu/drm/drm_bridge.c -@@ -635,13 +635,261 @@ static int drm_atomic_bridge_check(struct drm_bridge *bridge, - return 0; - } - -+/** -+ * drm_atomic_helper_bridge_propagate_bus_fmt() - Propagate output format to -+ * the input end of a bridge -+ * @bridge: bridge control structure -+ * @bridge_state: new bridge state -+ * @crtc_state: new CRTC state -+ * @conn_state: new connector state -+ * @output_fmt: tested output bus format -+ * @num_input_fmts: will contain the size of the returned array -+ * -+ * This helper is a pluggable implementation of the -+ * &drm_bridge_funcs.atomic_get_input_bus_fmts operation for bridges that don't -+ * modify the bus configuration between their input and their output. It -+ * returns an array of input formats with a single element set to @output_fmt. -+ * -+ * RETURNS: -+ * a valid format array of size @num_input_fmts, or NULL if the allocation -+ * failed -+ */ -+u32 * -+drm_atomic_helper_bridge_propagate_bus_fmt(struct drm_bridge *bridge, -+ struct drm_bridge_state *bridge_state, -+ struct drm_crtc_state *crtc_state, -+ struct drm_connector_state *conn_state, -+ u32 output_fmt, -+ unsigned int *num_input_fmts) -+{ -+ u32 *input_fmts; -+ -+ input_fmts = kzalloc(sizeof(*input_fmts), GFP_KERNEL); -+ if (!input_fmts) { -+ *num_input_fmts = 0; -+ return NULL; -+ } -+ -+ *num_input_fmts = 1; -+ input_fmts[0] = output_fmt; -+ return input_fmts; -+} -+EXPORT_SYMBOL(drm_atomic_helper_bridge_propagate_bus_fmt); -+ -+static int select_bus_fmt_recursive(struct drm_bridge *first_bridge, -+ struct drm_bridge *cur_bridge, -+ struct drm_crtc_state *crtc_state, -+ struct drm_connector_state *conn_state, -+ u32 out_bus_fmt) -+{ -+ struct drm_bridge_state *cur_state; -+ unsigned int num_in_bus_fmts, i; -+ struct drm_bridge *prev_bridge; -+ u32 *in_bus_fmts; -+ int ret; -+ -+ prev_bridge = drm_bridge_get_prev_bridge(cur_bridge); -+ cur_state = drm_atomic_get_new_bridge_state(crtc_state->state, -+ cur_bridge); -+ if (WARN_ON(!cur_state)) -+ return -EINVAL; -+ -+ /* -+ * If bus format negotiation is not supported by this bridge, let's -+ * pass MEDIA_BUS_FMT_FIXED to the previous bridge in the chain and -+ * hope that it can handle this situation gracefully (by providing -+ * appropriate default values). -+ */ -+ if (!cur_bridge->funcs->atomic_get_input_bus_fmts) { -+ if (cur_bridge != first_bridge) { -+ ret = select_bus_fmt_recursive(first_bridge, -+ prev_bridge, crtc_state, -+ conn_state, -+ MEDIA_BUS_FMT_FIXED); -+ if (ret) -+ return ret; -+ } -+ -+ cur_state->input_bus_cfg.format = MEDIA_BUS_FMT_FIXED; -+ cur_state->output_bus_cfg.format = out_bus_fmt; -+ return 0; -+ } -+ -+ in_bus_fmts = cur_bridge->funcs->atomic_get_input_bus_fmts(cur_bridge, -+ cur_state, -+ crtc_state, -+ conn_state, -+ out_bus_fmt, -+ &num_in_bus_fmts); -+ if (!num_in_bus_fmts) -+ return -ENOTSUPP; -+ else if (!in_bus_fmts) -+ return -ENOMEM; -+ -+ if (first_bridge == cur_bridge) { -+ cur_state->input_bus_cfg.format = in_bus_fmts[0]; -+ cur_state->output_bus_cfg.format = out_bus_fmt; -+ kfree(in_bus_fmts); -+ return 0; -+ } -+ -+ for (i = 0; i < num_in_bus_fmts; i++) { -+ ret = select_bus_fmt_recursive(first_bridge, prev_bridge, -+ crtc_state, conn_state, -+ in_bus_fmts[i]); -+ if (ret != -ENOTSUPP) -+ break; -+ } -+ -+ if (!ret) { -+ cur_state->input_bus_cfg.format = in_bus_fmts[i]; -+ cur_state->output_bus_cfg.format = out_bus_fmt; -+ } -+ -+ kfree(in_bus_fmts); -+ return ret; -+} -+ -+/* -+ * This function is called by &drm_atomic_bridge_chain_check() just before -+ * calling &drm_bridge_funcs.atomic_check() on all elements of the chain. -+ * It performs bus format negotiation between bridge elements. The negotiation -+ * happens in reverse order, starting from the last element in the chain up to -+ * @bridge. -+ * -+ * Negotiation starts by retrieving supported output bus formats on the last -+ * bridge element and testing them one by one. The test is recursive, meaning -+ * that for each tested output format, the whole chain will be walked backward, -+ * and each element will have to choose an input bus format that can be -+ * transcoded to the requested output format. When a bridge element does not -+ * support transcoding into a specific output format -ENOTSUPP is returned and -+ * the next bridge element will have to try a different format. If none of the -+ * combinations worked, -ENOTSUPP is returned and the atomic modeset will fail. -+ * -+ * This implementation is relying on -+ * &drm_bridge_funcs.atomic_get_output_bus_fmts() and -+ * &drm_bridge_funcs.atomic_get_input_bus_fmts() to gather supported -+ * input/output formats. -+ * -+ * When &drm_bridge_funcs.atomic_get_output_bus_fmts() is not implemented by -+ * the last element of the chain, &drm_atomic_bridge_chain_select_bus_fmts() -+ * tries a single format: &drm_connector.display_info.bus_formats[0] if -+ * available, MEDIA_BUS_FMT_FIXED otherwise. -+ * -+ * When &drm_bridge_funcs.atomic_get_input_bus_fmts() is not implemented, -+ * &drm_atomic_bridge_chain_select_bus_fmts() skips the negotiation on the -+ * bridge element that lacks this hook and asks the previous element in the -+ * chain to try MEDIA_BUS_FMT_FIXED. It's up to bridge drivers to decide what -+ * to do in that case (fail if they want to enforce bus format negotiation, or -+ * provide a reasonable default if they need to support pipelines where not -+ * all elements support bus format negotiation). -+ */ -+static int -+drm_atomic_bridge_chain_select_bus_fmts(struct drm_bridge *bridge, -+ struct drm_crtc_state *crtc_state, -+ struct drm_connector_state *conn_state) -+{ -+ struct drm_connector *conn = conn_state->connector; -+ struct drm_encoder *encoder = bridge->encoder; -+ struct drm_bridge_state *last_bridge_state; -+ unsigned int i, num_out_bus_fmts; -+ struct drm_bridge *last_bridge; -+ u32 *out_bus_fmts; -+ int ret = 0; -+ -+ last_bridge = list_last_entry(&encoder->bridge_chain, -+ struct drm_bridge, chain_node); -+ last_bridge_state = drm_atomic_get_new_bridge_state(crtc_state->state, -+ last_bridge); -+ if (WARN_ON(!last_bridge_state)) -+ return -EINVAL; -+ -+ if (last_bridge->funcs->atomic_get_output_bus_fmts) { -+ const struct drm_bridge_funcs *funcs = last_bridge->funcs; -+ -+ out_bus_fmts = funcs->atomic_get_output_bus_fmts(last_bridge, -+ last_bridge_state, -+ crtc_state, -+ conn_state, -+ &num_out_bus_fmts); -+ if (!num_out_bus_fmts) -+ return -ENOTSUPP; -+ else if (!out_bus_fmts) -+ return -ENOMEM; -+ } else { -+ num_out_bus_fmts = 1; -+ out_bus_fmts = kmalloc(sizeof(*out_bus_fmts), GFP_KERNEL); -+ if (!out_bus_fmts) -+ return -ENOMEM; -+ -+ if (conn->display_info.num_bus_formats && -+ conn->display_info.bus_formats) -+ out_bus_fmts[0] = conn->display_info.bus_formats[0]; -+ else -+ out_bus_fmts[0] = MEDIA_BUS_FMT_FIXED; -+ } -+ -+ for (i = 0; i < num_out_bus_fmts; i++) { -+ ret = select_bus_fmt_recursive(bridge, last_bridge, crtc_state, -+ conn_state, out_bus_fmts[i]); -+ if (ret != -ENOTSUPP) -+ break; -+ } -+ -+ kfree(out_bus_fmts); -+ -+ return ret; -+} -+ -+static void -+drm_atomic_bridge_propagate_bus_flags(struct drm_bridge *bridge, -+ struct drm_connector *conn, -+ struct drm_atomic_state *state) -+{ -+ struct drm_bridge_state *bridge_state, *next_bridge_state; -+ struct drm_bridge *next_bridge; -+ u32 output_flags; -+ -+ bridge_state = drm_atomic_get_new_bridge_state(state, bridge); -+ next_bridge = drm_bridge_get_next_bridge(bridge); -+ -+ /* -+ * Let's try to apply the most common case here, that is, propagate -+ * display_info flags for the last bridge, and propagate the input -+ * flags of the next bridge element to the output end of the current -+ * bridge when the bridge is not the last one. -+ * There are exceptions to this rule, like when signal inversion is -+ * happening at the board level, but that's something drivers can deal -+ * with from their &drm_bridge_funcs.atomic_check() implementation by -+ * simply overriding the flags value we've set here. -+ */ -+ if (!next_bridge) { -+ output_flags = conn->display_info.bus_flags; -+ } else { -+ next_bridge_state = drm_atomic_get_new_bridge_state(state, -+ next_bridge); -+ output_flags = next_bridge_state->input_bus_cfg.flags; -+ } -+ -+ bridge_state->output_bus_cfg.flags = output_flags; -+ -+ /* -+ * Propage the output flags to the input end of the bridge. Again, it's -+ * not necessarily what all bridges want, but that's what most of them -+ * do, and by doing that by default we avoid forcing drivers to -+ * duplicate the "dummy propagation" logic. -+ */ -+ bridge_state->input_bus_cfg.flags = output_flags; -+} -+ - /** - * drm_atomic_bridge_chain_check() - Do an atomic check on the bridge chain - * @bridge: bridge control structure - * @crtc_state: new CRTC state - * @conn_state: new connector state - * -- * Calls &drm_bridge_funcs.atomic_check() (falls back on -+ * First trigger a bus format negotiation before calling -+ * &drm_bridge_funcs.atomic_check() (falls back on - * &drm_bridge_funcs.mode_fixup()) op for all the bridges in the encoder chain, - * starting from the last bridge to the first. These are called before calling - * &drm_encoder_helper_funcs.atomic_check() -@@ -653,12 +901,29 @@ int drm_atomic_bridge_chain_check(struct drm_bridge *bridge, - struct drm_crtc_state *crtc_state, - struct drm_connector_state *conn_state) - { -+ struct drm_connector *conn = conn_state->connector; - struct drm_encoder *encoder = bridge->encoder; - struct drm_bridge *iter; -+ int ret; -+ -+ ret = drm_atomic_bridge_chain_select_bus_fmts(bridge, crtc_state, -+ conn_state); -+ if (ret) -+ return ret; - - list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) { - int ret; - -+ /* -+ * Bus flags are propagated by default. If a bridge needs to -+ * tweak the input bus flags for any reason, it should happen -+ * in its &drm_bridge_funcs.atomic_check() implementation such -+ * that preceding bridges in the chain can propagate the new -+ * bus flags. -+ */ -+ drm_atomic_bridge_propagate_bus_flags(iter, conn, -+ crtc_state->state); -+ - ret = drm_atomic_bridge_check(iter, crtc_state, conn_state); - if (ret) - return ret; -diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h -index 269f0d1da339..192227f03d4b 100644 ---- a/include/drm/drm_bridge.h -+++ b/include/drm/drm_bridge.h -@@ -35,6 +35,38 @@ struct drm_bridge; - struct drm_bridge_timings; - struct drm_panel; - -+/** -+ * struct drm_bus_cfg - bus configuration -+ * -+ * This structure stores the configuration of a physical bus between two -+ * components in an output pipeline, usually between two bridges, an encoder -+ * and a bridge, or a bridge and a connector. -+ * -+ * The bus configuration is stored in &drm_bridge_state separately for the -+ * input and output buses, as seen from the point of view of each bridge. The -+ * bus configuration of a bridge output is usually identical to the -+ * configuration of the next bridge's input, but may differ if the signals are -+ * modified between the two bridges, for instance by an inverter on the board. -+ * The input and output configurations of a bridge may differ if the bridge -+ * modifies the signals internally, for instance by performing format -+ * conversion, or modifying signals polarities. -+ */ -+struct drm_bus_cfg { -+ /** -+ * @fmt: format used on this bus (one of the MEDIA_BUS_FMT_* format) -+ * -+ * This field should not be directly modified by drivers -+ * (&drm_atomic_bridge_chain_select_bus_fmts() takes care of the bus -+ * format negotiation). -+ */ -+ u32 format; -+ -+ /** -+ * @flags: DRM_BUS_* flags used on this bus -+ */ -+ u32 flags; -+}; -+ - /** - * struct drm_bridge_state - Atomic bridge state object - * @base: inherit from &drm_private_state -@@ -44,6 +76,16 @@ struct drm_bridge_state { - struct drm_private_state base; - - struct drm_bridge *bridge; -+ -+ /** -+ * @input_bus_cfg: input bus configuration -+ */ -+ struct drm_bus_cfg input_bus_cfg; -+ -+ /** -+ * @output_bus_cfg: input bus configuration -+ */ -+ struct drm_bus_cfg output_bus_cfg; - }; - - static inline struct drm_bridge_state * -@@ -387,6 +429,72 @@ struct drm_bridge_funcs { - void (*atomic_destroy_state)(struct drm_bridge *bridge, - struct drm_bridge_state *state); - -+ /** -+ * @atomic_get_output_bus_fmts: -+ * -+ * Return the supported bus formats on the output end of a bridge. -+ * The returned array must be allocated with kmalloc() and will be -+ * freed by the caller. If the allocation fails, NULL should be -+ * returned. num_output_fmts must be set to the returned array size. -+ * Formats listed in the returned array should be listed in decreasing -+ * preference order (the core will try all formats until it finds one -+ * that works). -+ * -+ * This method is only called on the last element of the bridge chain -+ * as part of the bus format negotiation process that happens in -+ * &drm_atomic_bridge_chain_select_bus_fmts(). -+ * This method is optional. When not implemented, the core will -+ * fall back to &drm_connector.display_info.bus_formats[0] if -+ * &drm_connector.display_info.num_bus_formats > 0, -+ * or to MEDIA_BUS_FMT_FIXED otherwise. -+ */ -+ u32 *(*atomic_get_output_bus_fmts)(struct drm_bridge *bridge, -+ struct drm_bridge_state *bridge_state, -+ struct drm_crtc_state *crtc_state, -+ struct drm_connector_state *conn_state, -+ unsigned int *num_output_fmts); -+ -+ /** -+ * @atomic_get_input_bus_fmts: -+ * -+ * Return the supported bus formats on the input end of a bridge for -+ * a specific output bus format. -+ * -+ * The returned array must be allocated with kmalloc() and will be -+ * freed by the caller. If the allocation fails, NULL should be -+ * returned. num_output_fmts must be set to the returned array size. -+ * Formats listed in the returned array should be listed in decreasing -+ * preference order (the core will try all formats until it finds one -+ * that works). When the format is not supported NULL should be -+ * returned and *num_output_fmts should be set to 0. -+ * -+ * This method is called on all elements of the bridge chain as part of -+ * the bus format negotiation process that happens in -+ * &drm_atomic_bridge_chain_select_bus_fmts(). -+ * This method is optional. When not implemented, the core will bypass -+ * bus format negotiation on this element of the bridge without -+ * failing, and the previous element in the chain will be passed -+ * MEDIA_BUS_FMT_FIXED as its output bus format. -+ * -+ * Bridge drivers that need to support being linked to bridges that are -+ * not supporting bus format negotiation should handle the -+ * output_fmt == MEDIA_BUS_FMT_FIXED case appropriately, by selecting a -+ * sensible default value or extracting this information from somewhere -+ * else (FW property, &drm_display_mode, &drm_display_info, ...) -+ * -+ * Note: Even if input format selection on the first bridge has no -+ * impact on the negotiation process (bus format negotiation stops once -+ * we reach the first element of the chain), drivers are expected to -+ * return accurate input formats as the input format may be used to -+ * configure the CRTC output appropriately. -+ */ -+ u32 *(*atomic_get_input_bus_fmts)(struct drm_bridge *bridge, -+ struct drm_bridge_state *bridge_state, -+ struct drm_crtc_state *crtc_state, -+ struct drm_connector_state *conn_state, -+ u32 output_fmt, -+ unsigned int *num_input_fmts); -+ - /** - * @atomic_check: - * -@@ -401,6 +509,14 @@ struct drm_bridge_funcs { - * called when &drm_bridge_funcs.atomic_check() is implemented, so only - * one of them should be provided. - * -+ * If drivers need to tweak &drm_bridge_state.input_bus_cfg.flags or -+ * &drm_bridge_state.output_bus_cfg.flags it should should happen in -+ * this function. By default the &drm_bridge_state.output_bus_cfg.flags -+ * field is set to the next bridge -+ * &drm_bridge_state.input_bus_cfg.flags value or -+ * &drm_connector.display_info.bus_flags if the bridge is the last -+ * element in the chain. -+ * - * RETURNS: - * zero if the check passed, a negative error code otherwise. - */ -@@ -588,6 +704,14 @@ void drm_atomic_bridge_chain_pre_enable(struct drm_bridge *bridge, - void drm_atomic_bridge_chain_enable(struct drm_bridge *bridge, - struct drm_atomic_state *state); - -+u32 * -+drm_atomic_helper_bridge_propagate_bus_fmt(struct drm_bridge *bridge, -+ struct drm_bridge_state *bridge_state, -+ struct drm_crtc_state *crtc_state, -+ struct drm_connector_state *conn_state, -+ u32 output_fmt, -+ unsigned int *num_input_fmts); -+ - void __drm_atomic_helper_bridge_reset(struct drm_bridge *bridge, - struct drm_bridge_state *state); - void drm_atomic_helper_bridge_destroy_state(struct drm_bridge *bridge, --- -2.17.1 - - -From 152ee505b889cb0f5bc3ad4af82b43a8f4f6562b Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Wed, 18 Dec 2019 16:46:28 +0100 -Subject: [PATCH] drm/bridge: dw-hdmi: set mtmdsclock for deep color - -Configure the correct mtmdsclock for deep colors to prepare support -for 10, 12 & 16bit output. - -Signed-off-by: Jonas Karlman -Signed-off-by: Neil Armstrong ---- - drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 17 +++++++++++++++++ - 1 file changed, 17 insertions(+) - -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -index 24965e53d351..b8b91d28f398 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -@@ -1824,9 +1824,26 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi, - - dev_dbg(hdmi->dev, "final pixclk = %d\n", vmode->mpixelclock); - -+ if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format)) { -+ switch (hdmi_bus_fmt_color_depth( -+ hdmi->hdmi_data.enc_out_bus_format)) { -+ case 16: -+ vmode->mtmdsclock = (u64)vmode->mpixelclock * 2; -+ break; -+ case 12: -+ vmode->mtmdsclock = (u64)vmode->mpixelclock * 3 / 2; -+ break; -+ case 10: -+ vmode->mtmdsclock = (u64)vmode->mpixelclock * 5 / 4; -+ break; -+ } -+ } -+ - if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format)) - vmode->mtmdsclock /= 2; - -+ dev_dbg(hdmi->dev, "final tmdsclk = %d\n", vmode->mtmdsclock); -+ - /* Set up HDMI_FC_INVIDCONF */ - inv_val = (hdmi->hdmi_data.hdcp_enable || - (dw_hdmi_support_scdc(hdmi) && --- -2.17.1 - - -From 7cc0932dda90b853ff45cbe43688d5888a81d0b7 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Wed, 18 Dec 2019 16:46:29 +0100 -Subject: [PATCH] drm/bridge: dw-hdmi: add max bpc connector property - -Add the max_bpc property to the dw-hdmi connector to prepare support -for 10, 12 & 16bit output support. - -Signed-off-by: Jonas Karlman -Signed-off-by: Neil Armstrong ---- - drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -index b8b91d28f398..8da173798ed4 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -@@ -2412,6 +2412,10 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge) - DRM_MODE_CONNECTOR_HDMIA, - hdmi->ddc); - -+ drm_atomic_helper_connector_reset(connector); -+ -+ drm_connector_attach_max_bpc_property(connector, 8, 16); -+ - if (hdmi->version >= 0x200a && hdmi->plat_data->use_drm_infoframe) - drm_object_attach_property(&connector->base, - connector->dev->mode_config.hdr_output_metadata_property, 0); --- -2.17.1 - - -From d38c69cb5bb12563a7a533ae5eb75453e736f85b Mon Sep 17 00:00:00 2001 -From: Neil Armstrong -Date: Wed, 18 Dec 2019 16:46:30 +0100 -Subject: [PATCH] drm/bridge: synopsys: dw-hdmi: add bus format negociation - -Add the atomic_get_output_bus_fmts, atomic_get_input_bus_fmts to negociate -the possible output and input formats for the current mode and monitor, -and use the negotiated formats in a basic atomic_check callback. - -Signed-off-by: Neil Armstrong ---- - drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 272 +++++++++++++++++++++- - 1 file changed, 268 insertions(+), 4 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -index 8da173798ed4..88da301dc086 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -@@ -2101,11 +2101,10 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode) - hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 0; - hdmi->hdmi_data.video_mode.mpixelrepetitioninput = 0; - -- /* TOFIX: Get input format from plat data or fallback to RGB888 */ - if (hdmi->plat_data->input_bus_format) - hdmi->hdmi_data.enc_in_bus_format = - hdmi->plat_data->input_bus_format; -- else -+ else if (hdmi->hdmi_data.enc_in_bus_format == MEDIA_BUS_FMT_FIXED) - hdmi->hdmi_data.enc_in_bus_format = MEDIA_BUS_FMT_RGB888_1X24; - - /* TOFIX: Get input encoding from plat data or fallback to none */ -@@ -2115,8 +2114,8 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode) - else - hdmi->hdmi_data.enc_in_encoding = V4L2_YCBCR_ENC_DEFAULT; - -- /* TOFIX: Default to RGB888 output format */ -- hdmi->hdmi_data.enc_out_bus_format = MEDIA_BUS_FMT_RGB888_1X24; -+ if (hdmi->hdmi_data.enc_out_bus_format == MEDIA_BUS_FMT_FIXED) -+ hdmi->hdmi_data.enc_out_bus_format = MEDIA_BUS_FMT_RGB888_1X24; - - hdmi->hdmi_data.pix_repet_factor = 0; - hdmi->hdmi_data.hdcp_enable = 0; -@@ -2394,6 +2393,267 @@ static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = - .atomic_check = dw_hdmi_connector_atomic_check, - }; - -+/* -+ * Possible output formats : -+ * - MEDIA_BUS_FMT_UYYVYY16_0_5X48, -+ * - MEDIA_BUS_FMT_UYYVYY12_0_5X36, -+ * - MEDIA_BUS_FMT_UYYVYY10_0_5X30, -+ * - MEDIA_BUS_FMT_UYYVYY8_0_5X24, -+ * - MEDIA_BUS_FMT_YUV16_1X48, -+ * - MEDIA_BUS_FMT_RGB161616_1X48, -+ * - MEDIA_BUS_FMT_UYVY12_1X24, -+ * - MEDIA_BUS_FMT_YUV12_1X36, -+ * - MEDIA_BUS_FMT_RGB121212_1X36, -+ * - MEDIA_BUS_FMT_UYVY10_1X20, -+ * - MEDIA_BUS_FMT_YUV10_1X30, -+ * - MEDIA_BUS_FMT_RGB101010_1X30, -+ * - MEDIA_BUS_FMT_UYVY8_1X16, -+ * - MEDIA_BUS_FMT_YUV8_1X24, -+ * - MEDIA_BUS_FMT_RGB888_1X24, -+ */ -+ -+/* Can return a maximum of 12 possible output formats for a mode/connector */ -+#define MAX_OUTPUT_SEL_FORMATS 12 -+ -+static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, -+ struct drm_bridge_state *bridge_state, -+ struct drm_crtc_state *crtc_state, -+ struct drm_connector_state *conn_state, -+ unsigned int *num_output_fmts) -+{ -+ struct drm_connector *conn = conn_state->connector; -+ struct drm_display_info *info = &conn->display_info; -+ struct drm_display_mode *mode = &crtc_state->mode; -+ u8 max_bpc = conn_state->max_requested_bpc; -+ bool is_hdmi2_sink = info->hdmi.scdc.supported || -+ (info->color_formats & DRM_COLOR_FORMAT_YCRCB420); -+ u32 *output_fmts; -+ int i = 0; -+ -+ *num_output_fmts = 0; -+ -+ output_fmts = kcalloc(MAX_OUTPUT_SEL_FORMATS, sizeof(*output_fmts), -+ GFP_KERNEL); -+ if (!output_fmts) -+ return NULL; -+ -+ /* -+ * If the current mode enforces 4:2:0, force the output but format -+ * to 4:2:0 and do not add the YUV422/444/RGB formats -+ */ -+ if (conn->ycbcr_420_allowed && -+ (drm_mode_is_420_only(info, mode) || -+ (is_hdmi2_sink && drm_mode_is_420_also(info, mode)))) { -+ -+ /* Order bus formats from 16bit to 8bit if supported */ -+ if (max_bpc >= 16 && info->bpc == 16 && -+ (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_48)) -+ output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY16_0_5X48; -+ -+ if (max_bpc >= 12 && info->bpc >= 12 && -+ (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_36)) -+ output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY12_0_5X36; -+ -+ if (max_bpc >= 10 && info->bpc >= 10 && -+ (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30)) -+ output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY10_0_5X30; -+ -+ /* Default 8bit fallback */ -+ output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY8_0_5X24; -+ -+ *num_output_fmts = i; -+ -+ return output_fmts; -+ } -+ -+ /* -+ * Order bus formats from 16bit to 8bit and from YUV422 to RGB -+ * if supported. In any case the default RGB888 format is added -+ */ -+ -+ if (max_bpc >= 16 && info->bpc == 16) { -+ if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444) -+ output_fmts[i++] = MEDIA_BUS_FMT_YUV16_1X48; -+ -+ output_fmts[i++] = MEDIA_BUS_FMT_RGB161616_1X48; -+ } -+ -+ if (max_bpc >= 12 && info->bpc >= 12) { -+ if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422) -+ output_fmts[i++] = MEDIA_BUS_FMT_UYVY12_1X24; -+ -+ if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444) -+ output_fmts[i++] = MEDIA_BUS_FMT_YUV12_1X36; -+ -+ output_fmts[i++] = MEDIA_BUS_FMT_RGB121212_1X36; -+ } -+ -+ if (max_bpc >= 10 && info->bpc >= 10) { -+ if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422) -+ output_fmts[i++] = MEDIA_BUS_FMT_UYVY10_1X20; -+ -+ if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444) -+ output_fmts[i++] = MEDIA_BUS_FMT_YUV10_1X30; -+ -+ output_fmts[i++] = MEDIA_BUS_FMT_RGB101010_1X30; -+ } -+ -+ if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422) -+ output_fmts[i++] = MEDIA_BUS_FMT_UYVY8_1X16; -+ -+ if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444) -+ output_fmts[i++] = MEDIA_BUS_FMT_YUV8_1X24; -+ -+ /* Default 8bit RGB fallback */ -+ output_fmts[i++] = MEDIA_BUS_FMT_RGB888_1X24; -+ -+ *num_output_fmts = i; -+ -+ return output_fmts; -+} -+ -+/* -+ * Possible input formats : -+ * - MEDIA_BUS_FMT_RGB888_1X24 -+ * - MEDIA_BUS_FMT_YUV8_1X24 -+ * - MEDIA_BUS_FMT_UYVY8_1X16 -+ * - MEDIA_BUS_FMT_UYYVYY8_0_5X24 -+ * - MEDIA_BUS_FMT_RGB101010_1X30 -+ * - MEDIA_BUS_FMT_YUV10_1X30 -+ * - MEDIA_BUS_FMT_UYVY10_1X20 -+ * - MEDIA_BUS_FMT_UYYVYY10_0_5X30 -+ * - MEDIA_BUS_FMT_RGB121212_1X36 -+ * - MEDIA_BUS_FMT_YUV12_1X36 -+ * - MEDIA_BUS_FMT_UYVY12_1X24 -+ * - MEDIA_BUS_FMT_UYYVYY12_0_5X36 -+ * - MEDIA_BUS_FMT_RGB161616_1X48 -+ * - MEDIA_BUS_FMT_YUV16_1X48 -+ * - MEDIA_BUS_FMT_UYYVYY16_0_5X48 -+ */ -+ -+/* Can return a maximum of 4 possible input formats for an output format */ -+#define MAX_INPUT_SEL_FORMATS 4 -+ -+static u32 *dw_hdmi_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge, -+ struct drm_bridge_state *bridge_state, -+ struct drm_crtc_state *crtc_state, -+ struct drm_connector_state *conn_state, -+ u32 output_fmt, -+ unsigned int *num_input_fmts) -+{ -+ u32 *input_fmts; -+ int i = 0; -+ -+ *num_input_fmts = 0; -+ -+ input_fmts = kcalloc(MAX_INPUT_SEL_FORMATS, sizeof(*input_fmts), -+ GFP_KERNEL); -+ if (!input_fmts) -+ return NULL; -+ -+ switch (output_fmt) { -+ /* 8bit */ -+ case MEDIA_BUS_FMT_RGB888_1X24: -+ input_fmts[i++] = MEDIA_BUS_FMT_RGB888_1X24; -+ input_fmts[i++] = MEDIA_BUS_FMT_YUV8_1X24; -+ input_fmts[i++] = MEDIA_BUS_FMT_UYVY8_1X16; -+ break; -+ case MEDIA_BUS_FMT_YUV8_1X24: -+ input_fmts[i++] = MEDIA_BUS_FMT_YUV8_1X24; -+ input_fmts[i++] = MEDIA_BUS_FMT_UYVY8_1X16; -+ input_fmts[i++] = MEDIA_BUS_FMT_RGB888_1X24; -+ break; -+ case MEDIA_BUS_FMT_UYVY8_1X16: -+ input_fmts[i++] = MEDIA_BUS_FMT_UYVY8_1X16; -+ input_fmts[i++] = MEDIA_BUS_FMT_YUV8_1X24; -+ input_fmts[i++] = MEDIA_BUS_FMT_RGB888_1X24; -+ break; -+ -+ /* 10bit */ -+ case MEDIA_BUS_FMT_RGB101010_1X30: -+ input_fmts[i++] = MEDIA_BUS_FMT_RGB101010_1X30; -+ input_fmts[i++] = MEDIA_BUS_FMT_YUV10_1X30; -+ input_fmts[i++] = MEDIA_BUS_FMT_UYVY10_1X20; -+ break; -+ case MEDIA_BUS_FMT_YUV10_1X30: -+ input_fmts[i++] = MEDIA_BUS_FMT_YUV10_1X30; -+ input_fmts[i++] = MEDIA_BUS_FMT_UYVY10_1X20; -+ input_fmts[i++] = MEDIA_BUS_FMT_RGB101010_1X30; -+ break; -+ case MEDIA_BUS_FMT_UYVY10_1X20: -+ input_fmts[i++] = MEDIA_BUS_FMT_UYVY10_1X20; -+ input_fmts[i++] = MEDIA_BUS_FMT_YUV10_1X30; -+ input_fmts[i++] = MEDIA_BUS_FMT_RGB101010_1X30; -+ break; -+ -+ /* 12bit */ -+ case MEDIA_BUS_FMT_RGB121212_1X36: -+ input_fmts[i++] = MEDIA_BUS_FMT_RGB121212_1X36; -+ input_fmts[i++] = MEDIA_BUS_FMT_YUV12_1X36; -+ input_fmts[i++] = MEDIA_BUS_FMT_UYVY12_1X24; -+ break; -+ case MEDIA_BUS_FMT_YUV12_1X36: -+ input_fmts[i++] = MEDIA_BUS_FMT_YUV12_1X36; -+ input_fmts[i++] = MEDIA_BUS_FMT_UYVY12_1X24; -+ input_fmts[i++] = MEDIA_BUS_FMT_RGB121212_1X36; -+ break; -+ case MEDIA_BUS_FMT_UYVY12_1X24: -+ input_fmts[i++] = MEDIA_BUS_FMT_UYVY12_1X24; -+ input_fmts[i++] = MEDIA_BUS_FMT_YUV12_1X36; -+ input_fmts[i++] = MEDIA_BUS_FMT_RGB121212_1X36; -+ break; -+ -+ /* 16bit */ -+ case MEDIA_BUS_FMT_RGB161616_1X48: -+ input_fmts[i++] = MEDIA_BUS_FMT_RGB161616_1X48; -+ input_fmts[i++] = MEDIA_BUS_FMT_YUV16_1X48; -+ break; -+ case MEDIA_BUS_FMT_YUV16_1X48: -+ input_fmts[i++] = MEDIA_BUS_FMT_YUV16_1X48; -+ input_fmts[i++] = MEDIA_BUS_FMT_RGB161616_1X48; -+ break; -+ -+ /* 420 */ -+ case MEDIA_BUS_FMT_UYYVYY8_0_5X24: -+ case MEDIA_BUS_FMT_UYYVYY10_0_5X30: -+ case MEDIA_BUS_FMT_UYYVYY12_0_5X36: -+ case MEDIA_BUS_FMT_UYYVYY16_0_5X48: -+ input_fmts[i++] = output_fmt; -+ break; -+ } -+ -+ *num_input_fmts = i; -+ -+ if (*num_input_fmts == 0) { -+ kfree(input_fmts); -+ input_fmts = NULL; -+ } -+ -+ return input_fmts; -+} -+ -+static int dw_hdmi_bridge_atomic_check(struct drm_bridge *bridge, -+ struct drm_bridge_state *bridge_state, -+ struct drm_crtc_state *crtc_state, -+ struct drm_connector_state *conn_state) -+{ -+ struct dw_hdmi *hdmi = bridge->driver_private; -+ -+ dev_dbg(hdmi->dev, "selected output format %x\n", -+ bridge_state->output_bus_cfg.format); -+ -+ hdmi->hdmi_data.enc_out_bus_format = -+ bridge_state->output_bus_cfg.format; -+ -+ dev_dbg(hdmi->dev, "selected input format %x\n", -+ bridge_state->input_bus_cfg.format); -+ -+ hdmi->hdmi_data.enc_in_bus_format = -+ bridge_state->input_bus_cfg.format; -+ -+ return 0; -+} -+ - static int dw_hdmi_bridge_attach(struct drm_bridge *bridge) - { - struct dw_hdmi *hdmi = bridge->driver_private; -@@ -2502,6 +2762,9 @@ static void dw_hdmi_bridge_enable(struct drm_bridge *bridge) - static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = { - .attach = dw_hdmi_bridge_attach, - .detach = dw_hdmi_bridge_detach, -+ .atomic_check = dw_hdmi_bridge_atomic_check, -+ .atomic_get_output_bus_fmts = dw_hdmi_bridge_atomic_get_output_bus_fmts, -+ .atomic_get_input_bus_fmts = dw_hdmi_bridge_atomic_get_input_bus_fmts, - .enable = dw_hdmi_bridge_enable, - .disable = dw_hdmi_bridge_disable, - .mode_set = dw_hdmi_bridge_mode_set, -@@ -2966,6 +3229,7 @@ __dw_hdmi_probe(struct platform_device *pdev, - - hdmi->bridge.driver_private = hdmi; - hdmi->bridge.funcs = &dw_hdmi_bridge_funcs; -+ - #ifdef CONFIG_OF - hdmi->bridge.of_node = pdev->dev.of_node; - #endif --- -2.17.1 - - -From 9c8d9cb1a3fa8b7cfe1052c1e6e549c294f65f69 Mon Sep 17 00:00:00 2001 -From: Neil Armstrong -Date: Wed, 18 Dec 2019 16:46:31 +0100 -Subject: [PATCH] drm/bridge: synopsys: dw-hdmi: allow ycbcr420 modes for >= - 0x200a - -Now the DW-HDMI Controller supports the HDMI2.0 modes, enable support -for these modes in the connector if the platform supports them. -We limit these modes to DW-HDMI IP version >= 0x200a which -are designed to support HDMI2.0 display modes. - -Signed-off-by: Neil Armstrong ---- - drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 6 ++++++ - include/drm/bridge/dw_hdmi.h | 1 + - 2 files changed, 7 insertions(+) - -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -index 88da301dc086..5749bdaba95b 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -@@ -3234,6 +3234,12 @@ __dw_hdmi_probe(struct platform_device *pdev, - hdmi->bridge.of_node = pdev->dev.of_node; - #endif - -+ if (hdmi->version >= 0x200a) -+ hdmi->connector.ycbcr_420_allowed = -+ hdmi->plat_data->ycbcr_420_allowed; -+ else -+ hdmi->connector.ycbcr_420_allowed = false; -+ - memset(&pdevinfo, 0, sizeof(pdevinfo)); - pdevinfo.parent = dev; - pdevinfo.id = PLATFORM_DEVID_AUTO; -diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h -index 9d4d5cc47969..0b34a12c4a1c 100644 ---- a/include/drm/bridge/dw_hdmi.h -+++ b/include/drm/bridge/dw_hdmi.h -@@ -129,6 +129,7 @@ struct dw_hdmi_plat_data { - unsigned long input_bus_format; - unsigned long input_bus_encoding; - bool use_drm_infoframe; -+ bool ycbcr_420_allowed; - - /* Vendor PHY support */ - const struct dw_hdmi_phy_ops *phy_ops; --- -2.17.1 - diff --git a/patch/kernel/rk322x-current/01-linux-0008-fromlist-add-rockchip-nfc-driver.patch.disabled b/patch/kernel/rk322x-current/01-linux-0003-rockchip-fromlist.patch similarity index 55% rename from patch/kernel/rk322x-current/01-linux-0008-fromlist-add-rockchip-nfc-driver.patch.disabled rename to patch/kernel/rk322x-current/01-linux-0003-rockchip-fromlist.patch index 0afa2f2d6..1495e0bfe 100644 --- a/patch/kernel/rk322x-current/01-linux-0008-fromlist-add-rockchip-nfc-driver.patch.disabled +++ b/patch/kernel/rk322x-current/01-linux-0003-rockchip-fromlist.patch @@ -1,44 +1,279 @@ +From 01b6923a7d4b84609809a0695e58aeb7bd1376f1 Mon Sep 17 00:00:00 2001 +From: Yifeng Zhao +Date: Fri, 17 Jul 2020 17:24:17 +0800 +Subject: [PATCH] dt-bindings: mtd: Describe Rockchip RK3xxx NAND flash + controller + +Documentation support for Rockchip RK3xxx NAND flash controllers + +Signed-off-by: Yifeng Zhao +Reviewed-by: Rob Herring +--- + .../mtd/rockchip,nand-controller.yaml | 162 ++++++++++++++++++ + 1 file changed, 162 insertions(+) + create mode 100644 Documentation/devicetree/bindings/mtd/rockchip,nand-controller.yaml + +diff --git a/Documentation/devicetree/bindings/mtd/rockchip,nand-controller.yaml b/Documentation/devicetree/bindings/mtd/rockchip,nand-controller.yaml +new file mode 100644 +index 000000000000..b9d7a8c79402 +--- /dev/null ++++ b/Documentation/devicetree/bindings/mtd/rockchip,nand-controller.yaml +@@ -0,0 +1,162 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/mtd/rockchip,nand-controller.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Rockchip SoCs NAND FLASH Controller (NFC) ++ ++allOf: ++ - $ref: "nand-controller.yaml#" ++ ++maintainers: ++ - Heiko Stuebner ++ ++properties: ++ compatible: ++ oneOf: ++ - const: rockchip,px30-nfc ++ - const: rockchip,rk2928-nfc ++ - const: rockchip,rv1108-nfc ++ - items: ++ - const: rockchip,rk3036-nfc ++ - const: rockchip,rk2928-nfc ++ - items: ++ - const: rockchip,rk3308-nfc ++ - const: rockchip,rv1108-nfc ++ ++ reg: ++ maxItems: 1 ++ ++ interrupts: ++ maxItems: 1 ++ ++ clocks: ++ minItems: 1 ++ items: ++ - description: Bus Clock ++ - description: Module Clock ++ ++ clock-names: ++ minItems: 1 ++ items: ++ - const: ahb ++ - const: nfc ++ ++ assigned-clocks: ++ maxItems: 1 ++ ++ assigned-clock-rates: ++ maxItems: 1 ++ ++ power-domains: ++ maxItems: 1 ++ ++patternProperties: ++ "^nand@[0-7]$": ++ type: object ++ properties: ++ reg: ++ minimum: 0 ++ maximum: 7 ++ ++ nand-ecc-mode: ++ const: hw ++ ++ nand-ecc-step-size: ++ const: 1024 ++ ++ nand-ecc-strength: ++ enum: [16, 24, 40, 60, 70] ++ description: ++ The ECC configurations that can be supported are as follows. ++ NFC v600 ECC 16, 24, 40, 60 ++ RK2928, RK3066, RK3188 ++ ++ NFC v622 ECC 16, 24, 40, 60 ++ RK3036, RK3128 ++ ++ NFC v800 ECC 16 ++ RK3308, RV1108 ++ ++ NFC v900 ECC 16, 40, 60, 70 ++ RK3326, PX30 ++ ++ nand-bus-width: ++ const: 8 ++ ++ rockchip,boot-blks: ++ minimum: 2 ++ default: 16 ++ allOf: ++ - $ref: /schemas/types.yaml#/definitions/uint32 ++ description: ++ The NFC driver need this information to select ECC ++ algorithms supported by the boot ROM. ++ Only used in combination with 'nand-is-boot-medium'. ++ ++ rockchip,boot-ecc-strength: ++ enum: [16, 24, 40, 60, 70] ++ allOf: ++ - $ref: /schemas/types.yaml#/definitions/uint32 ++ description: ++ If specified it indicates that a different BCH/ECC setting is ++ supported by the boot ROM. ++ NFC v600 ECC 16, 24 ++ RK2928, RK3066, RK3188 ++ ++ NFC v622 ECC 16, 24, 40, 60 ++ RK3036, RK3128 ++ ++ NFC v800 ECC 16 ++ RK3308, RV1108 ++ ++ NFC v900 ECC 16, 70 ++ RK3326, PX30 ++ ++ Only used in combination with 'nand-is-boot-medium'. ++ ++required: ++ - compatible ++ - reg ++ - interrupts ++ - clocks ++ - clock-names ++ ++unevaluatedProperties: false ++ ++examples: ++ - | ++ #include ++ #include ++ nfc: nand-controller@ff4b0000 { ++ compatible = "rockchip,rk3308-nfc", ++ "rockchip,rv1108-nfc"; ++ reg = <0xff4b0000 0x4000>; ++ interrupts = ; ++ clocks = <&cru HCLK_NANDC>, <&cru SCLK_NANDC>; ++ clock-names = "ahb", "nfc"; ++ assigned-clocks = <&clks SCLK_NANDC>; ++ assigned-clock-rates = <150000000>; ++ ++ pinctrl-0 = <&flash_ale &flash_bus8 &flash_cle &flash_csn0 ++ &flash_rdn &flash_rdy &flash_wrn>; ++ pinctrl-names = "default"; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ nand@0 { ++ reg = <0>; ++ label = "rk-nand"; ++ nand-bus-width = <8>; ++ nand-ecc-mode = "hw"; ++ nand-ecc-step-size = <1024>; ++ nand-ecc-strength = <16>; ++ nand-is-boot-medium; ++ rockchip,boot-blks = <8>; ++ rockchip,boot-ecc-strength = <16>; ++ }; ++ }; ++ ++... + +From 8d00c3eb36f8fbccc159d6456bfd418a2841acff Mon Sep 17 00:00:00 2001 +From: Yifeng Zhao +Date: Fri, 17 Jul 2020 17:24:18 +0800 +Subject: [PATCH] mtd: rawnand: rockchip: NFC drivers for RK3308, RK2928 and + others + +This driver supports Rockchip NFC (NAND Flash Controller) found on RK3308, +RK2928, RKPX30, RV1108 and other SOCs. The driver has been tested using +8-bit NAND interface on the ARM based RK3308 platform. + +Support Rockchip SoCs and NFC versions: +- PX30 and RK3326(NFCv900). + ECC: 16/40/60/70 bits/1KB. + CLOCK: ahb and nfc. +- RK3308 and RV1108(NFCv800). + ECC: 16 bits/1KB. + CLOCK: ahb and nfc. +- RK3036 and RK3128(NFCv622). + ECC: 16/24/40/60 bits/1KB. + CLOCK: ahb and nfc. +- RK3066, RK3188 and RK2928(NFCv600). + ECC: 16/24/40/60 bits/1KB. + CLOCK: ahb. + +Supported features: +- Read full page data by DMA. +- Support HW ECC(one step is 1KB). +- Support 2 - 32K page size. +- Support 8 CS(depend on SoCs) + +Limitations: +- No support for the ecc step size is 512. +- Untested on some SoCs. +- No support for subpages. +- No support for the builtin randomizer. +- The original bad block mask is not supported. It is recommended to use + the BBT(bad block table). + +Signed-off-by: Yifeng Zhao +--- + drivers/mtd/nand/raw/Kconfig | 12 + + drivers/mtd/nand/raw/Makefile | 1 + + .../mtd/nand/raw/rockchip-nand-controller.c | 1422 +++++++++++++++++ + 3 files changed, 1435 insertions(+) + create mode 100644 drivers/mtd/nand/raw/rockchip-nand-controller.c + diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig -index a80a46bb5b8b..8313b12a9d85 100644 +index 113f61052269..6492855d4a55 100644 --- a/drivers/mtd/nand/raw/Kconfig +++ b/drivers/mtd/nand/raw/Kconfig -@@ -433,6 +433,13 @@ config MTD_NAND_MESON - Enables support for NAND controller on Amlogic's Meson SoCs. - This controller is found on Meson SoCs. +@@ -461,6 +461,18 @@ config MTD_NAND_ARASAN + Enables the driver for the Arasan NAND flash controller on + Zynq Ultrascale+ MPSoC. +config MTD_NAND_ROCKCHIP + tristate "Rockchip NAND controller" -+ depends on ARCH_ROCKCHIP || COMPILE_TEST -+ depends on HAS_IOMEM ++ depends on ARCH_ROCKCHIP && HAS_IOMEM + help + Enables support for NAND controller on Rockchip SoCs. ++ There are four different versions of NAND FLASH Controllers, ++ including: ++ NFC v600: RK2928, RK3066, RK3188 ++ NFC v622: RK3036, RK3128 ++ NFC v800: RK3308, RV1108 ++ NFC v900: PX30, RK3326 + - config MTD_NAND_GPIO - tristate "GPIO assisted NAND controller" - depends on GPIOLIB || COMPILE_TEST + comment "Misc" + + config MTD_SM_COMMON diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile -index 2d136b158fb7..8bafa59b8940 100644 +index 2930f5b9015d..960c9be25204 100644 --- a/drivers/mtd/nand/raw/Makefile +++ b/drivers/mtd/nand/raw/Makefile -@@ -58,6 +58,7 @@ obj-$(CONFIG_MTD_NAND_TEGRA) += tegra_nand.o - obj-$(CONFIG_MTD_NAND_STM32_FMC2) += stm32_fmc2_nand.o +@@ -58,6 +58,7 @@ obj-$(CONFIG_MTD_NAND_STM32_FMC2) += stm32_fmc2_nand.o obj-$(CONFIG_MTD_NAND_MESON) += meson_nand.o obj-$(CONFIG_MTD_NAND_CADENCE) += cadence-nand-controller.o -+obj-$(CONFIG_MTD_NAND_ROCKCHIP) += rockchip_nand.o + obj-$(CONFIG_MTD_NAND_ARASAN) += arasan-nand-controller.o ++obj-$(CONFIG_MTD_NAND_ROCKCHIP) += rockchip-nand-controller.o nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o nand-objs += nand_onfi.o -diff --git a/drivers/mtd/nand/raw/rockchip_nand.c b/drivers/mtd/nand/raw/rockchip_nand.c +diff --git a/drivers/mtd/nand/raw/rockchip-nand-controller.c b/drivers/mtd/nand/raw/rockchip-nand-controller.c new file mode 100644 -index 000000000000..1e37a1b6c702 +index 000000000000..fec1360603e0 --- /dev/null -+++ b/drivers/mtd/nand/raw/rockchip_nand.c -@@ -0,0 +1,1315 @@ ++++ b/drivers/mtd/nand/raw/rockchip-nand-controller.c +@@ -0,0 +1,1422 @@ +// SPDX-License-Identifier: GPL-2.0 OR MIT +/* + * Rockchip NAND Flash controller driver. + * Copyright (C) 2020 Rockchip Inc. -+ * Authors: Yifeng Zhao ++ * Author: Yifeng Zhao + */ + +#include @@ -47,9 +282,9 @@ index 000000000000..1e37a1b6c702 +#include +#include +#include -+#include -+#include +#include ++#include ++#include +#include +#include +#include @@ -62,9 +297,9 @@ index 000000000000..1e37a1b6c702 + * NAND Page Data Layout: + * 1024 * n Data + m Bytes oob + * Original Bad Block Mask Location: -+ * first byte of oob(spare) ++ * First byte of oob(spare). + * nand_chip->oob_poi data layout: -+ * 4Bytes sys data + .... + 4Bytes sys data + ecc data ++ * 4Bytes sys data + .... + 4Bytes sys data + ecc data. + */ + +/* NAND controller register definition */ @@ -80,7 +315,7 @@ index 000000000000..1e37a1b6c702 +#define FLCTL_WR (1) /* 0: read, 1: write */ +#define FLCTL_XFER_ST BIT(2) +#define FLCTL_XFER_EN BIT(3) -+#define FLCTL_ACORRECT BIT(10) /* auto correct error bits */ ++#define FLCTL_ACORRECT BIT(10) /* Auto correct error bits. */ +#define FLCTL_XFER_READY BIT(20) +#define FLCTL_XFER_SECTOR (22) +#define FLCTL_TOG_FIX BIT(29) @@ -103,16 +338,15 @@ index 000000000000..1e37a1b6c702 +#define NFC_SRAM0 (0x1000) +#define NFC_SRAM1 (0x1400) +#define NFC_SRAM_SIZE (0x400) -+#define THIS_NAME "rk-nand" +#define NFC_TIMEOUT (500000) +#define NFC_MAX_OOB_PER_STEP 128 +#define NFC_MIN_OOB_PER_STEP 64 +#define MAX_DATA_SIZE 0xFFFC +#define MAX_ADDRESS_CYC 6 +#define NFC_ECC_MAX_MODES 4 -+#define NFC_MAX_NSELS (4) /* Some Soc only has 1 or 2 CSs */ -+#define NFC_SYS_DATA_SIZE (4) /* 4 bytes sys data in oob pre 1024 data */ -+#define RK_DEFAULT_CLOCK_RATE (150 * 1000 * 1000) /* 150 Mhz*/ ++#define NFC_MAX_NSELS (8) /* Some Socs only have 1 or 2 CSs. */ ++#define NFC_SYS_DATA_SIZE (4) /* 4 bytes sys data in oob pre 1024 data.*/ ++#define RK_DEFAULT_CLOCK_RATE (150 * 1000 * 1000) /* 150 Mhz */ +#define ACCTIMING(csrw, rwpw, rwcs) ((csrw) << 12 | (rwpw) << 5 | (rwcs)) + +enum nfc_type { @@ -139,7 +373,7 @@ index 000000000000..1e37a1b6c702 + u8 high_mask; +}; + -+/** ++/* + * @type: nfc version + * @ecc_strengths: ecc strengths + * @ecc_cfgs: ecc config values @@ -182,14 +416,17 @@ index 000000000000..1e37a1b6c702 + +struct rk_nfc_nand_chip { + struct list_head node; -+ struct nand_chip nand; ++ struct nand_chip chip; + -+ u32 spare_per_sector; -+ u32 oob_buf_per_sector; ++ u16 spare_per_sector; ++ u16 oob_buf_per_sector; ++ u16 boot_blks; ++ u16 boot_ecc; ++ u16 metadata_size; + -+ int nsels; ++ u8 nsels; + u8 sels[0]; -+ /* nothing after this field */ ++ /* Nothing after this field. */ +}; + +struct rk_nfc_clk { @@ -219,9 +456,9 @@ index 000000000000..1e37a1b6c702 + unsigned long assigned_cs; +}; + -+static inline struct rk_nfc_nand_chip *to_rk_nand(struct nand_chip *nand) ++static inline struct rk_nfc_nand_chip *to_rknand(struct nand_chip *chip) +{ -+ return container_of(nand, struct rk_nfc_nand_chip, nand); ++ return container_of(chip, struct rk_nfc_nand_chip, chip); +} + +static inline u8 *data_ptr(struct nand_chip *chip, const u8 *p, int i) @@ -238,11 +475,22 @@ index 000000000000..1e37a1b6c702 + return poi; +} + ++static inline u8 *oob_ecc_ptr(struct nand_chip *chip, int i) ++{ ++ struct rk_nfc_nand_chip *rknand = to_rknand(chip); ++ u8 *poi; ++ ++ poi = chip->oob_poi + rknand->metadata_size + ++ chip->ecc.bytes * i; ++ ++ return poi; ++} ++ +static inline int rk_data_len(struct nand_chip *chip) +{ -+ struct rk_nfc_nand_chip *rk_nand = to_rk_nand(chip); ++ struct rk_nfc_nand_chip *rknand = to_rknand(chip); + -+ return chip->ecc.size + rk_nand->spare_per_sector; ++ return chip->ecc.size + rknand->spare_per_sector; +} + +static inline u8 *rk_data_ptr(struct nand_chip *chip, int i) @@ -259,22 +507,22 @@ index 000000000000..1e37a1b6c702 + return nfc->buffer + i * rk_data_len(chip) + chip->ecc.size; +} + -+static void rk_nfc_select_chip(struct nand_chip *nand, int chip) ++static void rk_nfc_select_chip(struct nand_chip *chip, int cs) +{ -+ struct rk_nfc *nfc = nand_get_controller_data(nand); -+ struct rk_nfc_nand_chip *rk_nand = to_rk_nand(nand); ++ struct rk_nfc *nfc = nand_get_controller_data(chip); ++ struct rk_nfc_nand_chip *rknand = to_rknand(chip); + u32 val; + -+ if (chip < 0) { ++ if (cs < 0) { + nfc->selected_bank = -1; -+ /* Deselect the currently selected target */ ++ /* Deselect the currently selected target. */ + val = readl_relaxed(nfc->regs + NFC_FMCTL); + val &= ~FMCTL_CE_SEL_M; + writel(val, nfc->regs + NFC_FMCTL); + return; + } + -+ nfc->selected_bank = rk_nand->sels[chip]; ++ nfc->selected_bank = rknand->sels[cs]; + nfc->band_offset = NFC_BANK + nfc->selected_bank * NFC_BANK_STEP; + + val = readl_relaxed(nfc->regs + NFC_FMCTL); @@ -284,15 +532,15 @@ index 000000000000..1e37a1b6c702 + writel(val, nfc->regs + NFC_FMCTL); +} + -+static inline void rk_nfc_wait_ioready(struct rk_nfc *nfc) ++static inline int rk_nfc_wait_ioready(struct rk_nfc *nfc) +{ + int rc; + u32 val; + + rc = readl_poll_timeout_atomic(nfc->regs + NFC_FMCTL, val, + val & FMCTL_RDY, 10, NFC_TIMEOUT); -+ if (rc < 0) -+ dev_err(nfc->dev, "data not ready\n"); ++ ++ return rc; +} + +static inline u8 rk_nfc_read_byte(struct nand_chip *chip) @@ -329,12 +577,13 @@ index 000000000000..1e37a1b6c702 + const struct nand_subop *subop) +{ + struct rk_nfc *nfc = nand_get_controller_data(chip); -+ u32 cnt = 0; + unsigned int i, j, remaining, start; + int reg_offset = nfc->band_offset; ++ void __iomem *data_reg; + u8 *inbuf = NULL; + const u8 *outbuf; -+ void __iomem *data_reg; ++ u32 cnt = 0; ++ int ret = 0; + + for (i = 0; i < subop->ninstrs; i++) { + const struct nand_op_instr *instr = &subop->instrs[i]; @@ -372,12 +621,15 @@ index 000000000000..1e37a1b6c702 + break; + + case NAND_OP_WAITRDY_INSTR: -+ rk_nfc_wait_ioready(nfc); ++ if (rk_nfc_wait_ioready(nfc) < 0) { ++ ret = -ETIMEDOUT; ++ dev_err(nfc->dev, "IO not ready\n"); ++ } + break; + } + } + -+ return 0; ++ return ret; +} + +static const struct nand_op_parser rk_nfc_op_parser = NAND_OP_PARSER( @@ -417,17 +669,19 @@ index 000000000000..1e37a1b6c702 + if (csline == NAND_DATA_IFACE_CHECK_ONLY) + return 0; + -+ /* not onfi nand flash */ + if (!chip->parameters.onfi) + return 0; + + timings = nand_get_sdr_timings(conf); + if (IS_ERR(timings)) -+ return -ENOTSUPP; ++ return -EOPNOTSUPP; + -+ rate = clk_get_rate(nfc->clk.nfc_clk); ++ if (IS_ERR(nfc->clk.nfc_clk)) ++ rate = clk_get_rate(nfc->clk.ahb_clk); ++ else ++ rate = clk_get_rate(nfc->clk.nfc_clk); + -+ /* turn clock rate into KHZ */ ++ /* Turn clock rate into kHz. */ + rate /= 1000; + + tc2rw = 1; @@ -459,12 +713,34 @@ index 000000000000..1e37a1b6c702 + return 0; +} + ++static int rk_nfc_hw_ecc_setup(struct nand_chip *chip, ++ struct nand_ecc_ctrl *ecc, ++ uint32_t strength) ++{ ++ struct rk_nfc *nfc = nand_get_controller_data(chip); ++ u32 reg, i; ++ ++ for (i = 0; i < NFC_ECC_MAX_MODES; i++) { ++ if (ecc->strength == nfc->cfg->ecc_strengths[i]) { ++ reg = nfc->cfg->ecc_cfgs[i]; ++ break; ++ } ++ } ++ ++ if (i >= NFC_ECC_MAX_MODES) ++ return -EINVAL; ++ ++ writel(reg, nfc->regs + nfc->cfg->bchctl_off); ++ ++ return 0; ++} ++ +static void rk_nfc_xfer_start(struct rk_nfc *nfc, u8 rw, u8 n_KB, + dma_addr_t dma_data, dma_addr_t dma_oob) +{ + u32 dma_reg, fl_reg, bch_reg; + -+ dma_reg = DMA_ST | ((!rw) << DMA_WR) | DMA_EN | (2 << DMA_AHB_SIZE) | ++ dma_reg = DMA_ST | ((!rw) << DMA_WR) | DMA_EN | (2 << DMA_AHB_SIZE) | + (7 << DMA_BURST_SIZE) | (16 << DMA_INC_NUM); + + fl_reg = (rw << FLCTL_WR) | FLCTL_XFER_EN | FLCTL_ACORRECT | @@ -487,17 +763,15 @@ index 000000000000..1e37a1b6c702 + +static int rk_nfc_wait_for_xfer_done(struct rk_nfc *nfc) +{ -+ u32 reg; -+ int ret = 0; + void __iomem *ptr; ++ int ret = 0; ++ u32 reg; + + ptr = nfc->regs + nfc->cfg->flctl_off; + + ret = readl_poll_timeout_atomic(ptr, reg, + reg & FLCTL_XFER_READY, + 10, NFC_TIMEOUT); -+ if (ret) -+ dev_err(nfc->dev, "timeout reg=%x\n", reg); + + return ret; +} @@ -506,41 +780,51 @@ index 000000000000..1e37a1b6c702 + const u8 *buf, int page, int raw) +{ + struct rk_nfc *nfc = nand_get_controller_data(chip); ++ struct rk_nfc_nand_chip *rknand = to_rknand(chip); + struct nand_ecc_ctrl *ecc = &chip->ecc; -+ u8 *oob; -+ dma_addr_t dma_data, dma_oob; + int oob_step = (ecc->bytes > 60) ? NFC_MAX_OOB_PER_STEP : + NFC_MIN_OOB_PER_STEP; + int pages_per_blk = mtd->erasesize / mtd->writesize; ++ int ret = 0, i, boot_rom_mode = 0; ++ dma_addr_t dma_data, dma_oob; + u32 reg; -+ int ret = 0, i; ++ u8 *oob; + + nand_prog_page_begin_op(chip, page, 0, NULL, 0); + + if (!raw) { + memcpy(nfc->page_buf, buf, mtd->writesize); + memset(nfc->oob_buf, 0xff, oob_step * ecc->steps); -+ /* -+ * The first 8 blocks is stored loader, the first -+ * 32 bits of oob need link to next page address -+ * in the same block for Bootrom. -+ * Swap the first oob with the seventh oob, -+ * and bad block mask save at seventh oob. -+ */ -+ swap(chip->oob_poi[0], chip->oob_poi[7]); -+ for (i = 0; i < ecc->steps; i++) { -+ oob = chip->oob_poi + i * NFC_SYS_DATA_SIZE; -+ reg = (oob[2] << 16) | (oob[3] << 24); -+ if (!i && page < pages_per_blk * 8) -+ reg |= (page & (pages_per_blk - 1)) * 4; -+ else -+ reg |= oob[0] | (oob[1] << 8); + -+ if (nfc->cfg->type == NFC_V6 || -+ nfc->cfg->type == NFC_V8) -+ nfc->oob_buf[i * oob_step / 4] = reg; -+ else ++ /* ++ * The first 8(some devices are 4 or 16) blocks are in use by ++ * the boot ROM and the first 32 bits of oob need to link ++ * to the next page address in the same block. ++ * Config the ECC algorithm supported by the boot ROM. ++ */ ++ if (page < pages_per_blk * rknand->boot_blks && ++ chip->options & NAND_IS_BOOT_MEDIUM) { ++ boot_rom_mode = 1; ++ if (rknand->boot_ecc != ecc->strength) ++ rk_nfc_hw_ecc_setup(chip, ecc, ++ rknand->boot_ecc); ++ } ++ ++ for (i = 0; i < ecc->steps; i++) { ++ if (!i) { ++ reg = 0xFFFFFFFF; ++ } else { ++ oob = chip->oob_poi + (i - 1) * NFC_SYS_DATA_SIZE; ++ reg = oob[0] | oob[1] << 8 | oob[2] << 16 | ++ oob[3] << 24; ++ } ++ if (!i && boot_rom_mode) ++ reg = (page & (pages_per_blk - 1)) * 4; ++ ++ if (nfc->cfg->type == NFC_V9) + nfc->oob_buf[i] = reg; ++ else ++ nfc->oob_buf[i * oob_step / 4] = reg; + } + + dma_data = dma_map_single(nfc->dev, (void *)nfc->page_buf, @@ -549,7 +833,7 @@ index 000000000000..1e37a1b6c702 + ecc->steps * oob_step, + DMA_TO_DEVICE); + -+ init_completion(&nfc->done); ++ reinit_completion(&nfc->done); + writel(INT_DMA, nfc->regs + nfc->cfg->int_en_off); + + rk_nfc_xfer_start(nfc, NFC_WRITE, ecc->steps, dma_data, @@ -557,15 +841,29 @@ index 000000000000..1e37a1b6c702 + ret = wait_for_completion_timeout(&nfc->done, + msecs_to_jiffies(100)); + if (!ret) -+ ret = -ETIMEDOUT; ++ dev_warn(nfc->dev, "write: wait dma done timeout.\n"); ++ /* ++ * Whether the DMA transfer is completed or not. The driver ++ * needs to check the NFC`s status register to see if the data ++ * transfer was completed. ++ */ + ret = rk_nfc_wait_for_xfer_done(nfc); + + dma_unmap_single(nfc->dev, dma_data, mtd->writesize, + DMA_TO_DEVICE); + dma_unmap_single(nfc->dev, dma_oob, ecc->steps * oob_step, + DMA_TO_DEVICE); ++ ++ if (boot_rom_mode && rknand->boot_ecc != ecc->strength) ++ rk_nfc_hw_ecc_setup(chip, ecc, ecc->strength); ++ ++ if (ret) { ++ ret = -EIO; ++ dev_err(nfc->dev, ++ "write: wait transfer done timeout.\n"); ++ } + } else { -+ rk_nfc_write_buf(chip, buf, mtd->writesize + + mtd->oobsize); ++ rk_nfc_write_buf(chip, buf, mtd->writesize + mtd->oobsize); + } + + if (ret) @@ -573,7 +871,7 @@ index 000000000000..1e37a1b6c702 + + ret = nand_prog_page_end_op(chip); + -+ /* Deselect the currently selected target */ ++ /* Deselect the currently selected target. */ + rk_nfc_select_chip(chip, -1); + + return ret; @@ -587,14 +885,23 @@ index 000000000000..1e37a1b6c702 + u32 i; + + memset(nfc->buffer, 0xff, mtd->writesize + mtd->oobsize); -+ swap(chip->oob_poi[0], chip->oob_poi[7]); ++ + for (i = 0; i < chip->ecc.steps; i++) { + if (buf) + memcpy(rk_data_ptr(chip, i), data_ptr(chip, buf, i), + chip->ecc.size); + -+ memcpy(rk_oob_ptr(chip, i), oob_ptr(chip, i), -+ NFC_SYS_DATA_SIZE); ++ if (!i) ++ memcpy(rk_oob_ptr(chip, i), ++ oob_ptr(chip, chip->ecc.steps - 1), ++ NFC_SYS_DATA_SIZE); ++ else ++ memcpy(rk_oob_ptr(chip, i), oob_ptr(chip, i - 1), ++ NFC_SYS_DATA_SIZE); ++ ++ memcpy(rk_oob_ptr(chip, i) + NFC_SYS_DATA_SIZE, ++ oob_ecc_ptr(chip, i), ++ chip->ecc.bytes); + } + + return rk_nfc_write_page(mtd, chip, nfc->buffer, page, 1); @@ -610,12 +917,14 @@ index 000000000000..1e37a1b6c702 + u8 *buf, int page, int raw) +{ + struct rk_nfc *nfc = nand_get_controller_data(chip); ++ struct rk_nfc_nand_chip *rknand = to_rknand(chip); + struct nand_ecc_ctrl *ecc = &chip->ecc; -+ dma_addr_t dma_data, dma_oob; + int oob_step = (ecc->bytes > 60) ? NFC_MAX_OOB_PER_STEP : + NFC_MIN_OOB_PER_STEP; -+ int bitflips = 0; -+ int ret, i, bch_st; ++ int pages_per_blk = mtd->erasesize / mtd->writesize; ++ dma_addr_t dma_data, dma_oob; ++ int ret = 0, i, boot_rom_mode = 0; ++ int bitflips = 0, bch_st; + u8 *oob; + u32 tmp; + @@ -627,33 +936,58 @@ index 000000000000..1e37a1b6c702 + dma_oob = dma_map_single(nfc->dev, nfc->oob_buf, + ecc->steps * oob_step, + DMA_FROM_DEVICE); -+ init_completion(&nfc->done); ++ ++ /* ++ * The first 8(some devices are 4 or 16) blocks are in use by ++ * the boot ROM. ++ * Config the ECC algorithm supported by the boot ROM. ++ */ ++ if (page < pages_per_blk * rknand->boot_blks && ++ chip->options & NAND_IS_BOOT_MEDIUM) { ++ boot_rom_mode = 1; ++ if (rknand->boot_ecc != ecc->strength) ++ rk_nfc_hw_ecc_setup(chip, ecc, ++ rknand->boot_ecc); ++ } ++ ++ reinit_completion(&nfc->done); + writel(INT_DMA, nfc->regs + nfc->cfg->int_en_off); + rk_nfc_xfer_start(nfc, NFC_READ, ecc->steps, dma_data, + dma_oob); + ret = wait_for_completion_timeout(&nfc->done, + msecs_to_jiffies(100)); + if (!ret) -+ dev_warn(nfc->dev, "read ahb/dma done timeout\n"); -+ rk_nfc_wait_for_xfer_done(nfc); ++ dev_warn(nfc->dev, "read: wait dma done timeout.\n"); ++ /* ++ * Whether the DMA transfer is completed or not. The driver ++ * needs to check the NFC`s status register to see if the data ++ * transfer was completed. ++ */ ++ ret = rk_nfc_wait_for_xfer_done(nfc); + dma_unmap_single(nfc->dev, dma_data, mtd->writesize, + DMA_FROM_DEVICE); + dma_unmap_single(nfc->dev, dma_oob, ecc->steps * oob_step, + DMA_FROM_DEVICE); + -+ for (i = 0; i < ecc->steps; i++) { -+ oob = chip->oob_poi + i * NFC_SYS_DATA_SIZE; -+ if (nfc->cfg->type == NFC_V6 || -+ nfc->cfg->type == NFC_V8) -+ tmp = nfc->oob_buf[i * oob_step / 4]; -+ else ++ if (ret) { ++ bitflips = -EIO; ++ dev_err(nfc->dev, ++ "read: wait transfer done timeout.\n"); ++ goto out; ++ } ++ ++ for (i = 1; i < ecc->steps; i++) { ++ oob = chip->oob_poi + (i - 1) * NFC_SYS_DATA_SIZE; ++ if (nfc->cfg->type == NFC_V9) + tmp = nfc->oob_buf[i]; ++ else ++ tmp = nfc->oob_buf[i * oob_step / 4]; + *oob++ = (u8)tmp; + *oob++ = (u8)(tmp >> 8); + *oob++ = (u8)(tmp >> 16); + *oob++ = (u8)(tmp >> 24); + } -+ swap(chip->oob_poi[0], chip->oob_poi[7]); ++ + for (i = 0; i < ecc->steps / 2; i++) { + bch_st = readl_relaxed(nfc->regs + + nfc->cfg->bch_st_off + i * 4); @@ -671,17 +1005,18 @@ index 000000000000..1e37a1b6c702 + bitflips = max_t(u32, bitflips, ret); + } + } ++out: + memcpy(buf, nfc->page_buf, mtd->writesize); + -+ if (bitflips == -1) -+ dev_err(nfc->dev, "read_page %x %x %x %x %x %x\n", -+ page, bitflips, bch_st, ((u32 *)buf)[0], -+ ((u32 *)buf)[1], (u32)dma_data); ++ if (boot_rom_mode && rknand->boot_ecc != ecc->strength) ++ rk_nfc_hw_ecc_setup(chip, ecc, ecc->strength); ++ ++ if (bitflips < 0) ++ dev_err(nfc->dev, "read page: %x ecc error!\n", page); + } else { + rk_nfc_read_buf(chip, buf, mtd->writesize + mtd->oobsize); + } -+ -+ /* Deselect the currently selected target */ ++ /* Deselect the currently selected target. */ + rk_nfc_select_chip(chip, -1); + + return bitflips; @@ -714,14 +1049,22 @@ index 000000000000..1e37a1b6c702 + return ret; + + for (i = 0; i < chip->ecc.steps; i++) { -+ memcpy(oob_ptr(chip, i), rk_oob_ptr(chip, i), -+ NFC_SYS_DATA_SIZE); ++ if (!i) ++ memcpy(oob_ptr(chip, chip->ecc.steps - 1), ++ rk_oob_ptr(chip, i), ++ NFC_SYS_DATA_SIZE); ++ else ++ memcpy(oob_ptr(chip, i - 1), rk_oob_ptr(chip, i), ++ NFC_SYS_DATA_SIZE); ++ ++ memcpy(oob_ecc_ptr(chip, i), ++ rk_oob_ptr(chip, i) + NFC_SYS_DATA_SIZE, ++ chip->ecc.bytes); + + if (buf) + memcpy(data_ptr(chip, buf, i), rk_data_ptr(chip, i), + chip->ecc.size); + } -+ swap(chip->oob_poi[0], chip->oob_poi[7]); + + return ret; +} @@ -733,11 +1076,11 @@ index 000000000000..1e37a1b6c702 + +static inline void rk_nfc_hw_init(struct rk_nfc *nfc) +{ -+ /* disable flash wp */ ++ /* Disable flash wp. */ + writel(FMCTL_WP, nfc->regs + NFC_FMCTL); -+ /* config default timing */ ++ /* Config default timing 40ns at 150 Mhz nfc clock. */ + writel(0x1081, nfc->regs + NFC_FMWAIT); -+ /* disable randomizer and dma */ ++ /* Disable randomizer and DMA. */ + writel(0, nfc->regs + nfc->cfg->randmz_off); + writel(0, nfc->regs + nfc->cfg->dma_cfg_off); + writel(FLCTL_RST, nfc->regs + nfc->cfg->flctl_off); @@ -766,16 +1109,19 @@ index 000000000000..1e37a1b6c702 +{ + int ret; + -+ ret = clk_prepare_enable(clk->nfc_clk); -+ if (ret) { -+ dev_err(dev, "failed to enable nfc clk\n"); -+ return ret; ++ if (!IS_ERR(clk->nfc_clk)) { ++ ret = clk_prepare_enable(clk->nfc_clk); ++ if (ret) { ++ dev_err(dev, "failed to enable nfc clk\n"); ++ return ret; ++ } + } + + ret = clk_prepare_enable(clk->ahb_clk); + if (ret) { + dev_err(dev, "failed to enable ahb clk\n"); -+ clk_disable_unprepare(clk->nfc_clk); ++ if (!IS_ERR(clk->nfc_clk)) ++ clk_disable_unprepare(clk->nfc_clk); + return ret; + } + @@ -784,7 +1130,8 @@ index 000000000000..1e37a1b6c702 + +static void rk_nfc_disable_clk(struct rk_nfc_clk *clk) +{ -+ clk_disable_unprepare(clk->nfc_clk); ++ if (!IS_ERR(clk->nfc_clk)) ++ clk_disable_unprepare(clk->nfc_clk); + clk_disable_unprepare(clk->ahb_clk); +} + @@ -792,18 +1139,17 @@ index 000000000000..1e37a1b6c702 + struct mtd_oob_region *oob_region) +{ + struct nand_chip *chip = mtd_to_nand(mtd); ++ struct rk_nfc_nand_chip *rknand = to_rknand(chip); + -+ if (section >= chip->ecc.steps) ++ if (section) + return -ERANGE; + -+ if (!section) { -+ /* The first byte is bad block mask flag */ -+ oob_region->length = NFC_SYS_DATA_SIZE - 1; -+ oob_region->offset = 1; -+ } else { -+ oob_region->length = NFC_SYS_DATA_SIZE; -+ oob_region->offset = section * NFC_SYS_DATA_SIZE; -+ } ++ /* ++ * The beginning of the oob area stores the reserved data for the NFC, ++ * the size of the reserved data is NFC_SYS_DATA_SIZE bytes. ++ */ ++ oob_region->length = rknand->metadata_size - NFC_SYS_DATA_SIZE - 2; ++ oob_region->offset = NFC_SYS_DATA_SIZE + 2; + + return 0; +} @@ -812,11 +1158,12 @@ index 000000000000..1e37a1b6c702 + struct mtd_oob_region *oob_region) +{ + struct nand_chip *chip = mtd_to_nand(mtd); ++ struct rk_nfc_nand_chip *rknand = to_rknand(chip); + + if (section) + return -ERANGE; + -+ oob_region->offset = NFC_SYS_DATA_SIZE * chip->ecc.steps; ++ oob_region->offset = rknand->metadata_size; + oob_region->length = mtd->oobsize - oob_region->offset; + + return 0; @@ -827,70 +1174,44 @@ index 000000000000..1e37a1b6c702 + .ecc = rk_nfc_ooblayout_ecc, +}; + -+static int rk_nfc_hw_ecc_setup(struct mtd_info *mtd, -+ struct nand_ecc_ctrl *ecc, -+ uint32_t strength) -+{ -+ struct nand_chip *nand = mtd_to_nand(mtd); -+ struct rk_nfc *nfc = nand_get_controller_data(nand); -+ u32 reg, i; -+ -+ ecc->strength = strength; -+ ecc->steps = mtd->writesize / ecc->size; -+ ecc->bytes = DIV_ROUND_UP(ecc->strength * 14, 8); -+ /* HW ECC always work with even numbers of ECC bytes */ -+ ecc->bytes = ALIGN(ecc->bytes, 2); -+ -+ for (i = 0; i < NFC_ECC_MAX_MODES; i++) { -+ if (ecc->strength == nfc->cfg->ecc_strengths[i]) { -+ reg = nfc->cfg->ecc_cfgs[i]; -+ break; -+ } -+ } -+ -+ if (i >= NFC_ECC_MAX_MODES) -+ return -EINVAL; -+ -+ writel(reg, nfc->regs + nfc->cfg->bchctl_off); -+ -+ return 0; -+} -+ +static int rk_nfc_ecc_init(struct device *dev, struct mtd_info *mtd) +{ -+ struct nand_chip *nand = mtd_to_nand(mtd); -+ struct rk_nfc *nfc = nand_get_controller_data(nand); -+ struct nand_ecc_ctrl *ecc = &nand->ecc; ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct rk_nfc *nfc = nand_get_controller_data(chip); ++ struct nand_ecc_ctrl *ecc = &chip->ecc; + const u8 *strengths = nfc->cfg->ecc_strengths; + u8 max_strength, nfc_max_strength; + int i; + + nfc_max_strength = nfc->cfg->ecc_strengths[0]; -+ /* if optional dt settings not present */ ++ /* If optional dt settings not present. */ + if (!ecc->size || !ecc->strength || + ecc->strength > nfc_max_strength) { -+ /* use datasheet requirements */ -+ ecc->strength = nand->base.eccreq.strength; -+ ecc->size = nand->base.eccreq.step_size; ++ /* Use datasheet requirements. */ ++ ecc->strength = chip->base.eccreq.strength; ++ ecc->size = chip->base.eccreq.step_size; + -+ /* -+ * align eccstrength and eccsize -+ * this controller only supports 512 and 1024 sizes -+ */ -+ if (nand->ecc.size < 1024) { ++ /* Align ECC strength and ECC size. */ ++ if (chip->ecc.size < 1024) { + if (mtd->writesize > 512) { -+ nand->ecc.size = 1024; -+ nand->ecc.strength <<= 1; ++ chip->ecc.size = 1024; ++ chip->ecc.strength <<= 1; + } else { -+ dev_err(dev, "ecc.size not supported\n"); ++ dev_err(dev, "Unsupported ecc.size\n"); + return -EINVAL; + } + } else { -+ nand->ecc.size = 1024; ++ chip->ecc.size = 1024; + } + + ecc->steps = mtd->writesize / ecc->size; -+ max_strength = ((mtd->oobsize / ecc->steps) - 4) * 8 / 14; ++ ++ /* ++ * HW ECC always requests the number of ECC bytes per 1024 byte ++ * blocks. 4 Bytes is oob for sys data. ++ */ ++ max_strength = ((mtd->oobsize / ecc->steps) - 4) * 8 / ++ fls(8 * 1024); + if (max_strength > nfc_max_strength) + max_strength = nfc_max_strength; + @@ -900,15 +1221,18 @@ index 000000000000..1e37a1b6c702 + } + + if (i >= 4) { -+ dev_err(nfc->dev, "unsupported strength\n"); -+ return -ENOTSUPP; ++ dev_err(nfc->dev, "Unsupported ECC strength\n"); ++ return -EOPNOTSUPP; + } + + ecc->strength = strengths[i]; + } -+ rk_nfc_hw_ecc_setup(mtd, ecc, ecc->strength); -+ dev_info(dev, "eccsize %d eccstrength %d\n", -+ nand->ecc.size, nand->ecc.strength); ++ ecc->steps = mtd->writesize / ecc->size; ++ ecc->bytes = DIV_ROUND_UP(ecc->strength * fls(8 * 1024), 8); ++ /* HW ECC always work with even numbers of ECC bytes. */ ++ ecc->bytes = ALIGN(ecc->bytes, 2); ++ ++ rk_nfc_hw_ecc_setup(chip, ecc, ecc->strength); + + return 0; +} @@ -918,13 +1242,13 @@ index 000000000000..1e37a1b6c702 + struct mtd_info *mtd = nand_to_mtd(chip); + struct device *dev = mtd->dev.parent; + struct rk_nfc *nfc = nand_get_controller_data(chip); -+ struct rk_nfc_nand_chip *rk_nand = to_rk_nand(chip); ++ struct rk_nfc_nand_chip *rknand = to_rknand(chip); + struct nand_ecc_ctrl *ecc = &chip->ecc; + int len; + int ret; + + if (chip->options & NAND_BUSWIDTH_16) { -+ dev_err(dev, "16bits buswidth not supported"); ++ dev_err(dev, "16 bits bus width not supported"); + return -EINVAL; + } + @@ -934,9 +1258,16 @@ index 000000000000..1e37a1b6c702 + ret = rk_nfc_ecc_init(dev, mtd); + if (ret) + return ret; -+ rk_nand->spare_per_sector = ecc->bytes + NFC_SYS_DATA_SIZE; ++ rknand->spare_per_sector = ecc->bytes + NFC_SYS_DATA_SIZE; ++ rknand->metadata_size = NFC_SYS_DATA_SIZE * ecc->steps; + -+ /* Check buffer first, avoid duplicate alloc buffer */ ++ if (rknand->metadata_size < NFC_SYS_DATA_SIZE + 2) { ++ dev_err(dev, ++ "Driver needs at least %d bytes of meta data\n", ++ NFC_SYS_DATA_SIZE + 2); ++ return -EIO; ++ } ++ /* Check buffer first, avoid duplicate alloc buffer. */ + if (nfc->buffer) + return 0; + @@ -949,7 +1280,6 @@ index 000000000000..1e37a1b6c702 + len = ecc->steps * NFC_MAX_OOB_PER_STEP; + nfc->oob_buf = devm_kzalloc(dev, len, GFP_KERNEL | GFP_DMA); + if (!nfc->oob_buf) { -+ devm_kfree(dev, nfc->buffer); + nfc->buffer = NULL; + nfc->oob_buf = NULL; + return -ENOMEM; @@ -977,8 +1307,8 @@ index 000000000000..1e37a1b6c702 +static int rk_nfc_nand_chip_init(struct device *dev, struct rk_nfc *nfc, + struct device_node *np) +{ -+ struct rk_nfc_nand_chip *chip; -+ struct nand_chip *nand; ++ struct rk_nfc_nand_chip *rknand; ++ struct nand_chip *chip; + struct mtd_info *mtd; + int nsels; + u32 tmp; @@ -993,12 +1323,12 @@ index 000000000000..1e37a1b6c702 + return -EINVAL; + } + -+ chip = devm_kzalloc(dev, sizeof(*chip) + nsels * sizeof(u8), -+ GFP_KERNEL); -+ if (!chip) ++ rknand = devm_kzalloc(dev, sizeof(*rknand) + nsels * sizeof(u8), ++ GFP_KERNEL); ++ if (!rknand) + return -ENOMEM; + -+ chip->nsels = nsels; ++ rknand->nsels = nsels; + for (i = 0; i < nsels; i++) { + ret = of_property_read_u32_index(np, "reg", i, &tmp); + if (ret) { @@ -1016,60 +1346,95 @@ index 000000000000..1e37a1b6c702 + return -EINVAL; + } + -+ chip->sels[i] = tmp; ++ rknand->sels[i] = tmp; + } + -+ nand = &chip->nand; -+ nand->controller = &nfc->controller; ++ chip = &rknand->chip; ++ chip->controller = &nfc->controller; + -+ nand_set_flash_node(nand, np); -+ nand_set_controller_data(nand, nfc); ++ nand_set_flash_node(chip, np); + -+ nand->options |= NAND_USE_BOUNCE_BUFFER | NAND_NO_SUBPAGE_WRITE; -+ nand->bbt_options = NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB; ++ nand_set_controller_data(chip, nfc); + -+ /* set default mode in case dt entry is missing */ -+ nand->ecc.mode = NAND_ECC_HW; ++ chip->options |= NAND_USES_DMA | NAND_NO_SUBPAGE_WRITE; ++ chip->bbt_options = NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB; + -+ mtd = nand_to_mtd(nand); ++ /* Set default mode in case dt entry is missing. */ ++ chip->ecc.mode = NAND_ECC_HW; ++ ++ mtd = nand_to_mtd(chip); + mtd->owner = THIS_MODULE; + mtd->dev.parent = dev; -+ mtd->name = THIS_NAME; ++ ++ if (!mtd->name) { ++ dev_err(nfc->dev, "NAND label property is mandatory\n"); ++ return -EINVAL; ++ } ++ + mtd_set_ooblayout(mtd, &rk_nfc_ooblayout_ops); + rk_nfc_hw_init(nfc); -+ ret = nand_scan(nand, nsels); ++ ret = nand_scan(chip, nsels); + if (ret) + return ret; ++ ++ if (chip->options & NAND_IS_BOOT_MEDIUM) { ++ ret = of_property_read_u32(np, "rockchip,boot-blks", &tmp); ++ rknand->boot_blks = ret ? 0 : tmp; ++ ++ ret = of_property_read_u32(np, "rockchip,boot-ecc-strength", ++ &tmp); ++ rknand->boot_ecc = ret ? chip->ecc.strength : tmp; ++ } ++ + ret = mtd_device_register(mtd, NULL, 0); + if (ret) { + dev_err(dev, "mtd parse partition error\n"); -+ nand_release(nand); ++ nand_cleanup(chip); + return ret; + } + -+ list_add_tail(&chip->node, &nfc->chips); ++ list_add_tail(&rknand->node, &nfc->chips); + + return 0; +} + ++static void rk_nfc_chips_cleanup(struct rk_nfc *nfc) ++{ ++ struct rk_nfc_nand_chip *rknand, *tmp; ++ struct nand_chip *chip; ++ int ret; ++ ++ list_for_each_entry_safe(rknand, tmp, &nfc->chips, node) { ++ chip = &rknand->chip; ++ ret = mtd_device_unregister(nand_to_mtd(chip)); ++ WARN_ON(ret); ++ nand_cleanup(chip); ++ list_del(&rknand->node); ++ } ++} ++ +static int rk_nfc_nand_chips_init(struct device *dev, struct rk_nfc *nfc) +{ -+ struct device_node *np = dev->of_node; -+ struct device_node *nand_np; -+ int ret = -EINVAL; -+ int tmp; ++ struct device_node *np = dev->of_node, *nand_np; ++ int nchips = of_get_child_count(np); ++ int ret; + -+ for_each_child_of_node(np, nand_np) { -+ tmp = rk_nfc_nand_chip_init(dev, nfc, nand_np); -+ if (tmp) { -+ of_node_put(nand_np); -+ return ret; -+ } -+ /* At least one nand chip is initialized */ -+ ret = 0; ++ if (!nchips || nchips > NFC_MAX_NSELS) { ++ dev_err(nfc->dev, "Incorrect number of NAND chips (%d)\n", ++ nchips); ++ return -EINVAL; + } + -+ return ret; ++ for_each_child_of_node(np, nand_np) { ++ ret = rk_nfc_nand_chip_init(dev, nfc, nand_np); ++ if (ret) { ++ of_node_put(nand_np); ++ rk_nfc_chips_cleanup(nfc); ++ return ret; ++ } ++ } ++ ++ return 0; +} + +static struct nfc_cfg nfc_v6_cfg = { @@ -1122,7 +1487,6 @@ index 000000000000..1e37a1b6c702 + .dma_oob_buf_off = 0x18, + .dma_st_off = 0x1C, + .bch_st_off = 0x20, -+ .bch_st_off = 0x20, + .randmz_off = 0x150, + .int_en_off = 0x16C, + .int_clr_off = 0x170, @@ -1185,29 +1549,13 @@ index 000000000000..1e37a1b6c702 +}; + +static const struct of_device_id rk_nfc_id_table[] = { -+ {.compatible = "rockchip,px30_nfc", ++ {.compatible = "rockchip,px30-nfc", + .data = &nfc_v9_cfg }, -+ {.compatible = "rockchip,rk3308_nfc", ++ {.compatible = "rockchip,rk2928-nfc", ++ .data = &nfc_v6_cfg }, ++ {.compatible = "rockchip,rv1108-nfc", + .data = &nfc_v8_cfg }, -+ {.compatible = "rockchip,rv1108_nfc", -+ .data = &nfc_v8_cfg }, -+ {.compatible = "rockchip,rk3066_nfc", -+ .data = &nfc_v6_cfg }, -+ {.compatible = "rockchip,rk3188_nfc", -+ .data = &nfc_v6_cfg }, -+ {.compatible = "rockchip,rk3288_nfc", -+ .data = &nfc_v6_cfg }, -+ {.compatible = "rockchip,rk3368_nfc", -+ .data = &nfc_v6_cfg }, -+ {.compatible = "rockchip,rk2928_nfc", -+ .data = &nfc_v6_cfg }, -+ {.compatible = "rockchip,rk3036_nfc", -+ .data = &nfc_v6_cfg }, -+ {.compatible = "rockchip,rk3128_nfc", -+ .data = &nfc_v6_cfg }, -+ {.compatible = "rockchip,rk3228_nfc", -+ .data = &nfc_v6_cfg }, -+ {} ++ { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, rk_nfc_id_table); + @@ -1215,7 +1563,6 @@ index 000000000000..1e37a1b6c702 +{ + struct device *dev = &pdev->dev; + struct rk_nfc *nfc; -+ struct resource *res; + int ret, irq; + + nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL); @@ -1229,18 +1576,20 @@ index 000000000000..1e37a1b6c702 + nfc->cfg = of_device_get_match_data(dev); + nfc->dev = dev; + -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ nfc->regs = devm_ioremap_resource(dev, res); ++ init_completion(&nfc->done); ++ ++ nfc->regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(nfc->regs)) { + ret = PTR_ERR(nfc->regs); + goto release_nfc; + } ++ + nfc->clk.nfc_clk = devm_clk_get(dev, "nfc"); + if (IS_ERR(nfc->clk.nfc_clk)) { -+ dev_err(dev, "no nfc clk\n"); -+ ret = PTR_ERR(nfc->clk.nfc_clk); -+ goto release_nfc; ++ dev_dbg(dev, "no nfc clk\n"); ++ /* Some earlier models, such as rk3066, have no nfc clk. */ + } ++ + nfc->clk.ahb_clk = devm_clk_get(dev, "ahb"); + if (IS_ERR(nfc->clk.ahb_clk)) { + dev_err(dev, "no ahb clk\n"); @@ -1270,7 +1619,7 @@ index 000000000000..1e37a1b6c702 + + ret = rk_nfc_nand_chips_init(dev, nfc); + if (ret) { -+ dev_err(dev, "failed to init nand chips\n"); ++ dev_err(dev, "failed to init NAND chips\n"); + goto clk_disable; + } + return 0; @@ -1284,15 +1633,8 @@ index 000000000000..1e37a1b6c702 +static int rk_nfc_remove(struct platform_device *pdev) +{ + struct rk_nfc *nfc = platform_get_drvdata(pdev); -+ struct rk_nfc_nand_chip *chip; -+ -+ while (!list_empty(&nfc->chips)) { -+ chip = list_first_entry(&nfc->chips, struct rk_nfc_nand_chip, -+ node); -+ nand_release(&chip->nand); -+ list_del(&chip->node); -+ } + ++ rk_nfc_chips_cleanup(nfc); + rk_nfc_disable_clk(&nfc->clk); + + return 0; @@ -1310,8 +1652,8 @@ index 000000000000..1e37a1b6c702 +static int __maybe_unused rk_nfc_resume(struct device *dev) +{ + struct rk_nfc *nfc = dev_get_drvdata(dev); -+ struct rk_nfc_nand_chip *chip; -+ struct nand_chip *nand; ++ struct rk_nfc_nand_chip *rknand; ++ struct nand_chip *chip; + int ret; + u32 i; + @@ -1319,11 +1661,11 @@ index 000000000000..1e37a1b6c702 + if (ret) + return ret; + -+ /* reset NAND chip if VCC was powered off */ -+ list_for_each_entry(chip, &nfc->chips, node) { -+ nand = &chip->nand; -+ for (i = 0; i < chip->nsels; i++) -+ nand_reset(nand, i); ++ /* Reset NAND chip if VCC was powered off. */ ++ list_for_each_entry(rknand, &nfc->chips, node) { ++ chip = &rknand->chip; ++ for (i = 0; i < rknand->nsels; i++) ++ nand_reset(chip, i); + } + + return 0; @@ -1334,10 +1676,10 @@ index 000000000000..1e37a1b6c702 +}; + +static struct platform_driver rk_nfc_driver = { -+ .probe = rk_nfc_probe, ++ .probe = rk_nfc_probe, + .remove = rk_nfc_remove, + .driver = { -+ .name = THIS_NAME, ++ .name = "rockchip-nfc", + .of_match_table = rk_nfc_id_table, + .pm = &rk_nfc_pm_ops, + }, @@ -1348,167 +1690,267 @@ index 000000000000..1e37a1b6c702 +MODULE_LICENSE("Dual MIT/GPL"); +MODULE_AUTHOR("Yifeng Zhao "); +MODULE_DESCRIPTION("Rockchip Nand Flash Controller Driver"); -+MODULE_ALIAS("platform:rockchip_nand"); --- -2.17.1 ++MODULE_ALIAS("platform:rockchip-nand-controller"); - -From d8b77253afb7292f637d62877f7c2e87f440a1ff Mon Sep 17 00:00:00 2001 +From 9f9bc458898c407f25a6d38551713317161b0092 Mon Sep 17 00:00:00 2001 From: Yifeng Zhao -Date: Fri, 20 Mar 2020 17:33:41 +0800 -Subject: [PATCH] dt-bindings: mtd: Describe Rockchip RK3xxx NAND flash - controller +Date: Fri, 17 Jul 2020 17:24:19 +0800 +Subject: [PATCH] MAINTAINERS: add maintainers to ROCKCHIP NFC -Documentation support for Rockchip RK3xxx NAND flash controllers - -Signed-off-by: Yifeng Zhao -Reviewed-by: Rob Herring ---- - .../bindings/mtd/rockchip,nand.yaml | 101 ++++++++++++++++++ - 1 file changed, 101 insertions(+) - create mode 100644 Documentation/devicetree/bindings/mtd/rockchip,nand.yaml - -diff --git a/Documentation/devicetree/bindings/mtd/rockchip,nand.yaml b/Documentation/devicetree/bindings/mtd/rockchip,nand.yaml -new file mode 100644 -index 000000000000..907af0d52b6b ---- /dev/null -+++ b/Documentation/devicetree/bindings/mtd/rockchip,nand.yaml -@@ -0,0 +1,101 @@ -+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/mtd/rockchip,nand.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Rockchip SoCs NAND FLASH Controller (NFC) Device Tree Bindings -+ -+allOf: -+ - $ref: "nand-controller.yaml" -+ -+maintainers: -+ - Yifeng Zhao -+ -+properties: -+ "#address-cells": true -+ "#size-cells": true -+ -+ compatible: -+ enum: -+ - rockchip,px30_nfc -+ - rockchip,rk3308_nfc -+ - rockchip,rv1108_nfc -+ - rockchip,rk3066_nfc -+ - rockchip,rk3188_nfc -+ - rockchip,rk3288_nfc -+ - rockchip,rk3368_nfc -+ - rockchip,rk2928_nfc -+ - rockchip,rk3036_nfc -+ - rockchip,rk3128_nfc -+ - rockchip,rk3228_nfc -+ -+ reg: -+ maxItems: 1 -+ -+ interrupts: -+ maxItems: 1 -+ -+ clocks: -+ items: -+ - description: Module Clock -+ - description: Bus Clock -+ -+ clock-names: -+ items: -+ - const: nfc -+ - const: ahb -+ -+patternProperties: -+ "^nand@[0-3]$": -+ type: object -+ properties: -+ reg: -+ minimum: 0 -+ maximum: 3 -+ -+ nand-ecc-step-size: -+ const: 1024 -+ -+ nand-ecc-strength: -+ enum: [16, 24 , 40, 60, 70] -+ -+ nand-bus-width: -+ const: 8 -+ -+required: -+ - compatible -+ - reg -+ - interrupts -+ - clocks -+ - clock-names -+ -+examples: -+ - | -+ #include -+ #include -+ nfc: nand-controller@ff4b0000 { -+ compatible = "rockchip,nfc"; -+ reg = <0x0 0xff4b0000 0x0 0x4000>; -+ interrupts = ; -+ clocks = <&cru SCLK_NANDC>, <&cru HCLK_NANDC>; -+ clock-names = "nfc", "ahb"; -+ assigned-clocks = <&clks SCLK_NANDC>; -+ assigned-clock-rates = <150000000>; -+ -+ pinctrl-names = "default"; -+ pinctrl-0 = <&flash_csn0 &flash_rdy &flash_ale &flash_cle -+ &flash_wrn &flash_rdn &flash_bus8>; -+ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ nand@0 { -+ reg = <0>; -+ nand-ecc-mode = "hw"; -+ nand-ecc-strength = <16>; -+ nand-ecc-step-size = <1024>; -+ nand-bus-width = <8>; -+ }; -+ }; -+ -+... --- -2.17.1 - - -From 7c0fa2538944c2b988b3575020e4e8b81e8f01ed Mon Sep 17 00:00:00 2001 -From: Yifeng Zhao -Date: Fri, 20 Mar 2020 17:33:42 +0800 -Subject: [PATCH] MAINTAINERS: add maintainers to rockchip nfc +Add maintainers to ROCKCHIP NFC. Signed-off-by: Yifeng Zhao --- - MAINTAINERS | 2 ++ - 1 file changed, 2 insertions(+) + MAINTAINERS | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS -index 5a5332b3591d..0bff05c4c96d 100644 +index 4e2698cc7e23..db98a799f409 100644 --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -2276,6 +2276,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git +@@ -2344,12 +2344,12 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) + L: linux-rockchip@lists.infradead.org S: Maintained - F: Documentation/devicetree/bindings/i2c/i2c-rk3x.txt - F: Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml + T: git git://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git +F: Documentation/devicetree/bindings/*/*rockchip*.yaml + F: Documentation/devicetree/bindings/i2c/i2c-rk3x.yaml +-F: Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml +-F: Documentation/devicetree/bindings/spi/spi-rockchip.yaml F: arch/arm/boot/dts/rk3* F: arch/arm/boot/dts/rv1108* F: arch/arm/mach-rockchip/ -@@ -2283,6 +2284,7 @@ F: drivers/clk/rockchip/ - F: drivers/i2c/busses/i2c-rk3x.c - F: drivers/*/*rockchip* - F: drivers/*/*/*rockchip* +F: drivers/*/*/*/*rockchip* - F: sound/soc/rockchip/ - N: rockchip - --- -2.17.1 + F: drivers/*/*/*rockchip* + F: drivers/*/*rockchip* + F: drivers/clk/rockchip/ +From 48604da8047dc2bb8009ee7af76655b41fb0c337 Mon Sep 17 00:00:00 2001 +From: Yifeng Zhao +Date: Fri, 17 Jul 2020 17:24:20 +0800 +Subject: [PATCH] arm64: dts: rockchip: Add NFC node for RK3308 SoC + +Add NAND FLASH Controller(NFC) node for RK3308 SoC. + +Signed-off-by: Yifeng Zhao +Signed-off-by: Yifeng Zhao +--- + arch/arm64/boot/dts/rockchip/rk3308.dtsi | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3308.dtsi b/arch/arm64/boot/dts/rockchip/rk3308.dtsi +index e8b754d415d8..e9d8610fccf5 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3308.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3308.dtsi +@@ -629,6 +629,21 @@ sdio: mmc@ff4a0000 { + status = "disabled"; + }; + ++ nfc: nand-controller@ff4b0000 { ++ compatible = "rockchip,rk3308-nfc", ++ "rockchip,rv1108-nfc"; ++ reg = <0x0 0xff4b0000 0x0 0x4000>; ++ interrupts = ; ++ clocks = <&cru HCLK_NANDC>, <&cru SCLK_NANDC>; ++ clock-names = "ahb", "nfc"; ++ assigned-clocks = <&cru SCLK_NANDC>; ++ assigned-clock-rates = <150000000>; ++ pinctrl-0 = <&flash_ale &flash_bus8 &flash_cle &flash_csn0 ++ &flash_rdn &flash_rdy &flash_wrn>; ++ pinctrl-names = "default"; ++ status = "disabled"; ++ }; ++ + cru: clock-controller@ff500000 { + compatible = "rockchip,rk3308-cru"; + reg = <0x0 0xff500000 0x0 0x1000>; + +From 046465fffd8f588097ed6f78bc3f193639bd5657 Mon Sep 17 00:00:00 2001 +From: Yifeng Zhao +Date: Fri, 17 Jul 2020 17:25:29 +0800 +Subject: [PATCH] arm64: dts: rockchip: Add NFC node for PX30 SoC + +Add NAND FLASH Controller(NFC) node for PX30 SoC. + +Signed-off-by: Yifeng Zhao +--- + arch/arm64/boot/dts/rockchip/px30.dtsi | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi +index 2695ea8cda14..6cd67e80d623 100644 +--- a/arch/arm64/boot/dts/rockchip/px30.dtsi ++++ b/arch/arm64/boot/dts/rockchip/px30.dtsi +@@ -973,6 +973,21 @@ emmc: mmc@ff390000 { + status = "disabled"; + }; + ++ nfc: nand-controller@ff3b0000 { ++ compatible = "rockchip,px30-nfc"; ++ reg = <0x0 0xff3b0000 0x0 0x4000>; ++ interrupts = ; ++ clocks = <&cru HCLK_NANDC>, <&cru SCLK_NANDC>; ++ clock-names = "ahb", "nfc"; ++ assigned-clocks = <&cru SCLK_NANDC>; ++ assigned-clock-rates = <150000000>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&flash_ale &flash_bus8 &flash_cle &flash_cs0 ++ &flash_rdn &flash_rdy &flash_wrn &flash_dqs>; ++ power-domains = <&power PX30_PD_MMC_NAND>; ++ status = "disabled"; ++ }; ++ + gpu: gpu@ff400000 { + compatible = "rockchip,px30-mali", "arm,mali-bifrost"; + reg = <0x0 0xff400000 0x0 0x4000>; + +From e67947a6ea98d31eda5e900909bc762714e97062 Mon Sep 17 00:00:00 2001 +From: Yifeng Zhao +Date: Fri, 17 Jul 2020 17:25:30 +0800 +Subject: [PATCH] arm: dts: rockchip: Add NFC node for RV1108 SoC + +Add NAND FLASH Controller(NFC) node for RV1108 SoC. + +Signed-off-by: Yifeng Zhao +--- + arch/arm/boot/dts/rv1108.dtsi | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/arch/arm/boot/dts/rv1108.dtsi b/arch/arm/boot/dts/rv1108.dtsi +index a1a08cb9364e..1696ea19488b 100644 +--- a/arch/arm/boot/dts/rv1108.dtsi ++++ b/arch/arm/boot/dts/rv1108.dtsi +@@ -452,6 +452,17 @@ cru: clock-controller@20200000 { + #reset-cells = <1>; + }; + ++ nfc: nand-controller@30100000 { ++ compatible = "rockchip,rv1108-nfc"; ++ reg = <0x30100000 0x1000>; ++ interrupts = ; ++ clocks = <&cru HCLK_NANDC>, <&cru SCLK_NANDC>; ++ clock-names = "ahb", "nfc"; ++ assigned-clocks = <&cru SCLK_NANDC>; ++ assigned-clock-rates = <150000000>; ++ status = "disabled"; ++ }; ++ + emmc: mmc@30110000 { + compatible = "rockchip,rv1108-dw-mshc", "rockchip,rk3288-dw-mshc"; + reg = <0x30110000 0x4000>; + +From 9f1eb721bf42f1470fe280b4f501526a8addd76e Mon Sep 17 00:00:00 2001 +From: Yifeng Zhao +Date: Fri, 17 Jul 2020 17:25:31 +0800 +Subject: [PATCH] arm: dts: rockchip: Add NFC node for RK2928 and other SoCs + +Add NAND FLASH Controller(NFC) node for RK2928, RK3066, RK3168 +and RK3188 SoCs. + +Signed-off-by: Yifeng Zhao +--- + arch/arm/boot/dts/rk3xxx.dtsi | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/arch/arm/boot/dts/rk3xxx.dtsi b/arch/arm/boot/dts/rk3xxx.dtsi +index 859a7477909f..97415180d5bb 100644 +--- a/arch/arm/boot/dts/rk3xxx.dtsi ++++ b/arch/arm/boot/dts/rk3xxx.dtsi +@@ -276,6 +276,15 @@ emmc: mmc@1021c000 { + status = "disabled"; + }; + ++ nfc: nand-controller@10500000 { ++ compatible = "rockchip,rk2928-nfc"; ++ reg = <0x10500000 0x4000>; ++ interrupts = ; ++ clocks = <&cru HCLK_NANDC0>; ++ clock-names = "ahb"; ++ status = "disabled"; ++ }; ++ + pmu: pmu@20004000 { + compatible = "rockchip,rk3066-pmu", "syscon", "simple-mfd"; + reg = <0x20004000 0x100>; + +From b299d8bd1f7b704e89fcb320b4d851cfc3a6f5e9 Mon Sep 17 00:00:00 2001 +From: Yifeng Zhao +Date: Fri, 17 Jul 2020 17:25:32 +0800 +Subject: [PATCH] arm: dts: rockchip: Add NFC node for RK3036 SoC + +Add NAND FLASH Controller(NFC) node for RK3036 SoC. + +Signed-off-by: Yifeng Zhao +--- + arch/arm/boot/dts/rk3036.dtsi | 52 +++++++++++++++++++++++++++++++++++ + 1 file changed, 52 insertions(+) + +diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi +index 093567022386..dda5a1f79aca 100644 +--- a/arch/arm/boot/dts/rk3036.dtsi ++++ b/arch/arm/boot/dts/rk3036.dtsi +@@ -292,6 +292,21 @@ i2s: i2s@10220000 { + status = "disabled"; + }; + ++ nfc: nand-controller@10500000 { ++ compatible = "rockchip,rk3036-nfc", ++ "rockchip,rk2928-nfc"; ++ reg = <0x10500000 0x4000>; ++ interrupts = ; ++ clocks = <&cru HCLK_NANDC>, <&cru SCLK_NANDC>; ++ clock-names = "ahb", "nfc"; ++ assigned-clocks = <&cru SCLK_NANDC>; ++ assigned-clock-rates = <150000000>; ++ pinctrl-0 = <&flash_ale &flash_bus8 &flash_cle &flash_csn0 ++ &flash_rdn &flash_rdy &flash_wrn>; ++ pinctrl-names = "default"; ++ status = "disabled"; ++ }; ++ + cru: clock-controller@20000000 { + compatible = "rockchip,rk3036-cru"; + reg = <0x20000000 0x1000>; +@@ -643,6 +658,43 @@ emmc_bus8: emmc-bus8 { + }; + }; + ++ nfc { ++ flash_ale: flash-ale { ++ rockchip,pins = <2 RK_PA0 1 &pcfg_pull_default>; ++ }; ++ ++ flash_bus8: flash-bus8 { ++ rockchip,pins = <1 RK_PD0 1 &pcfg_pull_default>, ++ <1 RK_PD1 1 &pcfg_pull_default>, ++ <1 RK_PD2 1 &pcfg_pull_default>, ++ <1 RK_PD3 1 &pcfg_pull_default>, ++ <1 RK_PD4 1 &pcfg_pull_default>, ++ <1 RK_PD5 1 &pcfg_pull_default>, ++ <1 RK_PD6 1 &pcfg_pull_default>, ++ <1 RK_PD7 1 &pcfg_pull_default>; ++ }; ++ ++ flash_cle: flash-cle { ++ rockchip,pins = <2 RK_PA1 1 &pcfg_pull_default>; ++ }; ++ ++ flash_csn0: flash-csn0 { ++ rockchip,pins = <2 RK_PA6 1 &pcfg_pull_default>; ++ }; ++ ++ flash_rdn: flash-rdn { ++ rockchip,pins = <2 RK_PA3 1 &pcfg_pull_default>; ++ }; ++ ++ flash_rdy: flash-rdy { ++ rockchip,pins = <2 RK_PA4 1 &pcfg_pull_default>; ++ }; ++ ++ flash_wrn: flash-wrn { ++ rockchip,pins = <2 RK_PA2 1 &pcfg_pull_default>; ++ }; ++ }; ++ + emac { + emac_xfer: emac-xfer { + rockchip,pins = <2 RK_PB2 1 &pcfg_pull_default>, /* crs_dvalid */ diff --git a/patch/kernel/rk322x-current/01-linux-0004-work-in-progress.patch.disabled b/patch/kernel/rk322x-current/01-linux-0004-work-in-progress.patch.disabled deleted file mode 100644 index c09268ef6..000000000 --- a/patch/kernel/rk322x-current/01-linux-0004-work-in-progress.patch.disabled +++ /dev/null @@ -1,2864 +0,0 @@ -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -index 5749bdaba95b..3b383f73fcb0 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -@@ -197,7 +197,7 @@ struct dw_hdmi { - - hdmi_codec_plugged_cb plugged_cb; - struct device *codec_dev; -- enum drm_connector_status last_connector_result; -+ enum drm_connector_status last_connector_status; - }; - - #define HDMI_IH_PHY_STAT0_RX_SENSE \ -@@ -236,7 +236,7 @@ int dw_hdmi_set_plugged_cb(struct dw_hdmi *hdmi, hdmi_codec_plugged_cb fn, - mutex_lock(&hdmi->mutex); - hdmi->plugged_cb = fn; - hdmi->codec_dev = codec_dev; -- plugged = hdmi->last_connector_result == connector_status_connected; -+ plugged = hdmi->last_connector_status == connector_status_connected; - handle_plugged_change(hdmi, plugged); - mutex_unlock(&hdmi->mutex); - -@@ -2277,7 +2277,7 @@ dw_hdmi_connector_detect(struct drm_connector *connector, bool force) - { - struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, - connector); -- enum drm_connector_status result; -+ enum drm_connector_status status; - - mutex_lock(&hdmi->mutex); - hdmi->force = DRM_FORCE_UNSPECIFIED; -@@ -2285,18 +2285,18 @@ dw_hdmi_connector_detect(struct drm_connector *connector, bool force) - dw_hdmi_update_phy_mask(hdmi); - mutex_unlock(&hdmi->mutex); - -- result = hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data); -+ status = hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data); - - mutex_lock(&hdmi->mutex); -- if (result != hdmi->last_connector_result) { -- dev_dbg(hdmi->dev, "read_hpd result: %d", result); -+ if (status != hdmi->last_connector_status) { -+ dev_dbg(hdmi->dev, "connector status: %d", status); - handle_plugged_change(hdmi, -- result == connector_status_connected); -- hdmi->last_connector_result = result; -+ status == connector_status_connected); -+ hdmi->last_connector_status = status; - } - mutex_unlock(&hdmi->mutex); - -- return result; -+ return status; - } - - static int dw_hdmi_connector_get_modes(struct drm_connector *connector) -@@ -3059,7 +3059,7 @@ __dw_hdmi_probe(struct platform_device *pdev, - hdmi->rxsense = true; - hdmi->phy_mask = (u8)~(HDMI_PHY_HPD | HDMI_PHY_RX_SENSE); - hdmi->mc_clkdis = 0x7f; -- hdmi->last_connector_result = connector_status_disconnected; -+ hdmi->last_connector_status = connector_status_disconnected; - - mutex_init(&hdmi->mutex); - mutex_init(&hdmi->audio_mutex); --- -2.17.1 - - -From 2cdd6cd8eae12254226b6f3e30c5bcc52ac93ca7 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 1 Dec 2019 20:51:22 +0000 -Subject: [PATCH] drm: dw-hdmi: extract handle_plugged_change call - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 22 ++++++++++++++-------- - 1 file changed, 14 insertions(+), 8 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -index 3b383f73fcb0..bb430c48488f 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -@@ -228,6 +228,19 @@ static void handle_plugged_change(struct dw_hdmi *hdmi, bool plugged) - hdmi->plugged_cb(hdmi->codec_dev, plugged); - } - -+static void dw_hdmi_update_connector_status(struct dw_hdmi *hdmi, -+ enum drm_connector_status status) -+{ -+ mutex_lock(&hdmi->mutex); -+ if (status != hdmi->last_connector_status) { -+ dev_dbg(hdmi->dev, "connector status: %d", status); -+ handle_plugged_change(hdmi, -+ status == connector_status_connected); -+ hdmi->last_connector_status = status; -+ } -+ mutex_unlock(&hdmi->mutex); -+} -+ - int dw_hdmi_set_plugged_cb(struct dw_hdmi *hdmi, hdmi_codec_plugged_cb fn, - struct device *codec_dev) - { -@@ -2287,14 +2300,7 @@ dw_hdmi_connector_detect(struct drm_connector *connector, bool force) - - status = hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data); - -- mutex_lock(&hdmi->mutex); -- if (status != hdmi->last_connector_status) { -- dev_dbg(hdmi->dev, "connector status: %d", status); -- handle_plugged_change(hdmi, -- status == connector_status_connected); -- hdmi->last_connector_status = status; -- } -- mutex_unlock(&hdmi->mutex); -+ dw_hdmi_update_connector_status(hdmi, status); - - return status; - } --- -2.17.1 - - -From 979981e11fa3ba5e94d25d22f7d0cdc55e8f9348 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sat, 28 Sep 2019 13:34:46 +0000 -Subject: [PATCH] drm: dw-hdmi: remove unused struct member - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 4 ---- - 1 file changed, 4 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -index bb430c48488f..06620adfed95 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -@@ -41,8 +41,6 @@ - #define DDC_CI_ADDR 0x37 - #define DDC_SEGMENT_ADDR 0x30 - --#define HDMI_EDID_LEN 512 -- - /* DW-HDMI Controller >= 0x200a are at least compliant with SCDC version 1 */ - #define SCDC_MIN_SOURCE_VERSION 0x1 - -@@ -152,8 +150,6 @@ struct dw_hdmi { - - int vic; - -- u8 edid[HDMI_EDID_LEN]; -- - struct { - const struct dw_hdmi_phy_ops *ops; - const char *name; --- -2.17.1 - - -From 74adf054fd1d83d31f03085ec4574318cb135c95 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sat, 28 Sep 2019 13:34:46 +0000 -Subject: [PATCH] drm: dw-hdmi: read edid in detect callback - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 79 +++++++++++++++++------ - 1 file changed, 58 insertions(+), 21 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -index 06620adfed95..a304dff5f1be 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -@@ -150,6 +150,8 @@ struct dw_hdmi { - - int vic; - -+ struct edid *cached_edid; -+ - struct { - const struct dw_hdmi_phy_ops *ops; - const char *name; -@@ -2223,9 +2225,55 @@ static void initialize_hdmi_ih_mutes(struct dw_hdmi *hdmi) - hdmi_writeb(hdmi, ih_mute, HDMI_IH_MUTE); - } - -+static void dw_hdmi_clear_edid(struct drm_connector *connector) -+{ -+ struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, -+ connector); -+ -+ if (!hdmi->cached_edid) -+ return; -+ -+ hdmi->sink_is_hdmi = false; -+ hdmi->sink_has_audio = false; -+ -+ kfree(hdmi->cached_edid); -+ hdmi->cached_edid = NULL; -+} -+ -+static void dw_hdmi_get_edid(struct drm_connector *connector) -+{ -+ struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, -+ connector); -+ struct edid *edid; -+ -+ if (!hdmi->ddc || hdmi->cached_edid) -+ return; -+ -+ edid = drm_get_edid(connector, hdmi->ddc); -+ -+ if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) { -+ dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]\n", -+ edid->width_cm, edid->height_cm); -+ -+ hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid); -+ hdmi->sink_has_audio = drm_detect_monitor_audio(edid); -+ -+ hdmi->cached_edid = edid; -+ } else { -+ dev_dbg(hdmi->dev, "failed to get edid\n"); -+ -+ kfree(edid); -+ edid = NULL; -+ } -+ -+ drm_connector_update_edid_property(connector, edid); -+ cec_notifier_set_phys_addr_from_edid(hdmi->cec_notifier, edid); -+} -+ - static void dw_hdmi_poweron(struct dw_hdmi *hdmi) - { - hdmi->bridge_is_on = true; -+ dw_hdmi_get_edid(&hdmi->connector); - dw_hdmi_setup(hdmi, &hdmi->previous_mode); - } - -@@ -2296,6 +2344,11 @@ dw_hdmi_connector_detect(struct drm_connector *connector, bool force) - - status = hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data); - -+ if (status == connector_status_disconnected) -+ dw_hdmi_clear_edid(connector); -+ else -+ dw_hdmi_get_edid(connector); -+ - dw_hdmi_update_connector_status(hdmi, status); - - return status; -@@ -2305,28 +2358,8 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector) - { - struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, - connector); -- struct edid *edid; -- int ret = 0; -- -- if (!hdmi->ddc) -- return 0; - -- edid = drm_get_edid(connector, hdmi->ddc); -- if (edid) { -- dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]\n", -- edid->width_cm, edid->height_cm); -- -- hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid); -- hdmi->sink_has_audio = drm_detect_monitor_audio(edid); -- drm_connector_update_edid_property(connector, edid); -- cec_notifier_set_phys_addr_from_edid(hdmi->cec_notifier, edid); -- ret = drm_add_edid_modes(connector, edid); -- kfree(edid); -- } else { -- dev_dbg(hdmi->dev, "failed to get edid\n"); -- } -- -- return ret; -+ return drm_add_edid_modes(connector, hdmi->cached_edid); - } - - static bool hdr_metadata_equal(const struct drm_connector_state *old_state, -@@ -2705,6 +2738,9 @@ static void dw_hdmi_bridge_detach(struct drm_bridge *bridge) - cec_notifier_conn_unregister(hdmi->cec_notifier); - hdmi->cec_notifier = NULL; - mutex_unlock(&hdmi->cec_notifier_mutex); -+ -+ kfree(hdmi->cached_edid); -+ hdmi->cached_edid = NULL; - } - - static enum drm_mode_status -@@ -3394,6 +3430,7 @@ EXPORT_SYMBOL_GPL(dw_hdmi_unbind); - - void dw_hdmi_resume(struct dw_hdmi *hdmi) - { -+ dw_hdmi_clear_edid(&hdmi->connector); - dw_hdmi_init_hw(hdmi); - } - EXPORT_SYMBOL_GPL(dw_hdmi_resume); --- -2.17.1 - - -From f44056d77b1e928d0eec26eef9d35ce3c7b04d30 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sat, 28 Sep 2019 13:34:47 +0000 -Subject: [PATCH] drm: dw-hdmi: read edid in force callback - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -index a304dff5f1be..49a9611249d2 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -@@ -2411,6 +2411,13 @@ static void dw_hdmi_connector_force(struct drm_connector *connector) - dw_hdmi_update_power(hdmi); - dw_hdmi_update_phy_mask(hdmi); - mutex_unlock(&hdmi->mutex); -+ -+ dw_hdmi_clear_edid(connector); -+ -+ if (connector->status != connector_status_connected) -+ return; -+ -+ dw_hdmi_get_edid(connector); - } - - static const struct drm_connector_funcs dw_hdmi_connector_funcs = { --- -2.17.1 - - -From 27119e85c5368957ac0182418a26d473dd94ab49 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sat, 28 Sep 2019 13:34:47 +0000 -Subject: [PATCH] drm: dw-hdmi: invalidate cec phys addr in detect callback - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 17 +++-------------- - 1 file changed, 3 insertions(+), 14 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -index 49a9611249d2..b9fa6c3b07c0 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -@@ -190,7 +190,6 @@ struct dw_hdmi { - void (*enable_audio)(struct dw_hdmi *hdmi); - void (*disable_audio)(struct dw_hdmi *hdmi); - -- struct mutex cec_notifier_mutex; - struct cec_notifier *cec_notifier; - - hdmi_codec_plugged_cb plugged_cb; -@@ -2238,6 +2237,8 @@ static void dw_hdmi_clear_edid(struct drm_connector *connector) - - kfree(hdmi->cached_edid); - hdmi->cached_edid = NULL; -+ -+ cec_notifier_phys_addr_invalidate(hdmi->cec_notifier); - } - - static void dw_hdmi_get_edid(struct drm_connector *connector) -@@ -2730,9 +2731,7 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge) - if (!notifier) - return -ENOMEM; - -- mutex_lock(&hdmi->cec_notifier_mutex); - hdmi->cec_notifier = notifier; -- mutex_unlock(&hdmi->cec_notifier_mutex); - - return 0; - } -@@ -2741,10 +2740,8 @@ static void dw_hdmi_bridge_detach(struct drm_bridge *bridge) - { - struct dw_hdmi *hdmi = bridge->driver_private; - -- mutex_lock(&hdmi->cec_notifier_mutex); - cec_notifier_conn_unregister(hdmi->cec_notifier); - hdmi->cec_notifier = NULL; -- mutex_unlock(&hdmi->cec_notifier_mutex); - - kfree(hdmi->cached_edid); - hdmi->cached_edid = NULL; -@@ -2912,18 +2909,11 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) - * ask the source to re-read the EDID. - */ - if (intr_stat & -- (HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD)) { -+ (HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD)) - dw_hdmi_setup_rx_sense(hdmi, - phy_stat & HDMI_PHY_HPD, - phy_stat & HDMI_PHY_RX_SENSE); - -- if ((phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD)) == 0) { -- mutex_lock(&hdmi->cec_notifier_mutex); -- cec_notifier_phys_addr_invalidate(hdmi->cec_notifier); -- mutex_unlock(&hdmi->cec_notifier_mutex); -- } -- } -- - if (intr_stat & HDMI_IH_PHY_STAT0_HPD) { - dev_dbg(hdmi->dev, "EVENT=%s\n", - phy_int_pol & HDMI_PHY_HPD ? "plugin" : "plugout"); -@@ -3108,7 +3098,6 @@ __dw_hdmi_probe(struct platform_device *pdev, - - mutex_init(&hdmi->mutex); - mutex_init(&hdmi->audio_mutex); -- mutex_init(&hdmi->cec_notifier_mutex); - spin_lock_init(&hdmi->audio_lock); - - ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0); --- -2.17.1 - - -From d6fca8d650a43ed3ef7d8efb3b51b2e7c3a0a8ba Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 8 Dec 2019 23:41:44 +0000 -Subject: [PATCH] WIP: drm: dw-hdmi: do not force none scan mode - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 2 -- - 1 file changed, 2 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -index b9fa6c3b07c0..4d253e5a1c79 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -@@ -1664,8 +1664,6 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode) - HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; - } - -- frame.scan_mode = HDMI_SCAN_MODE_NONE; -- - /* - * The Designware IP uses a different byte format from standard - * AVI info frames, though generally the bits are in the correct --- -2.17.1 - - -From b16f499ce83d7b9084073e813943ae98d4f5c716 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 8 Dec 2019 23:42:44 +0000 -Subject: [PATCH] WIP: drm: dw-hdmi: add content type connector property - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -index 4d253e5a1c79..cd10554cde76 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -@@ -1617,6 +1617,7 @@ static void hdmi_tx_hdcp_config(struct dw_hdmi *hdmi) - - static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode) - { -+ const struct drm_connector_state *conn_state = hdmi->connector.state; - struct hdmi_avi_infoframe frame; - u8 val; - -@@ -1664,6 +1665,8 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode) - HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; - } - -+ drm_hdmi_avi_infoframe_content_type(&frame, conn_state); -+ - /* - * The Designware IP uses a different byte format from standard - * AVI info frames, though generally the bits are in the correct -@@ -2389,7 +2392,8 @@ static int dw_hdmi_connector_atomic_check(struct drm_connector *connector, - if (!crtc) - return 0; - -- if (!hdr_metadata_equal(old_state, new_state)) { -+ if (!hdr_metadata_equal(old_state, new_state) || -+ old_state->content_type != new_state->content_type) { - crtc_state = drm_atomic_get_crtc_state(state, crtc); - if (IS_ERR(crtc_state)) - return PTR_ERR(crtc_state); -@@ -2717,6 +2721,8 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge) - - drm_connector_attach_max_bpc_property(connector, 8, 16); - -+ drm_connector_attach_content_type_property(connector); -+ - if (hdmi->version >= 0x200a && hdmi->plat_data->use_drm_infoframe) - drm_object_attach_property(&connector->base, - connector->dev->mode_config.hdr_output_metadata_property, 0); --- -2.17.1 - - -From 2203d10f59f25af58fe1f5aaaceb3980ccea2f39 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 8 Dec 2019 23:43:55 +0000 -Subject: [PATCH] WIP: drm: dw-hdmi: add SPD infoframe - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 42 +++++++++++++++++++---- - drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 32 +++++++++-------- - 2 files changed, 53 insertions(+), 21 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -index cd10554cde76..5377c55e9927 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -@@ -1733,6 +1733,35 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode) - hdmi_writeb(hdmi, (frame.right_bar >> 8) & 0xff, HDMI_FC_AVISRB1); - } - -+static void hdmi_config_spd_infoframe(struct dw_hdmi *hdmi) -+{ -+ struct hdmi_spd_infoframe frame; -+ u8 buffer[29]; -+ ssize_t err; -+ int i; -+ -+ hdmi_mask_writeb(hdmi, 0, HDMI_FC_DATAUTO0, HDMI_FC_DATAUTO0_SPD_OFFSET, -+ HDMI_FC_DATAUTO0_SPD_MASK); -+ -+ err = hdmi_spd_infoframe_init(&frame, "DW", "HDMI"); -+ if (err < 0) -+ return; -+ -+ frame.sdi = HDMI_SPD_SDI_PC; -+ -+ err = hdmi_spd_infoframe_pack(&frame, buffer, sizeof(buffer)); -+ if (err < 0) { -+ dev_err(hdmi->dev, "Failed to pack spd infoframe: %zd\n", err); -+ return; -+ } -+ -+ for (i = 0; i < frame.length; i++) -+ hdmi_writeb(hdmi, buffer[4 + i], HDMI_FC_SPDVENDORNAME0 + i); -+ -+ hdmi_mask_writeb(hdmi, 1, HDMI_FC_DATAUTO0, HDMI_FC_DATAUTO0_SPD_OFFSET, -+ HDMI_FC_DATAUTO0_SPD_MASK); -+} -+ - static void hdmi_config_vendor_specific_infoframe(struct dw_hdmi *hdmi, - struct drm_display_mode *mode) - { -@@ -1776,12 +1805,6 @@ static void hdmi_config_vendor_specific_infoframe(struct dw_hdmi *hdmi, - if (frame.s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF) - hdmi_writeb(hdmi, buffer[9], HDMI_FC_VSDPAYLOAD2); - -- /* Packet frame interpolation */ -- hdmi_writeb(hdmi, 1, HDMI_FC_DATAUTO1); -- -- /* Auto packets per frame and line spacing */ -- hdmi_writeb(hdmi, 0x11, HDMI_FC_DATAUTO2); -- - /* Configures the Frame Composer On RDRB mode */ - hdmi_mask_writeb(hdmi, 1, HDMI_FC_DATAUTO0, HDMI_FC_DATAUTO0_VSD_OFFSET, - HDMI_FC_DATAUTO0_VSD_MASK); -@@ -2158,8 +2181,15 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode) - - /* HDMI Initialization Step F - Configure AVI InfoFrame */ - hdmi_config_AVI(hdmi, mode); -+ hdmi_config_spd_infoframe(hdmi); - hdmi_config_vendor_specific_infoframe(hdmi, mode); - hdmi_config_drm_infoframe(hdmi); -+ -+ /* Packet frame interpolation */ -+ hdmi_writeb(hdmi, 1, HDMI_FC_DATAUTO1); -+ -+ /* Auto packets per frame and line spacing */ -+ hdmi_writeb(hdmi, 0x11, HDMI_FC_DATAUTO2); - } else { - dev_dbg(hdmi->dev, "%s DVI mode\n", __func__); - } -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h -index 1999db05bc3b..27a91128d0cc 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h -@@ -139,21 +139,21 @@ - #define HDMI_FC_SPDVENDORNAME5 0x104F - #define HDMI_FC_SPDVENDORNAME6 0x1050 - #define HDMI_FC_SPDVENDORNAME7 0x1051 --#define HDMI_FC_SDPPRODUCTNAME0 0x1052 --#define HDMI_FC_SDPPRODUCTNAME1 0x1053 --#define HDMI_FC_SDPPRODUCTNAME2 0x1054 --#define HDMI_FC_SDPPRODUCTNAME3 0x1055 --#define HDMI_FC_SDPPRODUCTNAME4 0x1056 --#define HDMI_FC_SDPPRODUCTNAME5 0x1057 --#define HDMI_FC_SDPPRODUCTNAME6 0x1058 --#define HDMI_FC_SDPPRODUCTNAME7 0x1059 --#define HDMI_FC_SDPPRODUCTNAME8 0x105A --#define HDMI_FC_SDPPRODUCTNAME9 0x105B --#define HDMI_FC_SDPPRODUCTNAME10 0x105C --#define HDMI_FC_SDPPRODUCTNAME11 0x105D --#define HDMI_FC_SDPPRODUCTNAME12 0x105E --#define HDMI_FC_SDPPRODUCTNAME13 0x105F --#define HDMI_FC_SDPPRODUCTNAME14 0x1060 -+#define HDMI_FC_SPDPRODUCTNAME0 0x1052 -+#define HDMI_FC_SPDPRODUCTNAME1 0x1053 -+#define HDMI_FC_SPDPRODUCTNAME2 0x1054 -+#define HDMI_FC_SPDPRODUCTNAME3 0x1055 -+#define HDMI_FC_SPDPRODUCTNAME4 0x1056 -+#define HDMI_FC_SPDPRODUCTNAME5 0x1057 -+#define HDMI_FC_SPDPRODUCTNAME6 0x1058 -+#define HDMI_FC_SPDPRODUCTNAME7 0x1059 -+#define HDMI_FC_SPDPRODUCTNAME8 0x105A -+#define HDMI_FC_SPDPRODUCTNAME9 0x105B -+#define HDMI_FC_SPDPRODUCTNAME10 0x105C -+#define HDMI_FC_SPDPRODUCTNAME11 0x105D -+#define HDMI_FC_SPDPRODUCTNAME12 0x105E -+#define HDMI_FC_SPDPRODUCTNAME13 0x105F -+#define HDMI_FC_SPDPRODUCTNAME14 0x1060 - #define HDMI_FC_SPDPRODUCTNAME15 0x1061 - #define HDMI_FC_SPDDEVICEINF 0x1062 - #define HDMI_FC_AUDSCONF 0x1063 -@@ -849,6 +849,8 @@ enum { - /* FC_DATAUTO0 field values */ - HDMI_FC_DATAUTO0_VSD_MASK = 0x08, - HDMI_FC_DATAUTO0_VSD_OFFSET = 3, -+ HDMI_FC_DATAUTO0_SPD_MASK = 0x10, -+ HDMI_FC_DATAUTO0_SPD_OFFSET = 4, - - /* PHY_CONF0 field values */ - HDMI_PHY_CONF0_PDZ_MASK = 0x80, --- -2.17.1 - - -From 02f9cee9acb20262ed704ac658c1f61fbcbb8294 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 29 Sep 2019 13:47:38 +0000 -Subject: [PATCH] WIP: drm: dw-hdmi: debugging logging - ---- - drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 28 +++++++++++++-- - drivers/video/hdmi.c | 44 +++++++++++++++++------ - 2 files changed, 59 insertions(+), 13 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -index 5377c55e9927..cc39b544ae6e 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -@@ -1667,6 +1667,8 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode) - - drm_hdmi_avi_infoframe_content_type(&frame, conn_state); - -+ hdmi_infoframe_log(KERN_INFO, hdmi->dev, (union hdmi_infoframe *)&frame); -+ - /* - * The Designware IP uses a different byte format from standard - * AVI info frames, though generally the bits are in the correct -@@ -1755,6 +1757,8 @@ static void hdmi_config_spd_infoframe(struct dw_hdmi *hdmi) - return; - } - -+ hdmi_infoframe_log(KERN_INFO, hdmi->dev, (union hdmi_infoframe *)&frame); -+ - for (i = 0; i < frame.length; i++) - hdmi_writeb(hdmi, buffer[4 + i], HDMI_FC_SPDVENDORNAME0 + i); - -@@ -1769,6 +1773,9 @@ static void hdmi_config_vendor_specific_infoframe(struct dw_hdmi *hdmi, - u8 buffer[10]; - ssize_t err; - -+ hdmi_mask_writeb(hdmi, 0, HDMI_FC_DATAUTO0, HDMI_FC_DATAUTO0_VSD_OFFSET, -+ HDMI_FC_DATAUTO0_VSD_MASK); -+ - err = drm_hdmi_vendor_infoframe_from_display_mode(&frame, - &hdmi->connector, - mode); -@@ -1787,8 +1794,8 @@ static void hdmi_config_vendor_specific_infoframe(struct dw_hdmi *hdmi, - err); - return; - } -- hdmi_mask_writeb(hdmi, 0, HDMI_FC_DATAUTO0, HDMI_FC_DATAUTO0_VSD_OFFSET, -- HDMI_FC_DATAUTO0_VSD_MASK); -+ -+ hdmi_infoframe_log(KERN_INFO, hdmi->dev, (union hdmi_infoframe *)&frame); - - /* Set the length of HDMI vendor specific InfoFrame payload */ - hdmi_writeb(hdmi, buffer[2], HDMI_FC_VSDSIZE); -@@ -1834,6 +1841,8 @@ static void hdmi_config_drm_infoframe(struct dw_hdmi *hdmi) - return; - } - -+ hdmi_infoframe_log(KERN_INFO, hdmi->dev, (union hdmi_infoframe *)&frame); -+ - hdmi_writeb(hdmi, frame.version, HDMI_FC_DRM_HB0); - hdmi_writeb(hdmi, frame.length, HDMI_FC_DRM_HB1); - -@@ -2368,6 +2377,9 @@ dw_hdmi_connector_detect(struct drm_connector *connector, bool force) - connector); - enum drm_connector_status status; - -+ DRM_DEBUG_KMS("[CONNECTOR:%d:%s] force=%d\n", -+ connector->base.id, connector->name, force); -+ - mutex_lock(&hdmi->mutex); - hdmi->force = DRM_FORCE_UNSPECIFIED; - dw_hdmi_update_power(hdmi); -@@ -2391,6 +2403,9 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector) - struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, - connector); - -+ DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", -+ connector->base.id, connector->name); -+ - return drm_add_edid_modes(connector, hdmi->cached_edid); - } - -@@ -2429,6 +2444,12 @@ static int dw_hdmi_connector_atomic_check(struct drm_connector *connector, - return PTR_ERR(crtc_state); - - crtc_state->mode_changed = true; -+ -+ DRM_DEBUG_KMS("[CONNECTOR:%d:%s] hdr_metadata_equal=false\n", -+ connector->base.id, connector->name); -+ } else { -+ DRM_DEBUG_KMS("[CONNECTOR:%d:%s] hdr_metadata_equal=true\n", -+ connector->base.id, connector->name); - } - - return 0; -@@ -2439,6 +2460,9 @@ static void dw_hdmi_connector_force(struct drm_connector *connector) - struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, - connector); - -+ DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", -+ connector->base.id, connector->name); -+ - mutex_lock(&hdmi->mutex); - hdmi->force = connector->force; - dw_hdmi_update_power(hdmi); -diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c -index 9c82e2a0a411..c3b96d3c59e1 100644 ---- a/drivers/video/hdmi.c -+++ b/drivers/video/hdmi.c -@@ -1419,6 +1419,27 @@ static void hdmi_audio_infoframe_log(const char *level, - frame->downmix_inhibit ? "Yes" : "No"); - } - -+static const char * -+hdmi_eotf_get_name(enum hdmi_eotf eotf) -+{ -+ if (eotf < 0 || eotf > 7) -+ return "Invalid"; -+ -+ switch (eotf) { -+ case HDMI_EOTF_TRADITIONAL_GAMMA_SDR: -+ return "Traditional Gamma - SDR"; -+ case HDMI_EOTF_TRADITIONAL_GAMMA_HDR: -+ return "Traditional Gamma - HDR"; -+ case HDMI_EOTF_SMPTE_ST2084: -+ return "SMPTE ST 2084"; -+ case HDMI_EOTF_BT_2100_HLG: -+ return "Hybrid Log-Gamma (HLG)"; -+ default: -+ break; -+ } -+ return "Reserved"; -+} -+ - static void hdmi_drm_infoframe_log(const char *level, - struct device *dev, - const struct hdmi_drm_infoframe *frame) -@@ -1427,24 +1448,25 @@ static void hdmi_drm_infoframe_log(const char *level, - - hdmi_infoframe_log_header(level, dev, - (struct hdmi_any_infoframe *)frame); -- hdmi_log("length: %d\n", frame->length); -- hdmi_log("metadata type: %d\n", frame->metadata_type); -- hdmi_log("eotf: %d\n", frame->eotf); -+ hdmi_log(" metadata type: %d\n", frame->metadata_type); -+ hdmi_log(" eotf: %s\n", hdmi_eotf_get_name(frame->eotf)); -+ -+ hdmi_log(" display primaries:\n"); - for (i = 0; i < 3; i++) { -- hdmi_log("x[%d]: %d\n", i, frame->display_primaries[i].x); -- hdmi_log("y[%d]: %d\n", i, frame->display_primaries[i].y); -+ hdmi_log(" x[%d]: %d\n", i, frame->display_primaries[i].x); -+ hdmi_log(" y[%d]: %d\n", i, frame->display_primaries[i].y); - } - -- hdmi_log("white point x: %d\n", frame->white_point.x); -- hdmi_log("white point y: %d\n", frame->white_point.y); -+ hdmi_log(" white point x: %d\n", frame->white_point.x); -+ hdmi_log(" white point y: %d\n", frame->white_point.y); - -- hdmi_log("max_display_mastering_luminance: %d\n", -+ hdmi_log(" max display mastering luminance: %d\n", - frame->max_display_mastering_luminance); -- hdmi_log("min_display_mastering_luminance: %d\n", -+ hdmi_log(" min display mastering luminance: %d\n", - frame->min_display_mastering_luminance); - -- hdmi_log("max_cll: %d\n", frame->max_cll); -- hdmi_log("max_fall: %d\n", frame->max_fall); -+ hdmi_log(" max cll: %d\n", frame->max_cll); -+ hdmi_log(" max fall: %d\n", frame->max_fall); - } - - static const char * --- -2.17.1 - - -From 3c3374a1fbf631037b9fa87a6ddbfdc921cdf16c Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Tue, 26 Feb 2019 20:45:14 +0000 -Subject: [PATCH] WIP: dw-hdmi-cec: sleep 100ms on error - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c | 19 +++++++++++++++++-- - 1 file changed, 17 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c -index 70ab4fbdc23e..f6a85f73b90d 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c -@@ -4,6 +4,7 @@ - * - * Copyright (C) 2015-2017 Russell King. - */ -+#include - #include - #include - #include -@@ -129,8 +130,16 @@ static irqreturn_t dw_hdmi_cec_hardirq(int irq, void *data) - - dw_hdmi_write(cec, stat, HDMI_IH_CEC_STAT0); - -- if (stat & CEC_STAT_ERROR_INIT) { -- cec->tx_status = CEC_TX_STATUS_ERROR; -+ /* -+ * Status with both done and error_initiator bits have been seen -+ * on Rockchip RK3328 devices, transmit attempt seems to have failed -+ * when this happens, report as low drive and block cec-framework -+ * 100ms before core retransmits the failed message, this seems to -+ * mitigate the issue with failed transmit attempts. -+ */ -+ if ((stat & (CEC_STAT_DONE|CEC_STAT_ERROR_INIT)) == (CEC_STAT_DONE|CEC_STAT_ERROR_INIT)) { -+ pr_info("dw_hdmi_cec_hardirq: stat=%02x LOW_DRIVE\n", stat); -+ cec->tx_status = CEC_TX_STATUS_LOW_DRIVE; - cec->tx_done = true; - ret = IRQ_WAKE_THREAD; - } else if (stat & CEC_STAT_DONE) { -@@ -141,6 +150,10 @@ static irqreturn_t dw_hdmi_cec_hardirq(int irq, void *data) - cec->tx_status = CEC_TX_STATUS_NACK; - cec->tx_done = true; - ret = IRQ_WAKE_THREAD; -+ } else if (stat & CEC_STAT_ERROR_INIT) { -+ cec->tx_status = CEC_TX_STATUS_ERROR; -+ cec->tx_done = true; -+ ret = IRQ_WAKE_THREAD; - } - - if (stat & CEC_STAT_EOM) { -@@ -173,6 +186,8 @@ static irqreturn_t dw_hdmi_cec_thread(int irq, void *data) - - if (cec->tx_done) { - cec->tx_done = false; -+ if (cec->tx_status == CEC_TX_STATUS_LOW_DRIVE) -+ msleep(100); - cec_transmit_attempt_done(adap, cec->tx_status); - } - if (cec->rx_done) { --- -2.17.1 - - -From 8a6b932299c4cf68942cbe1809c4f6a846ef54a1 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Fri, 11 Oct 2019 08:01:37 +0000 -Subject: [PATCH] mmc: dw_mmc: add power_off callback - -Signed-off-by: Jonas Karlman ---- - drivers/mmc/host/dw_mmc.c | 3 +++ - drivers/mmc/host/dw_mmc.h | 1 + - 2 files changed, 4 insertions(+) - -diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c -index bc5278ab5707..f192963c2c68 100644 ---- a/drivers/mmc/host/dw_mmc.c -+++ b/drivers/mmc/host/dw_mmc.c -@@ -1495,6 +1495,9 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) - regulator_disable(mmc->supply.vqmmc); - slot->host->vqmmc_enabled = false; - -+ if (drv_data && drv_data->power_off) -+ drv_data->power_off(slot->host); -+ - regs = mci_readl(slot->host, PWREN); - regs &= ~(1 << slot->id); - mci_writel(slot->host, PWREN, regs); -diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h -index da5923a92e60..0b5c880364c5 100644 ---- a/drivers/mmc/host/dw_mmc.h -+++ b/drivers/mmc/host/dw_mmc.h -@@ -563,5 +563,6 @@ struct dw_mci_drv_data { - struct mmc_ios *ios); - int (*switch_voltage)(struct mmc_host *mmc, - struct mmc_ios *ios); -+ void (*power_off)(struct dw_mci *host); - }; - #endif /* _DW_MMC_H_ */ --- -2.17.1 - - -From bcde49e61ee5dc752e4af4b0195a1c91c550e299 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Fri, 11 Oct 2019 08:01:37 +0000 -Subject: [PATCH] mmc: dw_mmc-rockchip: try set vqmmc regulator to 3.3V on - power_off - -Signed-off-by: Jonas Karlman ---- - drivers/mmc/host/dw_mmc-rockchip.c | 27 +++++++++++++++++++++++++++ - 1 file changed, 27 insertions(+) - -diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c -index d4d02134848c..05410f90ddd3 100644 ---- a/drivers/mmc/host/dw_mmc-rockchip.c -+++ b/drivers/mmc/host/dw_mmc-rockchip.c -@@ -24,6 +24,32 @@ struct dw_mci_rockchip_priv_data { - int num_phases; - }; - -+static void dw_mci_rk3288_power_off(struct dw_mci *host) -+{ -+ struct mmc_host *mmc = host->slot->mmc; -+ struct mmc_ios *ios = &mmc->ios; -+ int old_signal_voltage; -+ -+ if (IS_ERR(mmc->supply.vqmmc)) -+ return; -+ -+ if (mmc_host_is_spi(mmc)) -+ return; -+ -+ if (ios->vdd != 0 || ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) -+ return; -+ -+ old_signal_voltage = ios->signal_voltage; -+ -+ ios->signal_voltage = MMC_SIGNAL_VOLTAGE_330; -+ ios->vdd = fls(mmc->ocr_avail) - 1; -+ -+ if (mmc_regulator_set_vqmmc(mmc, ios)) -+ ios->signal_voltage = old_signal_voltage; -+ -+ ios->vdd = 0; -+} -+ - static void dw_mci_rk3288_set_ios(struct dw_mci *host, struct mmc_ios *ios) - { - struct dw_mci_rockchip_priv_data *priv = host->priv; -@@ -319,6 +345,7 @@ static const struct dw_mci_drv_data rk3288_drv_data = { - .execute_tuning = dw_mci_rk3288_execute_tuning, - .parse_dt = dw_mci_rk3288_parse_dt, - .init = dw_mci_rockchip_init, -+ .power_off = dw_mci_rk3288_power_off, - }; - - static const struct of_device_id dw_mci_rockchip_match[] = { --- -2.17.1 - - -From 0cf5aae67b723a0e2e0d1d7041214920b5bf1e59 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Fri, 11 Oct 2019 08:01:37 +0000 -Subject: [PATCH] ARM: dts: rockchip: enable sd ultra-high speeds on - rk3288-tinker - -Signed-off-by: Jonas Karlman ---- - arch/arm/boot/dts/rk3288-tinker.dtsi | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/arm/boot/dts/rk3288-tinker.dtsi b/arch/arm/boot/dts/rk3288-tinker.dtsi -index 312582c1bd37..67b32dc42220 100644 ---- a/arch/arm/boot/dts/rk3288-tinker.dtsi -+++ b/arch/arm/boot/dts/rk3288-tinker.dtsi -@@ -461,6 +461,7 @@ - disable-wp; /* wp not hooked up */ - pinctrl-names = "default"; - pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_bus4>; -+ sd-uhs-sdr104; - status = "okay"; - vmmc-supply = <&vcc33_sd>; - vqmmc-supply = <&vccio_sd>; --- -2.17.1 - - -From f74e8d61abd366cee71da7779109e5589b4c6c6e Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 8 Dec 2019 13:49:45 +0000 -Subject: [PATCH] ARM: dts: rockchip: enable sd ultra-high speeds on - rk3288-miqi - -Signed-off-by: Jonas Karlman ---- - arch/arm/boot/dts/rk3288-miqi.dts | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/boot/dts/rk3288-miqi.dts b/arch/arm/boot/dts/rk3288-miqi.dts -index c41d012c8850..820926e2feb1 100644 ---- a/arch/arm/boot/dts/rk3288-miqi.dts -+++ b/arch/arm/boot/dts/rk3288-miqi.dts -@@ -60,7 +60,7 @@ - - vcc_sd: sdmmc-regulator { - compatible = "regulator-fixed"; -- gpio = <&gpio7 RK_PB3 GPIO_ACTIVE_LOW>; -+ gpio = <&gpio7 RK_PB3 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&sdmmc_pwr>; - regulator-name = "vcc_sd"; -@@ -197,7 +197,7 @@ - - vccio_sd: REG5 { - regulator-name = "vccio_sd"; -- regulator-min-microvolt = <3300000>; -+ regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; -@@ -367,6 +367,7 @@ - disable-wp; - pinctrl-names = "default"; - pinctrl-0 = <&sdmmc_clk>, <&sdmmc_cmd>, <&sdmmc_cd>, <&sdmmc_bus4>; -+ sd-uhs-sdr104; - vmmc-supply = <&vcc_sd>; - vqmmc-supply = <&vccio_sd>; - status = "okay"; --- -2.17.1 - - -From f9ec6529193530bff8905ca5ffe36b884c93b12b Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Fri, 11 Oct 2019 08:01:37 +0000 -Subject: [PATCH] arm64: dts: rockchip: enable sd ultra-high speeds on - rk3399-sapphire - -Signed-off-by: Jonas Karlman ---- - arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi -index 1bc1579674e5..0885d48011ab 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi -@@ -77,7 +77,7 @@ - gpio = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&sdmmc0_pwr_h>; -- regulator-always-on; -+ regulator-boot-on; - regulator-max-microvolt = <3000000>; - regulator-min-microvolt = <3000000>; - regulator-name = "vcc3v0_sd"; -@@ -540,6 +540,7 @@ - max-frequency = <150000000>; - pinctrl-names = "default"; - pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_bus4>; -+ sd-uhs-sdr104; - vmmc-supply = <&vcc3v0_sd>; - vqmmc-supply = <&vcc_sdio>; - status = "okay"; --- -2.17.1 - - -From c73762d9ab7c852d7dc691b4d83a42b32ad09771 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Fri, 11 Oct 2019 08:01:37 +0000 -Subject: [PATCH] arm64: dts: rockchip: enable sd ultra-high speeds on - rk3399-rock-pi-4 - -Signed-off-by: Jonas Karlman ---- - arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts -index 3923ec01ef66..e4c71c77c3ef 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts -@@ -307,7 +307,7 @@ - regulator-name = "vcc_sdio"; - regulator-always-on; - regulator-boot-on; -- regulator-min-microvolt = <3000000>; -+ regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3000000>; - regulator-state-mem { - regulator-on-in-suspend; -@@ -609,6 +609,9 @@ - max-frequency = <150000000>; - pinctrl-names = "default"; - pinctrl-0 = <&sdmmc_clk &sdmmc_cd &sdmmc_cmd &sdmmc_bus4>; -+ sd-uhs-sdr104; -+ vmmc-supply = <&vcc3v3_sys>; -+ vqmmc-supply = <&vcc_sdio>; - status = "okay"; - }; - --- -2.17.1 - - -From c52ee775bd43bcecb26f464c28cdc9eb5bcc08b2 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Fri, 11 Oct 2019 08:01:38 +0000 -Subject: [PATCH] arm64: dts: rockchip: enable sd ultra-high speeds on - rk3399-rockpro64 - -Signed-off-by: Jonas Karlman ---- - .../boot/dts/rockchip/rk3399-rockpro64.dtsi | 22 +++++++++++++++++++ - 1 file changed, 22 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi -index 9bca25801260..72c9bb2cfceb 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi -@@ -108,6 +108,19 @@ - vin-supply = <&vcc12v_dcin>; - }; - -+ vcc3v0_sd: vcc3v0-sd { -+ compatible = "regulator-fixed"; -+ enable-active-high; -+ gpio = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdmmc0_pwr_h>; -+ regulator-boot-on; -+ regulator-max-microvolt = <3000000>; -+ regulator-min-microvolt = <3000000>; -+ regulator-name = "vcc3v0_sd"; -+ vin-supply = <&vcc3v3_sys>; -+ }; -+ - vcc3v3_sys: vcc3v3-sys { - compatible = "regulator-fixed"; - regulator-name = "vcc3v3_sys"; -@@ -603,6 +616,12 @@ - }; - }; - -+ sd { -+ sdmmc0_pwr_h: sdmmc0-pwr-h { -+ rockchip,pins = <0 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+ - sdio-pwrseq { - wifi_enable_h: wifi-enable-h { - rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; -@@ -661,6 +680,9 @@ - max-frequency = <150000000>; - pinctrl-names = "default"; - pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_bus4>; -+ sd-uhs-sdr104; -+ vmmc-supply = <&vcc3v0_sd>; -+ vqmmc-supply = <&vcc_sdio>; - status = "okay"; - }; - --- -2.17.1 - - -From 5d729739be59fe9a3435f80f6b13945b0a50e3a1 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 8 Dec 2019 13:27:12 +0000 -Subject: [PATCH] ARM: dts: rockchip: fix sdmmc-regulator gpio warning on - rk3288-tinker - -Fixes sdmmc-regulator GPIO handle specifies active low - ignored - -Signed-off-by: Jonas Karlman ---- - arch/arm/boot/dts/rk3288-tinker.dtsi | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/arch/arm/boot/dts/rk3288-tinker.dtsi b/arch/arm/boot/dts/rk3288-tinker.dtsi -index 67b32dc42220..dc5b4d81a46c 100644 ---- a/arch/arm/boot/dts/rk3288-tinker.dtsi -+++ b/arch/arm/boot/dts/rk3288-tinker.dtsi -@@ -98,7 +98,7 @@ - - vcc_sd: sdmmc-regulator { - compatible = "regulator-fixed"; -- gpio = <&gpio7 11 GPIO_ACTIVE_LOW>; -+ gpio = <&gpio7 RK_PB3 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&sdmmc_pwr>; - regulator-name = "vcc_sd"; --- -2.17.1 - - -From 896ce763b751403f9dcae8732335d53e5a6dcce9 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Thu, 7 Feb 2019 22:03:38 +0000 -Subject: [PATCH] ARM: dts: rockchip: rename hdmi sound card on rk3288-tinker - ---- - arch/arm/boot/dts/rk3288-tinker.dtsi | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/arch/arm/boot/dts/rk3288-tinker.dtsi b/arch/arm/boot/dts/rk3288-tinker.dtsi -index dc5b4d81a46c..49b64f4908cd 100644 ---- a/arch/arm/boot/dts/rk3288-tinker.dtsi -+++ b/arch/arm/boot/dts/rk3288-tinker.dtsi -@@ -75,7 +75,7 @@ - sound { - compatible = "simple-audio-card"; - simple-audio-card,format = "i2s"; -- simple-audio-card,name = "rockchip,tinker-codec"; -+ simple-audio-card,name = "HDMI"; - simple-audio-card,mclk-fs = <512>; - - simple-audio-card,codec { -@@ -352,7 +352,6 @@ - }; - - &i2s { -- #sound-dai-cells = <0>; - status = "okay"; - }; - --- -2.17.1 - - -From de9b4be54fd5ad12a33aa35aa46421b74411ee75 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 8 Dec 2019 13:49:19 +0000 -Subject: [PATCH] ARM: dts: rockchip: add hdmi sound node on rk3288-miqi - -Signed-off-by: Jonas Karlman ---- - arch/arm/boot/dts/rk3288-miqi.dts | 19 +++++++++++++++++++ - 1 file changed, 19 insertions(+) - -diff --git a/arch/arm/boot/dts/rk3288-miqi.dts b/arch/arm/boot/dts/rk3288-miqi.dts -index 820926e2feb1..0e17f66f142f 100644 ---- a/arch/arm/boot/dts/rk3288-miqi.dts -+++ b/arch/arm/boot/dts/rk3288-miqi.dts -@@ -37,6 +37,21 @@ - }; - }; - -+ sound { -+ compatible = "simple-audio-card"; -+ simple-audio-card,format = "i2s"; -+ simple-audio-card,name = "HDMI"; -+ simple-audio-card,mclk-fs = <512>; -+ -+ simple-audio-card,codec { -+ sound-dai = <&hdmi>; -+ }; -+ -+ simple-audio-card,cpu { -+ sound-dai = <&i2s>; -+ }; -+ }; -+ - vcc_flash: flash-regulator { - compatible = "regulator-fixed"; - regulator-name = "vcc_flash"; -@@ -267,6 +282,10 @@ - status = "okay"; - }; - -+&i2s { -+ status = "okay"; -+}; -+ - &io_domains { - status = "okay"; - --- -2.17.1 - - -From 882e6f0dcf1af01c4bfcf18b07c54894cc6b441e Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 2 Dec 2019 22:35:51 +0000 -Subject: [PATCH] ARM: dts: rockchip: enable ARM Mali GPU on rk3288-miqi - -Signed-off-by: Jonas Karlman ---- - arch/arm/boot/dts/rk3288-miqi.dts | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/arch/arm/boot/dts/rk3288-miqi.dts b/arch/arm/boot/dts/rk3288-miqi.dts -index 0e17f66f142f..2bee891466f5 100644 ---- a/arch/arm/boot/dts/rk3288-miqi.dts -+++ b/arch/arm/boot/dts/rk3288-miqi.dts -@@ -126,6 +126,11 @@ - status = "ok"; - }; - -+&gpu { -+ mali-supply = <&vdd_gpu>; -+ status = "okay"; -+}; -+ - &hdmi { - ddc-i2c-bus = <&i2c5>; - status = "okay"; --- -2.17.1 - - -From 72c61d5558abf21a5bb3e9ac4603a99a2594a647 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sat, 14 Dec 2019 01:43:17 +0000 -Subject: [PATCH] ARM: dts: rockchip: enable cec on rk3288-miqi - -Signed-off-by: Jonas Karlman ---- - arch/arm/boot/dts/rk3288-miqi.dts | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/arch/arm/boot/dts/rk3288-miqi.dts b/arch/arm/boot/dts/rk3288-miqi.dts -index 2bee891466f5..8428095934f5 100644 ---- a/arch/arm/boot/dts/rk3288-miqi.dts -+++ b/arch/arm/boot/dts/rk3288-miqi.dts -@@ -133,6 +133,8 @@ - - &hdmi { - ddc-i2c-bus = <&i2c5>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&hdmi_cec_c0>; - status = "okay"; - }; - --- -2.17.1 - - -From d189fcfc6950f6a2f67662e3b024eff83b929322 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 10 Mar 2019 19:18:36 +0000 -Subject: [PATCH] arm64: dts: rockchip: remove dc_12v regulator on - rk3328-roc-cc - -Remove unnecessary dc_12v regulator node on ROC-RK3328-CC, -the device uses 5v micro-usb as power input. - -Signed-off-by: Jonas Karlman ---- - arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts | 10 ---------- - 1 file changed, 10 deletions(-) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts -index 8d553c92182a..c4d908bcc82c 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts -@@ -21,15 +21,6 @@ - #clock-cells = <0>; - }; - -- dc_12v: dc-12v { -- compatible = "regulator-fixed"; -- regulator-name = "dc_12v"; -- regulator-always-on; -- regulator-boot-on; -- regulator-min-microvolt = <12000000>; -- regulator-max-microvolt = <12000000>; -- }; -- - vcc_sd: sdmmc-regulator { - compatible = "regulator-fixed"; - gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>; -@@ -73,7 +64,6 @@ - regulator-boot-on; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; -- vin-supply = <&dc_12v>; - }; - - vcc_phy: vcc-phy-regulator { --- -2.17.1 - - -From f6da47eada3ffa241c3c37917827ffa278391991 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 10 Mar 2019 19:23:58 +0000 -Subject: [PATCH] arm64: dts: rockchip: add ir-receiver node on rk3328-roc-cc - -Add ir-receiver node to enable on-board IR on ROC-RK3328-CC. - -Signed-off-by: Jonas Karlman ---- - arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts -index c4d908bcc82c..5a4aadffe9de 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts -@@ -73,6 +73,13 @@ - regulator-boot-on; - }; - -+ ir-receiver { -+ compatible = "gpio-ir-receiver"; -+ gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; -+ pinctrl-0 = <&ir_int>; -+ pinctrl-names = "default"; -+ }; -+ - leds { - compatible = "gpio-leds"; - -@@ -273,6 +280,12 @@ - }; - - &pinctrl { -+ ir { -+ ir_int: ir-int { -+ rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+ - pmic { - pmic_int_l: pmic-int-l { - rockchip,pins = <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>; --- -2.17.1 - - -From 5b7cc260ec063a6cd695ab0119d355b5a72c1a19 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 24 Mar 2019 11:20:51 +0000 -Subject: [PATCH] arm64: dts: rockchip: set tshut mode and priority on - rk3328-roc-cc - -Signed-off-by: Jonas Karlman ---- - arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts -index 5a4aadffe9de..71f3cd206e13 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts -@@ -317,6 +317,8 @@ - }; - - &tsadc { -+ rockchip,hw-tshut-mode = <0>; -+ rockchip,hw-tshut-polarity = <0>; - status = "okay"; - }; - --- -2.17.1 - - -From 456c5f7d3accc12acfc84cf6baddb5dcf05836aa Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 24 Mar 2019 11:22:06 +0000 -Subject: [PATCH] arm64: dts: rockchip: rename vcc_sdio regulator on - rk3328-roc-cc - -Signed-off-by: Jonas Karlman ---- - arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts -index 71f3cd206e13..95ff8f60e21f 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts -@@ -33,12 +33,12 @@ - vin-supply = <&vcc_io>; - }; - -- vcc_sdio: sdmmcio-regulator { -+ vccio_sd: sdmmcio-regulator { - compatible = "regulator-gpio"; - gpios = <&grf_gpio 0 GPIO_ACTIVE_HIGH>; - states = <1800000 0x1 - 3300000 0x0>; -- regulator-name = "vcc_sdio"; -+ regulator-name = "vccio_sd"; - regulator-type = "voltage"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; -@@ -272,7 +272,7 @@ - - vccio1-supply = <&vcc_io>; - vccio2-supply = <&vcc18_emmc>; -- vccio3-supply = <&vcc_sdio>; -+ vccio3-supply = <&vccio_sd>; - vccio4-supply = <&vcc_18>; - vccio5-supply = <&vcc_io>; - vccio6-supply = <&vcc_io>; -@@ -312,7 +312,7 @@ - sd-uhs-sdr50; - sd-uhs-sdr104; - vmmc-supply = <&vcc_sd>; -- vqmmc-supply = <&vcc_sdio>; -+ vqmmc-supply = <&vccio_sd>; - status = "okay"; - }; - --- -2.17.1 - - -From e077bfec3ae60d827dd8c4a6c1f777e88f2c2a53 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 24 Mar 2019 17:18:39 +0000 -Subject: [PATCH] arm64: dts: rockchip: use recommended regulator limits on - rk3328-roc-cc - -Signed-off-by: Jonas Karlman ---- - arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts | 10 ++++++---- - 1 file changed, 6 insertions(+), 4 deletions(-) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts -index 95ff8f60e21f..35d1f89f844c 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts -@@ -185,8 +185,9 @@ - regulators { - vdd_logic: DCDC_REG1 { - regulator-name = "vdd_logic"; -- regulator-min-microvolt = <712500>; -- regulator-max-microvolt = <1450000>; -+ regulator-min-microvolt = <900000>; -+ regulator-max-microvolt = <1150000>; -+ regulator-ramp-delay = <12500>; - regulator-always-on; - regulator-boot-on; - regulator-state-mem { -@@ -197,8 +198,9 @@ - - vdd_arm: DCDC_REG2 { - regulator-name = "vdd_arm"; -- regulator-min-microvolt = <712500>; -- regulator-max-microvolt = <1450000>; -+ regulator-min-microvolt = <950000>; -+ regulator-max-microvolt = <1350000>; -+ regulator-ramp-delay = <12500>; - regulator-always-on; - regulator-boot-on; - regulator-state-mem { --- -2.17.1 - - -From b66dcf8f337f9308ba232880f48a93d6594bbf5b Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 21 Apr 2019 10:28:27 +0000 -Subject: [PATCH] arm64: dts: rockchip: use recommended regulator limits on - rk3328-rock64 - -Signed-off-by: Jonas Karlman ---- - arch/arm64/boot/dts/rockchip/rk3328-rock64.dts | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -index 62936b432f9a..3725fcc7bb38 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -@@ -193,8 +193,8 @@ - regulators { - vdd_logic: DCDC_REG1 { - regulator-name = "vdd_logic"; -- regulator-min-microvolt = <712500>; -- regulator-max-microvolt = <1450000>; -+ regulator-min-microvolt = <900000>; -+ regulator-max-microvolt = <1150000>; - regulator-ramp-delay = <12500>; - regulator-always-on; - regulator-boot-on; -@@ -206,8 +206,8 @@ - - vdd_arm: DCDC_REG2 { - regulator-name = "vdd_arm"; -- regulator-min-microvolt = <712500>; -- regulator-max-microvolt = <1450000>; -+ regulator-min-microvolt = <950000>; -+ regulator-max-microvolt = <1350000>; - regulator-ramp-delay = <12500>; - regulator-always-on; - regulator-boot-on; --- -2.17.1 - - -From 52aeabe772f86828a7fd7b2d5f5ca4706214d09f Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 24 Mar 2019 11:23:55 +0000 -Subject: [PATCH] arm64: dts: rockchip: fix vccio4-supply on rk3328-roc-cc - -Signed-off-by: Jonas Karlman ---- - arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts -index 35d1f89f844c..dd18510fa473 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts -@@ -275,7 +275,7 @@ - vccio1-supply = <&vcc_io>; - vccio2-supply = <&vcc18_emmc>; - vccio3-supply = <&vccio_sd>; -- vccio4-supply = <&vcc_18>; -+ vccio4-supply = <&vcc_io>; - vccio5-supply = <&vcc_io>; - vccio6-supply = <&vcc_io>; - pmuio-supply = <&vcc_io>; --- -2.17.1 - - -From 589b2803582c476ae058e4fe2157eaa332c15bbf Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 21 Apr 2019 18:13:30 +0000 -Subject: [PATCH] arm64: dts: rockchip: fix vccio4-supply on rk3328-rock64 - ---- - arch/arm64/boot/dts/rockchip/rk3328-rock64.dts | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -index 3725fcc7bb38..1af6c56a4451 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -@@ -295,7 +295,7 @@ - vccio1-supply = <&vcc_io>; - vccio2-supply = <&vcc18_emmc>; - vccio3-supply = <&vcc_io>; -- vccio4-supply = <&vcc_18>; -+ vccio4-supply = <&vcc_io>; - vccio5-supply = <&vcc_io>; - vccio6-supply = <&vcc_io>; - pmuio-supply = <&vcc_io>; --- -2.17.1 - - -From 23aa1a305bffe72c7fb26afac16c475569bef79a Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 21 Apr 2019 18:07:33 +0000 -Subject: [PATCH] arm64: dts: rockchip: fix fixed-regulator gpio warning on - rk3328 - ---- - arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts | 2 +- - arch/arm64/boot/dts/rockchip/rk3328-rock64.dts | 6 +++--- - 2 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts -index dd18510fa473..48695a2dce7d 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts -@@ -23,7 +23,7 @@ - - vcc_sd: sdmmc-regulator { - compatible = "regulator-fixed"; -- gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>; -+ gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&sdmmc0m1_gpio>; - regulator-boot-on; -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -index 1af6c56a4451..7cca8808257e 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -@@ -23,7 +23,7 @@ - - vcc_sd: sdmmc-regulator { - compatible = "regulator-fixed"; -- gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>; -+ gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&sdmmc0m1_gpio>; - regulator-name = "vcc_sd"; -@@ -34,7 +34,7 @@ - - vcc_host_5v: vcc-host-5v-regulator { - compatible = "regulator-fixed"; -- gpio = <&gpio0 RK_PA2 GPIO_ACTIVE_LOW>; -+ gpio = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&usb20_host_drv>; - regulator-name = "vcc_host_5v"; -@@ -45,7 +45,7 @@ - - vcc_host1_5v: vcc_otg_5v: vcc-host1-5v-regulator { - compatible = "regulator-fixed"; -- gpio = <&gpio0 RK_PA2 GPIO_ACTIVE_LOW>; -+ gpio = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&usb20_host_drv>; - regulator-name = "vcc_host1_5v"; --- -2.17.1 - - -From b05c9d16191a716ba106abf6226410270ffa89a0 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 17 Mar 2019 22:38:09 +0000 -Subject: [PATCH] arm64: dts: rockchip: update gpu node on rk3328 - ---- - arch/arm64/boot/dts/rockchip/rk3328.dtsi | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi -index 1f53ead52c7f..1b45131e8e48 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi -@@ -319,6 +319,10 @@ - #address-cells = <1>; - #size-cells = <0>; - -+ pd_gpu@RK3328_PD_GPU { -+ reg = ; -+ clocks = <&cru ACLK_GPU>; -+ }; - pd_hevc@RK3328_PD_HEVC { - reg = ; - }; -@@ -621,6 +625,7 @@ - "ppmmu1"; - clocks = <&cru ACLK_GPU>, <&cru ACLK_GPU>; - clock-names = "bus", "core"; -+ power-domains = <&power RK3328_PD_GPU>; - resets = <&cru SRST_GPU_A>; - }; - -@@ -793,6 +798,7 @@ - <&cru ACLK_BUS_PRE>, <&cru HCLK_BUS_PRE>, - <&cru PCLK_BUS_PRE>, <&cru ACLK_PERI_PRE>, - <&cru HCLK_PERI>, <&cru PCLK_PERI>, -+ <&cru ACLK_GPU>, - <&cru SCLK_RTC32K>; - assigned-clock-parents = - <&cru HDMIPHY>, <&cru PLL_APLL>, -@@ -814,6 +820,7 @@ - <150000000>, <75000000>, - <75000000>, <150000000>, - <75000000>, <75000000>, -+ <500000000>, - <32768>; - }; - --- -2.17.1 - - -From c047d9759f3b5376259657dc0608a51252371219 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 8 Dec 2019 23:12:19 +0000 -Subject: [PATCH] arm64: dts: rockchip: add spdif audio pipeline on rk3328 - -Signed-off-by: Jonas Karlman ---- - arch/arm64/boot/dts/rockchip/rk3328.dtsi | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi -index 1b45131e8e48..c6f7cec13d15 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi -@@ -210,6 +210,26 @@ - method = "smc"; - }; - -+ spdif_out: spdif-out { -+ compatible = "linux,spdif-dit"; -+ #sound-dai-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ spdif_sound: spdif-sound { -+ compatible = "simple-audio-card"; -+ simple-audio-card,name = "SPDIF"; -+ status = "disabled"; -+ -+ simple-audio-card,cpu { -+ sound-dai = <&spdif>; -+ }; -+ -+ simple-audio-card,codec { -+ sound-dai = <&spdif_out>; -+ }; -+ }; -+ - timer { - compatible = "arm,armv8-timer"; - interrupts = , --- -2.17.1 - - -From 8d8e7349b476ae980239abfdb8c460ccd5e3df0a Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Tue, 19 Mar 2019 22:18:47 +0000 -Subject: [PATCH] arm64: dts: rockchip: enable sound nodes on rk3328-roc-cc - ---- - .../arm64/boot/dts/rockchip/rk3328-roc-cc.dts | 33 +++++++++++++++++++ - 1 file changed, 33 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts -index 48695a2dce7d..a340a23cf073 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts -@@ -101,6 +101,14 @@ - }; - }; - -+&analog_sound { -+ status = "okay"; -+}; -+ -+&codec { -+ status = "okay"; -+}; -+ - &cpu0 { - cpu-supply = <&vdd_arm>; - }; -@@ -158,6 +166,10 @@ - status = "okay"; - }; - -+&hdmi_sound { -+ status = "okay"; -+}; -+ - &i2c1 { - status = "okay"; - -@@ -269,6 +281,14 @@ - }; - }; - -+&i2s0 { -+ status = "okay"; -+}; -+ -+&i2s1 { -+ status = "okay"; -+}; -+ - &io_domains { - status = "okay"; - -@@ -318,6 +338,19 @@ - status = "okay"; - }; - -+&spdif { -+ pinctrl-0 = <&spdifm0_tx>; -+ status = "okay"; -+}; -+ -+&spdif_out { -+ status = "okay"; -+}; -+ -+&spdif_sound { -+ status = "okay"; -+}; -+ - &tsadc { - rockchip,hw-tshut-mode = <0>; - rockchip,hw-tshut-polarity = <0>; --- -2.17.1 - - -From b906dcd1489dd042dc67d9328952e18011fd6960 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 29 Dec 2019 22:13:22 +0000 -Subject: [PATCH] arm64: dts: rockchip: add mmc reset on rk3328 - ---- - arch/arm64/boot/dts/rockchip/rk3328.dtsi | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi -index c6f7cec13d15..b92645187b19 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi -@@ -890,6 +890,8 @@ - clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; - fifo-depth = <0x100>; - max-frequency = <150000000>; -+ resets = <&cru SRST_MMC0>; -+ reset-names = "reset"; - status = "disabled"; - }; - -@@ -902,6 +904,8 @@ - clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; - fifo-depth = <0x100>; - max-frequency = <150000000>; -+ resets = <&cru SRST_SDIO>; -+ reset-names = "reset"; - status = "disabled"; - }; - -@@ -914,6 +918,8 @@ - clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; - fifo-depth = <0x100>; - max-frequency = <150000000>; -+ resets = <&cru SRST_EMMC>; -+ reset-names = "reset"; - status = "disabled"; - }; - --- -2.17.1 - - -From 584300ab010fa3ab29f5f402d94274740d231e1c Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 29 Dec 2019 22:14:02 +0000 -Subject: [PATCH] arm64: dts: rockchip: add sdmmc_ext node on rk3328 - ---- - arch/arm64/boot/dts/rockchip/rk3328.dtsi | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi -index b92645187b19..cc44e17c8c43 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi -@@ -1018,6 +1018,20 @@ - status = "disabled"; - }; - -+ sdmmc_ext: dwmmc@ff5f0000 { -+ compatible = "rockchip,rk3328-dw-mshc", "rockchip,rk3288-dw-mshc"; -+ reg = <0x0 0xff5f0000 0x0 0x4000>; -+ interrupts = ; -+ clocks = <&cru HCLK_SDMMC_EXT>, <&cru SCLK_SDMMC_EXT>, -+ <&cru SCLK_SDMMC_EXT_DRV>, <&cru SCLK_SDMMC_EXT_SAMPLE>; -+ clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; -+ fifo-depth = <0x100>; -+ max-frequency = <150000000>; -+ resets = <&cru SRST_SDMMCEXT>; -+ reset-names = "reset"; -+ status = "disabled"; -+ }; -+ - gic: interrupt-controller@ff811000 { - compatible = "arm,gic-400"; - #interrupt-cells = <3>; --- -2.17.1 - - -From af46e567772628417233844bb0994437f842d2a3 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 29 Dec 2019 22:14:36 +0000 -Subject: [PATCH] WIP: arm64: dts: rockchip: add rkvdec power domain on rk3328 - ---- - arch/arm64/boot/dts/rockchip/rk3328.dtsi | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi -index cc44e17c8c43..a4b0947f82a7 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi -@@ -348,6 +348,10 @@ - }; - pd_video@RK3328_PD_VIDEO { - reg = ; -+ clocks = <&cru ACLK_RKVDEC>, -+ <&cru HCLK_RKVDEC>, -+ <&cru SCLK_VDEC_CABAC>, -+ <&cru SCLK_VDEC_CORE>; - }; - pd_vpu@RK3328_PD_VPU { - reg = ; -@@ -701,6 +705,7 @@ - clocks = <&cru ACLK_RKVDEC>, <&cru HCLK_RKVDEC>; - clock-names = "aclk", "iface"; - #iommu-cells = <0>; -+ power-domains = <&power RK3328_PD_VIDEO>; - status = "disabled"; - }; - --- -2.17.1 - - -From fe5ff9c9fcb07b629f57282a25eba796616fbb50 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 8 Dec 2019 23:23:41 +0000 -Subject: [PATCH] WIP: arm64: dts: rockchip: split sound cards on rk3328-rock64 - -Signed-off-by: Jonas Karlman ---- - .../arm64/boot/dts/rockchip/rk3328-rock64.dts | 54 +++++++------------ - 1 file changed, 18 insertions(+), 36 deletions(-) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -index 7cca8808257e..e926616b4a0c 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -@@ -83,34 +83,14 @@ - linux,default-trigger = "heartbeat"; - }; - }; -+}; - -- sound { -- compatible = "audio-graph-card"; -- label = "rockchip,rk3328"; -- dais = <&i2s1_p0 -- &spdif_p0>; -- }; -- -- spdif-dit { -- compatible = "linux,spdif-dit"; -- #sound-dai-cells = <0>; -- -- port { -- dit_p0_0: endpoint { -- remote-endpoint = <&spdif_p0_0>; -- }; -- }; -- }; -+&analog_sound { -+ status = "okay"; - }; - - &codec { - status = "okay"; -- -- port@0 { -- codec_p0_0: endpoint { -- remote-endpoint = <&i2s1_p0_0>; -- }; -- }; - }; - - &cpu0 { -@@ -166,6 +146,10 @@ - status = "okay"; - }; - -+&hdmi_sound { -+ status = "okay"; -+}; -+ - &i2c1 { - status = "okay"; - -@@ -277,16 +261,12 @@ - }; - }; - --&i2s1 { -+&i2s0 { - status = "okay"; -+}; - -- i2s1_p0: port { -- i2s1_p0_0: endpoint { -- dai-format = "i2s"; -- mclk-fs = <256>; -- remote-endpoint = <&codec_p0_0>; -- }; -- }; -+&i2s1 { -+ status = "okay"; - }; - - &io_domains { -@@ -336,12 +316,14 @@ - &spdif { - pinctrl-0 = <&spdifm0_tx>; - status = "okay"; -+}; - -- spdif_p0: port { -- spdif_p0_0: endpoint { -- remote-endpoint = <&dit_p0_0>; -- }; -- }; -+&spdif_out { -+ status = "okay"; -+}; -+ -+&spdif_sound { -+ status = "okay"; - }; - - &spi0 { --- -2.17.1 - - -From 1c472df59bdd77b5f9dc651e4c25959cd53a2778 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 8 Dec 2019 23:26:37 +0000 -Subject: [PATCH] WIP: arm64: dts: rockchip: add mali-supply on rk3328-rock64 - and rk3328-roc-cc - -Signed-off-by: Jonas Karlman ---- - arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts | 4 ++++ - arch/arm64/boot/dts/rockchip/rk3328-rock64.dts | 4 ++++ - 2 files changed, 8 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts -index a340a23cf073..3e564ba682b6 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts -@@ -158,6 +158,10 @@ - status = "okay"; - }; - -+&gpu { -+ mali-supply = <&vdd_logic>; -+}; -+ - &hdmi { - status = "okay"; - }; -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -index e926616b4a0c..9023f311f89b 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -@@ -138,6 +138,10 @@ - status = "okay"; - }; - -+&gpu { -+ mali-supply = <&vdd_logic>; -+}; -+ - &hdmi { - status = "okay"; - }; --- -2.17.1 - - -From 2fae05a90a56a71c1ad749a96fac8eeb8beefaf0 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 30 Dec 2019 00:30:38 +0000 -Subject: [PATCH] WIP: arm64: dts: rockchip: misc updates on rk3328-rock64 and - rk3328-roc-cc - ---- - .../arm64/boot/dts/rockchip/rk3328-roc-cc.dts | 34 +++++----------- - .../arm64/boot/dts/rockchip/rk3328-rock64.dts | 39 +++++++------------ - 2 files changed, 22 insertions(+), 51 deletions(-) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts -index 3e564ba682b6..b58948f478a1 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts -@@ -26,7 +26,6 @@ - gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&sdmmc0m1_gpio>; -- regulator-boot-on; - regulator-name = "vcc_sd"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; -@@ -54,25 +53,17 @@ - pinctrl-0 = <&usb20_host_drv>; - regulator-name = "vcc_host1_5v"; - regulator-always-on; -+ regulator-boot-on; - vin-supply = <&vcc_sys>; - }; - - vcc_sys: vcc-sys { - compatible = "regulator-fixed"; - regulator-name = "vcc_sys"; -- regulator-always-on; -- regulator-boot-on; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - }; - -- vcc_phy: vcc-phy-regulator { -- compatible = "regulator-fixed"; -- regulator-name = "vcc_phy"; -- regulator-always-on; -- regulator-boot-on; -- }; -- - ir-receiver { - compatible = "gpio-ir-receiver"; - gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; -@@ -128,7 +119,6 @@ - &emmc { - bus-width = <8>; - cap-mmc-highspeed; -- max-frequency = <150000000>; - mmc-ddr-1_8v; - mmc-hs200-1_8v; - non-removable; -@@ -143,16 +133,15 @@ - assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>; - assigned-clock-parents = <&gmac_clkin>, <&gmac_clkin>; - clock_in_out = "input"; -- phy-supply = <&vcc_phy>; - phy-mode = "rgmii"; -+ phy-supply = <&vcc_io>; - pinctrl-names = "default"; - pinctrl-0 = <&rgmiim1_pins>; - snps,aal; -+ snps,pbl = <0x4>; - snps,reset-gpio = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; - snps,reset-active-low; - snps,reset-delays-us = <0 10000 50000>; -- snps,rxpbl = <0x4>; -- snps,txpbl = <0x4>; - tx_delay = <0x24>; - rx_delay = <0x18>; - status = "okay"; -@@ -294,8 +283,6 @@ - }; - - &io_domains { -- status = "okay"; -- - vccio1-supply = <&vcc_io>; - vccio2-supply = <&vcc18_emmc>; - vccio3-supply = <&vccio_sd>; -@@ -303,6 +290,7 @@ - vccio5-supply = <&vcc_io>; - vccio6-supply = <&vcc_io>; - pmuio-supply = <&vcc_io>; -+ status = "okay"; - }; - - &pinctrl { -@@ -330,13 +318,8 @@ - cap-mmc-highspeed; - cap-sd-highspeed; - disable-wp; -- max-frequency = <150000000>; - pinctrl-names = "default"; - pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_dectn &sdmmc0_bus4>; -- sd-uhs-sdr12; -- sd-uhs-sdr25; -- sd-uhs-sdr50; -- sd-uhs-sdr104; - vmmc-supply = <&vcc_sd>; - vqmmc-supply = <&vccio_sd>; - status = "okay"; -@@ -361,23 +344,24 @@ - status = "okay"; - }; - --&u2phy { -+&uart2 { - status = "okay"; - }; - --&u2phy_host { -+&u2phy { - status = "okay"; - }; - --&u2phy_otg { -+&u2phy_host { - status = "okay"; - }; - --&uart2 { -+&u2phy_otg { - status = "okay"; - }; - - &usb20_otg { -+ dr_mode = "host"; - status = "okay"; - }; - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -index 9023f311f89b..345c045c58e6 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -@@ -32,7 +32,7 @@ - vin-supply = <&vcc_io>; - }; - -- vcc_host_5v: vcc-host-5v-regulator { -+ vcc_host_5v: vcc_host1_5v: vcc_otg_5v: vcc-host-5v-regulator { - compatible = "regulator-fixed"; - gpio = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; -@@ -43,22 +43,9 @@ - vin-supply = <&vcc_sys>; - }; - -- vcc_host1_5v: vcc_otg_5v: vcc-host1-5v-regulator { -- compatible = "regulator-fixed"; -- gpio = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; -- pinctrl-names = "default"; -- pinctrl-0 = <&usb20_host_drv>; -- regulator-name = "vcc_host1_5v"; -- regulator-always-on; -- regulator-boot-on; -- vin-supply = <&vcc_sys>; -- }; -- - vcc_sys: vcc-sys { - compatible = "regulator-fixed"; - regulator-name = "vcc_sys"; -- regulator-always-on; -- regulator-boot-on; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - }; -@@ -112,6 +99,7 @@ - &emmc { - bus-width = <8>; - cap-mmc-highspeed; -+ mmc-ddr-1_8v; - mmc-hs200-1_8v; - non-removable; - pinctrl-names = "default"; -@@ -125,11 +113,12 @@ - assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>; - assigned-clock-parents = <&gmac_clkin>, <&gmac_clkin>; - clock_in_out = "input"; -- phy-supply = <&vcc_io>; - phy-mode = "rgmii"; -+ phy-supply = <&vcc_io>; - pinctrl-names = "default"; - pinctrl-0 = <&rgmiim1_pins>; -- snps,force_thresh_dma_mode; -+ snps,aal; -+ snps,pbl = <0x4>; - snps,reset-gpio = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; - snps,reset-active-low; - snps,reset-delays-us = <0 10000 50000>; -@@ -176,7 +165,7 @@ - vcc3-supply = <&vcc_sys>; - vcc4-supply = <&vcc_sys>; - vcc5-supply = <&vcc_io>; -- vcc6-supply = <&vcc_sys>; -+ vcc6-supply = <&vcc_io>; - - regulators { - vdd_logic: DCDC_REG1 { -@@ -274,8 +263,6 @@ - }; - - &io_domains { -- status = "okay"; -- - vccio1-supply = <&vcc_io>; - vccio2-supply = <&vcc18_emmc>; - vccio3-supply = <&vcc_io>; -@@ -283,6 +270,7 @@ - vccio5-supply = <&vcc_io>; - vccio6-supply = <&vcc_io>; - pmuio-supply = <&vcc_io>; -+ status = "okay"; - }; - - &pinctrl { -@@ -310,7 +298,6 @@ - cap-mmc-highspeed; - cap-sd-highspeed; - disable-wp; -- max-frequency = <150000000>; - pinctrl-names = "default"; - pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_dectn &sdmmc0_bus4>; - vmmc-supply = <&vcc_sd>; -@@ -354,14 +341,14 @@ - - &u2phy { - status = "okay"; -+}; - -- u2phy_host: host-port { -- status = "okay"; -- }; -+&u2phy_host { -+ status = "okay"; -+}; - -- u2phy_otg: otg-port { -- status = "okay"; -- }; -+&u2phy_otg { -+ status = "okay"; - }; - - &usb20_otg { --- -2.17.1 - - -From 902ee56bf269bf4337eec25f0dc7d343bb9172b9 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 12 May 2019 12:40:00 +0000 -Subject: [PATCH] arm64: dts: rockchip: add rk3328-rockbox - ---- - arch/arm64/boot/dts/rockchip/Makefile | 1 + - .../boot/dts/rockchip/rk3328-rockbox.dts | 349 ++++++++++++++++++ - 2 files changed, 350 insertions(+) - create mode 100644 arch/arm64/boot/dts/rockchip/rk3328-rockbox.dts - -diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile -index 60d9437096c7..1df8933cb084 100644 ---- a/arch/arm64/boot/dts/rockchip/Makefile -+++ b/arch/arm64/boot/dts/rockchip/Makefile -@@ -5,6 +5,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3308-roc-cc.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-a1.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-evb.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-rock64.dtb -+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-rockbox.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-roc-cc.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-evb-act8846.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-geekbox.dtb -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rockbox.dts b/arch/arm64/boot/dts/rockchip/rk3328-rockbox.dts -new file mode 100644 -index 000000000000..b82708cfe742 ---- /dev/null -+++ b/arch/arm64/boot/dts/rockchip/rk3328-rockbox.dts -@@ -0,0 +1,349 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Copyright (c) 2017 PINE64 -+ */ -+ -+/dts-v1/; -+#include "rk3328.dtsi" -+ -+/ { -+ model = "Popcorn Hour RockBox Basic"; -+ compatible = "popcornhour,rockbox", "rockchip,rk3328"; -+ -+ chosen { -+ stdout-path = "serial2:1500000n8"; -+ }; -+ -+ vcc_sd: sdmmc-regulator { -+ compatible = "regulator-fixed"; -+ gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_HIGH>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdmmc0m1_gpio>; -+ regulator-name = "vcc_sd"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ vin-supply = <&vcc_io>; -+ }; -+ -+ vcc_host_5v: vcc_host1_5v: vcc_otg_5v: vcc-host-5v-regulator { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc_host_5v"; -+ regulator-always-on; -+ regulator-boot-on; -+ vin-supply = <&vcc_sys>; -+ }; -+ -+ vcc_sys: vcc-sys { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc_sys"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ }; -+ -+ ir-receiver { -+ compatible = "gpio-ir-receiver"; -+ gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; -+ linux,rc-map-name = "rc-pine64"; -+ pinctrl-0 = <&ir_int>; -+ pinctrl-names = "default"; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ power { -+ gpios = <&rk805 0 GPIO_ACTIVE_HIGH>; -+ linux,default-trigger = "default-on"; -+ default-state = "on"; -+ }; -+ }; -+ -+ sdio_pwrseq: sdio-pwrseq { -+ compatible = "mmc-pwrseq-simple"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&wifi_enable_h>; -+ reset-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; -+ }; -+}; -+ -+&cpu0 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&cpu1 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&cpu2 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&cpu3 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&emmc { -+ bus-width = <8>; -+ cap-mmc-highspeed; -+ mmc-ddr-1_8v; -+ mmc-hs200-1_8v; -+ non-removable; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; -+ vmmc-supply = <&vcc_io>; -+ vqmmc-supply = <&vcc18_emmc>; -+ status = "okay"; -+}; -+ -+&gmac2phy { -+ assigned-clocks = <&cru SCLK_MAC2PHY_SRC>; -+ assigned-clock-rate = <50000000>; -+ assigned-clocks = <&cru SCLK_MAC2PHY>; -+ assigned-clock-parents = <&cru SCLK_MAC2PHY_SRC>; -+ clock_in_out = "output"; -+ phy-supply = <&vcc_io>; -+ status = "okay"; -+}; -+ -+&gpu { -+ mali-supply = <&vdd_logic>; -+}; -+ -+&hdmi { -+ status = "okay"; -+}; -+ -+&hdmiphy { -+ status = "okay"; -+}; -+ -+&hdmi_sound { -+ status = "okay"; -+}; -+ -+&i2c1 { -+ status = "okay"; -+ -+ rk805: rk805@18 { -+ compatible = "rockchip,rk805"; -+ reg = <0x18>; -+ interrupt-parent = <&gpio2>; -+ interrupts = <6 IRQ_TYPE_LEVEL_LOW>; -+ #clock-cells = <1>; -+ clock-output-names = "xin32k", "rk805-clkout2"; -+ gpio-controller; -+ #gpio-cells = <2>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pmic_int_l>; -+ rockchip,system-power-controller; -+ wakeup-source; -+ -+ vcc1-supply = <&vcc_sys>; -+ vcc2-supply = <&vcc_sys>; -+ vcc3-supply = <&vcc_sys>; -+ vcc4-supply = <&vcc_sys>; -+ vcc5-supply = <&vcc_io>; -+ vcc6-supply = <&vcc_io>; -+ -+ regulators { -+ vdd_logic: DCDC_REG1 { -+ regulator-name = "vdd_logic"; -+ regulator-min-microvolt = <900000>; -+ regulator-max-microvolt = <1150000>; -+ regulator-ramp-delay = <12500>; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1000000>; -+ }; -+ }; -+ -+ vdd_arm: DCDC_REG2 { -+ regulator-name = "vdd_arm"; -+ regulator-min-microvolt = <950000>; -+ regulator-max-microvolt = <1350000>; -+ regulator-ramp-delay = <12500>; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <950000>; -+ }; -+ }; -+ -+ vcc_ddr: DCDC_REG3 { -+ regulator-name = "vcc_ddr"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ }; -+ }; -+ -+ vcc_io: DCDC_REG4 { -+ regulator-name = "vcc_io"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <3300000>; -+ }; -+ }; -+ -+ vcc_18: LDO_REG1 { -+ regulator-name = "vcc_18"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1800000>; -+ }; -+ }; -+ -+ vcc18_emmc: LDO_REG2 { -+ regulator-name = "vcc18_emmc"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1800000>; -+ }; -+ }; -+ -+ vdd_10: LDO_REG3 { -+ regulator-name = "vdd_10"; -+ regulator-min-microvolt = <1000000>; -+ regulator-max-microvolt = <1000000>; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1000000>; -+ }; -+ }; -+ }; -+ }; -+}; -+ -+&i2s0 { -+ status = "okay"; -+}; -+ -+&io_domains { -+ vccio1-supply = <&vcc_io>; -+ vccio2-supply = <&vcc18_emmc>; -+ vccio3-supply = <&vcc_io>; -+ vccio4-supply = <&vcc_io>; -+ vccio5-supply = <&vcc_io>; -+ vccio6-supply = <&vcc_io>; -+ pmuio-supply = <&vcc_io>; -+ status = "okay"; -+}; -+ -+&pinctrl { -+ ir { -+ ir_int: ir-int { -+ rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+ -+ pmic { -+ pmic_int_l: pmic-int-l { -+ rockchip,pins = <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>; -+ }; -+ }; -+ -+ sdio-pwrseq { -+ wifi_enable_h: wifi-enable-h { -+ rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none_4ma>, -+ <1 RK_PC3 RK_FUNC_GPIO &pcfg_pull_none_4ma>; -+ }; -+ }; -+}; -+ -+&sdio { -+ bus-width = <4>; -+ cap-sd-highspeed; -+ cap-sdio-irq; -+ keep-power-in-suspend; -+ mmc-pwrseq = <&sdio_pwrseq>; -+ non-removable; -+ num-slots = <1>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdmmc1_bus4 &sdmmc1_cmd &sdmmc1_clk>; -+ status = "disabled"; -+}; -+ -+&sdmmc { -+ bus-width = <4>; -+ cap-mmc-highspeed; -+ cap-sd-highspeed; -+ disable-wp; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_dectn &sdmmc0_bus4>; -+ vmmc-supply = <&vcc_sd>; -+ status = "okay"; -+}; -+ -+&spdif { -+ pinctrl-0 = <&spdifm0_tx>; -+ status = "okay"; -+}; -+ -+&spdif_out { -+ status = "okay"; -+}; -+ -+&spdif_sound { -+ status = "okay"; -+}; -+ -+&tsadc { -+ rockchip,hw-tshut-mode = <0>; -+ rockchip,hw-tshut-polarity = <0>; -+ status = "okay"; -+}; -+ -+&uart2 { -+ status = "okay"; -+}; -+ -+&u2phy { -+ status = "okay"; -+}; -+ -+&u2phy_host { -+ status = "okay"; -+}; -+ -+&u2phy_otg { -+ status = "okay"; -+}; -+ -+&usb20_otg { -+ dr_mode = "host"; -+ status = "okay"; -+}; -+ -+&usb_host0_ehci { -+ status = "okay"; -+}; -+ -+&usb_host0_ohci { -+ status = "okay"; -+}; -+ -+&vop { -+ status = "okay"; -+}; -+ -+&vop_mmu { -+ status = "okay"; -+}; --- -2.17.1 - - -From 175d289ac91694f01eaf5914a7e124ec1de1f9ac Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 8 Dec 2019 21:29:55 +0000 -Subject: [PATCH] arm64: dts: rockchip: enable hdmi sound on rk3399-firefly - ---- - arch/arm64/boot/dts/rockchip/rk3399-firefly.dts | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts b/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts -index d63faf38cc81..e9e2a6fb623b 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts -@@ -263,6 +263,10 @@ - status = "okay"; - }; - -+&hdmi_sound { -+ status = "okay"; -+}; -+ - &i2c0 { - clock-frequency = <400000>; - i2c-scl-rising-time-ns = <168>; --- -2.17.1 - - -From f8982a639da0310faf15639a8a068e7534b97b57 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 14 Apr 2019 21:25:34 +0000 -Subject: [PATCH] arm64: dts: rockchip: enable hdmi sound on rk3399-orangepi - ---- - arch/arm64/boot/dts/rockchip/rk3399-orangepi.dts | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3399-orangepi.dts b/arch/arm64/boot/dts/rockchip/rk3399-orangepi.dts -index 9c659f3115c8..bfb9fa11adcc 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399-orangepi.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3399-orangepi.dts -@@ -517,6 +517,10 @@ - }; - }; - -+&i2s2 { -+ status = "okay"; -+}; -+ - &io_domains { - status = "okay"; - bt656-supply = <&vcc_3v0>; --- -2.17.1 - diff --git a/patch/kernel/rk322x-current/01-linux-0005-for-libreelec.patch.disabled b/patch/kernel/rk322x-current/01-linux-0005-for-libreelec.patch.disabled deleted file mode 100644 index 22589ab70..000000000 --- a/patch/kernel/rk322x-current/01-linux-0005-for-libreelec.patch.disabled +++ /dev/null @@ -1,1651 +0,0 @@ -diff --git a/Documentation/devicetree/bindings/usb/rockchip,dwc3.txt b/Documentation/devicetree/bindings/usb/rockchip,dwc3.txt -index c8c4b00ecb94..4ca357835a48 100644 ---- a/Documentation/devicetree/bindings/usb/rockchip,dwc3.txt -+++ b/Documentation/devicetree/bindings/usb/rockchip,dwc3.txt -@@ -1,7 +1,9 @@ - Rockchip SuperSpeed DWC3 USB SoC controller - - Required properties: --- compatible: should contain "rockchip,rk3399-dwc3" for rk3399 SoC -+- compatible: should be one of the following: -+ - "rockchip,rk3399-dwc3": for rk3399 SoC -+ - "rockchip,rk3328-dwc3", "rockchip,rk3399-dwc3": for rk3328 SoC - - clocks: A list of phandle + clock-specifier pairs for the - clocks listed in clock-names - - clock-names: Should contain the following: --- -2.17.1 - - -From 041ddb731b5e025e1bea4d3d68c30f09521ca8dd Mon Sep 17 00:00:00 2001 -From: William Wu -Date: Mon, 4 Dec 2017 10:40:39 +0100 -Subject: [PATCH] arm64: dts: rockchip: add usb3 controller node for RK3328 - SoCs - -RK3328 has one USB 3.0 OTG controller which uses DWC_USB3 -core's general architecture. It can act as static xHCI host -controller, static device controller, USB 3.0/2.0 OTG basing -on ID of USB3.0 PHY. - -Signed-off-by: William Wu -Signed-off-by: Heiko Stuebner ---- - arch/arm64/boot/dts/rockchip/rk3328.dtsi | 32 ++++++++++++++++++++++++ - 1 file changed, 32 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi -index a4b0947f82a7..bc9186f66d9c 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi -@@ -1037,6 +1037,38 @@ - status = "disabled"; - }; - -+ usbdrd3: usb@ff600000 { -+ compatible = "rockchip,rk3328-dwc3", "rockchip,rk3399-dwc3"; -+ clocks = <&cru SCLK_USB3OTG_REF>, <&cru SCLK_USB3OTG_SUSPEND>, -+ <&cru ACLK_USB3OTG>; -+ clock-names = "ref_clk", "suspend_clk", -+ "bus_clk"; -+ resets = <&cru SRST_USB3OTG>; -+ reset-names = "usb3-otg"; -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ status = "disabled"; -+ -+ usbdrd_dwc3: dwc3@ff600000 { -+ compatible = "snps,dwc3"; -+ reg = <0x0 0xff600000 0x0 0x100000>; -+ interrupts = ; -+ clocks = <&cru SCLK_USB3OTG_REF>, <&cru ACLK_USB3OTG>, -+ <&cru SCLK_USB3OTG_SUSPEND>; -+ clock-names = "ref", "bus_early", "suspend"; -+ dr_mode = "otg"; -+ phy_type = "utmi_wide"; -+ snps,dis_enblslpm_quirk; -+ snps,dis-u2-freeclk-exists-quirk; -+ snps,dis_u2_susphy_quirk; -+ snps,dis_u3_susphy_quirk; -+ snps,dis-del-phy-power-chg-quirk; -+ snps,dis-tx-ipgap-linecheck-quirk; -+ status = "disabled"; -+ }; -+ }; -+ - gic: interrupt-controller@ff811000 { - compatible = "arm,gic-400"; - #interrupt-cells = <3>; --- -2.17.1 - - -From 6b2ec0b7974089cd179241595d76f204151a0329 Mon Sep 17 00:00:00 2001 -From: Heiko Stuebner -Date: Mon, 4 Dec 2017 10:40:41 +0100 -Subject: [PATCH] arm64: dts: rockchip: enable usb3 nodes on rk3328-rock64 - -Enable the nodes to make the usb3 port usable on that board. - -Signed-off-by: Heiko Stuebner ---- - arch/arm64/boot/dts/rockchip/rk3328-rock64.dts | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -index 345c045c58e6..1cc3a8f5c3d7 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -@@ -364,6 +364,15 @@ - status = "okay"; - }; - -+&usbdrd3 { -+ status = "okay"; -+}; -+ -+&usbdrd_dwc3 { -+ dr_mode = "host"; -+ status = "okay"; -+}; -+ - &vop { - status = "okay"; - }; --- -2.17.1 - - -From 39e4f61930b2b6108ae6423698f233d6d2b57958 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Tue, 12 Mar 2019 19:42:03 +0000 -Subject: [PATCH] arm64: dts: rockchip: enable usb3 nodes on rk3328-roc-cc - -Enable the nodes to make the usb3 port usable on that board. - -Signed-off-by: Jonas Karlman ---- - arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts -index b58948f478a1..78e0e23d1efb 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts -@@ -373,6 +373,15 @@ - status = "okay"; - }; - -+&usbdrd3 { -+ status = "okay"; -+}; -+ -+&usbdrd_dwc3 { -+ dr_mode = "host"; -+ status = "okay"; -+}; -+ - &vop { - status = "okay"; - }; --- -2.17.1 - - -From aec6055775b63eaeb6b4a509b37aa6718fa2f84f Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 12 May 2019 12:40:00 +0000 -Subject: [PATCH] arm64: dts: rockchip: enable usb3 nodes on rk3328-rockbox - ---- - arch/arm64/boot/dts/rockchip/rk3328-rockbox.dts | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rockbox.dts b/arch/arm64/boot/dts/rockchip/rk3328-rockbox.dts -index b82708cfe742..6f5eab7c0050 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328-rockbox.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3328-rockbox.dts -@@ -340,6 +340,15 @@ - status = "okay"; - }; - -+&usbdrd3 { -+ status = "okay"; -+}; -+ -+&usbdrd_dwc3 { -+ dr_mode = "host"; -+ status = "okay"; -+}; -+ - &vop { - status = "okay"; - }; --- -2.17.1 - - -From b1c19ab3e134c7ba1c0352b484fa5b3591f5af4d Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Thu, 7 Feb 2019 22:03:15 +0000 -Subject: [PATCH] HACK: ARM: dts: rockchip: disable vopl node on rk3288 - ---- - arch/arm/boot/dts/rk3288-miqi.dts | 8 -------- - arch/arm/boot/dts/rk3288-tinker.dtsi | 8 -------- - 2 files changed, 16 deletions(-) - -diff --git a/arch/arm/boot/dts/rk3288-miqi.dts b/arch/arm/boot/dts/rk3288-miqi.dts -index 8428095934f5..8d8a4f49e4af 100644 ---- a/arch/arm/boot/dts/rk3288-miqi.dts -+++ b/arch/arm/boot/dts/rk3288-miqi.dts -@@ -438,14 +438,6 @@ - status = "okay"; - }; - --&vopl { -- status = "okay"; --}; -- --&vopl_mmu { -- status = "okay"; --}; -- - &wdt { - status = "okay"; - }; -diff --git a/arch/arm/boot/dts/rk3288-tinker.dtsi b/arch/arm/boot/dts/rk3288-tinker.dtsi -index 49b64f4908cd..5976c9a8eb0c 100644 ---- a/arch/arm/boot/dts/rk3288-tinker.dtsi -+++ b/arch/arm/boot/dts/rk3288-tinker.dtsi -@@ -534,14 +534,6 @@ - status = "okay"; - }; - --&vopl { -- status = "okay"; --}; -- --&vopl_mmu { -- status = "okay"; --}; -- - &wdt { - status = "okay"; - }; --- -2.17.1 - - -From b255ef1b90ebee3cfb44b545f75aa00e653411e8 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 15 Apr 2019 05:06:50 +0000 -Subject: [PATCH] HACK: arm64: dts: rockchip: disable vopl node on rk3399 - ---- - arch/arm64/boot/dts/rockchip/rk3399-firefly.dts | 8 -------- - arch/arm64/boot/dts/rockchip/rk3399-khadas-edge.dtsi | 8 -------- - arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi | 8 -------- - arch/arm64/boot/dts/rockchip/rk3399-orangepi.dts | 8 -------- - arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi | 8 -------- - arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts | 8 -------- - arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi | 8 -------- - arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi | 8 -------- - 8 files changed, 64 deletions(-) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts b/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts -index e9e2a6fb623b..ee38f6da9368 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts -@@ -801,11 +801,3 @@ - &vopb_mmu { - status = "okay"; - }; -- --&vopl { -- status = "okay"; --}; -- --&vopl_mmu { -- status = "okay"; --}; -diff --git a/arch/arm64/boot/dts/rockchip/rk3399-khadas-edge.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-khadas-edge.dtsi -index e87a04477440..f22f54dd0b73 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399-khadas-edge.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3399-khadas-edge.dtsi -@@ -797,11 +797,3 @@ - &vopb_mmu { - status = "okay"; - }; -- --&vopl { -- status = "okay"; --}; -- --&vopl_mmu { -- status = "okay"; --}; -diff --git a/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi -index c88018a0ef35..002ed18477e6 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi -@@ -747,11 +747,3 @@ - &vopb_mmu { - status = "okay"; - }; -- --&vopl { -- status = "okay"; --}; -- --&vopl_mmu { -- status = "okay"; --}; -diff --git a/arch/arm64/boot/dts/rockchip/rk3399-orangepi.dts b/arch/arm64/boot/dts/rockchip/rk3399-orangepi.dts -index bfb9fa11adcc..aa7f5e89ad72 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399-orangepi.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3399-orangepi.dts -@@ -787,11 +787,3 @@ - &vopb_mmu { - status = "okay"; - }; -- --&vopl { -- status = "okay"; --}; -- --&vopl_mmu { -- status = "okay"; --}; -diff --git a/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi -index 9f225e9c3d54..e917060f34c7 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi -@@ -804,11 +804,3 @@ - &vopb_mmu { - status = "okay"; - }; -- --&vopl { -- status = "okay"; --}; -- --&vopl_mmu { -- status = "okay"; --}; -diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts -index e4c71c77c3ef..4fdbc692b138 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts -@@ -728,11 +728,3 @@ - &vopb_mmu { - status = "okay"; - }; -- --&vopl { -- status = "okay"; --}; -- --&vopl_mmu { -- status = "okay"; --}; -diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi -index b69f0f2cbd67..aab612855670 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi -@@ -654,11 +654,3 @@ - &vopb_mmu { - status = "okay"; - }; -- --&vopl { -- status = "okay"; --}; -- --&vopl_mmu { -- status = "okay"; --}; -diff --git a/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi -index 0885d48011ab..471161b1accf 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi -@@ -639,11 +639,3 @@ - &vopb_mmu { - status = "okay"; - }; -- --&vopl { -- status = "okay"; --}; -- --&vopl_mmu { -- status = "okay"; --}; --- -2.17.1 - - -From 915a6f4cd5cb34c183e26f1c0889f93e55fa9de9 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 14 Apr 2019 21:16:31 +0000 -Subject: [PATCH] HACK: arm64: dts: rockchip: rename hdmi sound card on rk3399 - ---- - arch/arm64/boot/dts/rockchip/rk3399.dtsi | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi -index 33cc21fcf4c1..adc8c1058196 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi -@@ -1735,7 +1735,7 @@ - compatible = "simple-audio-card"; - simple-audio-card,format = "i2s"; - simple-audio-card,mclk-fs = <256>; -- simple-audio-card,name = "hdmi-sound"; -+ simple-audio-card,name = "HDMI"; - status = "disabled"; - - simple-audio-card,cpu { --- -2.17.1 - - -From 259475f3ec472d65fe037e5c6c4d217062e4a55c Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 12 May 2019 12:40:00 +0000 -Subject: [PATCH] WIP: arm64: dts: rockchip: add rk3328-box devices - ---- - arch/arm64/boot/dts/rockchip/Makefile | 3 + - .../boot/dts/rockchip/rk3328-box-trn9.dts | 420 ++++++++++++++++++ - .../boot/dts/rockchip/rk3328-box-z28.dts | 367 +++++++++++++++ - arch/arm64/boot/dts/rockchip/rk3328-box.dts | 400 +++++++++++++++++ - 4 files changed, 1190 insertions(+) - create mode 100644 arch/arm64/boot/dts/rockchip/rk3328-box-trn9.dts - create mode 100644 arch/arm64/boot/dts/rockchip/rk3328-box-z28.dts - create mode 100644 arch/arm64/boot/dts/rockchip/rk3328-box.dts - -diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile -index 1df8933cb084..9ff568832af7 100644 ---- a/arch/arm64/boot/dts/rockchip/Makefile -+++ b/arch/arm64/boot/dts/rockchip/Makefile -@@ -3,6 +3,9 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += px30-evb.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3308-evb.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3308-roc-cc.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-a1.dtb -+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-box.dtb -+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-box-trn9.dtb -+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-box-z28.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-evb.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-rock64.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-rockbox.dtb -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-box-trn9.dts b/arch/arm64/boot/dts/rockchip/rk3328-box-trn9.dts -new file mode 100644 -index 000000000000..e611d12ea375 ---- /dev/null -+++ b/arch/arm64/boot/dts/rockchip/rk3328-box-trn9.dts -@@ -0,0 +1,420 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Copyright (c) 2017 PINE64 -+ */ -+ -+/dts-v1/; -+#include "rk3328.dtsi" -+ -+/ { -+ model = "Rockchip RK3328 TRN9"; -+ compatible = "rockchip,rk3328-box-trn9", "rockchip,rk3328"; -+ -+ gmac_clkin: external-gmac-clock { -+ compatible = "fixed-clock"; -+ clock-frequency = <125000000>; -+ clock-output-names = "gmac_clkin"; -+ #clock-cells = <0>; -+ }; -+ -+ vcc_sd: sdmmc-regulator { -+ compatible = "regulator-fixed"; -+ gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_HIGH>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdmmc0m1_gpio>; -+ regulator-name = "vcc_sd"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ vin-supply = <&vcc_io>; -+ }; -+ -+ vcc_host_5v: vcc-host-5v-regulator { -+ compatible = "regulator-fixed"; -+ enable-active-high; -+ gpio = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&usb30_host_drv>; -+ regulator-name = "vcc_host_5v"; -+ regulator-always-on; -+ regulator-boot-on; -+ vin-supply = <&vcc_sys>; -+ }; -+ -+ vcc_host1_5v: vcc_otg_5v: vcc-host1-5v-regulator { -+ compatible = "regulator-fixed"; -+ enable-active-high; -+ gpio = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&usb20_host_drv>; -+ regulator-name = "vcc_host1_5v"; -+ regulator-always-on; -+ regulator-boot-on; -+ vin-supply = <&vcc_sys>; -+ }; -+ -+ vcc_sys: vcc-sys { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc_sys"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ }; -+ -+ ir-receiver { -+ compatible = "gpio-ir-receiver"; -+ gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; -+ pinctrl-0 = <&ir_int>; -+ pinctrl-names = "default"; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ power { -+ gpios = <&rk805 0 GPIO_ACTIVE_LOW>; -+ linux,default-trigger = "default-on"; -+ default-state = "on"; -+ }; -+ }; -+ -+ sdio_pwrseq: sdio-pwrseq { -+ compatible = "mmc-pwrseq-simple"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&wifi_enable_h>; -+ reset-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>; -+ }; -+}; -+ -+&analog_sound { -+ status = "okay"; -+}; -+ -+&codec { -+ status = "okay"; -+}; -+ -+&cpu0 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&cpu1 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&cpu2 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&cpu3 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&emmc { -+ bus-width = <8>; -+ cap-mmc-highspeed; -+ mmc-ddr-1_8v; -+ mmc-hs200-1_8v; -+ non-removable; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; -+ vmmc-supply = <&vcc_io>; -+ vqmmc-supply = <&vcc18_emmc>; -+ status = "okay"; -+}; -+ -+&gmac2io { -+ assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>; -+ assigned-clock-parents = <&gmac_clkin>, <&gmac_clkin>; -+ clock_in_out = "input"; -+ phy-mode = "rgmii"; -+ phy-supply = <&vcc_io>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&rgmiim1_pins>; -+ snps,aal; -+ snps,pbl = <0x4>; -+ snps,reset-gpio = <&gpio2 RK_PC1 GPIO_ACTIVE_LOW>; -+ snps,reset-active-low; -+ snps,reset-delays-us = <0 10000 50000>; -+ tx_delay = <0x26>; -+ rx_delay = <0x11>; -+ status = "okay"; -+}; -+ -+&gpu { -+ mali-supply = <&vdd_logic>; -+}; -+ -+&hdmi { -+ status = "okay"; -+}; -+ -+&hdmiphy { -+ status = "okay"; -+}; -+ -+&hdmi_sound { -+ status = "okay"; -+}; -+ -+&i2c1 { -+ status = "okay"; -+ -+ rk805: rk805@18 { -+ compatible = "rockchip,rk805"; -+ reg = <0x18>; -+ interrupt-parent = <&gpio2>; -+ interrupts = <6 IRQ_TYPE_LEVEL_LOW>; -+ #clock-cells = <1>; -+ clock-output-names = "xin32k", "rk805-clkout2"; -+ gpio-controller; -+ #gpio-cells = <2>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pmic_int_l>; -+ rockchip,system-power-controller; -+ wakeup-source; -+ -+ vcc1-supply = <&vcc_sys>; -+ vcc2-supply = <&vcc_sys>; -+ vcc3-supply = <&vcc_sys>; -+ vcc4-supply = <&vcc_sys>; -+ vcc5-supply = <&vcc_io>; -+ vcc6-supply = <&vcc_io>; -+ -+ regulators { -+ vdd_logic: DCDC_REG1 { -+ regulator-name = "vdd_logic"; -+ regulator-min-microvolt = <900000>; -+ regulator-max-microvolt = <1150000>; -+ regulator-ramp-delay = <12500>; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1000000>; -+ }; -+ }; -+ -+ vdd_arm: DCDC_REG2 { -+ regulator-name = "vdd_arm"; -+ regulator-min-microvolt = <950000>; -+ regulator-max-microvolt = <1350000>; -+ regulator-ramp-delay = <12500>; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <950000>; -+ }; -+ }; -+ -+ vcc_ddr: DCDC_REG3 { -+ regulator-name = "vcc_ddr"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ }; -+ }; -+ -+ vcc_io: DCDC_REG4 { -+ regulator-name = "vcc_io"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <3300000>; -+ }; -+ }; -+ -+ vcc_18: LDO_REG1 { -+ regulator-name = "vcc_18"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1800000>; -+ }; -+ }; -+ -+ vcc18_emmc: LDO_REG2 { -+ regulator-name = "vcc18_emmc"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1800000>; -+ }; -+ }; -+ -+ vdd_10: LDO_REG3 { -+ regulator-name = "vdd_10"; -+ regulator-min-microvolt = <1000000>; -+ regulator-max-microvolt = <1000000>; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1000000>; -+ }; -+ }; -+ }; -+ }; -+}; -+ -+&i2s0 { -+ status = "okay"; -+}; -+ -+&i2s1 { -+ status = "okay"; -+}; -+ -+&io_domains { -+ vccio1-supply = <&vcc_io>; -+ vccio2-supply = <&vcc18_emmc>; -+ vccio3-supply = <&vcc_io>; -+ vccio4-supply = <&vcc_18>; -+ vccio5-supply = <&vcc_io>; -+ vccio6-supply = <&vcc_18>; -+ pmuio-supply = <&vcc_io>; -+ status = "okay"; -+}; -+ -+&pinctrl { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&clk_32k_out>; -+ -+ clk_32k { -+ clk_32k_out: clk-32k-out { -+ rockchip,pins = <1 RK_PD4 RK_FUNC_1 &pcfg_pull_none>; -+ }; -+ }; -+ -+ ir { -+ ir_int: ir-int { -+ rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+ -+ pmic { -+ pmic_int_l: pmic-int-l { -+ rockchip,pins = <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>; -+ }; -+ }; -+ -+ sdio-pwrseq { -+ wifi_enable_h: wifi-enable-h { -+ rockchip,pins = <3 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>, -+ <3 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none_4ma>, -+ <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>, -+ <1 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+ -+ usb2 { -+ usb20_host_drv: usb20-host-drv { -+ rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+ -+ usb3 { -+ usb30_host_drv: usb30-host-drv { -+ rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+}; -+ -+&sdmmc_ext { -+ bus-width = <4>; -+ cap-sd-highspeed; -+ cap-sdio-irq; -+ keep-power-in-suspend; -+ mmc-pwrseq = <&sdio_pwrseq>; -+ non-removable; -+ num-slots = <1>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdmmc0ext_bus4 &sdmmc0ext_cmd &sdmmc0ext_clk>; -+ sd-uhs-sdr104; -+ status = "okay"; -+}; -+ -+&sdmmc { -+ bus-width = <4>; -+ cap-mmc-highspeed; -+ cap-sd-highspeed; -+ disable-wp; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_dectn &sdmmc0_bus4>; -+ vmmc-supply = <&vcc_sd>; -+ status = "okay"; -+}; -+ -+&spdif { -+ pinctrl-0 = <&spdifm0_tx>; -+ status = "okay"; -+}; -+ -+&spdif_out { -+ status = "okay"; -+}; -+ -+&spdif_sound { -+ status = "okay"; -+}; -+ -+&tsadc { -+ rockchip,hw-tshut-mode = <0>; -+ rockchip,hw-tshut-polarity = <0>; -+ status = "okay"; -+}; -+ -+&uart2 { -+ status = "okay"; -+}; -+ -+&u2phy { -+ status = "okay"; -+}; -+ -+&u2phy_host { -+ status = "okay"; -+}; -+ -+&u2phy_otg { -+ status = "okay"; -+}; -+ -+&usb20_otg { -+ dr_mode = "host"; -+ status = "okay"; -+}; -+ -+&usb_host0_ehci { -+ status = "okay"; -+}; -+ -+&usb_host0_ohci { -+ status = "okay"; -+}; -+ -+&usbdrd3 { -+ status = "okay"; -+}; -+ -+&usbdrd_dwc3 { -+ dr_mode = "host"; -+ status = "okay"; -+}; -+ -+&vop { -+ status = "okay"; -+}; -+ -+&vop_mmu { -+ status = "okay"; -+}; -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-box-z28.dts b/arch/arm64/boot/dts/rockchip/rk3328-box-z28.dts -new file mode 100644 -index 000000000000..797b92924f21 ---- /dev/null -+++ b/arch/arm64/boot/dts/rockchip/rk3328-box-z28.dts -@@ -0,0 +1,367 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Copyright (c) 2017 PINE64 -+ */ -+ -+/dts-v1/; -+#include "rk3328.dtsi" -+ -+/ { -+ model = "Rockchip RK3328 Z28"; -+ compatible = "rockchip,rk3328-box-z28", "rockchip,rk3328"; -+ -+ chosen { -+ stdout-path = "serial2:1500000n8"; -+ }; -+ -+ vcc_sd: sdmmc-regulator { -+ compatible = "regulator-fixed"; -+ gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_HIGH>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdmmc0m1_gpio>; -+ regulator-name = "vcc_sd"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ vin-supply = <&vcc_io>; -+ }; -+ -+ vcc_host_5v: vcc-host-5v-regulator { -+ compatible = "regulator-fixed"; -+ enable-active-high; -+ gpio = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&usb30_host_drv>; -+ regulator-name = "vcc_host_5v"; -+ regulator-always-on; -+ regulator-boot-on; -+ vin-supply = <&vcc_sys>; -+ }; -+ -+ vcc_host1_5v: vcc_otg_5v: vcc-host1-5v-regulator { -+ compatible = "regulator-fixed"; -+ enable-active-high; -+ gpio = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&usb20_host_drv>; -+ regulator-name = "vcc_host1_5v"; -+ regulator-always-on; -+ regulator-boot-on; -+ vin-supply = <&vcc_sys>; -+ }; -+ -+ vcc_sys: vcc-sys { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc_sys"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ }; -+ -+ ir-receiver { -+ compatible = "gpio-ir-receiver"; -+ gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; -+ pinctrl-0 = <&ir_int>; -+ pinctrl-names = "default"; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ power { -+ gpios = <&rk805 0 GPIO_ACTIVE_HIGH>; -+ linux,default-trigger = "default-on"; -+ default-state = "on"; -+ }; -+ }; -+}; -+ -+&cpu0 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&cpu1 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&cpu2 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&cpu3 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&emmc { -+ bus-width = <8>; -+ cap-mmc-highspeed; -+ mmc-ddr-1_8v; -+ mmc-hs200-1_8v; -+ non-removable; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; -+ vmmc-supply = <&vcc_io>; -+ vqmmc-supply = <&vcc18_emmc>; -+ status = "okay"; -+}; -+ -+&gmac2phy { -+ assigned-clocks = <&cru SCLK_MAC2PHY_SRC>; -+ assigned-clock-rate = <50000000>; -+ assigned-clocks = <&cru SCLK_MAC2PHY>; -+ assigned-clock-parents = <&cru SCLK_MAC2PHY_SRC>; -+ clock_in_out = "output"; -+ phy-supply = <&vcc_io>; -+ status = "okay"; -+}; -+ -+&gpu { -+ mali-supply = <&vdd_logic>; -+}; -+ -+&hdmi { -+ status = "okay"; -+}; -+ -+&hdmiphy { -+ status = "okay"; -+}; -+ -+&hdmi_sound { -+ status = "okay"; -+}; -+ -+&i2c1 { -+ status = "okay"; -+ -+ rk805: rk805@18 { -+ compatible = "rockchip,rk805"; -+ reg = <0x18>; -+ interrupt-parent = <&gpio2>; -+ interrupts = <6 IRQ_TYPE_LEVEL_LOW>; -+ #clock-cells = <1>; -+ clock-output-names = "xin32k", "rk805-clkout2"; -+ gpio-controller; -+ #gpio-cells = <2>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pmic_int_l>; -+ rockchip,system-power-controller; -+ wakeup-source; -+ -+ vcc1-supply = <&vcc_sys>; -+ vcc2-supply = <&vcc_sys>; -+ vcc3-supply = <&vcc_sys>; -+ vcc4-supply = <&vcc_sys>; -+ vcc5-supply = <&vcc_io>; -+ vcc6-supply = <&vcc_io>; -+ -+ regulators { -+ vdd_logic: DCDC_REG1 { -+ regulator-name = "vdd_logic"; -+ regulator-min-microvolt = <900000>; -+ regulator-max-microvolt = <1150000>; -+ regulator-ramp-delay = <12500>; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1000000>; -+ }; -+ }; -+ -+ vdd_arm: DCDC_REG2 { -+ regulator-name = "vdd_arm"; -+ regulator-min-microvolt = <950000>; -+ regulator-max-microvolt = <1350000>; -+ regulator-ramp-delay = <12500>; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <950000>; -+ }; -+ }; -+ -+ vcc_ddr: DCDC_REG3 { -+ regulator-name = "vcc_ddr"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ }; -+ }; -+ -+ vcc_io: DCDC_REG4 { -+ regulator-name = "vcc_io"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <3300000>; -+ }; -+ }; -+ -+ vcc_18: LDO_REG1 { -+ regulator-name = "vcc_18"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1800000>; -+ }; -+ }; -+ -+ vcc18_emmc: LDO_REG2 { -+ regulator-name = "vcc18_emmc"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1800000>; -+ }; -+ }; -+ -+ vdd_10: LDO_REG3 { -+ regulator-name = "vdd_10"; -+ regulator-min-microvolt = <1000000>; -+ regulator-max-microvolt = <1000000>; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1000000>; -+ }; -+ }; -+ }; -+ }; -+}; -+ -+&i2s0 { -+ status = "okay"; -+}; -+ -+&io_domains { -+ vccio1-supply = <&vcc_io>; -+ vccio2-supply = <&vcc18_emmc>; -+ vccio3-supply = <&vcc_io>; -+ vccio4-supply = <&vcc_18>; -+ vccio5-supply = <&vcc_io>; -+ vccio6-supply = <&vcc_io>; -+ pmuio-supply = <&vcc_io>; -+ status = "okay"; -+}; -+ -+&pinctrl { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&clk_32k_out>; -+ -+ clk_32k { -+ clk_32k_out: clk-32k-out { -+ rockchip,pins = <1 RK_PD4 RK_FUNC_1 &pcfg_pull_none>; -+ }; -+ }; -+ -+ ir { -+ ir_int: ir-int { -+ rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+ -+ pmic { -+ pmic_int_l: pmic-int-l { -+ rockchip,pins = <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>; -+ }; -+ }; -+ -+ usb2 { -+ usb20_host_drv: usb20-host-drv { -+ rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+ -+ usb3 { -+ usb30_host_drv: usb30-host-drv { -+ rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+}; -+ -+&sdmmc { -+ bus-width = <4>; -+ cap-mmc-highspeed; -+ cap-sd-highspeed; -+ disable-wp; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_dectn &sdmmc0_bus4>; -+ vmmc-supply = <&vcc_sd>; -+ status = "okay"; -+}; -+ -+&spdif { -+ pinctrl-0 = <&spdifm0_tx>; -+ status = "okay"; -+}; -+ -+&spdif_out { -+ status = "okay"; -+}; -+ -+&spdif_sound { -+ status = "okay"; -+}; -+ -+&tsadc { -+ rockchip,hw-tshut-mode = <0>; -+ rockchip,hw-tshut-polarity = <0>; -+ status = "okay"; -+}; -+ -+&uart2 { -+ status = "okay"; -+}; -+ -+&u2phy { -+ status = "okay"; -+}; -+ -+&u2phy_host { -+ status = "okay"; -+}; -+ -+&u2phy_otg { -+ status = "okay"; -+}; -+ -+&usb20_otg { -+ dr_mode = "host"; -+ status = "okay"; -+}; -+ -+&usb_host0_ehci { -+ status = "okay"; -+}; -+ -+&usb_host0_ohci { -+ status = "okay"; -+}; -+ -+&usbdrd3 { -+ status = "okay"; -+}; -+ -+&usbdrd_dwc3 { -+ dr_mode = "host"; -+ status = "okay"; -+}; -+ -+&vop { -+ status = "okay"; -+}; -+ -+&vop_mmu { -+ status = "okay"; -+}; -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-box.dts b/arch/arm64/boot/dts/rockchip/rk3328-box.dts -new file mode 100644 -index 000000000000..2526147fd48b ---- /dev/null -+++ b/arch/arm64/boot/dts/rockchip/rk3328-box.dts -@@ -0,0 +1,400 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Copyright (c) 2017 PINE64 -+ */ -+ -+/dts-v1/; -+#include "rk3328.dtsi" -+ -+/ { -+ model = "Rockchip RK3328 BOX"; -+ compatible = "rockchip,rk3328-box", "rockchip,rk3328"; -+ -+ chosen { -+ stdout-path = "serial2:1500000n8"; -+ }; -+ -+ vcc_sd: sdmmc-regulator { -+ compatible = "regulator-fixed"; -+ gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_HIGH>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdmmc0m1_gpio>; -+ regulator-name = "vcc_sd"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ vin-supply = <&vcc_io>; -+ }; -+ -+ vcc_host_5v: vcc-host-5v-regulator { -+ compatible = "regulator-fixed"; -+ enable-active-high; -+ gpio = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&usb30_host_drv>; -+ regulator-name = "vcc_host_5v"; -+ regulator-always-on; -+ regulator-boot-on; -+ vin-supply = <&vcc_sys>; -+ }; -+ -+ vcc_host1_5v: vcc_otg_5v: vcc-host1-5v-regulator { -+ compatible = "regulator-fixed"; -+ enable-active-high; -+ gpio = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&usb20_host_drv>; -+ regulator-name = "vcc_host1_5v"; -+ regulator-always-on; -+ regulator-boot-on; -+ vin-supply = <&vcc_sys>; -+ }; -+ -+ vcc_sys: vcc-sys { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc_sys"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ }; -+ -+ ir-receiver { -+ compatible = "gpio-ir-receiver"; -+ gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; -+ pinctrl-0 = <&ir_int>; -+ pinctrl-names = "default"; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ led1 { -+ gpios = <&rk805 0 GPIO_ACTIVE_LOW>; -+ linux,default-trigger = "default-on"; -+ default-state = "on"; -+ }; -+ -+ led2 { -+ gpios = <&rk805 1 GPIO_ACTIVE_LOW>; -+ linux,default-trigger = "mmc0"; -+ }; -+ }; -+ -+ sdio_pwrseq: sdio-pwrseq { -+ compatible = "mmc-pwrseq-simple"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&wifi_enable_h>; -+ reset-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; -+ }; -+}; -+ -+&cpu0 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&cpu1 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&cpu2 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&cpu3 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&emmc { -+ bus-width = <8>; -+ cap-mmc-highspeed; -+ mmc-ddr-1_8v; -+ mmc-hs200-1_8v; -+ non-removable; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; -+ vmmc-supply = <&vcc_io>; -+ vqmmc-supply = <&vcc18_emmc>; -+ status = "okay"; -+}; -+ -+&gmac2phy { -+ assigned-clocks = <&cru SCLK_MAC2PHY_SRC>; -+ assigned-clock-rate = <50000000>; -+ assigned-clocks = <&cru SCLK_MAC2PHY>; -+ assigned-clock-parents = <&cru SCLK_MAC2PHY_SRC>; -+ clock_in_out = "output"; -+ phy-supply = <&vcc_io>; -+ status = "okay"; -+}; -+ -+&gpu { -+ mali-supply = <&vdd_logic>; -+}; -+ -+&hdmi { -+ status = "okay"; -+}; -+ -+&hdmiphy { -+ status = "okay"; -+}; -+ -+&hdmi_sound { -+ status = "okay"; -+}; -+ -+&i2c1 { -+ status = "okay"; -+ -+ rk805: rk805@18 { -+ compatible = "rockchip,rk805"; -+ reg = <0x18>; -+ interrupt-parent = <&gpio2>; -+ interrupts = <6 IRQ_TYPE_LEVEL_LOW>; -+ #clock-cells = <1>; -+ clock-output-names = "xin32k", "rk805-clkout2"; -+ gpio-controller; -+ #gpio-cells = <2>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pmic_int_l>; -+ rockchip,system-power-controller; -+ wakeup-source; -+ -+ vcc1-supply = <&vcc_sys>; -+ vcc2-supply = <&vcc_sys>; -+ vcc3-supply = <&vcc_sys>; -+ vcc4-supply = <&vcc_sys>; -+ vcc5-supply = <&vcc_io>; -+ vcc6-supply = <&vcc_io>; -+ -+ regulators { -+ vdd_logic: DCDC_REG1 { -+ regulator-name = "vdd_logic"; -+ regulator-min-microvolt = <900000>; -+ regulator-max-microvolt = <1150000>; -+ regulator-ramp-delay = <12500>; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1000000>; -+ }; -+ }; -+ -+ vdd_arm: DCDC_REG2 { -+ regulator-name = "vdd_arm"; -+ regulator-min-microvolt = <950000>; -+ regulator-max-microvolt = <1350000>; -+ regulator-ramp-delay = <12500>; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <950000>; -+ }; -+ }; -+ -+ vcc_ddr: DCDC_REG3 { -+ regulator-name = "vcc_ddr"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ }; -+ }; -+ -+ vcc_io: DCDC_REG4 { -+ regulator-name = "vcc_io"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <3300000>; -+ }; -+ }; -+ -+ vcc_18: LDO_REG1 { -+ regulator-name = "vcc_18"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1800000>; -+ }; -+ }; -+ -+ vcc18_emmc: LDO_REG2 { -+ regulator-name = "vcc18_emmc"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1800000>; -+ }; -+ }; -+ -+ vdd_10: LDO_REG3 { -+ regulator-name = "vdd_10"; -+ regulator-min-microvolt = <1000000>; -+ regulator-max-microvolt = <1000000>; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1000000>; -+ }; -+ }; -+ }; -+ }; -+}; -+ -+&i2s0 { -+ status = "okay"; -+}; -+ -+&io_domains { -+ vccio1-supply = <&vcc_io>; -+ vccio2-supply = <&vcc18_emmc>; -+ vccio3-supply = <&vcc_io>; -+ vccio4-supply = <&vcc_18>; -+ vccio5-supply = <&vcc_io>; -+ vccio6-supply = <&vcc_io>; -+ pmuio-supply = <&vcc_io>; -+ status = "okay"; -+}; -+ -+&pinctrl { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&clk_32k_out>; -+ -+ clk_32k { -+ clk_32k_out: clk-32k-out { -+ rockchip,pins = <1 RK_PD4 RK_FUNC_1 &pcfg_pull_none>; -+ }; -+ }; -+ -+ ir { -+ ir_int: ir-int { -+ rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+ -+ pmic { -+ pmic_int_l: pmic-int-l { -+ rockchip,pins = <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>; -+ }; -+ }; -+ -+ sdio-pwrseq { -+ wifi_enable_h: wifi-enable-h { -+ rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none_4ma>, -+ <1 RK_PC3 RK_FUNC_GPIO &pcfg_pull_none_4ma>; -+ }; -+ }; -+ -+ usb2 { -+ usb20_host_drv: usb20-host-drv { -+ rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+ -+ usb3 { -+ usb30_host_drv: usb30-host-drv { -+ rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+}; -+ -+&sdio { -+ bus-width = <4>; -+ cap-sd-highspeed; -+ cap-sdio-irq; -+ keep-power-in-suspend; -+ mmc-pwrseq = <&sdio_pwrseq>; -+ non-removable; -+ num-slots = <1>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdmmc1_bus4 &sdmmc1_cmd &sdmmc1_clk>; -+ sd-uhs-sdr104; -+ status = "disabled"; -+}; -+ -+&sdmmc { -+ bus-width = <4>; -+ cap-mmc-highspeed; -+ cap-sd-highspeed; -+ disable-wp; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_dectn &sdmmc0_bus4>; -+ vmmc-supply = <&vcc_sd>; -+ status = "okay"; -+}; -+ -+&spdif { -+ pinctrl-0 = <&spdifm0_tx>; -+ status = "okay"; -+}; -+ -+&spdif_out { -+ status = "okay"; -+}; -+ -+&spdif_sound { -+ status = "okay"; -+}; -+ -+&tsadc { -+ rockchip,hw-tshut-mode = <0>; -+ rockchip,hw-tshut-polarity = <0>; -+ status = "okay"; -+}; -+ -+&uart2 { -+ status = "okay"; -+}; -+ -+&u2phy { -+ status = "okay"; -+}; -+ -+&u2phy_host { -+ status = "okay"; -+}; -+ -+&u2phy_otg { -+ status = "okay"; -+}; -+ -+&usb20_otg { -+ dr_mode = "host"; -+ status = "okay"; -+}; -+ -+&usb_host0_ehci { -+ status = "okay"; -+}; -+ -+&usb_host0_ohci { -+ status = "okay"; -+}; -+ -+&usbdrd3 { -+ status = "okay"; -+}; -+ -+&usbdrd_dwc3 { -+ dr_mode = "host"; -+ status = "okay"; -+}; -+ -+&vop { -+ status = "okay"; -+}; -+ -+&vop_mmu { -+ status = "okay"; -+}; --- -2.17.1 - diff --git a/patch/kernel/rk322x-current/01-linux-0006-experimental.patch.disabled b/patch/kernel/rk322x-current/01-linux-0006-experimental.patch.disabled deleted file mode 100644 index 892c5b859..000000000 --- a/patch/kernel/rk322x-current/01-linux-0006-experimental.patch.disabled +++ /dev/null @@ -1,1825 +0,0 @@ -diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c -index 9ca20c947283..b0ac1d3ee390 100644 ---- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c -+++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c -@@ -790,8 +790,8 @@ static int inno_hdmi_phy_rk3328_clk_set_rate(struct clk_hw *hw, - RK3328_PRE_PLL_POWER_DOWN); - - /* Configure pre-pll */ -- inno_update_bits(inno, 0xa0, RK3228_PCLK_VCO_DIV_5_MASK, -- RK3228_PCLK_VCO_DIV_5(cfg->vco_div_5_en)); -+ inno_update_bits(inno, 0xa0, RK3328_PCLK_VCO_DIV_5_MASK, -+ RK3328_PCLK_VCO_DIV_5(cfg->vco_div_5_en)); - inno_write(inno, 0xa1, RK3328_PRE_PLL_PRE_DIV(cfg->prediv)); - - val = RK3328_SPREAD_SPECTRUM_MOD_DISABLE; --- -2.17.1 - - -From 0ae81f8167f59ad2c781dc51f2b2fa3e0c9f976b Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Fri, 20 Dec 2019 08:12:42 +0000 -Subject: [PATCH] phy/rockchip: inno-hdmi: round fractal pixclock in rk3328 - recalc_rate - -inno_hdmi_phy_rk3328_clk_recalc_rate() is returning a rate not found -in the pre pll config table when the fractal divider is used. -This can prevent proper power_on because a tmdsclock for the new rate -is not found in the pre pll config table. - -Fix this by saving and returning a rounded pixel rate that exist -in the pre pll config table. - -Fixes: 53706a116863 ("phy: add Rockchip Innosilicon hdmi phy") -Signed-off-by: Zheng Yang -Signed-off-by: Jonas Karlman ---- - drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - -diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c -index b0ac1d3ee390..093d2334e8cd 100644 ---- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c -+++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c -@@ -745,10 +745,12 @@ unsigned long inno_hdmi_phy_rk3328_clk_recalc_rate(struct clk_hw *hw, - do_div(vco, (nd * (no_a == 1 ? no_b : no_a) * no_d * 2)); - } - -- inno->pixclock = vco; -- dev_dbg(inno->dev, "%s rate %lu\n", __func__, inno->pixclock); -+ inno->pixclock = DIV_ROUND_CLOSEST((unsigned long)vco, 1000) * 1000; - -- return vco; -+ dev_dbg(inno->dev, "%s rate %lu vco %llu\n", -+ __func__, inno->pixclock, vco); -+ -+ return inno->pixclock; - } - - static long inno_hdmi_phy_rk3328_clk_round_rate(struct clk_hw *hw, --- -2.17.1 - - -From fcb6a75bac484bec5443241965757b2d7cf99182 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Fri, 20 Dec 2019 08:12:42 +0000 -Subject: [PATCH] phy/rockchip: inno-hdmi: remove unused no_c from rk3328 - recalc_rate - -no_c is not used in any calculation, lets remove it. - -Signed-off-by: Jonas Karlman ---- - drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 5 +---- - 1 file changed, 1 insertion(+), 4 deletions(-) - -diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c -index 093d2334e8cd..06db69c8373e 100644 ---- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c -+++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c -@@ -714,7 +714,7 @@ unsigned long inno_hdmi_phy_rk3328_clk_recalc_rate(struct clk_hw *hw, - { - struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw); - unsigned long frac; -- u8 nd, no_a, no_b, no_c, no_d; -+ u8 nd, no_a, no_b, no_d; - u64 vco; - u16 nf; - -@@ -737,9 +737,6 @@ unsigned long inno_hdmi_phy_rk3328_clk_recalc_rate(struct clk_hw *hw, - no_b = inno_read(inno, 0xa5) & RK3328_PRE_PLL_PCLK_DIV_B_MASK; - no_b >>= RK3328_PRE_PLL_PCLK_DIV_B_SHIFT; - no_b += 2; -- no_c = inno_read(inno, 0xa6) & RK3328_PRE_PLL_PCLK_DIV_C_MASK; -- no_c >>= RK3328_PRE_PLL_PCLK_DIV_C_SHIFT; -- no_c = 1 << no_c; - no_d = inno_read(inno, 0xa6) & RK3328_PRE_PLL_PCLK_DIV_D_MASK; - - do_div(vco, (nd * (no_a == 1 ? no_b : no_a) * no_d * 2)); --- -2.17.1 - - -From 8da78b0cf0c522be59656ed24a0018bd2fbea5a8 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Fri, 20 Dec 2019 08:12:42 +0000 -Subject: [PATCH] phy/rockchip: inno-hdmi: do not power on rk3328 post pll on - reg write - -inno_write is used to configure 0xaa reg, that also hold the -POST_PLL_POWER_DOWN bit. -When POST_PLL_REFCLK_SEL_TMDS is configured the power down bit is not -taken into consideration. - -Fix this by keeping the power down bit until configuration is complete. -Also reorder the reg write order for consistency. - -Fixes: 53706a116863 ("phy: add Rockchip Innosilicon hdmi phy") -Signed-off-by: Jonas Karlman ---- - drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c -index 06db69c8373e..3a59a6da0440 100644 ---- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c -+++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c -@@ -1020,9 +1020,10 @@ inno_hdmi_phy_rk3328_power_on(struct inno_hdmi_phy *inno, - - inno_write(inno, 0xac, RK3328_POST_PLL_FB_DIV_7_0(cfg->fbdiv)); - if (cfg->postdiv == 1) { -- inno_write(inno, 0xaa, RK3328_POST_PLL_REFCLK_SEL_TMDS); - inno_write(inno, 0xab, RK3328_POST_PLL_FB_DIV_8(cfg->fbdiv) | - RK3328_POST_PLL_PRE_DIV(cfg->prediv)); -+ inno_write(inno, 0xaa, RK3328_POST_PLL_REFCLK_SEL_TMDS | -+ RK3328_POST_PLL_POWER_DOWN); - } else { - v = (cfg->postdiv / 2) - 1; - v &= RK3328_POST_PLL_POST_DIV_MASK; -@@ -1030,7 +1031,8 @@ inno_hdmi_phy_rk3328_power_on(struct inno_hdmi_phy *inno, - inno_write(inno, 0xab, RK3328_POST_PLL_FB_DIV_8(cfg->fbdiv) | - RK3328_POST_PLL_PRE_DIV(cfg->prediv)); - inno_write(inno, 0xaa, RK3328_POST_PLL_POST_DIV_ENABLE | -- RK3328_POST_PLL_REFCLK_SEL_TMDS); -+ RK3328_POST_PLL_REFCLK_SEL_TMDS | -+ RK3328_POST_PLL_POWER_DOWN); - } - - for (v = 0; v < 14; v++) --- -2.17.1 - - -From 790af1279068ad1cc4ef471d90050570a850f426 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Fri, 20 Dec 2019 08:12:42 +0000 -Subject: [PATCH] phy/rockchip: inno-hdmi: force set_rate on power_on - -Regular 8-bit and Deep Color video formats mainly differ in TMDS rate and -not in pixel clock rate. -When the hdmiphy clock is configured with the same pixel clock rate using -clk_set_rate() the clock framework do not signal the hdmi phy driver -to set_rate when switching between 8-bit and Deep Color. -This result in pre/post pll not being re-configured when switching between -regular 8-bit and Deep Color video formats. - -Fix this by calling set_rate in power_on to force pre pll re-configuration. - -Signed-off-by: Jonas Karlman ---- - drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - -diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c -index 3a59a6da0440..3719309ad0d0 100644 ---- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c -+++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c -@@ -245,6 +245,7 @@ struct inno_hdmi_phy { - struct clk_hw hw; - struct clk *phyclk; - unsigned long pixclock; -+ unsigned long tmdsclock; - }; - - struct pre_pll_config { -@@ -485,6 +486,8 @@ static int inno_hdmi_phy_power_on(struct phy *phy) - - dev_dbg(inno->dev, "Inno HDMI PHY Power On\n"); - -+ inno->plat_data->clk_ops->set_rate(&inno->hw, inno->pixclock, 24000000); -+ - ret = clk_prepare_enable(inno->phyclk); - if (ret) - return ret; -@@ -509,6 +512,8 @@ static int inno_hdmi_phy_power_off(struct phy *phy) - - clk_disable_unprepare(inno->phyclk); - -+ inno->tmdsclock = 0; -+ - dev_dbg(inno->dev, "Inno HDMI PHY Power Off\n"); - - return 0; -@@ -628,6 +633,9 @@ static int inno_hdmi_phy_rk3228_clk_set_rate(struct clk_hw *hw, - dev_dbg(inno->dev, "%s rate %lu tmdsclk %lu\n", - __func__, rate, tmdsclock); - -+ if (inno->pixclock == rate && inno->tmdsclock == tmdsclock) -+ return 0; -+ - cfg = inno_hdmi_phy_get_pre_pll_cfg(inno, rate); - if (IS_ERR(cfg)) - return PTR_ERR(cfg); -@@ -670,6 +678,7 @@ static int inno_hdmi_phy_rk3228_clk_set_rate(struct clk_hw *hw, - } - - inno->pixclock = rate; -+ inno->tmdsclock = tmdsclock; - - return 0; - } -@@ -781,6 +790,9 @@ static int inno_hdmi_phy_rk3328_clk_set_rate(struct clk_hw *hw, - dev_dbg(inno->dev, "%s rate %lu tmdsclk %lu\n", - __func__, rate, tmdsclock); - -+ if (inno->pixclock == rate && inno->tmdsclock == tmdsclock) -+ return 0; -+ - cfg = inno_hdmi_phy_get_pre_pll_cfg(inno, rate); - if (IS_ERR(cfg)) - return PTR_ERR(cfg); -@@ -820,6 +832,7 @@ static int inno_hdmi_phy_rk3328_clk_set_rate(struct clk_hw *hw, - } - - inno->pixclock = rate; -+ inno->tmdsclock = tmdsclock; - - return 0; - } --- -2.17.1 - - -From 852eb17bca3ae36762eb2975bb9a5642cf0865d8 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sat, 21 Dec 2019 23:52:16 +0000 -Subject: [PATCH] drm/rockchip: vop: limit resolution width to 3840 - -Using a destination width that is more then 3840 pixels -is not supported in scl_vop_cal_scl_fac(). - -Work around this limitation by filtering all modes with -a width above 3840. - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -index d04b3492bdac..f181897cbfad 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -@@ -1036,6 +1036,15 @@ static void vop_crtc_disable_vblank(struct drm_crtc *crtc) - spin_unlock_irqrestore(&vop->irq_lock, flags); - } - -+enum drm_mode_status vop_crtc_mode_valid(struct drm_crtc *crtc, -+ const struct drm_display_mode *mode) -+{ -+ if (mode->hdisplay > 3840) -+ return MODE_BAD_HVALUE; -+ -+ return MODE_OK; -+} -+ - static bool vop_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -@@ -1377,6 +1386,7 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc, - } - - static const struct drm_crtc_helper_funcs vop_crtc_helper_funcs = { -+ .mode_valid = vop_crtc_mode_valid, - .mode_fixup = vop_crtc_mode_fixup, - .atomic_check = vop_crtc_atomic_check, - .atomic_begin = vop_crtc_atomic_begin, --- -2.17.1 - - -From 1f18ed83f51df960be0688db39b086b9a58ef7d1 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 22 Dec 2019 12:43:36 +0000 -Subject: [PATCH] drm/rockchip: dw-hdmi: allow high tmds bit rates - -Prepare support for High TMDS Bit Rates used by HDMI2.0 display modes. - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index 7f56d8c3491d..fae38b323a0c 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -318,6 +318,8 @@ static int dw_hdmi_rockchip_genphy_init(struct dw_hdmi *dw_hdmi, void *data, - { - struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; - -+ dw_hdmi_set_high_tmds_clock_ratio(dw_hdmi); -+ - return phy_power_on(hdmi->phy); - } - --- -2.17.1 - - -From d8ee714e54380f7b09dd088944f5c030aa1ee320 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 22 Dec 2019 12:35:16 +0000 -Subject: [PATCH] drm/rockchip: dw-hdmi: require valid vpll clock rate on - rk3228/rk3328 - -RK3228/RK3328 can only support clock rates defined in the pre pll table. -Lets validate the mode clock rate against the pre pll config and filter -out any mode with a clock rate returning error from clk_round_rate(). - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 17 +++++++++++++++++ - 1 file changed, 17 insertions(+) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index fae38b323a0c..45fcdce3f27f 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -245,6 +245,22 @@ static void dw_hdmi_rockchip_encoder_disable(struct drm_encoder *encoder) - { - } - -+static enum drm_mode_status -+dw_hdmi_rockchip_encoder_mode_valid(struct drm_encoder *encoder, -+ const struct drm_display_mode *mode) -+{ -+ struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); -+ long rate; -+ -+ if (hdmi->vpll_clk) { -+ rate = clk_round_rate(hdmi->vpll_clk, mode->clock * 1000); -+ if (rate < 0) -+ return MODE_CLOCK_RANGE; -+ } -+ -+ return MODE_OK; -+} -+ - static bool - dw_hdmi_rockchip_encoder_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, -@@ -306,6 +322,7 @@ dw_hdmi_rockchip_encoder_atomic_check(struct drm_encoder *encoder, - } - - static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_funcs = { -+ .mode_valid = dw_hdmi_rockchip_encoder_mode_valid, - .mode_fixup = dw_hdmi_rockchip_encoder_mode_fixup, - .mode_set = dw_hdmi_rockchip_encoder_mode_set, - .enable = dw_hdmi_rockchip_encoder_enable, --- -2.17.1 - - -From f305ae2094370127c797a4af3772bd9ff4e8dfc2 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 22 Dec 2019 23:42:45 +0000 -Subject: [PATCH] clk: rockchip: set parent rate for DCLK_VOP clock on rk3228 - -Signed-off-by: Jonas Karlman ---- - drivers/clk/rockchip/clk-rk3228.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c -index d17cfb7a3ff4..25f79af22cb8 100644 ---- a/drivers/clk/rockchip/clk-rk3228.c -+++ b/drivers/clk/rockchip/clk-rk3228.c -@@ -410,7 +410,7 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { - RK2928_CLKSEL_CON(29), 0, 3, DFLAGS), - DIV(0, "sclk_vop_pre", "sclk_vop_src", 0, - RK2928_CLKSEL_CON(27), 8, 8, DFLAGS), -- MUX(DCLK_VOP, "dclk_vop", mux_dclk_vop_p, 0, -+ MUX(DCLK_VOP, "dclk_vop", mux_dclk_vop_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, - RK2928_CLKSEL_CON(27), 1, 1, MFLAGS), - - FACTOR(0, "xin12m", "xin24m", 0, 1, 2), --- -2.17.1 - - -From 69f1bbcbc9c02c34f4fda49191ccae1f9dac410e Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 15 Dec 2019 10:05:46 +0000 -Subject: [PATCH] arm64: dts: rockchip: increase vop clock rate on rk3328 - -The VOP on RK3328 needs to run faster in order to procude a proper -3840x2160 signal. - -Signed-off-by: Jonas Karlman ---- - arch/arm64/boot/dts/rockchip/rk3328.dtsi | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi -index bc9186f66d9c..d4cfb1066c5a 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi -@@ -834,8 +834,8 @@ - <0>, <24000000>, - <24000000>, <24000000>, - <15000000>, <15000000>, -- <100000000>, <100000000>, -- <100000000>, <100000000>, -+ <300000000>, <100000000>, -+ <400000000>, <100000000>, - <50000000>, <100000000>, - <100000000>, <100000000>, - <50000000>, <50000000>, --- -2.17.1 - - -From 2aeb955b7a259182df7c2244531abd4bf233f60b Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 22 Dec 2019 23:43:40 +0000 -Subject: [PATCH] arm64: dts: rockchip: add vpll clock to hdmi node on rk3328 - -Add the hdmiphy clock as the vpll in hdmi node. - -Signed-off-by: Jonas Karlman ---- - arch/arm64/boot/dts/rockchip/rk3328.dtsi | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi -index d4cfb1066c5a..991d2a830887 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi -@@ -750,9 +750,11 @@ - ; - clocks = <&cru PCLK_HDMI>, - <&cru SCLK_HDMI_SFC>, -+ <&hdmiphy>, - <&cru SCLK_RTC32K>; - clock-names = "iahb", - "isfr", -+ "vpll", - "cec"; - phys = <&hdmiphy>; - phy-names = "hdmi"; --- -2.17.1 - - -From a972a8f4fbc0db4c71fcf2d7eb1c1dcc31a8d089 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 22 Dec 2019 23:43:58 +0000 -Subject: [PATCH] ARM: dts: rockchip: add vpll clock to hdmi node on rk3228 - -Add the hdmiphy clock as the vpll in hdmi node. - -Signed-off-by: Jonas Karlman ---- - arch/arm/boot/dts/rk322x.dtsi | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi -index 4e90efdc9630..1e31f6898797 100644 ---- a/arch/arm/boot/dts/rk322x.dtsi -+++ b/arch/arm/boot/dts/rk322x.dtsi -@@ -639,8 +639,8 @@ - interrupts = ; - assigned-clocks = <&cru SCLK_HDMI_PHY>; - assigned-clock-parents = <&hdmi_phy>; -- clocks = <&cru SCLK_HDMI_HDCP>, <&cru PCLK_HDMI_CTRL>, <&cru SCLK_HDMI_CEC>; -- clock-names = "isfr", "iahb", "cec"; -+ clocks = <&cru SCLK_HDMI_HDCP>, <&cru PCLK_HDMI_CTRL>, <&hdmi_phy>, <&cru SCLK_HDMI_CEC>; -+ clock-names = "isfr", "iahb", "vpll", "cec"; - pinctrl-names = "default"; - pinctrl-0 = <&hdmii2c_xfer &hdmi_hpd &hdmi_cec>; - resets = <&cru SRST_HDMI_P>; --- -2.17.1 - - -From ad13781b15e2a4657e52147461565b99e16dca65 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 22 Dec 2019 10:42:02 +0000 -Subject: [PATCH] drm/rockchip: dw-hdmi: limit tmds to 340mhz on rk3228/rk3328 - -RK3228/RK3328 does not provide a stable hdmi signal at TMDS rates -above 371.25MHz (340MHz pixel clock). - -Limit the pixel clock rate to 340MHz to provide a stable signal. -Also limit the pixel clock to the display reported max tmds clock. - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 22 +++++++++++++++++++-- - 1 file changed, 20 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index 45fcdce3f27f..66c14df4a680 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -237,6 +237,24 @@ dw_hdmi_rockchip_mode_valid(struct drm_connector *connector, - return (valid) ? MODE_OK : MODE_BAD; - } - -+static enum drm_mode_status -+dw_hdmi_rk3228_mode_valid(struct drm_connector *connector, -+ const struct drm_display_mode *mode) -+{ -+ struct drm_display_info *info = &connector->display_info; -+ int max_tmds_clock = max(info->max_tmds_clock, 165000); -+ int clock = mode->clock; -+ -+ if (connector->ycbcr_420_allowed && drm_mode_is_420(info, mode) && -+ (info->color_formats & DRM_COLOR_FORMAT_YCRCB420)) -+ clock /= 2; -+ -+ if (clock > max_tmds_clock || clock > 340000) -+ return MODE_CLOCK_HIGH; -+ -+ return MODE_OK; -+} -+ - static const struct drm_encoder_funcs dw_hdmi_rockchip_encoder_funcs = { - .destroy = drm_encoder_cleanup, - }; -@@ -424,7 +442,7 @@ static struct rockchip_hdmi_chip_data rk3228_chip_data = { - }; - - static const struct dw_hdmi_plat_data rk3228_hdmi_drv_data = { -- .mode_valid = dw_hdmi_rockchip_mode_valid, -+ .mode_valid = dw_hdmi_rk3228_mode_valid, - .mpll_cfg = rockchip_mpll_cfg, - .cur_ctr = rockchip_cur_ctr, - .phy_config = rockchip_phy_config, -@@ -461,7 +479,7 @@ static struct rockchip_hdmi_chip_data rk3328_chip_data = { - }; - - static const struct dw_hdmi_plat_data rk3328_hdmi_drv_data = { -- .mode_valid = dw_hdmi_rockchip_mode_valid, -+ .mode_valid = dw_hdmi_rk3228_mode_valid, - .mpll_cfg = rockchip_mpll_cfg, - .cur_ctr = rockchip_cur_ctr, - .phy_config = rockchip_phy_config, --- -2.17.1 - - -From 8e950f0d07a1cea3ad58bd654c91a747d2902c6c Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 22 Dec 2019 10:42:27 +0000 -Subject: [PATCH] drm/rockchip: dw-hdmi: remove unused plat_data on - rk3228/rk3328 - -mpll_cfg/cur_ctr/phy_config is not used when phy_force_vendor is true, -lets remove them. - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 6 ------ - 1 file changed, 6 deletions(-) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index 66c14df4a680..a813299e97a2 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -443,9 +443,6 @@ static struct rockchip_hdmi_chip_data rk3228_chip_data = { - - static const struct dw_hdmi_plat_data rk3228_hdmi_drv_data = { - .mode_valid = dw_hdmi_rk3228_mode_valid, -- .mpll_cfg = rockchip_mpll_cfg, -- .cur_ctr = rockchip_cur_ctr, -- .phy_config = rockchip_phy_config, - .phy_data = &rk3228_chip_data, - .phy_ops = &rk3228_hdmi_phy_ops, - .phy_name = "inno_dw_hdmi_phy2", -@@ -480,9 +477,6 @@ static struct rockchip_hdmi_chip_data rk3328_chip_data = { - - static const struct dw_hdmi_plat_data rk3328_hdmi_drv_data = { - .mode_valid = dw_hdmi_rk3228_mode_valid, -- .mpll_cfg = rockchip_mpll_cfg, -- .cur_ctr = rockchip_cur_ctr, -- .phy_config = rockchip_phy_config, - .phy_data = &rk3328_chip_data, - .phy_ops = &rk3328_hdmi_phy_ops, - .phy_name = "inno_dw_hdmi_phy2", --- -2.17.1 - - -From 34326d29065869cc262b2f1644310ec9417dac29 Mon Sep 17 00:00:00 2001 -From: Algea Cao -Date: Fri, 18 May 2018 14:32:08 +0800 -Subject: [PATCH] phy/rockchip: inno-hdmi: Support more pre-pll configuration - -Adding the following freq cfg in 8-bit and 10-bit color depth: - -{ - 40000000, 65000000, 71000000, 83500000, 85750000, - 88750000, 108000000, 119000000, 162000000 -} - -New freq has been validated by quantumdata 980. - -For some freq which can't be got by only using integer freq div, -frac freq div is needed, Such as 88.75Mhz 10-bit. But The actual -freq is different from the target freq, We must try to narrow -the gap between them. RK322X only support integer freq div. - -The VCO of pre-PLL must be more than 2Ghz, otherwise PLL may be -unlocked. - -Signed-off-by: Algea Cao -Signed-off-by: Jonas Karlman ---- - drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 74 ++++++++++++------- - 1 file changed, 49 insertions(+), 25 deletions(-) - -diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c -index 3719309ad0d0..bb8bdf5e3301 100644 ---- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c -+++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c -@@ -291,32 +291,56 @@ struct inno_hdmi_phy_drv_data { - const struct phy_config *phy_cfg_table; - }; - -+/* -+ * If only using integer freq div can't get frequency we want, frac -+ * freq div is needed. For example, pclk 88.75 Mhz and tmdsclk -+ * 110.9375 Mhz must use frac div 0xF00000. The actual frequency is different -+ * from the target frequency. Such as the tmds clock 110.9375 Mhz, -+ * the actual tmds clock we get is 110.93719 Mhz. It is important -+ * to note that RK322X platforms do not support frac div. -+ */ - static const struct pre_pll_config pre_pll_cfg_table[] = { -- { 27000000, 27000000, 1, 90, 3, 2, 2, 10, 3, 3, 4, 0, 0}, -- { 27000000, 33750000, 1, 90, 1, 3, 3, 10, 3, 3, 4, 0, 0}, -- { 40000000, 40000000, 1, 80, 2, 2, 2, 12, 2, 2, 2, 0, 0}, -- { 59341000, 59341000, 1, 98, 3, 1, 2, 1, 3, 3, 4, 0, 0xE6AE6B}, -- { 59400000, 59400000, 1, 99, 3, 1, 1, 1, 3, 3, 4, 0, 0}, -- { 59341000, 74176250, 1, 98, 0, 3, 3, 1, 3, 3, 4, 0, 0xE6AE6B}, -- { 59400000, 74250000, 1, 99, 1, 2, 2, 1, 3, 3, 4, 0, 0}, -- { 74176000, 74176000, 1, 98, 1, 2, 2, 1, 2, 3, 4, 0, 0xE6AE6B}, -- { 74250000, 74250000, 1, 99, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -- { 74176000, 92720000, 4, 494, 1, 2, 2, 1, 3, 3, 4, 0, 0x816817}, -- { 74250000, 92812500, 4, 495, 1, 2, 2, 1, 3, 3, 4, 0, 0}, -- {148352000, 148352000, 1, 98, 1, 1, 1, 1, 2, 2, 2, 0, 0xE6AE6B}, -- {148500000, 148500000, 1, 99, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -- {148352000, 185440000, 4, 494, 0, 2, 2, 1, 3, 2, 2, 0, 0x816817}, -- {148500000, 185625000, 4, 495, 0, 2, 2, 1, 3, 2, 2, 0, 0}, -- {296703000, 296703000, 1, 98, 0, 1, 1, 1, 0, 2, 2, 0, 0xE6AE6B}, -- {297000000, 297000000, 1, 99, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -- {296703000, 370878750, 4, 494, 1, 2, 0, 1, 3, 1, 1, 0, 0x816817}, -- {297000000, 371250000, 4, 495, 1, 2, 0, 1, 3, 1, 1, 0, 0}, -- {593407000, 296703500, 1, 98, 0, 1, 1, 1, 0, 2, 1, 0, 0xE6AE6B}, -- {594000000, 297000000, 1, 99, 0, 1, 1, 1, 0, 2, 1, 0, 0}, -- {593407000, 370879375, 4, 494, 1, 2, 0, 1, 3, 1, 1, 1, 0x816817}, -- {594000000, 371250000, 4, 495, 1, 2, 0, 1, 3, 1, 1, 1, 0}, -- {593407000, 593407000, 1, 98, 0, 2, 0, 1, 0, 1, 1, 0, 0xE6AE6B}, -- {594000000, 594000000, 1, 99, 0, 2, 0, 1, 0, 1, 1, 0, 0}, -+ { 27000000, 27000000, 1, 90, 3, 2, 2, 10, 3, 3, 4, 0, 0}, -+ { 27000000, 33750000, 1, 90, 1, 3, 3, 10, 3, 3, 4, 0, 0}, -+ { 40000000, 40000000, 1, 80, 2, 2, 2, 12, 2, 2, 2, 0, 0}, -+ { 40000000, 50000000, 1, 100, 2, 2, 2, 1, 0, 0, 15, 0, 0}, -+ { 59341000, 59341000, 1, 98, 3, 1, 2, 1, 3, 3, 4, 0, 0xE6AE6B}, -+ { 59400000, 59400000, 1, 99, 3, 1, 1, 1, 3, 3, 4, 0, 0}, -+ { 59341000, 74176250, 1, 98, 0, 3, 3, 1, 3, 3, 4, 0, 0xE6AE6B}, -+ { 59400000, 74250000, 1, 99, 1, 2, 2, 1, 3, 3, 4, 0, 0}, -+ { 65000000, 65000000, 1, 130, 2, 2, 2, 1, 0, 0, 12, 0, 0}, -+ { 65000000, 81250000, 3, 325, 0, 3, 3, 1, 0, 0, 10, 0, 0}, -+ { 71000000, 71000000, 3, 284, 0, 3, 3, 1, 0, 0, 8, 0, 0}, -+ { 71000000, 88750000, 3, 355, 0, 3, 3, 1, 0, 0, 10, 0, 0}, -+ { 74176000, 74176000, 1, 98, 1, 2, 2, 1, 2, 3, 4, 0, 0xE6AE6B}, -+ { 74250000, 74250000, 1, 99, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ { 74176000, 92720000, 4, 494, 1, 2, 2, 1, 3, 3, 4, 0, 0x816817}, -+ { 74250000, 92812500, 4, 495, 1, 2, 2, 1, 3, 3, 4, 0, 0}, -+ { 83500000, 83500000, 2, 167, 2, 1, 1, 1, 0, 0, 6, 0, 0}, -+ { 83500000, 104375000, 1, 104, 2, 1, 1, 1, 1, 0, 5, 0, 0x600000}, -+ { 85750000, 85750000, 3, 343, 0, 3, 3, 1, 0, 0, 8, 0, 0}, -+ { 88750000, 88750000, 3, 355, 0, 3, 3, 1, 0, 0, 8, 0, 0}, -+ { 88750000, 110937500, 1, 110, 2, 1, 1, 1, 1, 0, 5, 0, 0xF00000}, -+ {108000000, 108000000, 1, 90, 3, 0, 0, 1, 0, 0, 5, 0, 0}, -+ {108000000, 135000000, 1, 90, 0, 2, 2, 1, 0, 0, 5, 0, 0}, -+ {119000000, 119000000, 1, 119, 2, 1, 1, 1, 0, 0, 6, 0, 0}, -+ {119000000, 148750000, 1, 99, 0, 2, 2, 1, 0, 0, 5, 0, 0x2AAAAA}, -+ {148352000, 148352000, 1, 98, 1, 1, 1, 1, 2, 2, 2, 0, 0xE6AE6B}, -+ {148500000, 148500000, 1, 99, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {148352000, 185440000, 4, 494, 0, 2, 2, 1, 3, 2, 2, 0, 0x816817}, -+ {148500000, 185625000, 4, 495, 0, 2, 2, 1, 3, 2, 2, 0, 0}, -+ {162000000, 162000000, 1, 108, 0, 2, 2, 1, 0, 0, 4, 0, 0}, -+ {162000000, 202500000, 1, 135, 0, 2, 2, 1, 0, 0, 5, 0, 0}, -+ {296703000, 296703000, 1, 98, 0, 1, 1, 1, 0, 2, 2, 0, 0xE6AE6B}, -+ {297000000, 297000000, 1, 99, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {296703000, 370878750, 4, 494, 1, 2, 0, 1, 3, 1, 1, 0, 0x816817}, -+ {297000000, 371250000, 4, 495, 1, 2, 0, 1, 3, 1, 1, 0, 0}, -+ {593407000, 296703500, 1, 98, 0, 1, 1, 1, 0, 2, 1, 0, 0xE6AE6B}, -+ {594000000, 297000000, 1, 99, 0, 1, 1, 1, 0, 2, 1, 0, 0}, -+ {593407000, 370879375, 4, 494, 1, 2, 0, 1, 3, 1, 1, 1, 0x816817}, -+ {594000000, 371250000, 4, 495, 1, 2, 0, 1, 3, 1, 1, 1, 0}, -+ {593407000, 593407000, 1, 98, 0, 2, 0, 1, 0, 1, 1, 0, 0xE6AE6B}, -+ {594000000, 594000000, 1, 99, 0, 2, 0, 1, 0, 1, 1, 0, 0}, - { /* sentinel */ } - }; - --- -2.17.1 - - -From e63e0475c82b77a9e255b1dd354df20e02a73390 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Fri, 20 Dec 2019 08:12:43 +0000 -Subject: [PATCH] WIP: drm/bridge: dw-hdmi: limit mode and bus format to - max_tmds_clock - ---- - drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 121 ++++++++++++++-------- - 1 file changed, 78 insertions(+), 43 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -index cc39b544ae6e..66e3fed23f4b 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -@@ -1854,6 +1854,21 @@ static void hdmi_config_drm_infoframe(struct dw_hdmi *hdmi) - HDMI_FC_PACKET_TX_EN_DRM_MASK, HDMI_FC_PACKET_TX_EN); - } - -+static unsigned int -+hdmi_get_tmdsclock(unsigned int bus_format, unsigned int pixelclock) -+{ -+ int color_depth = hdmi_bus_fmt_color_depth(bus_format); -+ unsigned int tmdsclock = pixelclock; -+ -+ if (!hdmi_bus_fmt_is_yuv422(bus_format) && color_depth > 8) -+ tmdsclock = (u64)pixelclock * color_depth / 8; -+ -+ if (hdmi_bus_fmt_is_yuv420(bus_format)) -+ tmdsclock /= 2; -+ -+ return tmdsclock; -+} -+ - static void hdmi_av_composer(struct dw_hdmi *hdmi, - const struct drm_display_mode *mode) - { -@@ -1863,28 +1878,12 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi, - int hblank, vblank, h_de_hs, v_de_vs, hsync_len, vsync_len; - unsigned int vdisplay, hdisplay; - -- vmode->mtmdsclock = vmode->mpixelclock = mode->clock * 1000; -+ vmode->mpixelclock = mode->clock * 1000; -+ vmode->mtmdsclock = -+ hdmi_get_tmdsclock(hdmi->hdmi_data.enc_out_bus_format, -+ vmode->mpixelclock); - - dev_dbg(hdmi->dev, "final pixclk = %d\n", vmode->mpixelclock); -- -- if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format)) { -- switch (hdmi_bus_fmt_color_depth( -- hdmi->hdmi_data.enc_out_bus_format)) { -- case 16: -- vmode->mtmdsclock = (u64)vmode->mpixelclock * 2; -- break; -- case 12: -- vmode->mtmdsclock = (u64)vmode->mpixelclock * 3 / 2; -- break; -- case 10: -- vmode->mtmdsclock = (u64)vmode->mpixelclock * 5 / 4; -- break; -- } -- } -- -- if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format)) -- vmode->mtmdsclock /= 2; -- - dev_dbg(hdmi->dev, "final tmdsclk = %d\n", vmode->mtmdsclock); - - /* Set up HDMI_FC_INVIDCONF */ -@@ -2511,8 +2510,21 @@ static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = - * - MEDIA_BUS_FMT_RGB888_1X24, - */ - --/* Can return a maximum of 12 possible output formats for a mode/connector */ --#define MAX_OUTPUT_SEL_FORMATS 12 -+static bool is_tmds_allowed(struct drm_display_info *info, -+ struct drm_display_mode *mode, -+ u32 bus_format) -+{ -+ unsigned long tmdsclock = hdmi_get_tmdsclock(bus_format, mode->clock); -+ int max_tmds_clock = max(info->max_tmds_clock, 165000); -+ -+ if (max_tmds_clock >= tmdsclock) -+ return true; -+ -+ return false; -+} -+ -+/* Can return a maximum of 16 possible output formats for a mode/connector */ -+#define MAX_OUTPUT_SEL_FORMATS 16 - - static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, - struct drm_bridge_state *bridge_state, -@@ -2524,8 +2536,6 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, - struct drm_display_info *info = &conn->display_info; - struct drm_display_mode *mode = &crtc_state->mode; - u8 max_bpc = conn_state->max_requested_bpc; -- bool is_hdmi2_sink = info->hdmi.scdc.supported || -- (info->color_formats & DRM_COLOR_FORMAT_YCRCB420); - u32 *output_fmts; - int i = 0; - -@@ -2540,29 +2550,33 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, - * If the current mode enforces 4:2:0, force the output but format - * to 4:2:0 and do not add the YUV422/444/RGB formats - */ -- if (conn->ycbcr_420_allowed && -- (drm_mode_is_420_only(info, mode) || -- (is_hdmi2_sink && drm_mode_is_420_also(info, mode)))) { -+ if (conn->ycbcr_420_allowed && drm_mode_is_420(info, mode) && -+ (info->color_formats & DRM_COLOR_FORMAT_YCRCB420)) { - - /* Order bus formats from 16bit to 8bit if supported */ - if (max_bpc >= 16 && info->bpc == 16 && -- (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_48)) -+ (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_48) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYYVYY16_0_5X48)) - output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY16_0_5X48; - - if (max_bpc >= 12 && info->bpc >= 12 && -- (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_36)) -+ (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_36) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYYVYY12_0_5X36)) - output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY12_0_5X36; - - if (max_bpc >= 10 && info->bpc >= 10 && -- (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30)) -+ (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYYVYY10_0_5X30)) - output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY10_0_5X30; - - /* Default 8bit fallback */ -- output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY8_0_5X24; -+ if (is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYYVYY8_0_5X24)) -+ output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY8_0_5X24; - - *num_output_fmts = i; - -- return output_fmts; -+ if (drm_mode_is_420_only(info, mode)) -+ return output_fmts; - } - - /* -@@ -2571,40 +2585,51 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, - */ - - if (max_bpc >= 16 && info->bpc == 16) { -- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444) -+ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB444) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_YUV16_1X48)) - output_fmts[i++] = MEDIA_BUS_FMT_YUV16_1X48; - -- output_fmts[i++] = MEDIA_BUS_FMT_RGB161616_1X48; -+ if (is_tmds_allowed(info, mode, MEDIA_BUS_FMT_RGB161616_1X48)) -+ output_fmts[i++] = MEDIA_BUS_FMT_RGB161616_1X48; - } - - if (max_bpc >= 12 && info->bpc >= 12) { -- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422) -+ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB422) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYVY12_1X24)) - output_fmts[i++] = MEDIA_BUS_FMT_UYVY12_1X24; - -- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444) -+ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB444) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_YUV12_1X36)) - output_fmts[i++] = MEDIA_BUS_FMT_YUV12_1X36; - -- output_fmts[i++] = MEDIA_BUS_FMT_RGB121212_1X36; -+ if (is_tmds_allowed(info, mode, MEDIA_BUS_FMT_RGB121212_1X36)) -+ output_fmts[i++] = MEDIA_BUS_FMT_RGB121212_1X36; - } - - if (max_bpc >= 10 && info->bpc >= 10) { -- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422) -+ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB422) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYVY10_1X20)) - output_fmts[i++] = MEDIA_BUS_FMT_UYVY10_1X20; - -- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444) -+ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB444) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_YUV10_1X30)) - output_fmts[i++] = MEDIA_BUS_FMT_YUV10_1X30; - -- output_fmts[i++] = MEDIA_BUS_FMT_RGB101010_1X30; -+ if (is_tmds_allowed(info, mode, MEDIA_BUS_FMT_RGB101010_1X30)) -+ output_fmts[i++] = MEDIA_BUS_FMT_RGB101010_1X30; - } - -- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422) -+ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB422) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYVY8_1X16)) - output_fmts[i++] = MEDIA_BUS_FMT_UYVY8_1X16; - -- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444) -+ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB444) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_YUV8_1X24)) - output_fmts[i++] = MEDIA_BUS_FMT_YUV8_1X24; - - /* Default 8bit RGB fallback */ -- output_fmts[i++] = MEDIA_BUS_FMT_RGB888_1X24; -+ if (is_tmds_allowed(info, mode, MEDIA_BUS_FMT_RGB888_1X24)) -+ output_fmts[i++] = MEDIA_BUS_FMT_RGB888_1X24; - - *num_output_fmts = i; - -@@ -2811,12 +2836,22 @@ dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge, - { - struct dw_hdmi *hdmi = bridge->driver_private; - struct drm_connector *connector = &hdmi->connector; -+ struct drm_display_info *info = &connector->display_info; - enum drm_mode_status mode_status = MODE_OK; -+ int max_tmds_clock = max(info->max_tmds_clock, 165000); -+ int clock = mode->clock; - - /* We don't support double-clocked modes */ - if (mode->flags & DRM_MODE_FLAG_DBLCLK) - return MODE_BAD; - -+ if (connector->ycbcr_420_allowed && drm_mode_is_420(info, mode) && -+ (info->color_formats & DRM_COLOR_FORMAT_YCRCB420)) -+ clock /= 2; -+ -+ if (clock > max_tmds_clock) -+ return MODE_CLOCK_HIGH; -+ - if (hdmi->plat_data->mode_valid) - mode_status = hdmi->plat_data->mode_valid(connector, mode); - --- -2.17.1 - - -From 5c3bbae0afe43b4856b9c9e344bb7eea3702e4f0 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sat, 21 Dec 2019 06:23:52 +0000 -Subject: [PATCH] WIP: drm/bridge: dw-hdmi: do not enable csc for yuv2yuv - ---- - drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 12 +++++++++++- - 1 file changed, 11 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -index 66e3fed23f4b..df1789cd8712 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -@@ -966,6 +966,14 @@ static void hdmi_video_sample(struct dw_hdmi *hdmi) - - static int is_color_space_conversion(struct dw_hdmi *hdmi) - { -+ if (hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_in_bus_format) && -+ hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format)) -+ return 0; -+ -+ if (hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_in_bus_format) && -+ hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format)) -+ return 0; -+ - return hdmi->hdmi_data.enc_in_bus_format != hdmi->hdmi_data.enc_out_bus_format; - } - -@@ -2050,7 +2058,9 @@ static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi) - hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS); - - /* Enable csc path */ -- if (is_color_space_conversion(hdmi)) { -+ if (is_color_space_conversion(hdmi) || -+ is_color_space_decimation(hdmi) || -+ is_color_space_interpolation(hdmi)) { - hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE; - hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS); - } --- -2.17.1 - - -From fd86f78d28a4b6c5fc7440e42916f3f86a7797a4 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Fri, 20 Dec 2019 08:12:42 +0000 -Subject: [PATCH] drm/rockchip: dw-hdmi: add bridge and switch to - drm_bridge_funcs - -Switch the dw-hdmi driver to drm_bridge_funcs by implementing -a new local bridge, connecting it to the dw-hdmi bridge. - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 65 ++++++++++----------- - 1 file changed, 31 insertions(+), 34 deletions(-) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index a813299e97a2..8bc42090d0a3 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -67,6 +67,7 @@ struct rockchip_hdmi { - struct device *dev; - struct regmap *regmap; - struct drm_encoder encoder; -+ struct drm_bridge bridge; - const struct rockchip_hdmi_chip_data *chip_data; - struct clk *vpll_clk; - struct clk *grf_clk; -@@ -259,15 +260,11 @@ static const struct drm_encoder_funcs dw_hdmi_rockchip_encoder_funcs = { - .destroy = drm_encoder_cleanup, - }; - --static void dw_hdmi_rockchip_encoder_disable(struct drm_encoder *encoder) --{ --} -- - static enum drm_mode_status --dw_hdmi_rockchip_encoder_mode_valid(struct drm_encoder *encoder, -- const struct drm_display_mode *mode) -+dw_hdmi_rockchip_bridge_mode_valid(struct drm_bridge *bridge, -+ const struct drm_display_mode *mode) - { -- struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); -+ struct rockchip_hdmi *hdmi = to_rockchip_hdmi(bridge); - long rate; - - if (hdmi->vpll_clk) { -@@ -279,26 +276,20 @@ dw_hdmi_rockchip_encoder_mode_valid(struct drm_encoder *encoder, - return MODE_OK; - } - --static bool --dw_hdmi_rockchip_encoder_mode_fixup(struct drm_encoder *encoder, -- const struct drm_display_mode *mode, -- struct drm_display_mode *adj_mode) --{ -- return true; --} -- --static void dw_hdmi_rockchip_encoder_mode_set(struct drm_encoder *encoder, -- struct drm_display_mode *mode, -- struct drm_display_mode *adj_mode) -+static void -+dw_hdmi_rockchip_bridge_mode_set(struct drm_bridge *bridge, -+ const struct drm_display_mode *mode, -+ const struct drm_display_mode *adjusted_mode) - { -- struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); -+ struct rockchip_hdmi *hdmi = to_rockchip_hdmi(bridge); - -- clk_set_rate(hdmi->vpll_clk, adj_mode->clock * 1000); -+ clk_set_rate(hdmi->vpll_clk, adjusted_mode->clock * 1000); - } - --static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder) -+static void dw_hdmi_rockchip_bridge_enable(struct drm_bridge *bridge) - { -- struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); -+ struct rockchip_hdmi *hdmi = to_rockchip_hdmi(bridge); -+ struct drm_encoder *encoder = bridge->encoder; - u32 val; - int ret; - -@@ -327,9 +318,10 @@ static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder) - } - - static int --dw_hdmi_rockchip_encoder_atomic_check(struct drm_encoder *encoder, -- struct drm_crtc_state *crtc_state, -- struct drm_connector_state *conn_state) -+dw_hdmi_rockchip_bridge_atomic_check(struct drm_bridge *bridge, -+ struct drm_bridge_state *bridge_state, -+ struct drm_crtc_state *crtc_state, -+ struct drm_connector_state *conn_state) - { - struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); - -@@ -339,13 +331,11 @@ dw_hdmi_rockchip_encoder_atomic_check(struct drm_encoder *encoder, - return 0; - } - --static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_funcs = { -- .mode_valid = dw_hdmi_rockchip_encoder_mode_valid, -- .mode_fixup = dw_hdmi_rockchip_encoder_mode_fixup, -- .mode_set = dw_hdmi_rockchip_encoder_mode_set, -- .enable = dw_hdmi_rockchip_encoder_enable, -- .disable = dw_hdmi_rockchip_encoder_disable, -- .atomic_check = dw_hdmi_rockchip_encoder_atomic_check, -+static const struct drm_bridge_funcs dw_hdmi_rockchip_bridge_funcs = { -+ .mode_valid = dw_hdmi_rockchip_bridge_mode_valid, -+ .mode_set = dw_hdmi_rockchip_bridge_mode_set, -+ .enable = dw_hdmi_rockchip_bridge_enable, -+ .atomic_check = dw_hdmi_rockchip_bridge_atomic_check, - }; - - static int dw_hdmi_rockchip_genphy_init(struct dw_hdmi *dw_hdmi, void *data, -@@ -523,6 +513,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, - struct dw_hdmi_plat_data *plat_data; - const struct of_device_id *match; - struct drm_device *drm = data; -+ struct drm_bridge *next_bridge; - struct drm_encoder *encoder; - struct rockchip_hdmi *hdmi; - int ret; -@@ -576,13 +567,15 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, - return ret; - } - -- drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs); - drm_encoder_init(drm, encoder, &dw_hdmi_rockchip_encoder_funcs, - DRM_MODE_ENCODER_TMDS, NULL); - -+ hdmi->bridge.funcs = &dw_hdmi_rockchip_bridge_funcs; -+ drm_bridge_attach(encoder, &hdmi->bridge, NULL); -+ - platform_set_drvdata(pdev, hdmi); - -- hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data); -+ hdmi->hdmi = dw_hdmi_probe(pdev, plat_data); - - /* - * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(), -@@ -594,6 +587,10 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, - clk_disable_unprepare(hdmi->vpll_clk); - } - -+ next_bridge = of_drm_find_bridge(pdev->dev.of_node); -+ if (next_bridge) -+ drm_bridge_attach(encoder, next_bridge, &hdmi->bridge); -+ - return ret; - } - --- -2.17.1 - - -From 1e915225fe362b6ab98bec9bc71c62315347eccb Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Fri, 20 Dec 2019 08:12:42 +0000 -Subject: [PATCH] drm/rockchip: dw-hdmi: enable bridge bus format negotiation - -Enable bridge format negotiation by implementing -atomic_get_input_bus_fmts and support for 8-bit RGB 4:4:4. - -Signed-off-by: Jonas Karlman ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 35 +++++++++++++++++++++ - 1 file changed, 35 insertions(+) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index 8bc42090d0a3..83a22a061e52 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -317,6 +317,16 @@ static void dw_hdmi_rockchip_bridge_enable(struct drm_bridge *bridge) - ret ? "LIT" : "BIG"); - } - -+static bool is_rgb(u32 format) -+{ -+ switch (format) { -+ case MEDIA_BUS_FMT_RGB888_1X24: -+ return true; -+ default: -+ return false; -+ } -+} -+ - static int - dw_hdmi_rockchip_bridge_atomic_check(struct drm_bridge *bridge, - struct drm_bridge_state *bridge_state, -@@ -331,11 +341,36 @@ dw_hdmi_rockchip_bridge_atomic_check(struct drm_bridge *bridge, - return 0; - } - -+static u32 *dw_hdmi_rockchip_get_input_bus_fmts(struct drm_bridge *bridge, -+ struct drm_bridge_state *bridge_state, -+ struct drm_crtc_state *crtc_state, -+ struct drm_connector_state *conn_state, -+ u32 output_fmt, -+ unsigned int *num_input_fmts) -+{ -+ u32 *input_fmt; -+ -+ *num_input_fmts = 0; -+ -+ if (!is_rgb(output_fmt)) -+ return NULL; -+ -+ input_fmt = kzalloc(sizeof(*input_fmt), GFP_KERNEL); -+ if (!input_fmt) -+ return NULL; -+ -+ *num_input_fmts = 1; -+ *input_fmt = output_fmt; -+ -+ return input_fmt; -+} -+ - static const struct drm_bridge_funcs dw_hdmi_rockchip_bridge_funcs = { - .mode_valid = dw_hdmi_rockchip_bridge_mode_valid, - .mode_set = dw_hdmi_rockchip_bridge_mode_set, - .enable = dw_hdmi_rockchip_bridge_enable, - .atomic_check = dw_hdmi_rockchip_bridge_atomic_check, -+ .atomic_get_input_bus_fmts = dw_hdmi_rockchip_get_input_bus_fmts, - }; - - static int dw_hdmi_rockchip_genphy_init(struct dw_hdmi *dw_hdmi, void *data, --- -2.17.1 - - -From b4cbb8eae8f3a5dbdbb844d59dfd7c979a88f66a Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Fri, 20 Dec 2019 08:12:42 +0000 -Subject: [PATCH] WIP: drm/rockchip: dw_hdmi: add 10-bit rgb bus format - ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 41 +++++++++++++++++++++ - drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 2 + - drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 10 ++++- - 3 files changed, 52 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index 83a22a061e52..3c8a95cd38dc 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -76,6 +76,7 @@ struct rockchip_hdmi { - }; - - #define to_rockchip_hdmi(x) container_of(x, struct rockchip_hdmi, x) -+#define to_crtc_state(x) container_of(x, struct drm_crtc_state, x) - - static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = { - { -@@ -282,6 +283,11 @@ dw_hdmi_rockchip_bridge_mode_set(struct drm_bridge *bridge, - const struct drm_display_mode *adjusted_mode) - { - struct rockchip_hdmi *hdmi = to_rockchip_hdmi(bridge); -+ struct drm_crtc_state *crtc_state = to_crtc_state(adjusted_mode); -+ struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); -+ -+ if (hdmi->phy) -+ phy_set_bus_width(hdmi->phy, s->bus_width); - - clk_set_rate(hdmi->vpll_clk, adjusted_mode->clock * 1000); - } -@@ -320,6 +326,7 @@ static void dw_hdmi_rockchip_bridge_enable(struct drm_bridge *bridge) - static bool is_rgb(u32 format) - { - switch (format) { -+ case MEDIA_BUS_FMT_RGB101010_1X30: - case MEDIA_BUS_FMT_RGB888_1X24: - return true; - default: -@@ -327,6 +334,16 @@ static bool is_rgb(u32 format) - } - } - -+static bool is_10bit(u32 format) -+{ -+ switch (format) { -+ case MEDIA_BUS_FMT_RGB101010_1X30: -+ return true; -+ default: -+ return false; -+ } -+} -+ - static int - dw_hdmi_rockchip_bridge_atomic_check(struct drm_bridge *bridge, - struct drm_bridge_state *bridge_state, -@@ -334,9 +351,24 @@ dw_hdmi_rockchip_bridge_atomic_check(struct drm_bridge *bridge, - struct drm_connector_state *conn_state) - { - struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); -+ struct drm_atomic_state *state = bridge_state->base.state; -+ struct drm_crtc_state *old_crtc_state; -+ struct rockchip_crtc_state *old_state; -+ u32 format = bridge_state->output_bus_cfg.format; - - s->output_mode = ROCKCHIP_OUT_MODE_AAAA; - s->output_type = DRM_MODE_CONNECTOR_HDMIA; -+ s->output_bpc = 10; -+ s->bus_format = format; -+ s->bus_width = is_10bit(format) ? 10 : 8; -+ -+ old_crtc_state = drm_atomic_get_old_crtc_state(state, conn_state->crtc); -+ if (old_crtc_state && !crtc_state->mode_changed) { -+ old_state = to_rockchip_crtc_state(old_crtc_state); -+ if (s->bus_format != old_state->bus_format || -+ s->bus_width != old_state->bus_width) -+ crtc_state->mode_changed = true; -+ } - - return 0; - } -@@ -348,10 +380,19 @@ static u32 *dw_hdmi_rockchip_get_input_bus_fmts(struct drm_bridge *bridge, - u32 output_fmt, - unsigned int *num_input_fmts) - { -+ struct rockchip_hdmi *hdmi = to_rockchip_hdmi(bridge); -+ struct drm_encoder *encoder = bridge->encoder; - u32 *input_fmt; -+ bool has_10bit = true; - - *num_input_fmts = 0; - -+ if (drm_of_encoder_active_endpoint_id(hdmi->dev->of_node, encoder)) -+ has_10bit = false; -+ -+ if (!has_10bit && is_10bit(output_fmt)) -+ return NULL; -+ - if (!is_rgb(output_fmt)) - return NULL; - -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h -index c5b06048124e..af1b85d8f7ee 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h -@@ -30,6 +30,8 @@ struct rockchip_crtc_state { - int output_mode; - int output_bpc; - int output_flags; -+ u32 bus_format; -+ int bus_width; - }; - #define to_rockchip_crtc_state(s) \ - container_of(s, struct rockchip_crtc_state, base) -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -index f181897cbfad..e59213d3ea62 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -@@ -1402,13 +1402,21 @@ static void vop_crtc_destroy(struct drm_crtc *crtc) - - static struct drm_crtc_state *vop_crtc_duplicate_state(struct drm_crtc *crtc) - { -- struct rockchip_crtc_state *rockchip_state; -+ struct rockchip_crtc_state *rockchip_state, *s; -+ -+ if (WARN_ON(!crtc->state)) -+ return NULL; - - rockchip_state = kzalloc(sizeof(*rockchip_state), GFP_KERNEL); - if (!rockchip_state) - return NULL; - - __drm_atomic_helper_crtc_duplicate_state(crtc, &rockchip_state->base); -+ -+ s = to_rockchip_crtc_state(crtc->state); -+ rockchip_state->bus_format = s->bus_format; -+ rockchip_state->bus_width = s->bus_width; -+ - return &rockchip_state->base; - } - --- -2.17.1 - - -From 9fedc6efc787bddfad71c6145cf3cbee49ea257d Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Fri, 20 Dec 2019 08:12:43 +0000 -Subject: [PATCH] WIP: drm/rockchip: add yuv444 support - ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 29 ++++++++++++++++++++- - drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 29 +++++++++++++++++++++ - drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 5 ++++ - drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 10 +++++++ - 4 files changed, 72 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index 3c8a95cd38dc..9b3c2318ce0e 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -61,6 +61,7 @@ struct rockchip_hdmi_chip_data { - int lcdsel_grf_reg; - u32 lcdsel_big; - u32 lcdsel_lit; -+ bool ycbcr_444_allowed; - }; - - struct rockchip_hdmi { -@@ -334,10 +335,22 @@ static bool is_rgb(u32 format) - } - } - -+static bool is_yuv444(u32 format) -+{ -+ switch (format) { -+ case MEDIA_BUS_FMT_YUV10_1X30: -+ case MEDIA_BUS_FMT_YUV8_1X24: -+ return true; -+ default: -+ return false; -+ } -+} -+ - static bool is_10bit(u32 format) - { - switch (format) { - case MEDIA_BUS_FMT_RGB101010_1X30: -+ case MEDIA_BUS_FMT_YUV10_1X30: - return true; - default: - return false; -@@ -354,12 +367,22 @@ dw_hdmi_rockchip_bridge_atomic_check(struct drm_bridge *bridge, - struct drm_atomic_state *state = bridge_state->base.state; - struct drm_crtc_state *old_crtc_state; - struct rockchip_crtc_state *old_state; -+ struct drm_bridge *next_bridge; -+ struct drm_bridge_state *next_bridge_state; - u32 format = bridge_state->output_bus_cfg.format; - - s->output_mode = ROCKCHIP_OUT_MODE_AAAA; - s->output_type = DRM_MODE_CONNECTOR_HDMIA; - s->output_bpc = 10; - s->bus_format = format; -+ -+ next_bridge = drm_bridge_get_next_bridge(bridge); -+ if (next_bridge) { -+ next_bridge_state = drm_atomic_get_new_bridge_state(state, -+ next_bridge); -+ format = next_bridge_state->output_bus_cfg.format; -+ } -+ - s->bus_width = is_10bit(format) ? 10 : 8; - - old_crtc_state = drm_atomic_get_old_crtc_state(state, conn_state->crtc); -@@ -393,7 +416,10 @@ static u32 *dw_hdmi_rockchip_get_input_bus_fmts(struct drm_bridge *bridge, - if (!has_10bit && is_10bit(output_fmt)) - return NULL; - -- if (!is_rgb(output_fmt)) -+ if (is_yuv444(output_fmt)) { -+ if (!hdmi->chip_data->ycbcr_444_allowed) -+ return NULL; -+ } else if (!is_rgb(output_fmt)) - return NULL; - - input_fmt = kzalloc(sizeof(*input_fmt), GFP_KERNEL); -@@ -539,6 +565,7 @@ static const struct dw_hdmi_phy_ops rk3328_hdmi_phy_ops = { - - static struct rockchip_hdmi_chip_data rk3328_chip_data = { - .lcdsel_grf_reg = -1, -+ .ycbcr_444_allowed = true, - }; - - static const struct dw_hdmi_plat_data rk3328_hdmi_drv_data = { -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -index e59213d3ea62..5bf833ea8ce2 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -@@ -274,6 +274,17 @@ static enum vop_data_format vop_convert_format(uint32_t format) - } - } - -+static bool is_yuv_output(uint32_t bus_format) -+{ -+ switch (bus_format) { -+ case MEDIA_BUS_FMT_YUV8_1X24: -+ case MEDIA_BUS_FMT_YUV10_1X30: -+ return true; -+ default: -+ return false; -+ } -+} -+ - static uint16_t scl_vop_cal_scale(enum scale_mode mode, uint32_t src, - uint32_t dst, bool is_horizontal, - int vsu_mode, int *vskiplines) -@@ -1181,6 +1192,7 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, - u16 vact_end = vact_st + vdisplay; - uint32_t pin_pol, val; - int dither_bpc = s->output_bpc ? s->output_bpc : 10; -+ bool yuv_output = is_yuv_output(s->bus_format); - int ret; - - if (old_state && old_state->self_refresh_active) { -@@ -1254,6 +1266,8 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, - !(vop_data->feature & VOP_FEATURE_OUTPUT_RGB10)) - s->output_mode = ROCKCHIP_OUT_MODE_P888; - -+ VOP_REG_SET(vop, common, dsp_data_swap, yuv_output ? 2 : 0); -+ - if (s->output_mode == ROCKCHIP_OUT_MODE_AAAA && dither_bpc <= 8) - VOP_REG_SET(vop, common, pre_dither_down, 1); - else -@@ -1269,6 +1283,21 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, - - VOP_REG_SET(vop, common, out_mode, s->output_mode); - -+ VOP_REG_SET(vop, common, overlay_mode, yuv_output); -+ VOP_REG_SET(vop, common, dsp_out_yuv, yuv_output); -+ -+ /* -+ * Background color is 10bit depth if vop version >= 3.5 -+ */ -+ if (!yuv_output) -+ val = 0; -+ else if (VOP_MAJOR(vop_data->version) == 3 && -+ VOP_MINOR(vop_data->version) >= 5) -+ val = 0x20010200; -+ else -+ val = 0x801080; -+ VOP_REG_SET(vop, common, dsp_background, val); -+ - VOP_REG_SET(vop, modeset, htotal_pw, (htotal << 16) | hsync_len); - val = hact_st << 16; - val |= hact_end; -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h -index 0b3d18c457b2..9393cf12b1db 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h -@@ -77,6 +77,11 @@ struct vop_common { - struct vop_reg mmu_en; - struct vop_reg out_mode; - struct vop_reg standby; -+ -+ struct vop_reg overlay_mode; -+ struct vop_reg dsp_data_swap; -+ struct vop_reg dsp_out_yuv; -+ struct vop_reg dsp_background; - }; - - struct vop_misc { -diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -index 7a9d979c8d5d..b99e902d949e 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -@@ -606,6 +606,11 @@ static const struct vop_common rk3288_common = { - .dsp_blank = VOP_REG(RK3288_DSP_CTRL0, 0x3, 18), - .out_mode = VOP_REG(RK3288_DSP_CTRL0, 0xf, 0), - .cfg_done = VOP_REG_SYNC(RK3288_REG_CFG_DONE, 0x1, 0), -+ -+ .overlay_mode = VOP_REG(RK3288_SYS_CTRL, 0x1, 16), -+ .dsp_data_swap = VOP_REG(RK3288_DSP_CTRL0, 0x1f, 12), -+ .dsp_out_yuv = VOP_REG(RK3288_POST_SCL_CTRL, 0x1, 2), -+ .dsp_background = VOP_REG(RK3288_DSP_BG, 0xffffffff, 0), - }; - - /* -@@ -914,6 +919,11 @@ static const struct vop_common rk3328_common = { - .dsp_blank = VOP_REG(RK3328_DSP_CTRL0, 0x3, 18), - .out_mode = VOP_REG(RK3328_DSP_CTRL0, 0xf, 0), - .cfg_done = VOP_REG_SYNC(RK3328_REG_CFG_DONE, 0x1, 0), -+ -+ .overlay_mode = VOP_REG(RK3328_SYS_CTRL, 0x1, 16), -+ .dsp_data_swap = VOP_REG(RK3328_DSP_CTRL0, 0x1f, 12), -+ .dsp_out_yuv = VOP_REG(RK3328_POST_SCL_CTRL, 0x1, 2), -+ .dsp_background = VOP_REG(RK3328_DSP_BG, 0xffffffff, 0), - }; - - static const struct vop_intr rk3328_vop_intr = { --- -2.17.1 - - -From 111c35c19a742d7b76b6f548103f8b561c45a186 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Fri, 20 Dec 2019 08:12:43 +0000 -Subject: [PATCH] WIP: drm/rockchip: add yuv420 support - ---- - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 22 +++++++++++++++++++++ - drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 18 ++++++++++++++++- - drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 10 ++++++---- - drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 2 ++ - 4 files changed, 47 insertions(+), 5 deletions(-) - -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index 9b3c2318ce0e..eb405cb3d1f6 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -346,9 +346,21 @@ static bool is_yuv444(u32 format) - } - } - -+static bool is_yuv420(u32 format) -+{ -+ switch (format) { -+ case MEDIA_BUS_FMT_UYYVYY10_0_5X30: -+ case MEDIA_BUS_FMT_UYYVYY8_0_5X24: -+ return true; -+ default: -+ return false; -+ } -+} -+ - static bool is_10bit(u32 format) - { - switch (format) { -+ case MEDIA_BUS_FMT_UYYVYY10_0_5X30: - case MEDIA_BUS_FMT_RGB101010_1X30: - case MEDIA_BUS_FMT_YUV10_1X30: - return true; -@@ -385,6 +397,11 @@ dw_hdmi_rockchip_bridge_atomic_check(struct drm_bridge *bridge, - - s->bus_width = is_10bit(format) ? 10 : 8; - -+ if (is_yuv420(format)) { -+ s->output_mode = ROCKCHIP_OUT_MODE_YUV420; -+ s->bus_width /= 2; -+ } -+ - old_crtc_state = drm_atomic_get_old_crtc_state(state, conn_state->crtc); - if (old_crtc_state && !crtc_state->mode_changed) { - old_state = to_rockchip_crtc_state(old_crtc_state); -@@ -405,6 +422,7 @@ static u32 *dw_hdmi_rockchip_get_input_bus_fmts(struct drm_bridge *bridge, - { - struct rockchip_hdmi *hdmi = to_rockchip_hdmi(bridge); - struct drm_encoder *encoder = bridge->encoder; -+ struct drm_connector *connector = conn_state->connector; - u32 *input_fmt; - bool has_10bit = true; - -@@ -419,6 +437,9 @@ static u32 *dw_hdmi_rockchip_get_input_bus_fmts(struct drm_bridge *bridge, - if (is_yuv444(output_fmt)) { - if (!hdmi->chip_data->ycbcr_444_allowed) - return NULL; -+ } else if (is_yuv420(output_fmt)) { -+ if (!connector->ycbcr_420_allowed) -+ return NULL; - } else if (!is_rgb(output_fmt)) - return NULL; - -@@ -575,6 +596,7 @@ static const struct dw_hdmi_plat_data rk3328_hdmi_drv_data = { - .phy_name = "inno_dw_hdmi_phy2", - .phy_force_vendor = true, - .use_drm_infoframe = true, -+ .ycbcr_420_allowed = true, - }; - - static struct rockchip_hdmi_chip_data rk3399_chip_data = { -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -index 5bf833ea8ce2..b8c0d2fcc52a 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -@@ -275,6 +275,19 @@ static enum vop_data_format vop_convert_format(uint32_t format) - } - - static bool is_yuv_output(uint32_t bus_format) -+{ -+ switch (bus_format) { -+ case MEDIA_BUS_FMT_YUV8_1X24: -+ case MEDIA_BUS_FMT_YUV10_1X30: -+ case MEDIA_BUS_FMT_UYYVYY8_0_5X24: -+ case MEDIA_BUS_FMT_UYYVYY10_0_5X30: -+ return true; -+ default: -+ return false; -+ } -+} -+ -+static bool has_uv_swapped(uint32_t bus_format) - { - switch (bus_format) { - case MEDIA_BUS_FMT_YUV8_1X24: -@@ -1266,7 +1279,7 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, - !(vop_data->feature & VOP_FEATURE_OUTPUT_RGB10)) - s->output_mode = ROCKCHIP_OUT_MODE_P888; - -- VOP_REG_SET(vop, common, dsp_data_swap, yuv_output ? 2 : 0); -+ VOP_REG_SET(vop, common, dsp_data_swap, has_uv_swapped(s->bus_format) ? 2 : 0); - - if (s->output_mode == ROCKCHIP_OUT_MODE_AAAA && dither_bpc <= 8) - VOP_REG_SET(vop, common, pre_dither_down, 1); -@@ -1283,6 +1296,9 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, - - VOP_REG_SET(vop, common, out_mode, s->output_mode); - -+ VOP_REG_SET(vop, common, dclk_ddr, -+ s->output_mode == ROCKCHIP_OUT_MODE_YUV420 ? 1 : 0); -+ - VOP_REG_SET(vop, common, overlay_mode, yuv_output); - VOP_REG_SET(vop, common, dsp_out_yuv, yuv_output); - -diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h -index 9393cf12b1db..89fe8d5c7721 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h -+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h -@@ -79,6 +79,7 @@ struct vop_common { - struct vop_reg standby; - - struct vop_reg overlay_mode; -+ struct vop_reg dclk_ddr; - struct vop_reg dsp_data_swap; - struct vop_reg dsp_out_yuv; - struct vop_reg dsp_background; -@@ -230,11 +231,12 @@ struct vop_data { - /* - * display output interface supported by rockchip lcdc - */ --#define ROCKCHIP_OUT_MODE_P888 0 --#define ROCKCHIP_OUT_MODE_P666 1 --#define ROCKCHIP_OUT_MODE_P565 2 -+#define ROCKCHIP_OUT_MODE_P888 0 -+#define ROCKCHIP_OUT_MODE_P666 1 -+#define ROCKCHIP_OUT_MODE_P565 2 -+#define ROCKCHIP_OUT_MODE_YUV420 14 - /* for use special outface */ --#define ROCKCHIP_OUT_MODE_AAAA 15 -+#define ROCKCHIP_OUT_MODE_AAAA 15 - - /* output flags */ - #define ROCKCHIP_OUTPUT_DSI_DUAL BIT(0) -diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -index b99e902d949e..73d24c6bbf05 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -@@ -608,6 +608,7 @@ static const struct vop_common rk3288_common = { - .cfg_done = VOP_REG_SYNC(RK3288_REG_CFG_DONE, 0x1, 0), - - .overlay_mode = VOP_REG(RK3288_SYS_CTRL, 0x1, 16), -+ .dclk_ddr = VOP_REG(RK3288_DSP_CTRL0, 0x1, 8), - .dsp_data_swap = VOP_REG(RK3288_DSP_CTRL0, 0x1f, 12), - .dsp_out_yuv = VOP_REG(RK3288_POST_SCL_CTRL, 0x1, 2), - .dsp_background = VOP_REG(RK3288_DSP_BG, 0xffffffff, 0), -@@ -921,6 +922,7 @@ static const struct vop_common rk3328_common = { - .cfg_done = VOP_REG_SYNC(RK3328_REG_CFG_DONE, 0x1, 0), - - .overlay_mode = VOP_REG(RK3328_SYS_CTRL, 0x1, 16), -+ .dclk_ddr = VOP_REG(RK3328_DSP_CTRL0, 0x1, 8), - .dsp_data_swap = VOP_REG(RK3328_DSP_CTRL0, 0x1f, 12), - .dsp_out_yuv = VOP_REG(RK3328_POST_SCL_CTRL, 0x1, 2), - .dsp_background = VOP_REG(RK3328_DSP_BG, 0xffffffff, 0), --- -2.17.1 - - -From a8f40af332f87e74015d578a14e4491d1e0c9291 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 8 Dec 2019 23:49:00 +0000 -Subject: [PATCH] WIP: drm/bridge: dw-hdmi: signal default quant range - ---- - drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -index df1789cd8712..14a1131cfc21 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -@@ -1673,6 +1673,9 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode) - HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; - } - -+ drm_hdmi_avi_infoframe_quant_range(&frame, &hdmi->connector, mode, -+ drm_default_rgb_quant_range(mode)); -+ - drm_hdmi_avi_infoframe_content_type(&frame, conn_state); - - hdmi_infoframe_log(KERN_INFO, hdmi->dev, (union hdmi_infoframe *)&frame); --- -2.17.1 - - -From aa34fb23453ea76f533d0af601ec0ce5ee9d8312 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Fri, 20 Dec 2019 08:12:43 +0000 -Subject: [PATCH] WIP: drm/bridge: dw-hdmi: use avmute during modeset - ---- - drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 4 ++++ - drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 4 ++++ - 2 files changed, 8 insertions(+) - -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -index 14a1131cfc21..6344c8aac13e 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -@@ -2328,10 +2328,14 @@ static void dw_hdmi_poweron(struct dw_hdmi *hdmi) - hdmi->bridge_is_on = true; - dw_hdmi_get_edid(&hdmi->connector); - dw_hdmi_setup(hdmi, &hdmi->previous_mode); -+ -+ hdmi_writeb(hdmi, HDMI_FC_GCP_CLEAR_AVMUTE, HDMI_FC_GCP); - } - - static void dw_hdmi_poweroff(struct dw_hdmi *hdmi) - { -+ hdmi_writeb(hdmi, HDMI_FC_GCP_SET_AVMUTE, HDMI_FC_GCP); -+ - if (hdmi->phy.enabled) { - hdmi->phy.ops->disable(hdmi, hdmi->phy.data); - hdmi->phy.enabled = false; -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h -index 27a91128d0cc..3810326794cc 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h -@@ -842,6 +842,10 @@ enum { - HDMI_FC_AVICONF3_QUANT_RANGE_LIMITED = 0x00, - HDMI_FC_AVICONF3_QUANT_RANGE_FULL = 0x04, - -+/* HDMI_FC_GCP */ -+ HDMI_FC_GCP_SET_AVMUTE = 0x2, -+ HDMI_FC_GCP_CLEAR_AVMUTE = 0x1, -+ - /* FC_DBGFORCE field values */ - HDMI_FC_DBGFORCE_FORCEAUDIO = 0x10, - HDMI_FC_DBGFORCE_FORCEVIDEO = 0x1, --- -2.17.1 - diff --git a/patch/kernel/rk322x-current/01-linux-0007-fromlist-drm-lima-and-panfrost-for-5.8-plus.patch.disabled b/patch/kernel/rk322x-current/01-linux-0007-fromlist-drm-lima-and-panfrost-for-5.8-plus.patch.disabled deleted file mode 100644 index 9d3dbcbe0..000000000 --- a/patch/kernel/rk322x-current/01-linux-0007-fromlist-drm-lima-and-panfrost-for-5.8-plus.patch.disabled +++ /dev/null @@ -1,4172 +0,0 @@ -diff --git a/drivers/gpu/drm/panfrost/panfrost_gpu.c b/drivers/gpu/drm/panfrost/panfrost_gpu.c -index 8822ec13a0d6..cdebe9a9ade7 100644 ---- a/drivers/gpu/drm/panfrost/panfrost_gpu.c -+++ b/drivers/gpu/drm/panfrost/panfrost_gpu.c -@@ -351,7 +351,7 @@ int panfrost_gpu_init(struct panfrost_device *pfdev) - return -ENODEV; - - err = devm_request_irq(pfdev->dev, irq, panfrost_gpu_irq_handler, -- IRQF_SHARED, "gpu", pfdev); -+ IRQF_SHARED, KBUILD_MODNAME "-gpu", pfdev); - if (err) { - dev_err(pfdev->dev, "failed to request gpu irq"); - return err; -diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c b/drivers/gpu/drm/panfrost/panfrost_job.c -index 9a1a72a748e7..7914b1570841 100644 ---- a/drivers/gpu/drm/panfrost/panfrost_job.c -+++ b/drivers/gpu/drm/panfrost/panfrost_job.c -@@ -508,7 +508,7 @@ int panfrost_job_init(struct panfrost_device *pfdev) - return -ENODEV; - - ret = devm_request_irq(pfdev->dev, irq, panfrost_job_irq_handler, -- IRQF_SHARED, "job", pfdev); -+ IRQF_SHARED, KBUILD_MODNAME "-job", pfdev); - if (ret) { - dev_err(pfdev->dev, "failed to request job irq"); - return ret; -diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c -index 5d75f8cf6477..ed28aeba6d59 100644 ---- a/drivers/gpu/drm/panfrost/panfrost_mmu.c -+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c -@@ -640,9 +640,11 @@ int panfrost_mmu_init(struct panfrost_device *pfdev) - if (irq <= 0) - return -ENODEV; - -- err = devm_request_threaded_irq(pfdev->dev, irq, panfrost_mmu_irq_handler, -+ err = devm_request_threaded_irq(pfdev->dev, irq, -+ panfrost_mmu_irq_handler, - panfrost_mmu_irq_handler_thread, -- IRQF_SHARED, "mmu", pfdev); -+ IRQF_SHARED, KBUILD_MODNAME "-mmu", -+ pfdev); - - if (err) { - dev_err(pfdev->dev, "failed to request mmu irq"); --- -2.17.1 - - -From feabec154cc4e8e3e9f1005fc0fc2ad2d0d828ed Mon Sep 17 00:00:00 2001 -From: Qiang Yu -Date: Thu, 16 Jan 2020 21:11:53 +0800 -Subject: [PATCH] drm/lima: update register info - -From Mali r10p0 kernel driver source code. - -Reviewed-by: Vasily Khoruzhick -Tested-by: Andreas Baierl -Signed-off-by: Qiang Yu ---- - drivers/gpu/drm/lima/lima_regs.h | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/gpu/drm/lima/lima_regs.h b/drivers/gpu/drm/lima/lima_regs.h -index ace8ecefbe90..0124c90e0153 100644 ---- a/drivers/gpu/drm/lima/lima_regs.h -+++ b/drivers/gpu/drm/lima/lima_regs.h -@@ -239,6 +239,7 @@ - #define LIMA_MMU_STATUS_REPLAY_BUFFER_EMPTY BIT(4) - #define LIMA_MMU_STATUS_PAGE_FAULT_IS_WRITE BIT(5) - #define LIMA_MMU_STATUS_BUS_ID(x) ((x >> 6) & 0x1F) -+#define LIMA_MMU_STATUS_STALL_NOT_ACTIVE BIT(31) - #define LIMA_MMU_COMMAND 0x0008 - #define LIMA_MMU_COMMAND_ENABLE_PAGING 0x00 - #define LIMA_MMU_COMMAND_DISABLE_PAGING 0x01 --- -2.17.1 - - -From a39f09230ca6ddf9e147e86c1bad9850913f6d52 Mon Sep 17 00:00:00 2001 -From: Qiang Yu -Date: Thu, 16 Jan 2020 21:11:54 +0800 -Subject: [PATCH] drm/lima: add lima_vm_map_bo - -For dynamically mapping added backup memory of lima_bo to vm. -This is a preparation for adding heap buffer support. - -Reviewed-by: Vasily Khoruzhick -Tested-by: Andreas Baierl -Signed-off-by: Qiang Yu ---- - drivers/gpu/drm/lima/lima_vm.c | 42 ++++++++++++++++++++++++++++++++++ - drivers/gpu/drm/lima/lima_vm.h | 1 + - 2 files changed, 43 insertions(+) - -diff --git a/drivers/gpu/drm/lima/lima_vm.c b/drivers/gpu/drm/lima/lima_vm.c -index 840e2350d872..2e513841de6c 100644 ---- a/drivers/gpu/drm/lima/lima_vm.c -+++ b/drivers/gpu/drm/lima/lima_vm.c -@@ -277,3 +277,45 @@ void lima_vm_print(struct lima_vm *vm) - } - } - } -+ -+int lima_vm_map_bo(struct lima_vm *vm, struct lima_bo *bo, int pageoff) -+{ -+ struct lima_bo_va *bo_va; -+ struct sg_dma_page_iter sg_iter; -+ int offset = 0, err; -+ u32 base; -+ -+ mutex_lock(&bo->lock); -+ -+ bo_va = lima_vm_bo_find(vm, bo); -+ if (!bo_va) { -+ err = -ENOENT; -+ goto err_out0; -+ } -+ -+ mutex_lock(&vm->lock); -+ -+ base = bo_va->node.start + (pageoff << PAGE_SHIFT); -+ for_each_sg_dma_page(bo->base.sgt->sgl, &sg_iter, -+ bo->base.sgt->nents, pageoff) { -+ err = lima_vm_map_page(vm, sg_page_iter_dma_address(&sg_iter), -+ base + offset); -+ if (err) -+ goto err_out1; -+ -+ offset += PAGE_SIZE; -+ } -+ -+ mutex_unlock(&vm->lock); -+ -+ mutex_unlock(&bo->lock); -+ return 0; -+ -+err_out1: -+ if (offset) -+ lima_vm_unmap_range(vm, base, base + offset - 1); -+ mutex_unlock(&vm->lock); -+err_out0: -+ mutex_unlock(&bo->lock); -+ return err; -+} -diff --git a/drivers/gpu/drm/lima/lima_vm.h b/drivers/gpu/drm/lima/lima_vm.h -index e0bdedcf14dd..22aeec77d84d 100644 ---- a/drivers/gpu/drm/lima/lima_vm.h -+++ b/drivers/gpu/drm/lima/lima_vm.h -@@ -58,5 +58,6 @@ static inline void lima_vm_put(struct lima_vm *vm) - } - - void lima_vm_print(struct lima_vm *vm); -+int lima_vm_map_bo(struct lima_vm *vm, struct lima_bo *bo, int pageoff); - - #endif --- -2.17.1 - - -From 7855619e0208555bf2568e143747d86b882aa6f7 Mon Sep 17 00:00:00 2001 -From: Qiang Yu -Date: Thu, 16 Jan 2020 21:11:55 +0800 -Subject: [PATCH] drm/lima: support heap buffer creation - -heap buffer is used as output of GP and input of PP for -Mali Utgard GPU. Size of heap buffer depends on the task -so is a runtime variable. - -Previously we just create a large enough buffer as heap -buffer. Now we add a heap buffer type to be able to -increase the backup memory dynamically when GP fail due -to lack of heap memory. - -Reviewed-by: Vasily Khoruzhick -Tested-by: Andreas Baierl -Signed-off-by: Qiang Yu ---- - drivers/gpu/drm/lima/lima_drv.c | 6 +- - drivers/gpu/drm/lima/lima_drv.h | 1 + - drivers/gpu/drm/lima/lima_gem.c | 134 ++++++++++++++++++++++++++++++-- - drivers/gpu/drm/lima/lima_gem.h | 4 + - drivers/gpu/drm/lima/lima_vm.c | 4 +- - include/uapi/drm/lima_drm.h | 9 ++- - 6 files changed, 147 insertions(+), 11 deletions(-) - -diff --git a/drivers/gpu/drm/lima/lima_drv.c b/drivers/gpu/drm/lima/lima_drv.c -index 124efe4fa97b..18f88aaef1a2 100644 ---- a/drivers/gpu/drm/lima/lima_drv.c -+++ b/drivers/gpu/drm/lima/lima_drv.c -@@ -15,10 +15,14 @@ - #include "lima_vm.h" - - int lima_sched_timeout_ms; -+uint lima_heap_init_nr_pages = 8; - - MODULE_PARM_DESC(sched_timeout_ms, "task run timeout in ms"); - module_param_named(sched_timeout_ms, lima_sched_timeout_ms, int, 0444); - -+MODULE_PARM_DESC(heap_init_nr_pages, "heap buffer init number of pages"); -+module_param_named(heap_init_nr_pages, lima_heap_init_nr_pages, uint, 0444); -+ - static int lima_ioctl_get_param(struct drm_device *dev, void *data, struct drm_file *file) - { - struct drm_lima_get_param *args = data; -@@ -68,7 +72,7 @@ static int lima_ioctl_gem_create(struct drm_device *dev, void *data, struct drm_ - if (args->pad) - return -EINVAL; - -- if (args->flags) -+ if (args->flags & ~(LIMA_BO_FLAG_HEAP)) - return -EINVAL; - - if (args->size == 0) -diff --git a/drivers/gpu/drm/lima/lima_drv.h b/drivers/gpu/drm/lima/lima_drv.h -index 69c7344715c9..f492ecc6a5d9 100644 ---- a/drivers/gpu/drm/lima/lima_drv.h -+++ b/drivers/gpu/drm/lima/lima_drv.h -@@ -9,6 +9,7 @@ - #include "lima_ctx.h" - - extern int lima_sched_timeout_ms; -+extern uint lima_heap_init_nr_pages; - - struct lima_vm; - struct lima_bo; -diff --git a/drivers/gpu/drm/lima/lima_gem.c b/drivers/gpu/drm/lima/lima_gem.c -index d0059d8c97d8..5404e0d668db 100644 ---- a/drivers/gpu/drm/lima/lima_gem.c -+++ b/drivers/gpu/drm/lima/lima_gem.c -@@ -4,6 +4,8 @@ - #include - #include - #include -+#include -+#include - - #include - #include -@@ -15,6 +17,83 @@ - #include "lima_gem.h" - #include "lima_vm.h" - -+int lima_heap_alloc(struct lima_bo *bo, struct lima_vm *vm) -+{ -+ struct page **pages; -+ struct address_space *mapping = bo->base.base.filp->f_mapping; -+ struct device *dev = bo->base.base.dev->dev; -+ size_t old_size = bo->heap_size; -+ size_t new_size = bo->heap_size ? bo->heap_size * 2 : -+ (lima_heap_init_nr_pages << PAGE_SHIFT); -+ struct sg_table sgt; -+ int i, ret; -+ -+ if (bo->heap_size >= bo->base.base.size) -+ return -ENOSPC; -+ -+ new_size = min(new_size, bo->base.base.size); -+ -+ mutex_lock(&bo->base.pages_lock); -+ -+ if (bo->base.pages) { -+ pages = bo->base.pages; -+ } else { -+ pages = kvmalloc_array(bo->base.base.size >> PAGE_SHIFT, -+ sizeof(*pages), GFP_KERNEL | __GFP_ZERO); -+ if (!pages) { -+ mutex_unlock(&bo->base.pages_lock); -+ return -ENOMEM; -+ } -+ -+ bo->base.pages = pages; -+ bo->base.pages_use_count = 1; -+ -+ mapping_set_unevictable(mapping); -+ } -+ -+ for (i = old_size >> PAGE_SHIFT; i < new_size >> PAGE_SHIFT; i++) { -+ struct page *page = shmem_read_mapping_page(mapping, i); -+ -+ if (IS_ERR(page)) { -+ mutex_unlock(&bo->base.pages_lock); -+ return PTR_ERR(page); -+ } -+ pages[i] = page; -+ } -+ -+ mutex_unlock(&bo->base.pages_lock); -+ -+ ret = sg_alloc_table_from_pages(&sgt, pages, i, 0, -+ new_size, GFP_KERNEL); -+ if (ret) -+ return ret; -+ -+ if (bo->base.sgt) { -+ dma_unmap_sg(dev, bo->base.sgt->sgl, -+ bo->base.sgt->nents, DMA_BIDIRECTIONAL); -+ sg_free_table(bo->base.sgt); -+ } else { -+ bo->base.sgt = kmalloc(sizeof(*bo->base.sgt), GFP_KERNEL); -+ if (!bo->base.sgt) { -+ sg_free_table(&sgt); -+ return -ENOMEM; -+ } -+ } -+ -+ dma_map_sg(dev, sgt.sgl, sgt.nents, DMA_BIDIRECTIONAL); -+ -+ *bo->base.sgt = sgt; -+ -+ if (vm) { -+ ret = lima_vm_map_bo(vm, bo, old_size >> PAGE_SHIFT); -+ if (ret) -+ return ret; -+ } -+ -+ bo->heap_size = new_size; -+ return 0; -+} -+ - int lima_gem_create_handle(struct drm_device *dev, struct drm_file *file, - u32 size, u32 flags, u32 *handle) - { -@@ -22,7 +101,8 @@ int lima_gem_create_handle(struct drm_device *dev, struct drm_file *file, - gfp_t mask; - struct drm_gem_shmem_object *shmem; - struct drm_gem_object *obj; -- struct sg_table *sgt; -+ struct lima_bo *bo; -+ bool is_heap = flags & LIMA_BO_FLAG_HEAP; - - shmem = drm_gem_shmem_create(dev, size); - if (IS_ERR(shmem)) -@@ -36,10 +116,18 @@ int lima_gem_create_handle(struct drm_device *dev, struct drm_file *file, - mask |= __GFP_DMA32; - mapping_set_gfp_mask(obj->filp->f_mapping, mask); - -- sgt = drm_gem_shmem_get_pages_sgt(obj); -- if (IS_ERR(sgt)) { -- err = PTR_ERR(sgt); -- goto out; -+ if (is_heap) { -+ bo = to_lima_bo(obj); -+ err = lima_heap_alloc(bo, NULL); -+ if (err) -+ goto out; -+ } else { -+ struct sg_table *sgt = drm_gem_shmem_get_pages_sgt(obj); -+ -+ if (IS_ERR(sgt)) { -+ err = PTR_ERR(sgt); -+ goto out; -+ } - } - - err = drm_gem_handle_create(file, obj, handle); -@@ -79,17 +167,47 @@ static void lima_gem_object_close(struct drm_gem_object *obj, struct drm_file *f - lima_vm_bo_del(vm, bo); - } - -+static int lima_gem_pin(struct drm_gem_object *obj) -+{ -+ struct lima_bo *bo = to_lima_bo(obj); -+ -+ if (bo->heap_size) -+ return -EINVAL; -+ -+ return drm_gem_shmem_pin(obj); -+} -+ -+static void *lima_gem_vmap(struct drm_gem_object *obj) -+{ -+ struct lima_bo *bo = to_lima_bo(obj); -+ -+ if (bo->heap_size) -+ return ERR_PTR(-EINVAL); -+ -+ return drm_gem_shmem_vmap(obj); -+} -+ -+static int lima_gem_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) -+{ -+ struct lima_bo *bo = to_lima_bo(obj); -+ -+ if (bo->heap_size) -+ return -EINVAL; -+ -+ return drm_gem_shmem_mmap(obj, vma); -+} -+ - static const struct drm_gem_object_funcs lima_gem_funcs = { - .free = lima_gem_free_object, - .open = lima_gem_object_open, - .close = lima_gem_object_close, - .print_info = drm_gem_shmem_print_info, -- .pin = drm_gem_shmem_pin, -+ .pin = lima_gem_pin, - .unpin = drm_gem_shmem_unpin, - .get_sg_table = drm_gem_shmem_get_sg_table, -- .vmap = drm_gem_shmem_vmap, -+ .vmap = lima_gem_vmap, - .vunmap = drm_gem_shmem_vunmap, -- .mmap = drm_gem_shmem_mmap, -+ .mmap = lima_gem_mmap, - }; - - struct drm_gem_object *lima_gem_create_object(struct drm_device *dev, size_t size) -diff --git a/drivers/gpu/drm/lima/lima_gem.h b/drivers/gpu/drm/lima/lima_gem.h -index 1800feb3e47f..ccea06142f4b 100644 ---- a/drivers/gpu/drm/lima/lima_gem.h -+++ b/drivers/gpu/drm/lima/lima_gem.h -@@ -7,12 +7,15 @@ - #include - - struct lima_submit; -+struct lima_vm; - - struct lima_bo { - struct drm_gem_shmem_object base; - - struct mutex lock; - struct list_head va; -+ -+ size_t heap_size; - }; - - static inline struct lima_bo * -@@ -31,6 +34,7 @@ static inline struct dma_resv *lima_bo_resv(struct lima_bo *bo) - return bo->base.base.resv; - } - -+int lima_heap_alloc(struct lima_bo *bo, struct lima_vm *vm); - struct drm_gem_object *lima_gem_create_object(struct drm_device *dev, size_t size); - int lima_gem_create_handle(struct drm_device *dev, struct drm_file *file, - u32 size, u32 flags, u32 *handle); -diff --git a/drivers/gpu/drm/lima/lima_vm.c b/drivers/gpu/drm/lima/lima_vm.c -index 2e513841de6c..5b92fb82674a 100644 ---- a/drivers/gpu/drm/lima/lima_vm.c -+++ b/drivers/gpu/drm/lima/lima_vm.c -@@ -155,6 +155,7 @@ int lima_vm_bo_add(struct lima_vm *vm, struct lima_bo *bo, bool create) - void lima_vm_bo_del(struct lima_vm *vm, struct lima_bo *bo) - { - struct lima_bo_va *bo_va; -+ u32 size; - - mutex_lock(&bo->lock); - -@@ -166,8 +167,9 @@ void lima_vm_bo_del(struct lima_vm *vm, struct lima_bo *bo) - - mutex_lock(&vm->lock); - -+ size = bo->heap_size ? bo->heap_size : bo_va->node.size; - lima_vm_unmap_range(vm, bo_va->node.start, -- bo_va->node.start + bo_va->node.size - 1); -+ bo_va->node.start + size - 1); - - drm_mm_remove_node(&bo_va->node); - -diff --git a/include/uapi/drm/lima_drm.h b/include/uapi/drm/lima_drm.h -index 95a00fb867e6..1ec58d652a5a 100644 ---- a/include/uapi/drm/lima_drm.h -+++ b/include/uapi/drm/lima_drm.h -@@ -32,12 +32,19 @@ struct drm_lima_get_param { - __u64 value; /* out, parameter value */ - }; - -+/* -+ * heap buffer dynamically increase backup memory size when GP task fail -+ * due to lack of heap memory. size field of heap buffer is an up bound of -+ * the backup memory which can be set to a fairly large value. -+ */ -+#define LIMA_BO_FLAG_HEAP (1 << 0) -+ - /** - * create a buffer for used by GPU - */ - struct drm_lima_gem_create { - __u32 size; /* in, buffer size */ -- __u32 flags; /* in, currently no flags, must be zero */ -+ __u32 flags; /* in, buffer flags */ - __u32 handle; /* out, GEM buffer handle */ - __u32 pad; /* pad, must be zero */ - }; --- -2.17.1 - - -From a9e57ad7709f2f0794da7ec3ef69fa0075c715d5 Mon Sep 17 00:00:00 2001 -From: Qiang Yu -Date: Thu, 16 Jan 2020 21:11:56 +0800 -Subject: [PATCH] drm/lima: recover task by enlarging heap buffer - -Increase heap buffer backup memory when GP receive PLBU -out of memory interrupt, then resume the task. - -Reviewed-by: Vasily Khoruzhick -Tested-by: Andreas Baierl -Signed-off-by: Qiang Yu ---- - drivers/gpu/drm/lima/lima_gp.c | 58 +++++++++++++++++++++++++++++-- - drivers/gpu/drm/lima/lima_mmu.c | 5 +++ - drivers/gpu/drm/lima/lima_mmu.h | 1 + - drivers/gpu/drm/lima/lima_sched.c | 35 ++++++++++++++++--- - drivers/gpu/drm/lima/lima_sched.h | 6 ++++ - 5 files changed, 98 insertions(+), 7 deletions(-) - -diff --git a/drivers/gpu/drm/lima/lima_gp.c b/drivers/gpu/drm/lima/lima_gp.c -index ccf49faedebf..52b210f9a605 100644 ---- a/drivers/gpu/drm/lima/lima_gp.c -+++ b/drivers/gpu/drm/lima/lima_gp.c -@@ -11,6 +11,8 @@ - #include "lima_device.h" - #include "lima_gp.h" - #include "lima_regs.h" -+#include "lima_gem.h" -+#include "lima_vm.h" - - #define gp_write(reg, data) writel(data, ip->iomem + reg) - #define gp_read(reg) readl(ip->iomem + reg) -@@ -20,6 +22,7 @@ static irqreturn_t lima_gp_irq_handler(int irq, void *data) - struct lima_ip *ip = data; - struct lima_device *dev = ip->dev; - struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_gp; -+ struct lima_sched_task *task = pipe->current_task; - u32 state = gp_read(LIMA_GP_INT_STAT); - u32 status = gp_read(LIMA_GP_STATUS); - bool done = false; -@@ -29,8 +32,16 @@ static irqreturn_t lima_gp_irq_handler(int irq, void *data) - return IRQ_NONE; - - if (state & LIMA_GP_IRQ_MASK_ERROR) { -- dev_err(dev->dev, "gp error irq state=%x status=%x\n", -- state, status); -+ if ((state & LIMA_GP_IRQ_MASK_ERROR) == -+ LIMA_GP_IRQ_PLBU_OUT_OF_MEM) { -+ dev_dbg(dev->dev, "gp out of heap irq status=%x\n", -+ status); -+ } else { -+ dev_err(dev->dev, "gp error irq state=%x status=%x\n", -+ state, status); -+ if (task) -+ task->recoverable = false; -+ } - - /* mask all interrupts before hard reset */ - gp_write(LIMA_GP_INT_MASK, 0); -@@ -43,6 +54,7 @@ static irqreturn_t lima_gp_irq_handler(int irq, void *data) - bool active = status & (LIMA_GP_STATUS_VS_ACTIVE | - LIMA_GP_STATUS_PLBU_ACTIVE); - done = valid && !active; -+ pipe->error = false; - } - - gp_write(LIMA_GP_INT_CLEAR, state); -@@ -121,6 +133,22 @@ static void lima_gp_task_run(struct lima_sched_pipe *pipe, - u32 cmd = 0; - int i; - -+ /* update real heap buffer size for GP */ -+ for (i = 0; i < task->num_bos; i++) { -+ struct lima_bo *bo = task->bos[i]; -+ -+ if (bo->heap_size && -+ lima_vm_get_va(task->vm, bo) == -+ f[LIMA_GP_PLBU_ALLOC_START_ADDR >> 2]) { -+ f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2] = -+ f[LIMA_GP_PLBU_ALLOC_START_ADDR >> 2] + -+ bo->heap_size; -+ task->recoverable = true; -+ task->heap = bo; -+ break; -+ } -+ } -+ - if (f[LIMA_GP_VSCL_START_ADDR >> 2] != - f[LIMA_GP_VSCL_END_ADDR >> 2]) - cmd |= LIMA_GP_CMD_START_VS; -@@ -184,6 +212,31 @@ static void lima_gp_task_mmu_error(struct lima_sched_pipe *pipe) - lima_sched_pipe_task_done(pipe); - } - -+static int lima_gp_task_recover(struct lima_sched_pipe *pipe) -+{ -+ struct lima_ip *ip = pipe->processor[0]; -+ struct lima_sched_task *task = pipe->current_task; -+ struct drm_lima_gp_frame *frame = task->frame; -+ u32 *f = frame->frame; -+ size_t fail_size = -+ f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2] - -+ f[LIMA_GP_PLBU_ALLOC_START_ADDR >> 2]; -+ -+ if (fail_size == task->heap->heap_size) { -+ int ret; -+ -+ ret = lima_heap_alloc(task->heap, task->vm); -+ if (ret < 0) -+ return ret; -+ } -+ -+ gp_write(LIMA_GP_INT_MASK, LIMA_GP_IRQ_MASK_USED); -+ gp_write(LIMA_GP_PLBU_ALLOC_END_ADDR, -+ f[LIMA_GP_PLBU_ALLOC_START_ADDR >> 2] + task->heap->heap_size); -+ gp_write(LIMA_GP_CMD, LIMA_GP_CMD_UPDATE_PLBU_ALLOC); -+ return 0; -+} -+ - static void lima_gp_print_version(struct lima_ip *ip) - { - u32 version, major, minor; -@@ -270,6 +323,7 @@ int lima_gp_pipe_init(struct lima_device *dev) - pipe->task_fini = lima_gp_task_fini; - pipe->task_error = lima_gp_task_error; - pipe->task_mmu_error = lima_gp_task_mmu_error; -+ pipe->task_recover = lima_gp_task_recover; - - return 0; - } -diff --git a/drivers/gpu/drm/lima/lima_mmu.c b/drivers/gpu/drm/lima/lima_mmu.c -index 97ec09dee572..f79d2af427e7 100644 ---- a/drivers/gpu/drm/lima/lima_mmu.c -+++ b/drivers/gpu/drm/lima/lima_mmu.c -@@ -99,6 +99,11 @@ void lima_mmu_fini(struct lima_ip *ip) - - } - -+void lima_mmu_flush_tlb(struct lima_ip *ip) -+{ -+ mmu_write(LIMA_MMU_COMMAND, LIMA_MMU_COMMAND_ZAP_CACHE); -+} -+ - void lima_mmu_switch_vm(struct lima_ip *ip, struct lima_vm *vm) - { - struct lima_device *dev = ip->dev; -diff --git a/drivers/gpu/drm/lima/lima_mmu.h b/drivers/gpu/drm/lima/lima_mmu.h -index 8c78319bcc8e..4f8ccbebcba1 100644 ---- a/drivers/gpu/drm/lima/lima_mmu.h -+++ b/drivers/gpu/drm/lima/lima_mmu.h -@@ -10,6 +10,7 @@ struct lima_vm; - int lima_mmu_init(struct lima_ip *ip); - void lima_mmu_fini(struct lima_ip *ip); - -+void lima_mmu_flush_tlb(struct lima_ip *ip); - void lima_mmu_switch_vm(struct lima_ip *ip, struct lima_vm *vm); - void lima_mmu_page_fault_resume(struct lima_ip *ip); - -diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c -index b561dd05bd62..3886999b4533 100644 ---- a/drivers/gpu/drm/lima/lima_sched.c -+++ b/drivers/gpu/drm/lima/lima_sched.c -@@ -313,6 +313,26 @@ static const struct drm_sched_backend_ops lima_sched_ops = { - .free_job = lima_sched_free_job, - }; - -+static void lima_sched_recover_work(struct work_struct *work) -+{ -+ struct lima_sched_pipe *pipe = -+ container_of(work, struct lima_sched_pipe, recover_work); -+ int i; -+ -+ for (i = 0; i < pipe->num_l2_cache; i++) -+ lima_l2_cache_flush(pipe->l2_cache[i]); -+ -+ if (pipe->bcast_mmu) { -+ lima_mmu_flush_tlb(pipe->bcast_mmu); -+ } else { -+ for (i = 0; i < pipe->num_mmu; i++) -+ lima_mmu_flush_tlb(pipe->mmu[i]); -+ } -+ -+ if (pipe->task_recover(pipe)) -+ drm_sched_fault(&pipe->base); -+} -+ - int lima_sched_pipe_init(struct lima_sched_pipe *pipe, const char *name) - { - unsigned int timeout = lima_sched_timeout_ms > 0 ? -@@ -321,6 +341,8 @@ int lima_sched_pipe_init(struct lima_sched_pipe *pipe, const char *name) - pipe->fence_context = dma_fence_context_alloc(1); - spin_lock_init(&pipe->fence_lock); - -+ INIT_WORK(&pipe->recover_work, lima_sched_recover_work); -+ - return drm_sched_init(&pipe->base, &lima_sched_ops, 1, 0, - msecs_to_jiffies(timeout), name); - } -@@ -332,11 +354,14 @@ void lima_sched_pipe_fini(struct lima_sched_pipe *pipe) - - void lima_sched_pipe_task_done(struct lima_sched_pipe *pipe) - { -- if (pipe->error) -- drm_sched_fault(&pipe->base); -- else { -- struct lima_sched_task *task = pipe->current_task; -- -+ struct lima_sched_task *task = pipe->current_task; -+ -+ if (pipe->error) { -+ if (task && task->recoverable) -+ schedule_work(&pipe->recover_work); -+ else -+ drm_sched_fault(&pipe->base); -+ } else { - pipe->task_fini(pipe); - dma_fence_signal(task->fence); - } -diff --git a/drivers/gpu/drm/lima/lima_sched.h b/drivers/gpu/drm/lima/lima_sched.h -index 1d814fecbcc0..d64393fb50a9 100644 ---- a/drivers/gpu/drm/lima/lima_sched.h -+++ b/drivers/gpu/drm/lima/lima_sched.h -@@ -20,6 +20,9 @@ struct lima_sched_task { - struct lima_bo **bos; - int num_bos; - -+ bool recoverable; -+ struct lima_bo *heap; -+ - /* pipe fence */ - struct dma_fence *fence; - }; -@@ -68,6 +71,9 @@ struct lima_sched_pipe { - void (*task_fini)(struct lima_sched_pipe *pipe); - void (*task_error)(struct lima_sched_pipe *pipe); - void (*task_mmu_error)(struct lima_sched_pipe *pipe); -+ int (*task_recover)(struct lima_sched_pipe *pipe); -+ -+ struct work_struct recover_work; - }; - - int lima_sched_task_init(struct lima_sched_task *task, --- -2.17.1 - - -From 6e3dc43aea43e83182588b79dd85e9c5f4d1d033 Mon Sep 17 00:00:00 2001 -From: Qiang Yu -Date: Thu, 16 Jan 2020 21:11:57 +0800 -Subject: [PATCH] drm/lima: increase driver version to 1.1 - -Increase driver version for mesa driver to identify -the support of new heap buffer interface. - -Reviewed-by: Vasily Khoruzhick -Tested-by: Andreas Baierl -Signed-off-by: Qiang Yu ---- - drivers/gpu/drm/lima/lima_drv.c | 10 ++++++++-- - 1 file changed, 8 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/lima/lima_drv.c b/drivers/gpu/drm/lima/lima_drv.c -index 18f88aaef1a2..2daac64d8955 100644 ---- a/drivers/gpu/drm/lima/lima_drv.c -+++ b/drivers/gpu/drm/lima/lima_drv.c -@@ -245,6 +245,12 @@ static const struct drm_ioctl_desc lima_drm_driver_ioctls[] = { - - DEFINE_DRM_GEM_FOPS(lima_drm_driver_fops); - -+/** -+ * Changelog: -+ * -+ * - 1.1.0 - add heap buffer support -+ */ -+ - static struct drm_driver lima_drm_driver = { - .driver_features = DRIVER_RENDER | DRIVER_GEM | DRIVER_SYNCOBJ, - .open = lima_drm_driver_open, -@@ -254,9 +260,9 @@ static struct drm_driver lima_drm_driver = { - .fops = &lima_drm_driver_fops, - .name = "lima", - .desc = "lima DRM", -- .date = "20190217", -+ .date = "20191231", - .major = 1, -- .minor = 0, -+ .minor = 1, - .patchlevel = 0, - - .gem_create_object = lima_gem_create_object, --- -2.17.1 - - -From 1a3901778598bc71d64bdbb71ea2278113aeb611 Mon Sep 17 00:00:00 2001 -From: Vasily Khoruzhick -Date: Fri, 14 Feb 2020 19:50:26 -0800 -Subject: [PATCH] drm/lima: fix recovering from PLBU out of memory - -It looks like on PLBU_OUT_OF_MEM interrupt we need to resume from where we -stopped, i.e. new PLBU heap start is old end. Also update end address -in GP frame to grow heap on 2nd and subsequent out of memory interrupts. - -Fixes: 2081e8dcf1ee ("drm/lima: recover task by enlarging heap buffer") -Signed-off-by: Vasily Khoruzhick -Signed-off-by: Qiang Yu ---- - drivers/gpu/drm/lima/lima_gp.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/lima/lima_gp.c b/drivers/gpu/drm/lima/lima_gp.c -index 52b210f9a605..d8841c870d90 100644 ---- a/drivers/gpu/drm/lima/lima_gp.c -+++ b/drivers/gpu/drm/lima/lima_gp.c -@@ -231,8 +231,13 @@ static int lima_gp_task_recover(struct lima_sched_pipe *pipe) - } - - gp_write(LIMA_GP_INT_MASK, LIMA_GP_IRQ_MASK_USED); -+ /* Resume from where we stopped, i.e. new start is old end */ -+ gp_write(LIMA_GP_PLBU_ALLOC_START_ADDR, -+ f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2]); -+ f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2] = -+ f[LIMA_GP_PLBU_ALLOC_START_ADDR >> 2] + task->heap->heap_size; - gp_write(LIMA_GP_PLBU_ALLOC_END_ADDR, -- f[LIMA_GP_PLBU_ALLOC_START_ADDR >> 2] + task->heap->heap_size); -+ f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2]); - gp_write(LIMA_GP_CMD, LIMA_GP_CMD_UPDATE_PLBU_ALLOC); - return 0; - } --- -2.17.1 - - -From 619bbf1237ff25c39fbef0809bdfb28aa691e925 Mon Sep 17 00:00:00 2001 -From: Nicolas Boichat -Date: Fri, 7 Feb 2020 13:26:23 +0800 -Subject: [PATCH] drm/panfrost: Improve error reporting in - panfrost_gpu_power_on - -It is useful to know which component cannot be powered on. - -Signed-off-by: Nicolas Boichat -Reviewed-by: Alyssa Rosenzweig -Reviewed-by: Steven Price -Signed-off-by: Rob Herring ---- - drivers/gpu/drm/panfrost/panfrost_gpu.c | 14 ++++++++++---- - 1 file changed, 10 insertions(+), 4 deletions(-) - -diff --git a/drivers/gpu/drm/panfrost/panfrost_gpu.c b/drivers/gpu/drm/panfrost/panfrost_gpu.c -index cdebe9a9ade7..2881f439ff85 100644 ---- a/drivers/gpu/drm/panfrost/panfrost_gpu.c -+++ b/drivers/gpu/drm/panfrost/panfrost_gpu.c -@@ -308,21 +308,27 @@ void panfrost_gpu_power_on(struct panfrost_device *pfdev) - gpu_write(pfdev, L2_PWRON_LO, pfdev->features.l2_present); - ret = readl_relaxed_poll_timeout(pfdev->iomem + L2_READY_LO, - val, val == pfdev->features.l2_present, 100, 1000); -+ if (ret) -+ dev_err(pfdev->dev, "error powering up gpu L2"); - - gpu_write(pfdev, STACK_PWRON_LO, pfdev->features.stack_present); -- ret |= readl_relaxed_poll_timeout(pfdev->iomem + STACK_READY_LO, -+ ret = readl_relaxed_poll_timeout(pfdev->iomem + STACK_READY_LO, - val, val == pfdev->features.stack_present, 100, 1000); -+ if (ret) -+ dev_err(pfdev->dev, "error powering up gpu stack"); - - gpu_write(pfdev, SHADER_PWRON_LO, pfdev->features.shader_present); -- ret |= readl_relaxed_poll_timeout(pfdev->iomem + SHADER_READY_LO, -+ ret = readl_relaxed_poll_timeout(pfdev->iomem + SHADER_READY_LO, - val, val == pfdev->features.shader_present, 100, 1000); -+ if (ret) -+ dev_err(pfdev->dev, "error powering up gpu shader"); - - gpu_write(pfdev, TILER_PWRON_LO, pfdev->features.tiler_present); -- ret |= readl_relaxed_poll_timeout(pfdev->iomem + TILER_READY_LO, -+ ret = readl_relaxed_poll_timeout(pfdev->iomem + TILER_READY_LO, - val, val == pfdev->features.tiler_present, 100, 1000); - - if (ret) -- dev_err(pfdev->dev, "error powering up gpu"); -+ dev_err(pfdev->dev, "error powering up gpu tiler"); - } - - void panfrost_gpu_power_off(struct panfrost_device *pfdev) --- -2.17.1 - - -From 96780fcbe44b27fda4c273d5b9b726dc4ba1ab5b Mon Sep 17 00:00:00 2001 -From: Nicolas Boichat -Date: Fri, 7 Feb 2020 13:26:24 +0800 -Subject: [PATCH] drm/panfrost: Add support for multiple regulators - -Some GPUs, namely, the bifrost/g72 part on MT8183, have a second -regulator for their SRAM, let's add support for that. - -We extend the framework in a generic manner so that we could -support more than 2 regulators, if required. - -Signed-off-by: Nicolas Boichat -Reviewed-by: Steven Price -Reviwed-by: Mark Brown -Signed-off-by: Rob Herring ---- - drivers/gpu/drm/panfrost/panfrost_device.c | 26 +++++++++++++------- - drivers/gpu/drm/panfrost/panfrost_device.h | 15 +++++++++++- - drivers/gpu/drm/panfrost/panfrost_drv.c | 28 +++++++++++++++------- - 3 files changed, 51 insertions(+), 18 deletions(-) - -diff --git a/drivers/gpu/drm/panfrost/panfrost_device.c b/drivers/gpu/drm/panfrost/panfrost_device.c -index 238fb6d54df4..3720d50f6d9f 100644 ---- a/drivers/gpu/drm/panfrost/panfrost_device.c -+++ b/drivers/gpu/drm/panfrost/panfrost_device.c -@@ -87,18 +87,27 @@ static void panfrost_clk_fini(struct panfrost_device *pfdev) - - static int panfrost_regulator_init(struct panfrost_device *pfdev) - { -- int ret; -+ int ret, i; - -- pfdev->regulator = devm_regulator_get(pfdev->dev, "mali"); -- if (IS_ERR(pfdev->regulator)) { -- ret = PTR_ERR(pfdev->regulator); -- dev_err(pfdev->dev, "failed to get regulator: %d\n", ret); -+ if (WARN(pfdev->comp->num_supplies > ARRAY_SIZE(pfdev->regulators), -+ "Too many supplies in compatible structure.\n")) -+ return -EINVAL; -+ -+ for (i = 0; i < pfdev->comp->num_supplies; i++) -+ pfdev->regulators[i].supply = pfdev->comp->supply_names[i]; -+ -+ ret = devm_regulator_bulk_get(pfdev->dev, -+ pfdev->comp->num_supplies, -+ pfdev->regulators); -+ if (ret < 0) { -+ dev_err(pfdev->dev, "failed to get regulators: %d\n", ret); - return ret; - } - -- ret = regulator_enable(pfdev->regulator); -+ ret = regulator_bulk_enable(pfdev->comp->num_supplies, -+ pfdev->regulators); - if (ret < 0) { -- dev_err(pfdev->dev, "failed to enable regulator: %d\n", ret); -+ dev_err(pfdev->dev, "failed to enable regulators: %d\n", ret); - return ret; - } - -@@ -107,7 +116,8 @@ static int panfrost_regulator_init(struct panfrost_device *pfdev) - - static void panfrost_regulator_fini(struct panfrost_device *pfdev) - { -- regulator_disable(pfdev->regulator); -+ regulator_bulk_disable(pfdev->comp->num_supplies, -+ pfdev->regulators); - } - - int panfrost_device_init(struct panfrost_device *pfdev) -diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h -index 06713811b92c..c9468bc5573a 100644 ---- a/drivers/gpu/drm/panfrost/panfrost_device.h -+++ b/drivers/gpu/drm/panfrost/panfrost_device.h -@@ -7,6 +7,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -19,6 +20,7 @@ struct panfrost_job; - struct panfrost_perfcnt; - - #define NUM_JOB_SLOTS 3 -+#define MAX_REGULATORS 2 - - struct panfrost_features { - u16 id; -@@ -51,6 +53,16 @@ struct panfrost_features { - unsigned long hw_issues[64 / BITS_PER_LONG]; - }; - -+/* -+ * Features that cannot be automatically detected and need matching using the -+ * compatible string, typically SoC-specific. -+ */ -+struct panfrost_compatible { -+ /* Supplies count and names. */ -+ int num_supplies; -+ const char * const *supply_names; -+}; -+ - struct panfrost_device { - struct device *dev; - struct drm_device *ddev; -@@ -59,10 +71,11 @@ struct panfrost_device { - void __iomem *iomem; - struct clk *clock; - struct clk *bus_clock; -- struct regulator *regulator; -+ struct regulator_bulk_data regulators[MAX_REGULATORS]; - struct reset_control *rstc; - - struct panfrost_features features; -+ const struct panfrost_compatible *comp; - - spinlock_t as_lock; - unsigned long as_in_use_mask; -diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c -index b7a618db3ee2..4d0850752623 100644 ---- a/drivers/gpu/drm/panfrost/panfrost_drv.c -+++ b/drivers/gpu/drm/panfrost/panfrost_drv.c -@@ -584,6 +584,10 @@ static int panfrost_probe(struct platform_device *pdev) - - platform_set_drvdata(pdev, pfdev); - -+ pfdev->comp = of_device_get_match_data(&pdev->dev); -+ if (!pfdev->comp) -+ return -ENODEV; -+ - /* Allocate and initialze the DRM device. */ - ddev = drm_dev_alloc(&panfrost_drm_driver, &pdev->dev); - if (IS_ERR(ddev)) -@@ -655,16 +659,22 @@ static int panfrost_remove(struct platform_device *pdev) - return 0; - } - -+const char * const default_supplies[] = { "mali" }; -+static const struct panfrost_compatible default_data = { -+ .num_supplies = ARRAY_SIZE(default_supplies), -+ .supply_names = default_supplies, -+}; -+ - static const struct of_device_id dt_match[] = { -- { .compatible = "arm,mali-t604" }, -- { .compatible = "arm,mali-t624" }, -- { .compatible = "arm,mali-t628" }, -- { .compatible = "arm,mali-t720" }, -- { .compatible = "arm,mali-t760" }, -- { .compatible = "arm,mali-t820" }, -- { .compatible = "arm,mali-t830" }, -- { .compatible = "arm,mali-t860" }, -- { .compatible = "arm,mali-t880" }, -+ { .compatible = "arm,mali-t604", .data = &default_data, }, -+ { .compatible = "arm,mali-t624", .data = &default_data, }, -+ { .compatible = "arm,mali-t628", .data = &default_data, }, -+ { .compatible = "arm,mali-t720", .data = &default_data, }, -+ { .compatible = "arm,mali-t760", .data = &default_data, }, -+ { .compatible = "arm,mali-t820", .data = &default_data, }, -+ { .compatible = "arm,mali-t830", .data = &default_data, }, -+ { .compatible = "arm,mali-t860", .data = &default_data, }, -+ { .compatible = "arm,mali-t880", .data = &default_data, }, - {} - }; - MODULE_DEVICE_TABLE(of, dt_match); --- -2.17.1 - - -From 7de0cdd88c14fec1927a563e843fae6e6c79f6be Mon Sep 17 00:00:00 2001 -From: Nicolas Boichat -Date: Fri, 7 Feb 2020 13:26:25 +0800 -Subject: [PATCH] drm/panfrost: Add support for multiple power domains - -When there is a single power domain per device, the core will -ensure the power domain is switched on (so it is technically -equivalent to having not power domain specified at all). - -However, when there are multiple domains, as in MT8183 Bifrost -GPU, we need to handle them in driver code. - -Signed-off-by: Nicolas Boichat -Reviewed-by: Ulf Hansson -Reviewed-by: Steven Price -Signed-off-by: Rob Herring ---- - drivers/gpu/drm/panfrost/panfrost_device.c | 97 ++++++++++++++++++++-- - drivers/gpu/drm/panfrost/panfrost_device.h | 11 +++ - drivers/gpu/drm/panfrost/panfrost_drv.c | 2 + - 3 files changed, 102 insertions(+), 8 deletions(-) - -diff --git a/drivers/gpu/drm/panfrost/panfrost_device.c b/drivers/gpu/drm/panfrost/panfrost_device.c -index 3720d50f6d9f..8136babd3ba9 100644 ---- a/drivers/gpu/drm/panfrost/panfrost_device.c -+++ b/drivers/gpu/drm/panfrost/panfrost_device.c -@@ -5,6 +5,7 @@ - #include - #include - #include -+#include - #include - - #include "panfrost_device.h" -@@ -120,6 +121,79 @@ static void panfrost_regulator_fini(struct panfrost_device *pfdev) - pfdev->regulators); - } - -+static void panfrost_pm_domain_fini(struct panfrost_device *pfdev) -+{ -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(pfdev->pm_domain_devs); i++) { -+ if (!pfdev->pm_domain_devs[i]) -+ break; -+ -+ if (pfdev->pm_domain_links[i]) -+ device_link_del(pfdev->pm_domain_links[i]); -+ -+ dev_pm_domain_detach(pfdev->pm_domain_devs[i], true); -+ } -+} -+ -+static int panfrost_pm_domain_init(struct panfrost_device *pfdev) -+{ -+ int err; -+ int i, num_domains; -+ -+ num_domains = of_count_phandle_with_args(pfdev->dev->of_node, -+ "power-domains", -+ "#power-domain-cells"); -+ -+ /* -+ * Single domain is handled by the core, and, if only a single power -+ * the power domain is requested, the property is optional. -+ */ -+ if (num_domains < 2 && pfdev->comp->num_pm_domains < 2) -+ return 0; -+ -+ if (num_domains != pfdev->comp->num_pm_domains) { -+ dev_err(pfdev->dev, -+ "Incorrect number of power domains: %d provided, %d needed\n", -+ num_domains, pfdev->comp->num_pm_domains); -+ return -EINVAL; -+ } -+ -+ if (WARN(num_domains > ARRAY_SIZE(pfdev->pm_domain_devs), -+ "Too many supplies in compatible structure.\n")) -+ return -EINVAL; -+ -+ for (i = 0; i < num_domains; i++) { -+ pfdev->pm_domain_devs[i] = -+ dev_pm_domain_attach_by_name(pfdev->dev, -+ pfdev->comp->pm_domain_names[i]); -+ if (IS_ERR_OR_NULL(pfdev->pm_domain_devs[i])) { -+ err = PTR_ERR(pfdev->pm_domain_devs[i]) ? : -ENODATA; -+ pfdev->pm_domain_devs[i] = NULL; -+ dev_err(pfdev->dev, -+ "failed to get pm-domain %s(%d): %d\n", -+ pfdev->comp->pm_domain_names[i], i, err); -+ goto err; -+ } -+ -+ pfdev->pm_domain_links[i] = device_link_add(pfdev->dev, -+ pfdev->pm_domain_devs[i], DL_FLAG_PM_RUNTIME | -+ DL_FLAG_STATELESS | DL_FLAG_RPM_ACTIVE); -+ if (!pfdev->pm_domain_links[i]) { -+ dev_err(pfdev->pm_domain_devs[i], -+ "adding device link failed!\n"); -+ err = -ENODEV; -+ goto err; -+ } -+ } -+ -+ return 0; -+ -+err: -+ panfrost_pm_domain_fini(pfdev); -+ return err; -+} -+ - int panfrost_device_init(struct panfrost_device *pfdev) - { - int err; -@@ -150,37 +224,43 @@ int panfrost_device_init(struct panfrost_device *pfdev) - goto err_out1; - } - -+ err = panfrost_pm_domain_init(pfdev); -+ if (err) -+ goto err_out2; -+ - res = platform_get_resource(pfdev->pdev, IORESOURCE_MEM, 0); - pfdev->iomem = devm_ioremap_resource(pfdev->dev, res); - if (IS_ERR(pfdev->iomem)) { - dev_err(pfdev->dev, "failed to ioremap iomem\n"); - err = PTR_ERR(pfdev->iomem); -- goto err_out2; -+ goto err_out3; - } - - err = panfrost_gpu_init(pfdev); - if (err) -- goto err_out2; -+ goto err_out3; - - err = panfrost_mmu_init(pfdev); - if (err) -- goto err_out3; -+ goto err_out4; - - err = panfrost_job_init(pfdev); - if (err) -- goto err_out4; -+ goto err_out5; - - err = panfrost_perfcnt_init(pfdev); - if (err) -- goto err_out5; -+ goto err_out6; - - return 0; --err_out5: -+err_out6: - panfrost_job_fini(pfdev); --err_out4: -+err_out5: - panfrost_mmu_fini(pfdev); --err_out3: -+err_out4: - panfrost_gpu_fini(pfdev); -+err_out3: -+ panfrost_pm_domain_fini(pfdev); - err_out2: - panfrost_reset_fini(pfdev); - err_out1: -@@ -196,6 +276,7 @@ void panfrost_device_fini(struct panfrost_device *pfdev) - panfrost_job_fini(pfdev); - panfrost_mmu_fini(pfdev); - panfrost_gpu_fini(pfdev); -+ panfrost_pm_domain_fini(pfdev); - panfrost_reset_fini(pfdev); - panfrost_regulator_fini(pfdev); - panfrost_clk_fini(pfdev); -diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h -index c9468bc5573a..c30c719a8059 100644 ---- a/drivers/gpu/drm/panfrost/panfrost_device.h -+++ b/drivers/gpu/drm/panfrost/panfrost_device.h -@@ -21,6 +21,7 @@ struct panfrost_perfcnt; - - #define NUM_JOB_SLOTS 3 - #define MAX_REGULATORS 2 -+#define MAX_PM_DOMAINS 3 - - struct panfrost_features { - u16 id; -@@ -61,6 +62,13 @@ struct panfrost_compatible { - /* Supplies count and names. */ - int num_supplies; - const char * const *supply_names; -+ /* -+ * Number of power domains required, note that values 0 and 1 are -+ * handled identically, as only values > 1 need special handling. -+ */ -+ int num_pm_domains; -+ /* Only required if num_pm_domains > 1. */ -+ const char * const *pm_domain_names; - }; - - struct panfrost_device { -@@ -73,6 +81,9 @@ struct panfrost_device { - struct clk *bus_clock; - struct regulator_bulk_data regulators[MAX_REGULATORS]; - struct reset_control *rstc; -+ /* pm_domains for devices with more than one. */ -+ struct device *pm_domain_devs[MAX_PM_DOMAINS]; -+ struct device_link *pm_domain_links[MAX_PM_DOMAINS]; - - struct panfrost_features features; - const struct panfrost_compatible *comp; -diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c -index 4d0850752623..a6e162236d67 100644 ---- a/drivers/gpu/drm/panfrost/panfrost_drv.c -+++ b/drivers/gpu/drm/panfrost/panfrost_drv.c -@@ -663,6 +663,8 @@ const char * const default_supplies[] = { "mali" }; - static const struct panfrost_compatible default_data = { - .num_supplies = ARRAY_SIZE(default_supplies), - .supply_names = default_supplies, -+ .num_pm_domains = 1, /* optional */ -+ .pm_domain_names = NULL, - }; - - static const struct of_device_id dt_match[] = { --- -2.17.1 - - -From 4a210ebba6b01cb060a1de524d5d000981025b5b Mon Sep 17 00:00:00 2001 -From: kbuild test robot -Date: Thu, 27 Feb 2020 09:41:46 +0800 -Subject: [PATCH] drm/panfrost: default_supplies[] can be static - -Fixes: 3e1399bccf51 ("drm/panfrost: Add support for multiple regulators") -Signed-off-by: kbuild test robot -Reviewed-by: Nicolas Boichat -Signed-off-by: Rob Herring ---- - drivers/gpu/drm/panfrost/panfrost_drv.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c -index a6e162236d67..882fecc33fdb 100644 ---- a/drivers/gpu/drm/panfrost/panfrost_drv.c -+++ b/drivers/gpu/drm/panfrost/panfrost_drv.c -@@ -659,7 +659,7 @@ static int panfrost_remove(struct platform_device *pdev) - return 0; - } - --const char * const default_supplies[] = { "mali" }; -+static const char * const default_supplies[] = { "mali" }; - static const struct panfrost_compatible default_data = { - .num_supplies = ARRAY_SIZE(default_supplies), - .supply_names = default_supplies, --- -2.17.1 - - -From 95695d5e36c49319b2cc6eabae04d32a13ca962e Mon Sep 17 00:00:00 2001 -From: Qiang Yu -Date: Sat, 22 Feb 2020 10:42:06 +0800 -Subject: [PATCH] drm/lima: save process info for debug usage - -When task fail, we can find its process with this information. - -Tested-by: Andreas Baierl -Reviewed-by: Vasily Khoruzhick -Signed-off-by: Qiang Yu ---- - drivers/gpu/drm/lima/lima_ctx.c | 3 +++ - drivers/gpu/drm/lima/lima_ctx.h | 5 +++++ - 2 files changed, 8 insertions(+) - -diff --git a/drivers/gpu/drm/lima/lima_ctx.c b/drivers/gpu/drm/lima/lima_ctx.c -index 22fff6caa961..891d5cd5019a 100644 ---- a/drivers/gpu/drm/lima/lima_ctx.c -+++ b/drivers/gpu/drm/lima/lima_ctx.c -@@ -27,6 +27,9 @@ int lima_ctx_create(struct lima_device *dev, struct lima_ctx_mgr *mgr, u32 *id) - if (err < 0) - goto err_out0; - -+ ctx->pid = task_pid_nr(current); -+ get_task_comm(ctx->pname, current); -+ - return 0; - - err_out0: -diff --git a/drivers/gpu/drm/lima/lima_ctx.h b/drivers/gpu/drm/lima/lima_ctx.h -index 6154e5c9bfe4..74e2be09090f 100644 ---- a/drivers/gpu/drm/lima/lima_ctx.h -+++ b/drivers/gpu/drm/lima/lima_ctx.h -@@ -5,6 +5,7 @@ - #define __LIMA_CTX_H__ - - #include -+#include - - #include "lima_device.h" - -@@ -13,6 +14,10 @@ struct lima_ctx { - struct lima_device *dev; - struct lima_sched_context context[lima_pipe_num]; - atomic_t guilty; -+ -+ /* debug info */ -+ char pname[TASK_COMM_LEN]; -+ pid_t pid; - }; - - struct lima_ctx_mgr { --- -2.17.1 - - -From c70385c2415949d2a8eecdb3242b0e27fcc56c25 Mon Sep 17 00:00:00 2001 -From: Qiang Yu -Date: Sat, 22 Feb 2020 10:42:07 +0800 -Subject: [PATCH] drm/lima: add max_error_tasks module parameter - -Limit error tasks to save. - -Tested-by: Andreas Baierl -Reviewed-by: Vasily Khoruzhick -Signed-off-by: Qiang Yu ---- - drivers/gpu/drm/lima/lima_drv.c | 4 ++++ - drivers/gpu/drm/lima/lima_drv.h | 1 + - 2 files changed, 5 insertions(+) - -diff --git a/drivers/gpu/drm/lima/lima_drv.c b/drivers/gpu/drm/lima/lima_drv.c -index 2daac64d8955..e235d4545b6c 100644 ---- a/drivers/gpu/drm/lima/lima_drv.c -+++ b/drivers/gpu/drm/lima/lima_drv.c -@@ -16,6 +16,7 @@ - - int lima_sched_timeout_ms; - uint lima_heap_init_nr_pages = 8; -+uint lima_max_error_tasks; - - MODULE_PARM_DESC(sched_timeout_ms, "task run timeout in ms"); - module_param_named(sched_timeout_ms, lima_sched_timeout_ms, int, 0444); -@@ -23,6 +24,9 @@ module_param_named(sched_timeout_ms, lima_sched_timeout_ms, int, 0444); - MODULE_PARM_DESC(heap_init_nr_pages, "heap buffer init number of pages"); - module_param_named(heap_init_nr_pages, lima_heap_init_nr_pages, uint, 0444); - -+MODULE_PARM_DESC(max_error_tasks, "max number of error tasks to save"); -+module_param_named(max_error_tasks, lima_max_error_tasks, uint, 0644); -+ - static int lima_ioctl_get_param(struct drm_device *dev, void *data, struct drm_file *file) - { - struct drm_lima_get_param *args = data; -diff --git a/drivers/gpu/drm/lima/lima_drv.h b/drivers/gpu/drm/lima/lima_drv.h -index f492ecc6a5d9..fdbd4077c768 100644 ---- a/drivers/gpu/drm/lima/lima_drv.h -+++ b/drivers/gpu/drm/lima/lima_drv.h -@@ -10,6 +10,7 @@ - - extern int lima_sched_timeout_ms; - extern uint lima_heap_init_nr_pages; -+extern uint lima_max_error_tasks; - - struct lima_vm; - struct lima_bo; --- -2.17.1 - - -From 3090b38955b4cb7c17b724fbdda56f5cab02e327 Mon Sep 17 00:00:00 2001 -From: Qiang Yu -Date: Sat, 7 Mar 2020 21:44:23 +0800 -Subject: [PATCH] drm/lima: save task info dump when task fail - -Save all information to start a task which can be exported to user -for debug usage. Dump file data format is specified in lima_dump.h - -v2: -Add include header to address build robot complain. - -Tested-by: Andreas Baierl -Reviewed-by: Vasily Khoruzhick -Signed-off-by: Qiang Yu ---- - drivers/gpu/drm/lima/lima_device.c | 13 +++ - drivers/gpu/drm/lima/lima_device.h | 8 ++ - drivers/gpu/drm/lima/lima_dump.h | 77 +++++++++++++++++ - drivers/gpu/drm/lima/lima_sched.c | 130 +++++++++++++++++++++++++++++ - drivers/gpu/drm/lima/lima_sched.h | 7 ++ - 5 files changed, 235 insertions(+) - create mode 100644 drivers/gpu/drm/lima/lima_dump.h - -diff --git a/drivers/gpu/drm/lima/lima_device.c b/drivers/gpu/drm/lima/lima_device.c -index 19829b543024..42a00171fea5 100644 ---- a/drivers/gpu/drm/lima/lima_device.c -+++ b/drivers/gpu/drm/lima/lima_device.c -@@ -344,6 +344,12 @@ int lima_device_init(struct lima_device *ldev) - if (err) - goto err_out5; - -+ ldev->dump.magic = LIMA_DUMP_MAGIC; -+ ldev->dump.version_major = LIMA_DUMP_MAJOR; -+ ldev->dump.version_minor = LIMA_DUMP_MINOR; -+ INIT_LIST_HEAD(&ldev->error_task_list); -+ mutex_init(&ldev->error_task_list_lock); -+ - dev_info(ldev->dev, "bus rate = %lu\n", clk_get_rate(ldev->clk_bus)); - dev_info(ldev->dev, "mod rate = %lu", clk_get_rate(ldev->clk_gpu)); - -@@ -370,6 +376,13 @@ int lima_device_init(struct lima_device *ldev) - void lima_device_fini(struct lima_device *ldev) - { - int i; -+ struct lima_sched_error_task *et, *tmp; -+ -+ list_for_each_entry_safe(et, tmp, &ldev->error_task_list, list) { -+ list_del(&et->list); -+ kvfree(et); -+ } -+ mutex_destroy(&ldev->error_task_list_lock); - - lima_fini_pp_pipe(ldev); - lima_fini_gp_pipe(ldev); -diff --git a/drivers/gpu/drm/lima/lima_device.h b/drivers/gpu/drm/lima/lima_device.h -index 31158d86271c..f17173f47f26 100644 ---- a/drivers/gpu/drm/lima/lima_device.h -+++ b/drivers/gpu/drm/lima/lima_device.h -@@ -6,8 +6,11 @@ - - #include - #include -+#include -+#include - - #include "lima_sched.h" -+#include "lima_dump.h" - - enum lima_gpu_id { - lima_gpu_mali400 = 0, -@@ -94,6 +97,11 @@ struct lima_device { - - u32 *dlbu_cpu; - dma_addr_t dlbu_dma; -+ -+ /* debug info */ -+ struct lima_dump_head dump; -+ struct list_head error_task_list; -+ struct mutex error_task_list_lock; - }; - - static inline struct lima_device * -diff --git a/drivers/gpu/drm/lima/lima_dump.h b/drivers/gpu/drm/lima/lima_dump.h -new file mode 100644 -index 000000000000..ca243d99c51b ---- /dev/null -+++ b/drivers/gpu/drm/lima/lima_dump.h -@@ -0,0 +1,77 @@ -+/* SPDX-License-Identifier: GPL-2.0 OR MIT */ -+/* Copyright 2020 Qiang Yu */ -+ -+#ifndef __LIMA_DUMP_H__ -+#define __LIMA_DUMP_H__ -+ -+#include -+ -+/** -+ * dump file format for all the information to start a lima task -+ * -+ * top level format -+ * | magic code "LIMA" | format version | num tasks | data size | -+ * | reserved | reserved | reserved | reserved | -+ * | task 1 ID | task 1 size | num chunks | reserved | task 1 data | -+ * | task 2 ID | task 2 size | num chunks | reserved | task 2 data | -+ * ... -+ * -+ * task data format -+ * | chunk 1 ID | chunk 1 size | reserved | reserved | chunk 1 data | -+ * | chunk 2 ID | chunk 2 size | reserved | reserved | chunk 2 data | -+ * ... -+ * -+ */ -+ -+#define LIMA_DUMP_MAJOR 1 -+#define LIMA_DUMP_MINOR 0 -+ -+#define LIMA_DUMP_MAGIC 0x414d494c -+ -+struct lima_dump_head { -+ __u32 magic; -+ __u16 version_major; -+ __u16 version_minor; -+ __u32 num_tasks; -+ __u32 size; -+ __u32 reserved[4]; -+}; -+ -+#define LIMA_DUMP_TASK_GP 0 -+#define LIMA_DUMP_TASK_PP 1 -+#define LIMA_DUMP_TASK_NUM 2 -+ -+struct lima_dump_task { -+ __u32 id; -+ __u32 size; -+ __u32 num_chunks; -+ __u32 reserved; -+}; -+ -+#define LIMA_DUMP_CHUNK_FRAME 0 -+#define LIMA_DUMP_CHUNK_BUFFER 1 -+#define LIMA_DUMP_CHUNK_PROCESS_NAME 2 -+#define LIMA_DUMP_CHUNK_PROCESS_ID 3 -+#define LIMA_DUMP_CHUNK_NUM 4 -+ -+struct lima_dump_chunk { -+ __u32 id; -+ __u32 size; -+ __u32 reserved[2]; -+}; -+ -+struct lima_dump_chunk_buffer { -+ __u32 id; -+ __u32 size; -+ __u32 va; -+ __u32 reserved; -+}; -+ -+struct lima_dump_chunk_pid { -+ __u32 id; -+ __u32 size; -+ __u32 pid; -+ __u32 reserved; -+}; -+ -+#endif -diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c -index 3886999b4533..86192422a689 100644 ---- a/drivers/gpu/drm/lima/lima_sched.c -+++ b/drivers/gpu/drm/lima/lima_sched.c -@@ -4,6 +4,7 @@ - #include - #include - #include -+#include - - #include "lima_drv.h" - #include "lima_sched.h" -@@ -256,6 +257,133 @@ static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job) - return task->fence; - } - -+static void lima_sched_build_error_task_list(struct lima_sched_task *task) -+{ -+ struct lima_sched_error_task *et; -+ struct lima_sched_pipe *pipe = to_lima_pipe(task->base.sched); -+ struct lima_ip *ip = pipe->processor[0]; -+ int pipe_id = ip->id == lima_ip_gp ? lima_pipe_gp : lima_pipe_pp; -+ struct lima_device *dev = ip->dev; -+ struct lima_sched_context *sched_ctx = -+ container_of(task->base.entity, -+ struct lima_sched_context, base); -+ struct lima_ctx *ctx = -+ container_of(sched_ctx, struct lima_ctx, context[pipe_id]); -+ struct lima_dump_task *dt; -+ struct lima_dump_chunk *chunk; -+ struct lima_dump_chunk_pid *pid_chunk; -+ struct lima_dump_chunk_buffer *buffer_chunk; -+ u32 size, task_size, mem_size; -+ int i; -+ -+ mutex_lock(&dev->error_task_list_lock); -+ -+ if (dev->dump.num_tasks >= lima_max_error_tasks) { -+ dev_info(dev->dev, "fail to save task state: error task list is full\n"); -+ goto out; -+ } -+ -+ /* frame chunk */ -+ size = sizeof(struct lima_dump_chunk) + pipe->frame_size; -+ /* process name chunk */ -+ size += sizeof(struct lima_dump_chunk) + sizeof(ctx->pname); -+ /* pid chunk */ -+ size += sizeof(struct lima_dump_chunk); -+ /* buffer chunks */ -+ for (i = 0; i < task->num_bos; i++) { -+ struct lima_bo *bo = task->bos[i]; -+ -+ size += sizeof(struct lima_dump_chunk); -+ size += bo->heap_size ? bo->heap_size : lima_bo_size(bo); -+ } -+ -+ task_size = size + sizeof(struct lima_dump_task); -+ mem_size = task_size + sizeof(*et); -+ et = kvmalloc(mem_size, GFP_KERNEL); -+ if (!et) { -+ dev_err(dev->dev, "fail to alloc task dump buffer of size %x\n", -+ mem_size); -+ goto out; -+ } -+ -+ et->data = et + 1; -+ et->size = task_size; -+ -+ dt = et->data; -+ memset(dt, 0, sizeof(*dt)); -+ dt->id = pipe_id; -+ dt->size = size; -+ -+ chunk = (struct lima_dump_chunk *)(dt + 1); -+ memset(chunk, 0, sizeof(*chunk)); -+ chunk->id = LIMA_DUMP_CHUNK_FRAME; -+ chunk->size = pipe->frame_size; -+ memcpy(chunk + 1, task->frame, pipe->frame_size); -+ dt->num_chunks++; -+ -+ chunk = (void *)(chunk + 1) + chunk->size; -+ memset(chunk, 0, sizeof(*chunk)); -+ chunk->id = LIMA_DUMP_CHUNK_PROCESS_NAME; -+ chunk->size = sizeof(ctx->pname); -+ memcpy(chunk + 1, ctx->pname, sizeof(ctx->pname)); -+ dt->num_chunks++; -+ -+ pid_chunk = (void *)(chunk + 1) + chunk->size; -+ memset(pid_chunk, 0, sizeof(*pid_chunk)); -+ pid_chunk->id = LIMA_DUMP_CHUNK_PROCESS_ID; -+ pid_chunk->pid = ctx->pid; -+ dt->num_chunks++; -+ -+ buffer_chunk = (void *)(pid_chunk + 1) + pid_chunk->size; -+ for (i = 0; i < task->num_bos; i++) { -+ struct lima_bo *bo = task->bos[i]; -+ void *data; -+ -+ memset(buffer_chunk, 0, sizeof(*buffer_chunk)); -+ buffer_chunk->id = LIMA_DUMP_CHUNK_BUFFER; -+ buffer_chunk->va = lima_vm_get_va(task->vm, bo); -+ -+ if (bo->heap_size) { -+ buffer_chunk->size = bo->heap_size; -+ -+ data = vmap(bo->base.pages, bo->heap_size >> PAGE_SHIFT, -+ VM_MAP, pgprot_writecombine(PAGE_KERNEL)); -+ if (!data) { -+ kvfree(et); -+ goto out; -+ } -+ -+ memcpy(buffer_chunk + 1, data, buffer_chunk->size); -+ -+ vunmap(data); -+ } else { -+ buffer_chunk->size = lima_bo_size(bo); -+ -+ data = drm_gem_shmem_vmap(&bo->base.base); -+ if (IS_ERR_OR_NULL(data)) { -+ kvfree(et); -+ goto out; -+ } -+ -+ memcpy(buffer_chunk + 1, data, buffer_chunk->size); -+ -+ drm_gem_shmem_vunmap(&bo->base.base, data); -+ } -+ -+ buffer_chunk = (void *)(buffer_chunk + 1) + buffer_chunk->size; -+ dt->num_chunks++; -+ } -+ -+ list_add(&et->list, &dev->error_task_list); -+ dev->dump.size += et->size; -+ dev->dump.num_tasks++; -+ -+ dev_info(dev->dev, "save error task state success\n"); -+ -+out: -+ mutex_unlock(&dev->error_task_list_lock); -+} -+ - static void lima_sched_timedout_job(struct drm_sched_job *job) - { - struct lima_sched_pipe *pipe = to_lima_pipe(job->sched); -@@ -268,6 +396,8 @@ static void lima_sched_timedout_job(struct drm_sched_job *job) - - drm_sched_increase_karma(&task->base); - -+ lima_sched_build_error_task_list(task); -+ - pipe->task_error(pipe); - - if (pipe->bcast_mmu) -diff --git a/drivers/gpu/drm/lima/lima_sched.h b/drivers/gpu/drm/lima/lima_sched.h -index d64393fb50a9..a1496cb7bc41 100644 ---- a/drivers/gpu/drm/lima/lima_sched.h -+++ b/drivers/gpu/drm/lima/lima_sched.h -@@ -5,9 +5,16 @@ - #define __LIMA_SCHED_H__ - - #include -+#include - - struct lima_vm; - -+struct lima_sched_error_task { -+ struct list_head list; -+ void *data; -+ u32 size; -+}; -+ - struct lima_sched_task { - struct drm_sched_job base; - --- -2.17.1 - - -From 3b95414439abca4e9129238481a36ee9025a8889 Mon Sep 17 00:00:00 2001 -From: Qiang Yu -Date: Sat, 22 Feb 2020 10:42:09 +0800 -Subject: [PATCH] drm/lima: add error sysfs to export error task dump - -Export /sys/class/drm/cardX/device/error sysfs for user read out -error task dump file. - -Tested-by: Andreas Baierl -Reviewed-by: Vasily Khoruzhick -Signed-off-by: Qiang Yu ---- - drivers/gpu/drm/lima/lima_drv.c | 94 +++++++++++++++++++++++++++++++++ - 1 file changed, 94 insertions(+) - -diff --git a/drivers/gpu/drm/lima/lima_drv.c b/drivers/gpu/drm/lima/lima_drv.c -index e235d4545b6c..97ed70c36340 100644 ---- a/drivers/gpu/drm/lima/lima_drv.c -+++ b/drivers/gpu/drm/lima/lima_drv.c -@@ -276,6 +276,93 @@ static struct drm_driver lima_drm_driver = { - .gem_prime_mmap = drm_gem_prime_mmap, - }; - -+struct lima_block_reader { -+ void *dst; -+ size_t base; -+ size_t count; -+ size_t off; -+ ssize_t read; -+}; -+ -+static bool lima_read_block(struct lima_block_reader *reader, -+ void *src, size_t src_size) -+{ -+ size_t max_off = reader->base + src_size; -+ -+ if (reader->off < max_off) { -+ size_t size = min_t(size_t, max_off - reader->off, -+ reader->count); -+ -+ memcpy(reader->dst, src + (reader->off - reader->base), size); -+ -+ reader->dst += size; -+ reader->off += size; -+ reader->read += size; -+ reader->count -= size; -+ } -+ -+ reader->base = max_off; -+ -+ return !!reader->count; -+} -+ -+static ssize_t lima_error_state_read(struct file *filp, struct kobject *kobj, -+ struct bin_attribute *attr, char *buf, -+ loff_t off, size_t count) -+{ -+ struct device *dev = kobj_to_dev(kobj); -+ struct lima_device *ldev = dev_get_drvdata(dev); -+ struct lima_sched_error_task *et; -+ struct lima_block_reader reader = { -+ .dst = buf, -+ .count = count, -+ .off = off, -+ }; -+ -+ mutex_lock(&ldev->error_task_list_lock); -+ -+ if (lima_read_block(&reader, &ldev->dump, sizeof(ldev->dump))) { -+ list_for_each_entry(et, &ldev->error_task_list, list) { -+ if (!lima_read_block(&reader, et->data, et->size)) -+ break; -+ } -+ } -+ -+ mutex_unlock(&ldev->error_task_list_lock); -+ return reader.read; -+} -+ -+static ssize_t lima_error_state_write(struct file *file, struct kobject *kobj, -+ struct bin_attribute *attr, char *buf, -+ loff_t off, size_t count) -+{ -+ struct device *dev = kobj_to_dev(kobj); -+ struct lima_device *ldev = dev_get_drvdata(dev); -+ struct lima_sched_error_task *et, *tmp; -+ -+ mutex_lock(&ldev->error_task_list_lock); -+ -+ list_for_each_entry_safe(et, tmp, &ldev->error_task_list, list) { -+ list_del(&et->list); -+ kvfree(et); -+ } -+ -+ ldev->dump.size = 0; -+ ldev->dump.num_tasks = 0; -+ -+ mutex_unlock(&ldev->error_task_list_lock); -+ -+ return count; -+} -+ -+static const struct bin_attribute lima_error_state_attr = { -+ .attr.name = "error", -+ .attr.mode = 0600, -+ .size = 0, -+ .read = lima_error_state_read, -+ .write = lima_error_state_write, -+}; -+ - static int lima_pdev_probe(struct platform_device *pdev) - { - struct lima_device *ldev; -@@ -318,6 +405,11 @@ static int lima_pdev_probe(struct platform_device *pdev) - if (err < 0) - goto err_out2; - -+ platform_set_drvdata(pdev, ldev); -+ -+ if (sysfs_create_bin_file(&ldev->dev->kobj, &lima_error_state_attr)) -+ dev_warn(ldev->dev, "fail to create error state sysfs\n"); -+ - return 0; - - err_out2: -@@ -334,6 +426,8 @@ static int lima_pdev_remove(struct platform_device *pdev) - struct lima_device *ldev = platform_get_drvdata(pdev); - struct drm_device *ddev = ldev->ddev; - -+ sysfs_remove_bin_file(&ldev->dev->kobj, &lima_error_state_attr); -+ platform_set_drvdata(pdev, NULL); - drm_dev_unregister(ddev); - lima_device_fini(ldev); - drm_dev_put(ddev); --- -2.17.1 - - -From e58efe898da54ddc1148539961ef3aeefe19fc80 Mon Sep 17 00:00:00 2001 -From: Qiang Yu -Date: Sat, 7 Mar 2020 21:54:38 +0800 -Subject: [PATCH] drm/lima: add trace point for tasks - -track lima task start which can be combined with -dma_fence_signal to identify task execution time. - -example command to record: - -trace-cmd record -i \ - -e "lima:lima_task_submit" -e "lima:lima_task_run" \ - -e "*fence:*fence_signaled" -e "drm:drm_vblank_event" \ - -e "drm:drm_vblank_event_queued" sleep 4 - -Reviewed-by: Vasily Khoruzhick -Signed-off-by: Qiang Yu ---- - drivers/gpu/drm/lima/Makefile | 3 +- - drivers/gpu/drm/lima/lima_sched.c | 5 +++- - drivers/gpu/drm/lima/lima_sched.h | 1 + - drivers/gpu/drm/lima/lima_trace.c | 7 +++++ - drivers/gpu/drm/lima/lima_trace.h | 50 +++++++++++++++++++++++++++++++ - 5 files changed, 64 insertions(+), 2 deletions(-) - create mode 100644 drivers/gpu/drm/lima/lima_trace.c - create mode 100644 drivers/gpu/drm/lima/lima_trace.h - -diff --git a/drivers/gpu/drm/lima/Makefile b/drivers/gpu/drm/lima/Makefile -index a85444b0a1d4..6e7b788408e8 100644 ---- a/drivers/gpu/drm/lima/Makefile -+++ b/drivers/gpu/drm/lima/Makefile -@@ -14,6 +14,7 @@ lima-y := \ - lima_sched.o \ - lima_ctx.o \ - lima_dlbu.o \ -- lima_bcast.o -+ lima_bcast.o \ -+ lima_trace.o - - obj-$(CONFIG_DRM_LIMA) += lima.o -diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c -index 86192422a689..4fbf2c489507 100644 ---- a/drivers/gpu/drm/lima/lima_sched.c -+++ b/drivers/gpu/drm/lima/lima_sched.c -@@ -3,7 +3,6 @@ - - #include - #include --#include - #include - - #include "lima_drv.h" -@@ -12,6 +11,7 @@ - #include "lima_mmu.h" - #include "lima_l2_cache.h" - #include "lima_gem.h" -+#include "lima_trace.h" - - struct lima_fence { - struct dma_fence base; -@@ -177,6 +177,7 @@ struct dma_fence *lima_sched_context_queue_task(struct lima_sched_context *conte - { - struct dma_fence *fence = dma_fence_get(&task->base.s_fence->finished); - -+ trace_lima_task_submit(task); - drm_sched_entity_push_job(&task->base, &context->base); - return fence; - } -@@ -251,6 +252,8 @@ static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job) - if (last_vm) - lima_vm_put(last_vm); - -+ trace_lima_task_run(task); -+ - pipe->error = false; - pipe->task_run(pipe, task); - -diff --git a/drivers/gpu/drm/lima/lima_sched.h b/drivers/gpu/drm/lima/lima_sched.h -index a1496cb7bc41..02dfa14d7083 100644 ---- a/drivers/gpu/drm/lima/lima_sched.h -+++ b/drivers/gpu/drm/lima/lima_sched.h -@@ -6,6 +6,7 @@ - - #include - #include -+#include - - struct lima_vm; - -diff --git a/drivers/gpu/drm/lima/lima_trace.c b/drivers/gpu/drm/lima/lima_trace.c -new file mode 100644 -index 000000000000..ea1c7289bebc ---- /dev/null -+++ b/drivers/gpu/drm/lima/lima_trace.c -@@ -0,0 +1,7 @@ -+// SPDX-License-Identifier: GPL-2.0 OR MIT -+/* Copyright 2020 Qiang Yu */ -+ -+#include "lima_sched.h" -+ -+#define CREATE_TRACE_POINTS -+#include "lima_trace.h" -diff --git a/drivers/gpu/drm/lima/lima_trace.h b/drivers/gpu/drm/lima/lima_trace.h -new file mode 100644 -index 000000000000..3a430e93d384 ---- /dev/null -+++ b/drivers/gpu/drm/lima/lima_trace.h -@@ -0,0 +1,50 @@ -+/* SPDX-License-Identifier: GPL-2.0 OR MIT */ -+/* Copyright 2020 Qiang Yu */ -+ -+#if !defined(_LIMA_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) -+#define _LIMA_TRACE_H_ -+ -+#include -+ -+#undef TRACE_SYSTEM -+#define TRACE_SYSTEM lima -+#define TRACE_INCLUDE_FILE lima_trace -+ -+DECLARE_EVENT_CLASS(lima_task, -+ TP_PROTO(struct lima_sched_task *task), -+ TP_ARGS(task), -+ TP_STRUCT__entry( -+ __field(uint64_t, task_id) -+ __field(unsigned int, context) -+ __field(unsigned int, seqno) -+ __string(pipe, task->base.sched->name) -+ ), -+ -+ TP_fast_assign( -+ __entry->task_id = task->base.id; -+ __entry->context = task->base.s_fence->finished.context; -+ __entry->seqno = task->base.s_fence->finished.seqno; -+ __assign_str(pipe, task->base.sched->name) -+ ), -+ -+ TP_printk("task=%llu, context=%u seqno=%u pipe=%s", -+ __entry->task_id, __entry->context, __entry->seqno, -+ __get_str(pipe)) -+); -+ -+DEFINE_EVENT(lima_task, lima_task_submit, -+ TP_PROTO(struct lima_sched_task *task), -+ TP_ARGS(task) -+); -+ -+DEFINE_EVENT(lima_task, lima_task_run, -+ TP_PROTO(struct lima_sched_task *task), -+ TP_ARGS(task) -+); -+ -+#endif -+ -+/* This part must be outside protection */ -+#undef TRACE_INCLUDE_PATH -+#define TRACE_INCLUDE_PATH ../../drivers/gpu/drm/lima -+#include --- -2.17.1 - - -From f567d140f87225a04ba6c6035b4a0b79e816f9a9 Mon Sep 17 00:00:00 2001 -From: Martin Blumenstingl -Date: Thu, 19 Mar 2020 21:34:27 +0100 -Subject: [PATCH] drm/lima: Add optional devfreq and cooling device support - -Most platforms with a Mali-400 or Mali-450 GPU also have support for -changing the GPU clock frequency. Add devfreq support so the GPU clock -rate is updated based on the actual GPU usage when the -"operating-points-v2" property is present in the board.dts. - -The actual devfreq code is taken from panfrost_devfreq.c and modified so -it matches what the lima hardware needs: -- a call to dev_pm_opp_set_clkname() during initialization because there - are two clocks on Mali-4x0 IPs. "core" is the one that actually clocks - the GPU so we need to control it using devfreq. -- locking when reading or writing the devfreq statistics because (unlike - than panfrost) we have multiple PP and GP IRQs which may finish jobs - concurrently. - -Signed-off-by: Martin Blumenstingl -Signed-off-by: Qiang Yu ---- - drivers/gpu/drm/lima/Kconfig | 2 + - drivers/gpu/drm/lima/Makefile | 3 +- - drivers/gpu/drm/lima/lima_devfreq.c | 234 ++++++++++++++++++++++++++++ - drivers/gpu/drm/lima/lima_devfreq.h | 41 +++++ - drivers/gpu/drm/lima/lima_device.c | 4 + - drivers/gpu/drm/lima/lima_device.h | 3 + - drivers/gpu/drm/lima/lima_drv.c | 14 +- - drivers/gpu/drm/lima/lima_sched.c | 7 + - drivers/gpu/drm/lima/lima_sched.h | 3 + - 9 files changed, 308 insertions(+), 3 deletions(-) - create mode 100644 drivers/gpu/drm/lima/lima_devfreq.c - create mode 100644 drivers/gpu/drm/lima/lima_devfreq.h - -diff --git a/drivers/gpu/drm/lima/Kconfig b/drivers/gpu/drm/lima/Kconfig -index d589f09d04d9..fa1d4f5df31e 100644 ---- a/drivers/gpu/drm/lima/Kconfig -+++ b/drivers/gpu/drm/lima/Kconfig -@@ -10,5 +10,7 @@ config DRM_LIMA - depends on OF - select DRM_SCHED - select DRM_GEM_SHMEM_HELPER -+ select PM_DEVFREQ -+ select DEVFREQ_GOV_SIMPLE_ONDEMAND - help - DRM driver for ARM Mali 400/450 GPUs. -diff --git a/drivers/gpu/drm/lima/Makefile b/drivers/gpu/drm/lima/Makefile -index 6e7b788408e8..ca2097b8e1ad 100644 ---- a/drivers/gpu/drm/lima/Makefile -+++ b/drivers/gpu/drm/lima/Makefile -@@ -15,6 +15,7 @@ lima-y := \ - lima_ctx.o \ - lima_dlbu.o \ - lima_bcast.o \ -- lima_trace.o -+ lima_trace.o \ -+ lima_devfreq.o - - obj-$(CONFIG_DRM_LIMA) += lima.o -diff --git a/drivers/gpu/drm/lima/lima_devfreq.c b/drivers/gpu/drm/lima/lima_devfreq.c -new file mode 100644 -index 000000000000..8c4d21d07529 ---- /dev/null -+++ b/drivers/gpu/drm/lima/lima_devfreq.c -@@ -0,0 +1,234 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright 2020 Martin Blumenstingl -+ * -+ * Based on panfrost_devfreq.c: -+ * Copyright 2019 Collabora ltd. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "lima_device.h" -+#include "lima_devfreq.h" -+ -+static void lima_devfreq_update_utilization(struct lima_devfreq *devfreq) -+{ -+ ktime_t now, last; -+ -+ now = ktime_get(); -+ last = devfreq->time_last_update; -+ -+ if (devfreq->busy_count > 0) -+ devfreq->busy_time += ktime_sub(now, last); -+ else -+ devfreq->idle_time += ktime_sub(now, last); -+ -+ devfreq->time_last_update = now; -+} -+ -+static int lima_devfreq_target(struct device *dev, unsigned long *freq, -+ u32 flags) -+{ -+ struct dev_pm_opp *opp; -+ int err; -+ -+ opp = devfreq_recommended_opp(dev, freq, flags); -+ if (IS_ERR(opp)) -+ return PTR_ERR(opp); -+ dev_pm_opp_put(opp); -+ -+ err = dev_pm_opp_set_rate(dev, *freq); -+ if (err) -+ return err; -+ -+ return 0; -+} -+ -+static void lima_devfreq_reset(struct lima_devfreq *devfreq) -+{ -+ devfreq->busy_time = 0; -+ devfreq->idle_time = 0; -+ devfreq->time_last_update = ktime_get(); -+} -+ -+static int lima_devfreq_get_dev_status(struct device *dev, -+ struct devfreq_dev_status *status) -+{ -+ struct lima_device *ldev = dev_get_drvdata(dev); -+ struct lima_devfreq *devfreq = &ldev->devfreq; -+ unsigned long irqflags; -+ -+ status->current_frequency = clk_get_rate(ldev->clk_gpu); -+ -+ spin_lock_irqsave(&devfreq->lock, irqflags); -+ -+ lima_devfreq_update_utilization(devfreq); -+ -+ status->total_time = ktime_to_ns(ktime_add(devfreq->busy_time, -+ devfreq->idle_time)); -+ status->busy_time = ktime_to_ns(devfreq->busy_time); -+ -+ lima_devfreq_reset(devfreq); -+ -+ spin_unlock_irqrestore(&devfreq->lock, irqflags); -+ -+ dev_dbg(ldev->dev, "busy %lu total %lu %lu %% freq %lu MHz\n", -+ status->busy_time, status->total_time, -+ status->busy_time / (status->total_time / 100), -+ status->current_frequency / 1000 / 1000); -+ -+ return 0; -+} -+ -+static struct devfreq_dev_profile lima_devfreq_profile = { -+ .polling_ms = 50, /* ~3 frames */ -+ .target = lima_devfreq_target, -+ .get_dev_status = lima_devfreq_get_dev_status, -+}; -+ -+void lima_devfreq_fini(struct lima_device *ldev) -+{ -+ struct lima_devfreq *devfreq = &ldev->devfreq; -+ -+ if (devfreq->cooling) { -+ devfreq_cooling_unregister(devfreq->cooling); -+ devfreq->cooling = NULL; -+ } -+ -+ if (devfreq->devfreq) { -+ devm_devfreq_remove_device(&ldev->pdev->dev, -+ devfreq->devfreq); -+ devfreq->devfreq = NULL; -+ } -+ -+ if (devfreq->opp_of_table_added) { -+ dev_pm_opp_of_remove_table(&ldev->pdev->dev); -+ devfreq->opp_of_table_added = false; -+ } -+ -+ if (devfreq->regulators_opp_table) { -+ dev_pm_opp_put_regulators(devfreq->regulators_opp_table); -+ devfreq->regulators_opp_table = NULL; -+ } -+ -+ if (devfreq->clkname_opp_table) { -+ dev_pm_opp_put_clkname(devfreq->clkname_opp_table); -+ devfreq->clkname_opp_table = NULL; -+ } -+} -+ -+int lima_devfreq_init(struct lima_device *ldev) -+{ -+ struct thermal_cooling_device *cooling; -+ struct device *dev = &ldev->pdev->dev; -+ struct opp_table *opp_table; -+ struct devfreq *devfreq; -+ struct lima_devfreq *ldevfreq = &ldev->devfreq; -+ struct dev_pm_opp *opp; -+ unsigned long cur_freq; -+ int ret; -+ -+ if (!device_property_present(dev, "operating-points-v2")) -+ /* Optional, continue without devfreq */ -+ return 0; -+ -+ spin_lock_init(&ldevfreq->lock); -+ -+ opp_table = dev_pm_opp_set_clkname(dev, "core"); -+ if (IS_ERR(opp_table)) { -+ ret = PTR_ERR(opp_table); -+ goto err_fini; -+ } -+ -+ ldevfreq->clkname_opp_table = opp_table; -+ -+ opp_table = dev_pm_opp_set_regulators(dev, -+ (const char *[]){ "mali" }, -+ 1); -+ if (IS_ERR(opp_table)) { -+ ret = PTR_ERR(opp_table); -+ -+ /* Continue if the optional regulator is missing */ -+ if (ret != -ENODEV) -+ goto err_fini; -+ } else { -+ ldevfreq->regulators_opp_table = opp_table; -+ } -+ -+ ret = dev_pm_opp_of_add_table(dev); -+ if (ret) -+ goto err_fini; -+ ldevfreq->opp_of_table_added = true; -+ -+ lima_devfreq_reset(ldevfreq); -+ -+ cur_freq = clk_get_rate(ldev->clk_gpu); -+ -+ opp = devfreq_recommended_opp(dev, &cur_freq, 0); -+ if (IS_ERR(opp)) { -+ ret = PTR_ERR(opp); -+ goto err_fini; -+ } -+ -+ lima_devfreq_profile.initial_freq = cur_freq; -+ dev_pm_opp_put(opp); -+ -+ devfreq = devm_devfreq_add_device(dev, &lima_devfreq_profile, -+ DEVFREQ_GOV_SIMPLE_ONDEMAND, NULL); -+ if (IS_ERR(devfreq)) { -+ dev_err(dev, "Couldn't initialize GPU devfreq\n"); -+ ret = PTR_ERR(devfreq); -+ goto err_fini; -+ } -+ -+ ldevfreq->devfreq = devfreq; -+ -+ cooling = of_devfreq_cooling_register(dev->of_node, devfreq); -+ if (IS_ERR(cooling)) -+ dev_info(dev, "Failed to register cooling device\n"); -+ else -+ ldevfreq->cooling = cooling; -+ -+ return 0; -+ -+err_fini: -+ lima_devfreq_fini(ldev); -+ return ret; -+} -+ -+void lima_devfreq_record_busy(struct lima_devfreq *devfreq) -+{ -+ unsigned long irqflags; -+ -+ if (!devfreq->devfreq) -+ return; -+ -+ spin_lock_irqsave(&devfreq->lock, irqflags); -+ -+ lima_devfreq_update_utilization(devfreq); -+ -+ devfreq->busy_count++; -+ -+ spin_unlock_irqrestore(&devfreq->lock, irqflags); -+} -+ -+void lima_devfreq_record_idle(struct lima_devfreq *devfreq) -+{ -+ unsigned long irqflags; -+ -+ if (!devfreq->devfreq) -+ return; -+ -+ spin_lock_irqsave(&devfreq->lock, irqflags); -+ -+ lima_devfreq_update_utilization(devfreq); -+ -+ WARN_ON(--devfreq->busy_count < 0); -+ -+ spin_unlock_irqrestore(&devfreq->lock, irqflags); -+} -diff --git a/drivers/gpu/drm/lima/lima_devfreq.h b/drivers/gpu/drm/lima/lima_devfreq.h -new file mode 100644 -index 000000000000..8d71ba9fb22a ---- /dev/null -+++ b/drivers/gpu/drm/lima/lima_devfreq.h -@@ -0,0 +1,41 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* Copyright 2020 Martin Blumenstingl */ -+ -+#ifndef __LIMA_DEVFREQ_H__ -+#define __LIMA_DEVFREQ_H__ -+ -+#include -+#include -+ -+struct devfreq; -+struct opp_table; -+struct thermal_cooling_device; -+ -+struct lima_device; -+ -+struct lima_devfreq { -+ struct devfreq *devfreq; -+ struct opp_table *clkname_opp_table; -+ struct opp_table *regulators_opp_table; -+ struct thermal_cooling_device *cooling; -+ bool opp_of_table_added; -+ -+ ktime_t busy_time; -+ ktime_t idle_time; -+ ktime_t time_last_update; -+ int busy_count; -+ /* -+ * Protect busy_time, idle_time, time_last_update and busy_count -+ * because these can be updated concurrently, for example by the GP -+ * and PP interrupts. -+ */ -+ spinlock_t lock; -+}; -+ -+int lima_devfreq_init(struct lima_device *ldev); -+void lima_devfreq_fini(struct lima_device *ldev); -+ -+void lima_devfreq_record_busy(struct lima_devfreq *devfreq); -+void lima_devfreq_record_idle(struct lima_devfreq *devfreq); -+ -+#endif -diff --git a/drivers/gpu/drm/lima/lima_device.c b/drivers/gpu/drm/lima/lima_device.c -index 42a00171fea5..247f51fd40a2 100644 ---- a/drivers/gpu/drm/lima/lima_device.c -+++ b/drivers/gpu/drm/lima/lima_device.c -@@ -214,6 +214,8 @@ static int lima_init_gp_pipe(struct lima_device *dev) - struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_gp; - int err; - -+ pipe->ldev = dev; -+ - err = lima_sched_pipe_init(pipe, "gp"); - if (err) - return err; -@@ -244,6 +246,8 @@ static int lima_init_pp_pipe(struct lima_device *dev) - struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_pp; - int err, i; - -+ pipe->ldev = dev; -+ - err = lima_sched_pipe_init(pipe, "pp"); - if (err) - return err; -diff --git a/drivers/gpu/drm/lima/lima_device.h b/drivers/gpu/drm/lima/lima_device.h -index f17173f47f26..06fd9636dd72 100644 ---- a/drivers/gpu/drm/lima/lima_device.h -+++ b/drivers/gpu/drm/lima/lima_device.h -@@ -11,6 +11,7 @@ - - #include "lima_sched.h" - #include "lima_dump.h" -+#include "lima_devfreq.h" - - enum lima_gpu_id { - lima_gpu_mali400 = 0, -@@ -98,6 +99,8 @@ struct lima_device { - u32 *dlbu_cpu; - dma_addr_t dlbu_dma; - -+ struct lima_devfreq devfreq; -+ - /* debug info */ - struct lima_dump_head dump; - struct list_head error_task_list; -diff --git a/drivers/gpu/drm/lima/lima_drv.c b/drivers/gpu/drm/lima/lima_drv.c -index 97ed70c36340..bbbdc8455e2f 100644 ---- a/drivers/gpu/drm/lima/lima_drv.c -+++ b/drivers/gpu/drm/lima/lima_drv.c -@@ -10,6 +10,7 @@ - #include - #include - -+#include "lima_device.h" - #include "lima_drv.h" - #include "lima_gem.h" - #include "lima_vm.h" -@@ -397,13 +398,19 @@ static int lima_pdev_probe(struct platform_device *pdev) - if (err) - goto err_out1; - -+ err = lima_devfreq_init(ldev); -+ if (err) { -+ dev_err(&pdev->dev, "Fatal error during devfreq init\n"); -+ goto err_out2; -+ } -+ - /* - * Register the DRM device with the core and the connectors with - * sysfs. - */ - err = drm_dev_register(ddev, 0); - if (err < 0) -- goto err_out2; -+ goto err_out3; - - platform_set_drvdata(pdev, ldev); - -@@ -412,8 +419,10 @@ static int lima_pdev_probe(struct platform_device *pdev) - - return 0; - --err_out2: -+err_out3: - lima_device_fini(ldev); -+err_out2: -+ lima_devfreq_fini(ldev); - err_out1: - drm_dev_put(ddev); - err_out0: -@@ -429,6 +438,7 @@ static int lima_pdev_remove(struct platform_device *pdev) - sysfs_remove_bin_file(&ldev->dev->kobj, &lima_error_state_attr); - platform_set_drvdata(pdev, NULL); - drm_dev_unregister(ddev); -+ lima_devfreq_fini(ldev); - lima_device_fini(ldev); - drm_dev_put(ddev); - lima_sched_slab_fini(); -diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c -index 4fbf2c489507..a2db1c937424 100644 ---- a/drivers/gpu/drm/lima/lima_sched.c -+++ b/drivers/gpu/drm/lima/lima_sched.c -@@ -5,6 +5,7 @@ - #include - #include - -+#include "lima_devfreq.h" - #include "lima_drv.h" - #include "lima_sched.h" - #include "lima_vm.h" -@@ -216,6 +217,8 @@ static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job) - */ - ret = dma_fence_get(task->fence); - -+ lima_devfreq_record_busy(&pipe->ldev->devfreq); -+ - pipe->current_task = task; - - /* this is needed for MMU to work correctly, otherwise GP/PP -@@ -418,6 +421,8 @@ static void lima_sched_timedout_job(struct drm_sched_job *job) - pipe->current_vm = NULL; - pipe->current_task = NULL; - -+ lima_devfreq_record_idle(&pipe->ldev->devfreq); -+ - drm_sched_resubmit_jobs(&pipe->base); - drm_sched_start(&pipe->base, true); - } -@@ -497,5 +502,7 @@ void lima_sched_pipe_task_done(struct lima_sched_pipe *pipe) - } else { - pipe->task_fini(pipe); - dma_fence_signal(task->fence); -+ -+ lima_devfreq_record_idle(&pipe->ldev->devfreq); - } - } -diff --git a/drivers/gpu/drm/lima/lima_sched.h b/drivers/gpu/drm/lima/lima_sched.h -index 02dfa14d7083..90f03c48ef4a 100644 ---- a/drivers/gpu/drm/lima/lima_sched.h -+++ b/drivers/gpu/drm/lima/lima_sched.h -@@ -8,6 +8,7 @@ - #include - #include - -+struct lima_device; - struct lima_vm; - - struct lima_sched_error_task { -@@ -52,6 +53,8 @@ struct lima_sched_pipe { - u32 fence_seqno; - spinlock_t fence_lock; - -+ struct lima_device *ldev; -+ - struct lima_sched_task *current_task; - struct lima_vm *current_vm; - --- -2.17.1 - - -From 60e8ac9f8b772f5f3cbab5e361531d625444a320 Mon Sep 17 00:00:00 2001 -From: Robin Murphy -Date: Tue, 21 Apr 2020 23:51:36 +0100 -Subject: [PATCH] drm/lima: Clean up IRQ warnings - -Use the optional form of platform_get_irq() for blocks that legitimately -may not be present, to avoid getting an annoying barrage of spurious -warnings for non-existent PPs on configurations like Mali-450 MP2. - -Signed-off-by: Robin Murphy -Signed-off-by: Qiang Yu ---- - drivers/gpu/drm/lima/lima_device.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/lima/lima_device.c b/drivers/gpu/drm/lima/lima_device.c -index 247f51fd40a2..c334d297796a 100644 ---- a/drivers/gpu/drm/lima/lima_device.c -+++ b/drivers/gpu/drm/lima/lima_device.c -@@ -171,8 +171,10 @@ static void lima_regulator_fini(struct lima_device *dev) - - static int lima_init_ip(struct lima_device *dev, int index) - { -+ struct platform_device *pdev = to_platform_device(dev->dev); - struct lima_ip_desc *desc = lima_ip_desc + index; - struct lima_ip *ip = dev->ip + index; -+ const char *irq_name = desc->irq_name; - int offset = desc->offset[dev->id]; - bool must = desc->must_have[dev->id]; - int err; -@@ -183,8 +185,9 @@ static int lima_init_ip(struct lima_device *dev, int index) - ip->dev = dev; - ip->id = index; - ip->iomem = dev->iomem + offset; -- if (desc->irq_name) { -- err = platform_get_irq_byname(dev->pdev, desc->irq_name); -+ if (irq_name) { -+ err = must ? platform_get_irq_byname(pdev, irq_name) : -+ platform_get_irq_byname_optional(pdev, irq_name); - if (err < 0) - goto out; - ip->irq = err; --- -2.17.1 - - -From 8bb48350b7a927e98b59299ba82c4231fef9816c Mon Sep 17 00:00:00 2001 -From: Robin Murphy -Date: Tue, 21 Apr 2020 23:51:37 +0100 -Subject: [PATCH] drm/lima: Clean up redundant pdev pointer - -There's no point explicitly tracking the platform device when it can be -trivially derived from the regular device pointer in the couple of -places it's ever used. - -Signed-off-by: Robin Murphy -Signed-off-by: Qiang Yu ---- - drivers/gpu/drm/lima/lima_devfreq.c | 7 +++---- - drivers/gpu/drm/lima/lima_device.c | 5 ++--- - drivers/gpu/drm/lima/lima_device.h | 1 - - drivers/gpu/drm/lima/lima_drv.c | 1 - - 4 files changed, 5 insertions(+), 9 deletions(-) - -diff --git a/drivers/gpu/drm/lima/lima_devfreq.c b/drivers/gpu/drm/lima/lima_devfreq.c -index 8c4d21d07529..1d479b5924fe 100644 ---- a/drivers/gpu/drm/lima/lima_devfreq.c -+++ b/drivers/gpu/drm/lima/lima_devfreq.c -@@ -101,13 +101,12 @@ void lima_devfreq_fini(struct lima_device *ldev) - } - - if (devfreq->devfreq) { -- devm_devfreq_remove_device(&ldev->pdev->dev, -- devfreq->devfreq); -+ devm_devfreq_remove_device(ldev->dev, devfreq->devfreq); - devfreq->devfreq = NULL; - } - - if (devfreq->opp_of_table_added) { -- dev_pm_opp_of_remove_table(&ldev->pdev->dev); -+ dev_pm_opp_of_remove_table(ldev->dev); - devfreq->opp_of_table_added = false; - } - -@@ -125,7 +124,7 @@ void lima_devfreq_fini(struct lima_device *ldev) - int lima_devfreq_init(struct lima_device *ldev) - { - struct thermal_cooling_device *cooling; -- struct device *dev = &ldev->pdev->dev; -+ struct device *dev = ldev->dev; - struct opp_table *opp_table; - struct devfreq *devfreq; - struct lima_devfreq *ldevfreq = &ldev->devfreq; -diff --git a/drivers/gpu/drm/lima/lima_device.c b/drivers/gpu/drm/lima/lima_device.c -index c334d297796a..29285dedd124 100644 ---- a/drivers/gpu/drm/lima/lima_device.c -+++ b/drivers/gpu/drm/lima/lima_device.c -@@ -297,8 +297,8 @@ static void lima_fini_pp_pipe(struct lima_device *dev) - - int lima_device_init(struct lima_device *ldev) - { -+ struct platform_device *pdev = to_platform_device(ldev->dev); - int err, i; -- struct resource *res; - - dma_set_coherent_mask(ldev->dev, DMA_BIT_MASK(32)); - -@@ -329,8 +329,7 @@ int lima_device_init(struct lima_device *ldev) - } else - ldev->va_end = LIMA_VA_RESERVE_END; - -- res = platform_get_resource(ldev->pdev, IORESOURCE_MEM, 0); -- ldev->iomem = devm_ioremap_resource(ldev->dev, res); -+ ldev->iomem = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(ldev->iomem)) { - dev_err(ldev->dev, "fail to ioremap iomem\n"); - err = PTR_ERR(ldev->iomem); -diff --git a/drivers/gpu/drm/lima/lima_device.h b/drivers/gpu/drm/lima/lima_device.h -index 06fd9636dd72..99b1fb147dad 100644 ---- a/drivers/gpu/drm/lima/lima_device.h -+++ b/drivers/gpu/drm/lima/lima_device.h -@@ -76,7 +76,6 @@ enum lima_pipe_id { - struct lima_device { - struct device *dev; - struct drm_device *ddev; -- struct platform_device *pdev; - - enum lima_gpu_id id; - u32 gp_version; -diff --git a/drivers/gpu/drm/lima/lima_drv.c b/drivers/gpu/drm/lima/lima_drv.c -index bbbdc8455e2f..4e5dd75822c0 100644 ---- a/drivers/gpu/drm/lima/lima_drv.c -+++ b/drivers/gpu/drm/lima/lima_drv.c -@@ -380,7 +380,6 @@ static int lima_pdev_probe(struct platform_device *pdev) - goto err_out0; - } - -- ldev->pdev = pdev; - ldev->dev = &pdev->dev; - ldev->id = (enum lima_gpu_id)of_device_get_match_data(&pdev->dev); - --- -2.17.1 - - -From 82f5f9c4e3bca70b8c6c745be7a0c794d0fded53 Mon Sep 17 00:00:00 2001 -From: Qiang Yu -Date: Tue, 21 Apr 2020 21:35:42 +0800 -Subject: [PATCH] drm/lima: use module_platform_driver helper - -Simplify module init/exit with module_platform_driver. - -Tested-by: Bhushan Shah -Reviewed-by: Vasily Khoruzhick -Signed-off-by: Qiang Yu ---- - drivers/gpu/drm/lima/lima_drv.c | 12 +----------- - 1 file changed, 1 insertion(+), 11 deletions(-) - -diff --git a/drivers/gpu/drm/lima/lima_drv.c b/drivers/gpu/drm/lima/lima_drv.c -index 4e5dd75822c0..3d63d496cfc2 100644 ---- a/drivers/gpu/drm/lima/lima_drv.c -+++ b/drivers/gpu/drm/lima/lima_drv.c -@@ -460,17 +460,7 @@ static struct platform_driver lima_platform_driver = { - }, - }; - --static int __init lima_init(void) --{ -- return platform_driver_register(&lima_platform_driver); --} --module_init(lima_init); -- --static void __exit lima_exit(void) --{ -- platform_driver_unregister(&lima_platform_driver); --} --module_exit(lima_exit); -+module_platform_driver(lima_platform_driver); - - MODULE_AUTHOR("Lima Project Developers"); - MODULE_DESCRIPTION("Lima DRM Driver"); --- -2.17.1 - - -From 2cb93a9b51b7c7105fc6baa0799c9474693c15a6 Mon Sep 17 00:00:00 2001 -From: Qiang Yu -Date: Tue, 21 Apr 2020 21:35:43 +0800 -Subject: [PATCH] drm/lima: print process name and pid when task error - -When error task list is full, print the process info where -the error task come from for debug usage. - -Tested-by: Bhushan Shah -Reviewed-by: Vasily Khoruzhick -Signed-off-by: Qiang Yu ---- - drivers/gpu/drm/lima/lima_sched.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c -index a2db1c937424..387f9439450a 100644 ---- a/drivers/gpu/drm/lima/lima_sched.c -+++ b/drivers/gpu/drm/lima/lima_sched.c -@@ -285,7 +285,8 @@ static void lima_sched_build_error_task_list(struct lima_sched_task *task) - mutex_lock(&dev->error_task_list_lock); - - if (dev->dump.num_tasks >= lima_max_error_tasks) { -- dev_info(dev->dev, "fail to save task state: error task list is full\n"); -+ dev_info(dev->dev, "fail to save task state from %s pid %d: " -+ "error task list is full\n", ctx->pname, ctx->pid); - goto out; - } - --- -2.17.1 - - -From 392cc15d77ef4f3dacff6b991690882051b683ad Mon Sep 17 00:00:00 2001 -From: Qiang Yu -Date: Tue, 21 Apr 2020 21:35:44 +0800 -Subject: [PATCH] drm/lima: check vm != NULL in lima_vm_put - -No need to handle this check before calling lima_vm_put. - -Tested-by: Bhushan Shah -Reviewed-by: Vasily Khoruzhick -Signed-off-by: Qiang Yu ---- - drivers/gpu/drm/lima/lima_sched.c | 7 ++----- - drivers/gpu/drm/lima/lima_vm.h | 3 ++- - 2 files changed, 4 insertions(+), 6 deletions(-) - -diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c -index 387f9439450a..3ac5797e31fc 100644 ---- a/drivers/gpu/drm/lima/lima_sched.c -+++ b/drivers/gpu/drm/lima/lima_sched.c -@@ -252,8 +252,7 @@ static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job) - lima_mmu_switch_vm(pipe->mmu[i], vm); - } - -- if (last_vm) -- lima_vm_put(last_vm); -+ lima_vm_put(last_vm); - - trace_lima_task_run(task); - -@@ -416,9 +415,7 @@ static void lima_sched_timedout_job(struct drm_sched_job *job) - lima_mmu_page_fault_resume(pipe->mmu[i]); - } - -- if (pipe->current_vm) -- lima_vm_put(pipe->current_vm); -- -+ lima_vm_put(pipe->current_vm); - pipe->current_vm = NULL; - pipe->current_task = NULL; - -diff --git a/drivers/gpu/drm/lima/lima_vm.h b/drivers/gpu/drm/lima/lima_vm.h -index 22aeec77d84d..3a7c74822d8b 100644 ---- a/drivers/gpu/drm/lima/lima_vm.h -+++ b/drivers/gpu/drm/lima/lima_vm.h -@@ -54,7 +54,8 @@ static inline struct lima_vm *lima_vm_get(struct lima_vm *vm) - - static inline void lima_vm_put(struct lima_vm *vm) - { -- kref_put(&vm->refcount, lima_vm_release); -+ if (vm) -+ kref_put(&vm->refcount, lima_vm_release); - } - - void lima_vm_print(struct lima_vm *vm); --- -2.17.1 - - -From 60fd3f2cb896fe4727ad7da32aaa85b4baedb097 Mon Sep 17 00:00:00 2001 -From: Qiang Yu -Date: Tue, 21 Apr 2020 21:35:45 +0800 -Subject: [PATCH] drm/lima: always set page directory when switch vm - -We need to flush TLB anyway before every task start, and the -page directory will be set to empty vm after suspend/resume, -so always set it to the task vm even no ctx switch happens. - -Tested-by: Bhushan Shah -Reviewed-by: Vasily Khoruzhick -Signed-off-by: Qiang Yu ---- - drivers/gpu/drm/lima/lima_mmu.c | 3 +-- - drivers/gpu/drm/lima/lima_sched.c | 14 ++++---------- - 2 files changed, 5 insertions(+), 12 deletions(-) - -diff --git a/drivers/gpu/drm/lima/lima_mmu.c b/drivers/gpu/drm/lima/lima_mmu.c -index f79d2af427e7..c26b751b0f9d 100644 ---- a/drivers/gpu/drm/lima/lima_mmu.c -+++ b/drivers/gpu/drm/lima/lima_mmu.c -@@ -113,8 +113,7 @@ void lima_mmu_switch_vm(struct lima_ip *ip, struct lima_vm *vm) - LIMA_MMU_STATUS, v, - v & LIMA_MMU_STATUS_STALL_ACTIVE); - -- if (vm) -- mmu_write(LIMA_MMU_DTE_ADDR, vm->pd.dma); -+ mmu_write(LIMA_MMU_DTE_ADDR, vm->pd.dma); - - /* flush the TLB */ - mmu_write(LIMA_MMU_COMMAND, LIMA_MMU_COMMAND_ZAP_CACHE); -diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c -index 3ac5797e31fc..eb46db0717cd 100644 ---- a/drivers/gpu/drm/lima/lima_sched.c -+++ b/drivers/gpu/drm/lima/lima_sched.c -@@ -200,7 +200,6 @@ static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job) - struct lima_sched_pipe *pipe = to_lima_pipe(job->sched); - struct lima_fence *fence; - struct dma_fence *ret; -- struct lima_vm *vm = NULL, *last_vm = NULL; - int i; - - /* after GPU reset */ -@@ -239,21 +238,16 @@ static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job) - for (i = 0; i < pipe->num_l2_cache; i++) - lima_l2_cache_flush(pipe->l2_cache[i]); - -- if (task->vm != pipe->current_vm) { -- vm = lima_vm_get(task->vm); -- last_vm = pipe->current_vm; -- pipe->current_vm = task->vm; -- } -+ lima_vm_put(pipe->current_vm); -+ pipe->current_vm = lima_vm_get(task->vm); - - if (pipe->bcast_mmu) -- lima_mmu_switch_vm(pipe->bcast_mmu, vm); -+ lima_mmu_switch_vm(pipe->bcast_mmu, pipe->current_vm); - else { - for (i = 0; i < pipe->num_mmu; i++) -- lima_mmu_switch_vm(pipe->mmu[i], vm); -+ lima_mmu_switch_vm(pipe->mmu[i], pipe->current_vm); - } - -- lima_vm_put(last_vm); -- - trace_lima_task_run(task); - - pipe->error = false; --- -2.17.1 - - -From e88c2e9bf4d246ef449323208fc731aad659fc43 Mon Sep 17 00:00:00 2001 -From: Qiang Yu -Date: Tue, 21 Apr 2020 21:35:46 +0800 -Subject: [PATCH] drm/lima: add lima_devfreq_resume/suspend - -Used for device resume/suspend in the following commits. - -Tested-by: Bhushan Shah -Reviewed-by: Vasily Khoruzhick -Signed-off-by: Qiang Yu ---- - drivers/gpu/drm/lima/lima_devfreq.c | 24 ++++++++++++++++++++++++ - drivers/gpu/drm/lima/lima_devfreq.h | 3 +++ - 2 files changed, 27 insertions(+) - -diff --git a/drivers/gpu/drm/lima/lima_devfreq.c b/drivers/gpu/drm/lima/lima_devfreq.c -index 1d479b5924fe..bbe02817721b 100644 ---- a/drivers/gpu/drm/lima/lima_devfreq.c -+++ b/drivers/gpu/drm/lima/lima_devfreq.c -@@ -231,3 +231,27 @@ void lima_devfreq_record_idle(struct lima_devfreq *devfreq) - - spin_unlock_irqrestore(&devfreq->lock, irqflags); - } -+ -+int lima_devfreq_resume(struct lima_devfreq *devfreq) -+{ -+ unsigned long irqflags; -+ -+ if (!devfreq->devfreq) -+ return 0; -+ -+ spin_lock_irqsave(&devfreq->lock, irqflags); -+ -+ lima_devfreq_reset(devfreq); -+ -+ spin_unlock_irqrestore(&devfreq->lock, irqflags); -+ -+ return devfreq_resume_device(devfreq->devfreq); -+} -+ -+int lima_devfreq_suspend(struct lima_devfreq *devfreq) -+{ -+ if (!devfreq->devfreq) -+ return 0; -+ -+ return devfreq_suspend_device(devfreq->devfreq); -+} -diff --git a/drivers/gpu/drm/lima/lima_devfreq.h b/drivers/gpu/drm/lima/lima_devfreq.h -index 8d71ba9fb22a..5eed2975a375 100644 ---- a/drivers/gpu/drm/lima/lima_devfreq.h -+++ b/drivers/gpu/drm/lima/lima_devfreq.h -@@ -38,4 +38,7 @@ void lima_devfreq_fini(struct lima_device *ldev); - void lima_devfreq_record_busy(struct lima_devfreq *devfreq); - void lima_devfreq_record_idle(struct lima_devfreq *devfreq); - -+int lima_devfreq_resume(struct lima_devfreq *devfreq); -+int lima_devfreq_suspend(struct lima_devfreq *devfreq); -+ - #endif --- -2.17.1 - - -From 1f828aa538ce8def9479aec4669b655ff7e9cbf0 Mon Sep 17 00:00:00 2001 -From: Qiang Yu -Date: Tue, 21 Apr 2020 21:35:47 +0800 -Subject: [PATCH] drm/lima: power down ip blocks when pmu exit - -Prepare resume/suspend PM. - -v2: -Fix lima_pmu_wait_cmd timeout when mali400 case. - -Tested-by: Bhushan Shah -Reviewed-by: Vasily Khoruzhick -Signed-off-by: Qiang Yu ---- - drivers/gpu/drm/lima/lima_device.h | 2 ++ - drivers/gpu/drm/lima/lima_pmu.c | 53 +++++++++++++++++++++++++++++- - 2 files changed, 54 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/lima/lima_device.h b/drivers/gpu/drm/lima/lima_device.h -index 99b1fb147dad..9cd2718079bd 100644 ---- a/drivers/gpu/drm/lima/lima_device.h -+++ b/drivers/gpu/drm/lima/lima_device.h -@@ -64,6 +64,8 @@ struct lima_ip { - bool async_reset; - /* l2 cache */ - spinlock_t lock; -+ /* pmu */ -+ u32 mask; - } data; - }; - -diff --git a/drivers/gpu/drm/lima/lima_pmu.c b/drivers/gpu/drm/lima/lima_pmu.c -index 571f6d661581..d476569f2043 100644 ---- a/drivers/gpu/drm/lima/lima_pmu.c -+++ b/drivers/gpu/drm/lima/lima_pmu.c -@@ -21,7 +21,7 @@ static int lima_pmu_wait_cmd(struct lima_ip *ip) - v, v & LIMA_PMU_INT_CMD_MASK, - 100, 100000); - if (err) { -- dev_err(dev->dev, "timeout wait pmd cmd\n"); -+ dev_err(dev->dev, "timeout wait pmu cmd\n"); - return err; - } - -@@ -29,6 +29,40 @@ static int lima_pmu_wait_cmd(struct lima_ip *ip) - return 0; - } - -+static u32 lima_pmu_get_ip_mask(struct lima_ip *ip) -+{ -+ struct lima_device *dev = ip->dev; -+ u32 ret = 0; -+ int i; -+ -+ ret |= LIMA_PMU_POWER_GP0_MASK; -+ -+ if (dev->id == lima_gpu_mali400) { -+ ret |= LIMA_PMU_POWER_L2_MASK; -+ for (i = 0; i < 4; i++) { -+ if (dev->ip[lima_ip_pp0 + i].present) -+ ret |= LIMA_PMU_POWER_PP_MASK(i); -+ } -+ } else { -+ if (dev->ip[lima_ip_pp0].present) -+ ret |= LIMA450_PMU_POWER_PP0_MASK; -+ for (i = lima_ip_pp1; i <= lima_ip_pp3; i++) { -+ if (dev->ip[i].present) { -+ ret |= LIMA450_PMU_POWER_PP13_MASK; -+ break; -+ } -+ } -+ for (i = lima_ip_pp4; i <= lima_ip_pp7; i++) { -+ if (dev->ip[i].present) { -+ ret |= LIMA450_PMU_POWER_PP47_MASK; -+ break; -+ } -+ } -+ } -+ -+ return ret; -+} -+ - int lima_pmu_init(struct lima_ip *ip) - { - int err; -@@ -56,5 +90,22 @@ int lima_pmu_init(struct lima_ip *ip) - - void lima_pmu_fini(struct lima_ip *ip) - { -+ u32 stat; -+ -+ if (!ip->data.mask) -+ ip->data.mask = lima_pmu_get_ip_mask(ip); - -+ stat = ~pmu_read(LIMA_PMU_STATUS) & ip->data.mask; -+ if (stat) { -+ pmu_write(LIMA_PMU_POWER_DOWN, stat); -+ -+ /* Don't wait for interrupt on Mali400 if all domains are -+ * powered off because the HW won't generate an interrupt -+ * in this case. -+ */ -+ if (ip->dev->id == lima_gpu_mali400) -+ pmu_write(LIMA_PMU_INT_CLEAR, LIMA_PMU_INT_CMD_MASK); -+ else -+ lima_pmu_wait_cmd(ip); -+ } - } --- -2.17.1 - - -From e7a53d7606fd2e3d6f513f4d8440e2243a9968ae Mon Sep 17 00:00:00 2001 -From: Qiang Yu -Date: Tue, 21 Apr 2020 21:35:48 +0800 -Subject: [PATCH] drm/lima: add resume/suspend callback for each ip - -For called when PM do resume/suspend. - -Tested-by: Bhushan Shah -Reviewed-by: Vasily Khoruzhick -Signed-off-by: Qiang Yu ---- - drivers/gpu/drm/lima/lima_bcast.c | 25 ++++++++++++--- - drivers/gpu/drm/lima/lima_bcast.h | 2 ++ - drivers/gpu/drm/lima/lima_device.c | 4 +++ - drivers/gpu/drm/lima/lima_device.h | 2 +- - drivers/gpu/drm/lima/lima_dlbu.c | 17 +++++++++- - drivers/gpu/drm/lima/lima_dlbu.h | 2 ++ - drivers/gpu/drm/lima/lima_gp.c | 21 +++++++++++-- - drivers/gpu/drm/lima/lima_gp.h | 2 ++ - drivers/gpu/drm/lima/lima_l2_cache.c | 38 +++++++++++++++++------ - drivers/gpu/drm/lima/lima_l2_cache.h | 2 ++ - drivers/gpu/drm/lima/lima_mmu.c | 46 ++++++++++++++++++++-------- - drivers/gpu/drm/lima/lima_mmu.h | 2 ++ - drivers/gpu/drm/lima/lima_pmu.c | 24 +++++++++++++-- - drivers/gpu/drm/lima/lima_pmu.h | 2 ++ - drivers/gpu/drm/lima/lima_pp.c | 31 +++++++++++++++++-- - drivers/gpu/drm/lima/lima_pp.h | 4 +++ - 16 files changed, 187 insertions(+), 37 deletions(-) - -diff --git a/drivers/gpu/drm/lima/lima_bcast.c b/drivers/gpu/drm/lima/lima_bcast.c -index 288398027bfa..fbc43f243c54 100644 ---- a/drivers/gpu/drm/lima/lima_bcast.c -+++ b/drivers/gpu/drm/lima/lima_bcast.c -@@ -26,18 +26,33 @@ void lima_bcast_enable(struct lima_device *dev, int num_pp) - bcast_write(LIMA_BCAST_BROADCAST_MASK, mask); - } - -+static int lima_bcast_hw_init(struct lima_ip *ip) -+{ -+ bcast_write(LIMA_BCAST_BROADCAST_MASK, ip->data.mask << 16); -+ bcast_write(LIMA_BCAST_INTERRUPT_MASK, ip->data.mask); -+ return 0; -+} -+ -+int lima_bcast_resume(struct lima_ip *ip) -+{ -+ return lima_bcast_hw_init(ip); -+} -+ -+void lima_bcast_suspend(struct lima_ip *ip) -+{ -+ -+} -+ - int lima_bcast_init(struct lima_ip *ip) - { -- int i, mask = 0; -+ int i; - - for (i = lima_ip_pp0; i <= lima_ip_pp7; i++) { - if (ip->dev->ip[i].present) -- mask |= 1 << (i - lima_ip_pp0); -+ ip->data.mask |= 1 << (i - lima_ip_pp0); - } - -- bcast_write(LIMA_BCAST_BROADCAST_MASK, mask << 16); -- bcast_write(LIMA_BCAST_INTERRUPT_MASK, mask); -- return 0; -+ return lima_bcast_hw_init(ip); - } - - void lima_bcast_fini(struct lima_ip *ip) -diff --git a/drivers/gpu/drm/lima/lima_bcast.h b/drivers/gpu/drm/lima/lima_bcast.h -index c47e58563d0a..465ee587bceb 100644 ---- a/drivers/gpu/drm/lima/lima_bcast.h -+++ b/drivers/gpu/drm/lima/lima_bcast.h -@@ -6,6 +6,8 @@ - - struct lima_ip; - -+int lima_bcast_resume(struct lima_ip *ip); -+void lima_bcast_suspend(struct lima_ip *ip); - int lima_bcast_init(struct lima_ip *ip); - void lima_bcast_fini(struct lima_ip *ip); - -diff --git a/drivers/gpu/drm/lima/lima_device.c b/drivers/gpu/drm/lima/lima_device.c -index 29285dedd124..a2d4ec75b3b3 100644 ---- a/drivers/gpu/drm/lima/lima_device.c -+++ b/drivers/gpu/drm/lima/lima_device.c -@@ -25,6 +25,8 @@ struct lima_ip_desc { - - int (*init)(struct lima_ip *ip); - void (*fini)(struct lima_ip *ip); -+ int (*resume)(struct lima_ip *ip); -+ void (*suspend)(struct lima_ip *ip); - }; - - #define LIMA_IP_DESC(ipname, mst0, mst1, off0, off1, func, irq) \ -@@ -41,6 +43,8 @@ struct lima_ip_desc { - }, \ - .init = lima_##func##_init, \ - .fini = lima_##func##_fini, \ -+ .resume = lima_##func##_resume, \ -+ .suspend = lima_##func##_suspend, \ - } - - static struct lima_ip_desc lima_ip_desc[lima_ip_num] = { -diff --git a/drivers/gpu/drm/lima/lima_device.h b/drivers/gpu/drm/lima/lima_device.h -index 9cd2718079bd..d9df1b45dfa9 100644 ---- a/drivers/gpu/drm/lima/lima_device.h -+++ b/drivers/gpu/drm/lima/lima_device.h -@@ -64,7 +64,7 @@ struct lima_ip { - bool async_reset; - /* l2 cache */ - spinlock_t lock; -- /* pmu */ -+ /* pmu/bcast */ - u32 mask; - } data; - }; -diff --git a/drivers/gpu/drm/lima/lima_dlbu.c b/drivers/gpu/drm/lima/lima_dlbu.c -index 8399ceffb94b..c1d5ea35daa7 100644 ---- a/drivers/gpu/drm/lima/lima_dlbu.c -+++ b/drivers/gpu/drm/lima/lima_dlbu.c -@@ -42,7 +42,7 @@ void lima_dlbu_set_reg(struct lima_ip *ip, u32 *reg) - dlbu_write(LIMA_DLBU_START_TILE_POS, reg[3]); - } - --int lima_dlbu_init(struct lima_ip *ip) -+static int lima_dlbu_hw_init(struct lima_ip *ip) - { - struct lima_device *dev = ip->dev; - -@@ -52,6 +52,21 @@ int lima_dlbu_init(struct lima_ip *ip) - return 0; - } - -+int lima_dlbu_resume(struct lima_ip *ip) -+{ -+ return lima_dlbu_hw_init(ip); -+} -+ -+void lima_dlbu_suspend(struct lima_ip *ip) -+{ -+ -+} -+ -+int lima_dlbu_init(struct lima_ip *ip) -+{ -+ return lima_dlbu_hw_init(ip); -+} -+ - void lima_dlbu_fini(struct lima_ip *ip) - { - -diff --git a/drivers/gpu/drm/lima/lima_dlbu.h b/drivers/gpu/drm/lima/lima_dlbu.h -index 16f877984466..be71daaaee89 100644 ---- a/drivers/gpu/drm/lima/lima_dlbu.h -+++ b/drivers/gpu/drm/lima/lima_dlbu.h -@@ -12,6 +12,8 @@ void lima_dlbu_disable(struct lima_device *dev); - - void lima_dlbu_set_reg(struct lima_ip *ip, u32 *reg); - -+int lima_dlbu_resume(struct lima_ip *ip); -+void lima_dlbu_suspend(struct lima_ip *ip); - int lima_dlbu_init(struct lima_ip *ip); - void lima_dlbu_fini(struct lima_ip *ip); - -diff --git a/drivers/gpu/drm/lima/lima_gp.c b/drivers/gpu/drm/lima/lima_gp.c -index d8841c870d90..8dd501b7a3d0 100644 ---- a/drivers/gpu/drm/lima/lima_gp.c -+++ b/drivers/gpu/drm/lima/lima_gp.c -@@ -274,6 +274,23 @@ static void lima_gp_print_version(struct lima_ip *ip) - static struct kmem_cache *lima_gp_task_slab; - static int lima_gp_task_slab_refcnt; - -+static int lima_gp_hw_init(struct lima_ip *ip) -+{ -+ ip->data.async_reset = false; -+ lima_gp_soft_reset_async(ip); -+ return lima_gp_soft_reset_async_wait(ip); -+} -+ -+int lima_gp_resume(struct lima_ip *ip) -+{ -+ return lima_gp_hw_init(ip); -+} -+ -+void lima_gp_suspend(struct lima_ip *ip) -+{ -+ -+} -+ - int lima_gp_init(struct lima_ip *ip) - { - struct lima_device *dev = ip->dev; -@@ -281,9 +298,7 @@ int lima_gp_init(struct lima_ip *ip) - - lima_gp_print_version(ip); - -- ip->data.async_reset = false; -- lima_gp_soft_reset_async(ip); -- err = lima_gp_soft_reset_async_wait(ip); -+ err = lima_gp_hw_init(ip); - if (err) - return err; - -diff --git a/drivers/gpu/drm/lima/lima_gp.h b/drivers/gpu/drm/lima/lima_gp.h -index 516e5c1babbb..02ec9af78a51 100644 ---- a/drivers/gpu/drm/lima/lima_gp.h -+++ b/drivers/gpu/drm/lima/lima_gp.h -@@ -7,6 +7,8 @@ - struct lima_ip; - struct lima_device; - -+int lima_gp_resume(struct lima_ip *ip); -+void lima_gp_suspend(struct lima_ip *ip); - int lima_gp_init(struct lima_ip *ip); - void lima_gp_fini(struct lima_ip *ip); - -diff --git a/drivers/gpu/drm/lima/lima_l2_cache.c b/drivers/gpu/drm/lima/lima_l2_cache.c -index 6873a7af5a5c..c4080a02957b 100644 ---- a/drivers/gpu/drm/lima/lima_l2_cache.c -+++ b/drivers/gpu/drm/lima/lima_l2_cache.c -@@ -38,9 +38,35 @@ int lima_l2_cache_flush(struct lima_ip *ip) - return ret; - } - -+static int lima_l2_cache_hw_init(struct lima_ip *ip) -+{ -+ int err; -+ -+ err = lima_l2_cache_flush(ip); -+ if (err) -+ return err; -+ -+ l2_cache_write(LIMA_L2_CACHE_ENABLE, -+ LIMA_L2_CACHE_ENABLE_ACCESS | -+ LIMA_L2_CACHE_ENABLE_READ_ALLOCATE); -+ l2_cache_write(LIMA_L2_CACHE_MAX_READS, 0x1c); -+ -+ return 0; -+} -+ -+int lima_l2_cache_resume(struct lima_ip *ip) -+{ -+ return lima_l2_cache_hw_init(ip); -+} -+ -+void lima_l2_cache_suspend(struct lima_ip *ip) -+{ -+ -+} -+ - int lima_l2_cache_init(struct lima_ip *ip) - { -- int i, err; -+ int i; - u32 size; - struct lima_device *dev = ip->dev; - -@@ -63,15 +89,7 @@ int lima_l2_cache_init(struct lima_ip *ip) - 1 << (size & 0xff), - 1 << ((size >> 24) & 0xff)); - -- err = lima_l2_cache_flush(ip); -- if (err) -- return err; -- -- l2_cache_write(LIMA_L2_CACHE_ENABLE, -- LIMA_L2_CACHE_ENABLE_ACCESS|LIMA_L2_CACHE_ENABLE_READ_ALLOCATE); -- l2_cache_write(LIMA_L2_CACHE_MAX_READS, 0x1c); -- -- return 0; -+ return lima_l2_cache_hw_init(ip); - } - - void lima_l2_cache_fini(struct lima_ip *ip) -diff --git a/drivers/gpu/drm/lima/lima_l2_cache.h b/drivers/gpu/drm/lima/lima_l2_cache.h -index c63fb676ff14..1aeeefd53fb9 100644 ---- a/drivers/gpu/drm/lima/lima_l2_cache.h -+++ b/drivers/gpu/drm/lima/lima_l2_cache.h -@@ -6,6 +6,8 @@ - - struct lima_ip; - -+int lima_l2_cache_resume(struct lima_ip *ip); -+void lima_l2_cache_suspend(struct lima_ip *ip); - int lima_l2_cache_init(struct lima_ip *ip); - void lima_l2_cache_fini(struct lima_ip *ip); - -diff --git a/drivers/gpu/drm/lima/lima_mmu.c b/drivers/gpu/drm/lima/lima_mmu.c -index c26b751b0f9d..a1ae6c252dc2 100644 ---- a/drivers/gpu/drm/lima/lima_mmu.c -+++ b/drivers/gpu/drm/lima/lima_mmu.c -@@ -59,12 +59,44 @@ static irqreturn_t lima_mmu_irq_handler(int irq, void *data) - return IRQ_HANDLED; - } - --int lima_mmu_init(struct lima_ip *ip) -+static int lima_mmu_hw_init(struct lima_ip *ip) - { - struct lima_device *dev = ip->dev; - int err; - u32 v; - -+ mmu_write(LIMA_MMU_COMMAND, LIMA_MMU_COMMAND_HARD_RESET); -+ err = lima_mmu_send_command(LIMA_MMU_COMMAND_HARD_RESET, -+ LIMA_MMU_DTE_ADDR, v, v == 0); -+ if (err) -+ return err; -+ -+ mmu_write(LIMA_MMU_INT_MASK, -+ LIMA_MMU_INT_PAGE_FAULT | LIMA_MMU_INT_READ_BUS_ERROR); -+ mmu_write(LIMA_MMU_DTE_ADDR, dev->empty_vm->pd.dma); -+ return lima_mmu_send_command(LIMA_MMU_COMMAND_ENABLE_PAGING, -+ LIMA_MMU_STATUS, v, -+ v & LIMA_MMU_STATUS_PAGING_ENABLED); -+} -+ -+int lima_mmu_resume(struct lima_ip *ip) -+{ -+ if (ip->id == lima_ip_ppmmu_bcast) -+ return 0; -+ -+ return lima_mmu_hw_init(ip); -+} -+ -+void lima_mmu_suspend(struct lima_ip *ip) -+{ -+ -+} -+ -+int lima_mmu_init(struct lima_ip *ip) -+{ -+ struct lima_device *dev = ip->dev; -+ int err; -+ - if (ip->id == lima_ip_ppmmu_bcast) - return 0; - -@@ -74,12 +106,6 @@ int lima_mmu_init(struct lima_ip *ip) - return -EIO; - } - -- mmu_write(LIMA_MMU_COMMAND, LIMA_MMU_COMMAND_HARD_RESET); -- err = lima_mmu_send_command(LIMA_MMU_COMMAND_HARD_RESET, -- LIMA_MMU_DTE_ADDR, v, v == 0); -- if (err) -- return err; -- - err = devm_request_irq(dev->dev, ip->irq, lima_mmu_irq_handler, - IRQF_SHARED, lima_ip_name(ip), ip); - if (err) { -@@ -87,11 +113,7 @@ int lima_mmu_init(struct lima_ip *ip) - return err; - } - -- mmu_write(LIMA_MMU_INT_MASK, LIMA_MMU_INT_PAGE_FAULT | LIMA_MMU_INT_READ_BUS_ERROR); -- mmu_write(LIMA_MMU_DTE_ADDR, dev->empty_vm->pd.dma); -- return lima_mmu_send_command(LIMA_MMU_COMMAND_ENABLE_PAGING, -- LIMA_MMU_STATUS, v, -- v & LIMA_MMU_STATUS_PAGING_ENABLED); -+ return lima_mmu_hw_init(ip); - } - - void lima_mmu_fini(struct lima_ip *ip) -diff --git a/drivers/gpu/drm/lima/lima_mmu.h b/drivers/gpu/drm/lima/lima_mmu.h -index 4f8ccbebcba1..f0c97ac75ea0 100644 ---- a/drivers/gpu/drm/lima/lima_mmu.h -+++ b/drivers/gpu/drm/lima/lima_mmu.h -@@ -7,6 +7,8 @@ - struct lima_ip; - struct lima_vm; - -+int lima_mmu_resume(struct lima_ip *ip); -+void lima_mmu_suspend(struct lima_ip *ip); - int lima_mmu_init(struct lima_ip *ip); - void lima_mmu_fini(struct lima_ip *ip); - -diff --git a/drivers/gpu/drm/lima/lima_pmu.c b/drivers/gpu/drm/lima/lima_pmu.c -index d476569f2043..e397e1146e96 100644 ---- a/drivers/gpu/drm/lima/lima_pmu.c -+++ b/drivers/gpu/drm/lima/lima_pmu.c -@@ -63,7 +63,7 @@ static u32 lima_pmu_get_ip_mask(struct lima_ip *ip) - return ret; - } - --int lima_pmu_init(struct lima_ip *ip) -+static int lima_pmu_hw_init(struct lima_ip *ip) - { - int err; - u32 stat; -@@ -88,7 +88,7 @@ int lima_pmu_init(struct lima_ip *ip) - return 0; - } - --void lima_pmu_fini(struct lima_ip *ip) -+static void lima_pmu_hw_fini(struct lima_ip *ip) - { - u32 stat; - -@@ -109,3 +109,23 @@ void lima_pmu_fini(struct lima_ip *ip) - lima_pmu_wait_cmd(ip); - } - } -+ -+int lima_pmu_resume(struct lima_ip *ip) -+{ -+ return lima_pmu_hw_init(ip); -+} -+ -+void lima_pmu_suspend(struct lima_ip *ip) -+{ -+ lima_pmu_hw_fini(ip); -+} -+ -+int lima_pmu_init(struct lima_ip *ip) -+{ -+ return lima_pmu_hw_init(ip); -+} -+ -+void lima_pmu_fini(struct lima_ip *ip) -+{ -+ lima_pmu_hw_fini(ip); -+} -diff --git a/drivers/gpu/drm/lima/lima_pmu.h b/drivers/gpu/drm/lima/lima_pmu.h -index a2a18775eb07..652dc7af3047 100644 ---- a/drivers/gpu/drm/lima/lima_pmu.h -+++ b/drivers/gpu/drm/lima/lima_pmu.h -@@ -6,6 +6,8 @@ - - struct lima_ip; - -+int lima_pmu_resume(struct lima_ip *ip); -+void lima_pmu_suspend(struct lima_ip *ip); - int lima_pmu_init(struct lima_ip *ip); - void lima_pmu_fini(struct lima_ip *ip); - -diff --git a/drivers/gpu/drm/lima/lima_pp.c b/drivers/gpu/drm/lima/lima_pp.c -index 8fef224b93c8..33f01383409c 100644 ---- a/drivers/gpu/drm/lima/lima_pp.c -+++ b/drivers/gpu/drm/lima/lima_pp.c -@@ -223,6 +223,23 @@ static void lima_pp_print_version(struct lima_ip *ip) - lima_ip_name(ip), name, major, minor); - } - -+static int lima_pp_hw_init(struct lima_ip *ip) -+{ -+ ip->data.async_reset = false; -+ lima_pp_soft_reset_async(ip); -+ return lima_pp_soft_reset_async_wait(ip); -+} -+ -+int lima_pp_resume(struct lima_ip *ip) -+{ -+ return lima_pp_hw_init(ip); -+} -+ -+void lima_pp_suspend(struct lima_ip *ip) -+{ -+ -+} -+ - int lima_pp_init(struct lima_ip *ip) - { - struct lima_device *dev = ip->dev; -@@ -230,9 +247,7 @@ int lima_pp_init(struct lima_ip *ip) - - lima_pp_print_version(ip); - -- ip->data.async_reset = false; -- lima_pp_soft_reset_async(ip); -- err = lima_pp_soft_reset_async_wait(ip); -+ err = lima_pp_hw_init(ip); - if (err) - return err; - -@@ -254,6 +269,16 @@ void lima_pp_fini(struct lima_ip *ip) - - } - -+int lima_pp_bcast_resume(struct lima_ip *ip) -+{ -+ return 0; -+} -+ -+void lima_pp_bcast_suspend(struct lima_ip *ip) -+{ -+ -+} -+ - int lima_pp_bcast_init(struct lima_ip *ip) - { - struct lima_device *dev = ip->dev; -diff --git a/drivers/gpu/drm/lima/lima_pp.h b/drivers/gpu/drm/lima/lima_pp.h -index bf60c77b2633..16ec96de15a9 100644 ---- a/drivers/gpu/drm/lima/lima_pp.h -+++ b/drivers/gpu/drm/lima/lima_pp.h -@@ -7,9 +7,13 @@ - struct lima_ip; - struct lima_device; - -+int lima_pp_resume(struct lima_ip *ip); -+void lima_pp_suspend(struct lima_ip *ip); - int lima_pp_init(struct lima_ip *ip); - void lima_pp_fini(struct lima_ip *ip); - -+int lima_pp_bcast_resume(struct lima_ip *ip); -+void lima_pp_bcast_suspend(struct lima_ip *ip); - int lima_pp_bcast_init(struct lima_ip *ip); - void lima_pp_bcast_fini(struct lima_ip *ip); - --- -2.17.1 - - -From 26ee4346a85cd75c531cb31dc1fe66e43226f275 Mon Sep 17 00:00:00 2001 -From: Qiang Yu -Date: Tue, 21 Apr 2020 21:35:49 +0800 -Subject: [PATCH] drm/lima: separate clk/regulator enable/disable function - -For being used by both device init/fini and suspend/resume. - -Tested-by: Bhushan Shah -Reviewed-by: Vasily Khoruzhick -Signed-off-by: Qiang Yu ---- - drivers/gpu/drm/lima/lima_device.c | 105 +++++++++++++++++++---------- - 1 file changed, 68 insertions(+), 37 deletions(-) - -diff --git a/drivers/gpu/drm/lima/lima_device.c b/drivers/gpu/drm/lima/lima_device.c -index a2d4ec75b3b3..1d9b7f415da1 100644 ---- a/drivers/gpu/drm/lima/lima_device.c -+++ b/drivers/gpu/drm/lima/lima_device.c -@@ -81,26 +81,10 @@ const char *lima_ip_name(struct lima_ip *ip) - return lima_ip_desc[ip->id].name; - } - --static int lima_clk_init(struct lima_device *dev) -+static int lima_clk_enable(struct lima_device *dev) - { - int err; - -- dev->clk_bus = devm_clk_get(dev->dev, "bus"); -- if (IS_ERR(dev->clk_bus)) { -- err = PTR_ERR(dev->clk_bus); -- if (err != -EPROBE_DEFER) -- dev_err(dev->dev, "get bus clk failed %d\n", err); -- return err; -- } -- -- dev->clk_gpu = devm_clk_get(dev->dev, "core"); -- if (IS_ERR(dev->clk_gpu)) { -- err = PTR_ERR(dev->clk_gpu); -- if (err != -EPROBE_DEFER) -- dev_err(dev->dev, "get core clk failed %d\n", err); -- return err; -- } -- - err = clk_prepare_enable(dev->clk_bus); - if (err) - return err; -@@ -109,15 +93,7 @@ static int lima_clk_init(struct lima_device *dev) - if (err) - goto error_out0; - -- dev->reset = devm_reset_control_array_get_optional_shared(dev->dev); -- -- if (IS_ERR(dev->reset)) { -- err = PTR_ERR(dev->reset); -- if (err != -EPROBE_DEFER) -- dev_err(dev->dev, "get reset controller failed %d\n", -- err); -- goto error_out1; -- } else if (dev->reset != NULL) { -+ if (dev->reset) { - err = reset_control_deassert(dev->reset); - if (err) { - dev_err(dev->dev, -@@ -135,14 +111,76 @@ static int lima_clk_init(struct lima_device *dev) - return err; - } - --static void lima_clk_fini(struct lima_device *dev) -+static void lima_clk_disable(struct lima_device *dev) - { -- if (dev->reset != NULL) -+ if (dev->reset) - reset_control_assert(dev->reset); - clk_disable_unprepare(dev->clk_gpu); - clk_disable_unprepare(dev->clk_bus); - } - -+static int lima_clk_init(struct lima_device *dev) -+{ -+ int err; -+ -+ dev->clk_bus = devm_clk_get(dev->dev, "bus"); -+ if (IS_ERR(dev->clk_bus)) { -+ err = PTR_ERR(dev->clk_bus); -+ if (err != -EPROBE_DEFER) -+ dev_err(dev->dev, "get bus clk failed %d\n", err); -+ dev->clk_bus = NULL; -+ return err; -+ } -+ -+ dev->clk_gpu = devm_clk_get(dev->dev, "core"); -+ if (IS_ERR(dev->clk_gpu)) { -+ err = PTR_ERR(dev->clk_gpu); -+ if (err != -EPROBE_DEFER) -+ dev_err(dev->dev, "get core clk failed %d\n", err); -+ dev->clk_gpu = NULL; -+ return err; -+ } -+ -+ dev->reset = devm_reset_control_array_get_optional_shared(dev->dev); -+ if (IS_ERR(dev->reset)) { -+ err = PTR_ERR(dev->reset); -+ if (err != -EPROBE_DEFER) -+ dev_err(dev->dev, "get reset controller failed %d\n", -+ err); -+ dev->reset = NULL; -+ return err; -+ } -+ -+ return lima_clk_enable(dev); -+} -+ -+static void lima_clk_fini(struct lima_device *dev) -+{ -+ lima_clk_disable(dev); -+} -+ -+static int lima_regulator_enable(struct lima_device *dev) -+{ -+ int ret; -+ -+ if (!dev->regulator) -+ return 0; -+ -+ ret = regulator_enable(dev->regulator); -+ if (ret < 0) { -+ dev_err(dev->dev, "failed to enable regulator: %d\n", ret); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static void lima_regulator_disable(struct lima_device *dev) -+{ -+ if (dev->regulator) -+ regulator_disable(dev->regulator); -+} -+ - static int lima_regulator_init(struct lima_device *dev) - { - int ret; -@@ -158,19 +196,12 @@ static int lima_regulator_init(struct lima_device *dev) - return ret; - } - -- ret = regulator_enable(dev->regulator); -- if (ret < 0) { -- dev_err(dev->dev, "failed to enable regulator: %d\n", ret); -- return ret; -- } -- -- return 0; -+ return lima_regulator_enable(dev); - } - - static void lima_regulator_fini(struct lima_device *dev) - { -- if (dev->regulator) -- regulator_disable(dev->regulator); -+ lima_regulator_disable(dev); - } - - static int lima_init_ip(struct lima_device *dev, int index) --- -2.17.1 - - -From 90f27ceb82a87cabf926e65748bdd60cf0e191b6 Mon Sep 17 00:00:00 2001 -From: Qiang Yu -Date: Tue, 21 Apr 2020 21:35:50 +0800 -Subject: [PATCH] drm/lima: add pm resume/suspend ops - -Add driver pm system and runtime hardware resume/suspend ops. -Note this won't enable runtime pm of the device yet. - -v2: -Do clock and power gating when suspend/resume. - -Tested-by: Bhushan Shah -Reviewed-by: Vasily Khoruzhick -Signed-off-by: Qiang Yu ---- - drivers/gpu/drm/lima/lima_device.c | 90 ++++++++++++++++++++++++++++++ - drivers/gpu/drm/lima/lima_device.h | 3 + - drivers/gpu/drm/lima/lima_drv.c | 7 +++ - 3 files changed, 100 insertions(+) - -diff --git a/drivers/gpu/drm/lima/lima_device.c b/drivers/gpu/drm/lima/lima_device.c -index 1d9b7f415da1..65fdca366e41 100644 ---- a/drivers/gpu/drm/lima/lima_device.c -+++ b/drivers/gpu/drm/lima/lima_device.c -@@ -247,6 +247,27 @@ static void lima_fini_ip(struct lima_device *ldev, int index) - desc->fini(ip); - } - -+static int lima_resume_ip(struct lima_device *ldev, int index) -+{ -+ struct lima_ip_desc *desc = lima_ip_desc + index; -+ struct lima_ip *ip = ldev->ip + index; -+ int ret = 0; -+ -+ if (ip->present) -+ ret = desc->resume(ip); -+ -+ return ret; -+} -+ -+static void lima_suspend_ip(struct lima_device *ldev, int index) -+{ -+ struct lima_ip_desc *desc = lima_ip_desc + index; -+ struct lima_ip *ip = ldev->ip + index; -+ -+ if (ip->present) -+ desc->suspend(ip); -+} -+ - static int lima_init_gp_pipe(struct lima_device *dev) - { - struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_gp; -@@ -441,3 +462,72 @@ void lima_device_fini(struct lima_device *ldev) - - lima_clk_fini(ldev); - } -+ -+int lima_device_resume(struct device *dev) -+{ -+ struct lima_device *ldev = dev_get_drvdata(dev); -+ int i, err; -+ -+ err = lima_clk_enable(ldev); -+ if (err) { -+ dev_err(dev, "resume clk fail %d\n", err); -+ return err; -+ } -+ -+ err = lima_regulator_enable(ldev); -+ if (err) { -+ dev_err(dev, "resume regulator fail %d\n", err); -+ goto err_out0; -+ } -+ -+ for (i = 0; i < lima_ip_num; i++) { -+ err = lima_resume_ip(ldev, i); -+ if (err) { -+ dev_err(dev, "resume ip %d fail\n", i); -+ goto err_out1; -+ } -+ } -+ -+ err = lima_devfreq_resume(&ldev->devfreq); -+ if (err) { -+ dev_err(dev, "devfreq resume fail\n"); -+ goto err_out1; -+ } -+ -+ return 0; -+ -+err_out1: -+ while (--i >= 0) -+ lima_suspend_ip(ldev, i); -+ lima_regulator_disable(ldev); -+err_out0: -+ lima_clk_disable(ldev); -+ return err; -+} -+ -+int lima_device_suspend(struct device *dev) -+{ -+ struct lima_device *ldev = dev_get_drvdata(dev); -+ int i, err; -+ -+ /* check any task running */ -+ for (i = 0; i < lima_pipe_num; i++) { -+ if (atomic_read(&ldev->pipe[i].base.hw_rq_count)) -+ return -EBUSY; -+ } -+ -+ err = lima_devfreq_suspend(&ldev->devfreq); -+ if (err) { -+ dev_err(dev, "devfreq suspend fail\n"); -+ return err; -+ } -+ -+ for (i = lima_ip_num - 1; i >= 0; i--) -+ lima_suspend_ip(ldev, i); -+ -+ lima_regulator_disable(ldev); -+ -+ lima_clk_disable(ldev); -+ -+ return 0; -+} -diff --git a/drivers/gpu/drm/lima/lima_device.h b/drivers/gpu/drm/lima/lima_device.h -index d9df1b45dfa9..41b9d7b4bcc7 100644 ---- a/drivers/gpu/drm/lima/lima_device.h -+++ b/drivers/gpu/drm/lima/lima_device.h -@@ -140,4 +140,7 @@ static inline int lima_poll_timeout(struct lima_ip *ip, lima_poll_func_t func, - return 0; - } - -+int lima_device_suspend(struct device *dev); -+int lima_device_resume(struct device *dev); -+ - #endif -diff --git a/drivers/gpu/drm/lima/lima_drv.c b/drivers/gpu/drm/lima/lima_drv.c -index 3d63d496cfc2..f3fe0a2f764b 100644 ---- a/drivers/gpu/drm/lima/lima_drv.c -+++ b/drivers/gpu/drm/lima/lima_drv.c -@@ -5,6 +5,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -451,11 +452,17 @@ static const struct of_device_id dt_match[] = { - }; - MODULE_DEVICE_TABLE(of, dt_match); - -+static const struct dev_pm_ops lima_pm_ops = { -+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) -+ SET_RUNTIME_PM_OPS(lima_device_suspend, lima_device_resume, NULL) -+}; -+ - static struct platform_driver lima_platform_driver = { - .probe = lima_pdev_probe, - .remove = lima_pdev_remove, - .driver = { - .name = "lima", -+ .pm = &lima_pm_ops, - .of_match_table = dt_match, - }, - }; --- -2.17.1 - - -From 77f3ae2361292cef89c0a06e745991cefb52fcdc Mon Sep 17 00:00:00 2001 -From: Qiang Yu -Date: Tue, 21 Apr 2020 21:35:51 +0800 -Subject: [PATCH] drm/lima: enable runtime pm - -Enable runtime pm by default so GPU suspend when idle -for 200ms. This value can be changed by -autosuspend_delay_ms in device's power sysfs dir. - -On Allwinner H3 lima_device_resume takes ~40us and -lima_device_suspend takes ~20us. - -Tested-by: Bhushan Shah -Reviewed-by: Vasily Khoruzhick -Signed-off-by: Qiang Yu ---- - drivers/gpu/drm/lima/lima_drv.c | 21 ++++++++++++---- - drivers/gpu/drm/lima/lima_sched.c | 41 +++++++++++++++++++++++++++---- - 2 files changed, 52 insertions(+), 10 deletions(-) - -diff --git a/drivers/gpu/drm/lima/lima_drv.c b/drivers/gpu/drm/lima/lima_drv.c -index f3fe0a2f764b..a831565af813 100644 ---- a/drivers/gpu/drm/lima/lima_drv.c -+++ b/drivers/gpu/drm/lima/lima_drv.c -@@ -404,6 +404,12 @@ static int lima_pdev_probe(struct platform_device *pdev) - goto err_out2; - } - -+ pm_runtime_set_active(ldev->dev); -+ pm_runtime_mark_last_busy(ldev->dev); -+ pm_runtime_set_autosuspend_delay(ldev->dev, 200); -+ pm_runtime_use_autosuspend(ldev->dev); -+ pm_runtime_enable(ldev->dev); -+ - /* - * Register the DRM device with the core and the connectors with - * sysfs. -@@ -412,17 +418,16 @@ static int lima_pdev_probe(struct platform_device *pdev) - if (err < 0) - goto err_out3; - -- platform_set_drvdata(pdev, ldev); -- - if (sysfs_create_bin_file(&ldev->dev->kobj, &lima_error_state_attr)) - dev_warn(ldev->dev, "fail to create error state sysfs\n"); - - return 0; - - err_out3: -- lima_device_fini(ldev); --err_out2: -+ pm_runtime_disable(ldev->dev); - lima_devfreq_fini(ldev); -+err_out2: -+ lima_device_fini(ldev); - err_out1: - drm_dev_put(ddev); - err_out0: -@@ -436,10 +441,16 @@ static int lima_pdev_remove(struct platform_device *pdev) - struct drm_device *ddev = ldev->ddev; - - sysfs_remove_bin_file(&ldev->dev->kobj, &lima_error_state_attr); -- platform_set_drvdata(pdev, NULL); -+ - drm_dev_unregister(ddev); -+ -+ /* stop autosuspend to make sure device is in active state */ -+ pm_runtime_set_autosuspend_delay(ldev->dev, -1); -+ pm_runtime_disable(ldev->dev); -+ - lima_devfreq_fini(ldev); - lima_device_fini(ldev); -+ - drm_dev_put(ddev); - lima_sched_slab_fini(); - return 0; -diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c -index eb46db0717cd..e6cefda00279 100644 ---- a/drivers/gpu/drm/lima/lima_sched.c -+++ b/drivers/gpu/drm/lima/lima_sched.c -@@ -4,6 +4,7 @@ - #include - #include - #include -+#include - - #include "lima_devfreq.h" - #include "lima_drv.h" -@@ -194,13 +195,36 @@ static struct dma_fence *lima_sched_dependency(struct drm_sched_job *job, - return NULL; - } - -+static int lima_pm_busy(struct lima_device *ldev) -+{ -+ int ret; -+ -+ /* resume GPU if it has been suspended by runtime PM */ -+ ret = pm_runtime_get_sync(ldev->dev); -+ if (ret < 0) -+ return ret; -+ -+ lima_devfreq_record_busy(&ldev->devfreq); -+ return 0; -+} -+ -+static void lima_pm_idle(struct lima_device *ldev) -+{ -+ lima_devfreq_record_idle(&ldev->devfreq); -+ -+ /* GPU can do auto runtime suspend */ -+ pm_runtime_mark_last_busy(ldev->dev); -+ pm_runtime_put_autosuspend(ldev->dev); -+} -+ - static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job) - { - struct lima_sched_task *task = to_lima_task(job); - struct lima_sched_pipe *pipe = to_lima_pipe(job->sched); -+ struct lima_device *ldev = pipe->ldev; - struct lima_fence *fence; - struct dma_fence *ret; -- int i; -+ int i, err; - - /* after GPU reset */ - if (job->s_fence->finished.error < 0) -@@ -209,6 +233,13 @@ static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job) - fence = lima_fence_create(pipe); - if (!fence) - return NULL; -+ -+ err = lima_pm_busy(ldev); -+ if (err < 0) { -+ dma_fence_put(&fence->base); -+ return NULL; -+ } -+ - task->fence = &fence->base; - - /* for caller usage of the fence, otherwise irq handler -@@ -216,8 +247,6 @@ static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job) - */ - ret = dma_fence_get(task->fence); - -- lima_devfreq_record_busy(&pipe->ldev->devfreq); -- - pipe->current_task = task; - - /* this is needed for MMU to work correctly, otherwise GP/PP -@@ -388,6 +417,7 @@ static void lima_sched_timedout_job(struct drm_sched_job *job) - { - struct lima_sched_pipe *pipe = to_lima_pipe(job->sched); - struct lima_sched_task *task = to_lima_task(job); -+ struct lima_device *ldev = pipe->ldev; - - if (!pipe->error) - DRM_ERROR("lima job timeout\n"); -@@ -413,7 +443,7 @@ static void lima_sched_timedout_job(struct drm_sched_job *job) - pipe->current_vm = NULL; - pipe->current_task = NULL; - -- lima_devfreq_record_idle(&pipe->ldev->devfreq); -+ lima_pm_idle(ldev); - - drm_sched_resubmit_jobs(&pipe->base); - drm_sched_start(&pipe->base, true); -@@ -485,6 +515,7 @@ void lima_sched_pipe_fini(struct lima_sched_pipe *pipe) - void lima_sched_pipe_task_done(struct lima_sched_pipe *pipe) - { - struct lima_sched_task *task = pipe->current_task; -+ struct lima_device *ldev = pipe->ldev; - - if (pipe->error) { - if (task && task->recoverable) -@@ -495,6 +526,6 @@ void lima_sched_pipe_task_done(struct lima_sched_pipe *pipe) - pipe->task_fini(pipe); - dma_fence_signal(task->fence); - -- lima_devfreq_record_idle(&pipe->ldev->devfreq); -+ lima_pm_idle(ldev); - } - } --- -2.17.1 - - -From 5f88c11fbc001f7cd701af13a4a40c94572848c7 Mon Sep 17 00:00:00 2001 -From: Martin Blumenstingl -Date: Thu, 19 Mar 2020 21:34:26 +0100 -Subject: [PATCH] dt-bindings: gpu: mali-utgard: Add the #cooling-cells - property - -The GPU can be one of the big heat sources on a SoC. Allow the -"#cooling-cells" property to be specified for ARM Mali Utgard GPUs so -the GPU clock speeds (and voltages) can be reduced to prevent a SoC from -overheating. - -Signed-off-by: Martin Blumenstingl -Reviewed-by: Qiang Yu ---- - Documentation/devicetree/bindings/gpu/arm,mali-utgard.yaml | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/Documentation/devicetree/bindings/gpu/arm,mali-utgard.yaml b/Documentation/devicetree/bindings/gpu/arm,mali-utgard.yaml -index afde81be3c29..33548ca2a759 100644 ---- a/Documentation/devicetree/bindings/gpu/arm,mali-utgard.yaml -+++ b/Documentation/devicetree/bindings/gpu/arm,mali-utgard.yaml -@@ -107,6 +107,9 @@ properties: - - operating-points-v2: true - -+ "#cooling-cells": -+ const: 2 -+ - required: - - compatible - - reg -@@ -162,6 +165,7 @@ examples: - clocks = <&ccu 1>, <&ccu 2>; - clock-names = "bus", "core"; - resets = <&ccu 1>; -+ #cooling-cells = <2>; - }; - - ... --- -2.17.1 - diff --git a/patch/kernel/rk322x-current/01-linux-0011-v4l2-from-5.9.patch b/patch/kernel/rk322x-current/01-linux-0011-v4l2-from-5.9.patch new file mode 100644 index 000000000..79efdfdb0 --- /dev/null +++ b/patch/kernel/rk322x-current/01-linux-0011-v4l2-from-5.9.patch @@ -0,0 +1,1190 @@ +From 7ecb99ec97624da3354bc7702179e21309fb3a4e Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Wed, 1 Jul 2020 15:17:30 +0200 +Subject: [PATCH] v4l2-core: Print control name in VIDIOC_S/G_(EXT)_CTRL(S) + +While debugging, it's currently really hard to identify controls +by their ID. Print the control name making the print more helpful. + +With this change, the print changes from: + +video1: VIDIOC_S_EXT_CTRLS: which=0xf010000, count=5, error_idx=4, request_fd=45, id/size=0x990ce8/1048, id/size=0x990ce9/12, id/size=0x990cea/480, id/size=0x990ceb/896, id/size=0x990cec/400 + +video1: VIDIOC_S_EXT_CTRLS: which=0xf010000, count=5, error_idx=4, request_fd=42, name=H264 Sequence Parameter Set, id/size=0x990ce8/1048, name=H264 Picture Parameter Set, id/size=0x990ce9/12, name=H264 Scaling Matrix, id/size=0x990cea/480, name=H264 Slice Parameters, id/size=0x990ceb/896, name=H264 Decode Parameters, id/size=0x990cec/400 + +For instance, this is specially helpful when the ioctl fails. Consider +the following example: + +v4l2-ctrls: prepare_ext_ctrls: video1: pointer control id 0x990cec size too small, 400 bytes but 784 bytes needed +v4l2-ctrls: try_set_ext_ctrls: video1: video1: try_set_ext_ctrls_common failed (-14) +video1: VIDIOC_S_EXT_CTRLS: error -14: which=0xf010000, count=5, error_idx=5, request_fd=39, name=H264 Sequence Parameter Set, id/size=0x990ce8/1048, name=H264 Picture Parameter Set, id/size=0x990ce9/12, name=H264 Scaling Matrix, id/size=0x990cea/480, name=H264 Slice Parameters, id/size=0x990ceb/896, name=H264 Decode Parameters, id/size=0x990cec/400 + +Signed-off-by: Ezequiel Garcia +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +(cherry picked from commit a69a7a33268308ddcc9abf0f7d7cd61ec4300cbe) +--- + drivers/media/v4l2-core/v4l2-ioctl.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c +index 5e057f798a15..ccf947632a3b 100644 +--- a/drivers/media/v4l2-core/v4l2-ioctl.c ++++ b/drivers/media/v4l2-core/v4l2-ioctl.c +@@ -582,7 +582,10 @@ static void v4l_print_querymenu(const void *arg, bool write_only) + static void v4l_print_control(const void *arg, bool write_only) + { + const struct v4l2_control *p = arg; ++ const char *name = v4l2_ctrl_get_name(p->id); + ++ if (name) ++ pr_cont("name=%s, ", name); + pr_cont("id=0x%x, value=%d\n", p->id, p->value); + } + +@@ -594,12 +597,15 @@ static void v4l_print_ext_controls(const void *arg, bool write_only) + pr_cont("which=0x%x, count=%d, error_idx=%d, request_fd=%d", + p->which, p->count, p->error_idx, p->request_fd); + for (i = 0; i < p->count; i++) { ++ unsigned int id = p->controls[i].id; ++ const char *name = v4l2_ctrl_get_name(id); ++ ++ if (name) ++ pr_cont(", name=%s", name); + if (!p->controls[i].size) +- pr_cont(", id/val=0x%x/0x%x", +- p->controls[i].id, p->controls[i].value); ++ pr_cont(", id/val=0x%x/0x%x", id, p->controls[i].value); + else +- pr_cont(", id/size=0x%x/%u", +- p->controls[i].id, p->controls[i].size); ++ pr_cont(", id/size=0x%x/%u", id, p->controls[i].size); + } + pr_cont("\n"); + } + +From d524e0ef051dcccefbdff08e1023489922da198f Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Wed, 24 Jun 2020 21:28:00 +0200 +Subject: [PATCH] media: Add V4L2_TYPE_IS_CAPTURE helper + +It's all too easy to get confused by the V4L2_TYPE_IS_OUTPUT +macro, when it's used as !V4L2_TYPE_IS_OUTPUT. + +Reduce the risk of confusion with macro to explicitly +check for the CAPTURE queue type case. + +This change does not affect functionality, and it's +only intended to make the code more readable. + +Suggested-by: Nicolas Dufresne +Signed-off-by: Ezequiel Garcia +Signed-off-by: Hans Verkuil +[hverkuil-cisco@xs4all.nl: checkpatch: align with parenthesis] +Signed-off-by: Mauro Carvalho Chehab +(cherry picked from commit b3ab1c6058fad8cd5726f24e9ed9053e43bb2af4) +--- + drivers/media/common/videobuf2/videobuf2-v4l2.c | 4 ++-- + drivers/media/platform/exynos-gsc/gsc-core.c | 2 +- + drivers/media/platform/exynos-gsc/gsc-m2m.c | 2 +- + drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c | 2 +- + drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c | 7 +++---- + drivers/media/platform/rcar_jpu.c | 2 +- + drivers/media/platform/sti/hva/hva-v4l2.c | 2 +- + drivers/media/platform/ti-vpe/vpe.c | 2 +- + drivers/media/test-drivers/vicodec/vicodec-core.c | 6 +++--- + drivers/media/v4l2-core/v4l2-mem2mem.c | 6 +++--- + drivers/staging/media/hantro/hantro_v4l2.c | 2 +- + drivers/staging/media/rkvdec/rkvdec.c | 2 +- + include/uapi/linux/videodev2.h | 2 ++ + 13 files changed, 21 insertions(+), 20 deletions(-) + +diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c +index eb5d5db96552..fd32c2e64809 100644 +--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c ++++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c +@@ -94,7 +94,7 @@ static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b) + unsigned int bytesused; + unsigned int plane; + +- if (!V4L2_TYPE_IS_OUTPUT(b->type)) ++ if (V4L2_TYPE_IS_CAPTURE(b->type)) + return 0; + + if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) { +@@ -307,7 +307,7 @@ static int vb2_fill_vb2_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b + + /* Zero flags that we handle */ + vbuf->flags = b->flags & ~V4L2_BUFFER_MASK_FLAGS; +- if (!vb->vb2_queue->copy_timestamp || !V4L2_TYPE_IS_OUTPUT(b->type)) { ++ if (!vb->vb2_queue->copy_timestamp || V4L2_TYPE_IS_CAPTURE(b->type)) { + /* + * Non-COPY timestamps and non-OUTPUT queues will get + * their timestamp and timestamp source flags from the +diff --git a/drivers/media/platform/exynos-gsc/gsc-core.c b/drivers/media/platform/exynos-gsc/gsc-core.c +index f6650b45bc3d..9f41c2e7097a 100644 +--- a/drivers/media/platform/exynos-gsc/gsc-core.c ++++ b/drivers/media/platform/exynos-gsc/gsc-core.c +@@ -577,7 +577,7 @@ int gsc_try_selection(struct gsc_ctx *ctx, struct v4l2_selection *s) + v4l_bound_align_image(&tmp_w, min_w, max_w, mod_x, + &tmp_h, min_h, max_h, mod_y, 0); + +- if (!V4L2_TYPE_IS_OUTPUT(s->type) && ++ if (V4L2_TYPE_IS_CAPTURE(s->type) && + (ctx->gsc_ctrls.rotate->val == 90 || + ctx->gsc_ctrls.rotate->val == 270)) + gsc_check_crop_change(tmp_h, tmp_w, +diff --git a/drivers/media/platform/exynos-gsc/gsc-m2m.c b/drivers/media/platform/exynos-gsc/gsc-m2m.c +index e2c162635f72..27a3c92c73bc 100644 +--- a/drivers/media/platform/exynos-gsc/gsc-m2m.c ++++ b/drivers/media/platform/exynos-gsc/gsc-m2m.c +@@ -255,7 +255,7 @@ static int gsc_m2m_buf_prepare(struct vb2_buffer *vb) + if (IS_ERR(frame)) + return PTR_ERR(frame); + +- if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { ++ if (V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type)) { + for (i = 0; i < frame->fmt->num_planes; i++) + vb2_set_plane_payload(vb, i, frame->payload[i]); + } +diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c +index f82a81a3bdee..61fed1e35a00 100644 +--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c ++++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c +@@ -731,7 +731,7 @@ static void mtk_jpeg_stop_streaming(struct vb2_queue *q) + * subsampling. Update capture queue when the stream is off. + */ + if (ctx->state == MTK_JPEG_SOURCE_CHANGE && +- !V4L2_TYPE_IS_OUTPUT(q->type)) { ++ V4L2_TYPE_IS_CAPTURE(q->type)) { + struct mtk_jpeg_src_buf *src_buf; + + vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); +diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c b/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c +index 821f2cf325f0..a6ea22b57416 100644 +--- a/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c ++++ b/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c +@@ -193,7 +193,7 @@ static const struct mtk_mdp_fmt *mtk_mdp_try_fmt_mplane(struct mtk_mdp_ctx *ctx, + + pix_mp->field = V4L2_FIELD_NONE; + pix_mp->pixelformat = fmt->pixelformat; +- if (!V4L2_TYPE_IS_OUTPUT(f->type)) { ++ if (V4L2_TYPE_IS_CAPTURE(f->type)) { + pix_mp->colorspace = ctx->colorspace; + pix_mp->xfer_func = ctx->xfer_func; + pix_mp->ycbcr_enc = ctx->ycbcr_enc; +@@ -327,9 +327,8 @@ static int mtk_mdp_try_crop(struct mtk_mdp_ctx *ctx, u32 type, + mtk_mdp_bound_align_image(&new_w, min_w, max_w, align_w, + &new_h, min_h, max_h, align_h); + +- if (!V4L2_TYPE_IS_OUTPUT(type) && +- (ctx->ctrls.rotate->val == 90 || +- ctx->ctrls.rotate->val == 270)) ++ if (V4L2_TYPE_IS_CAPTURE(type) && ++ (ctx->ctrls.rotate->val == 90 || ctx->ctrls.rotate->val == 270)) + mtk_mdp_check_crop_change(new_h, new_w, + &r->width, &r->height); + else +diff --git a/drivers/media/platform/rcar_jpu.c b/drivers/media/platform/rcar_jpu.c +index 5250a14324e9..9b99ff368698 100644 +--- a/drivers/media/platform/rcar_jpu.c ++++ b/drivers/media/platform/rcar_jpu.c +@@ -1066,7 +1066,7 @@ static int jpu_buf_prepare(struct vb2_buffer *vb) + } + + /* decoder capture queue */ +- if (!ctx->encoder && !V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) ++ if (!ctx->encoder && V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type)) + vb2_set_plane_payload(vb, i, size); + } + +diff --git a/drivers/media/platform/sti/hva/hva-v4l2.c b/drivers/media/platform/sti/hva/hva-v4l2.c +index 197b99d8fd9c..bb34d6997d99 100644 +--- a/drivers/media/platform/sti/hva/hva-v4l2.c ++++ b/drivers/media/platform/sti/hva/hva-v4l2.c +@@ -1087,7 +1087,7 @@ static void hva_stop_streaming(struct vb2_queue *vq) + + if ((V4L2_TYPE_IS_OUTPUT(vq->type) && + vb2_is_streaming(&ctx->fh.m2m_ctx->cap_q_ctx.q)) || +- (!V4L2_TYPE_IS_OUTPUT(vq->type) && ++ (V4L2_TYPE_IS_CAPTURE(vq->type) && + vb2_is_streaming(&ctx->fh.m2m_ctx->out_q_ctx.q))) { + dev_dbg(dev, "%s %s out=%d cap=%d\n", + ctx->name, to_type_str(vq->type), +diff --git a/drivers/media/platform/ti-vpe/vpe.c b/drivers/media/platform/ti-vpe/vpe.c +index cff2fcd6d812..346f8212791c 100644 +--- a/drivers/media/platform/ti-vpe/vpe.c ++++ b/drivers/media/platform/ti-vpe/vpe.c +@@ -1576,7 +1576,7 @@ static int vpe_g_fmt(struct file *file, void *priv, struct v4l2_format *f) + + *f = q_data->format; + +- if (!V4L2_TYPE_IS_OUTPUT(f->type)) { ++ if (V4L2_TYPE_IS_CAPTURE(f->type)) { + struct vpe_q_data *s_q_data; + struct v4l2_pix_format_mplane *spix; + +diff --git a/drivers/media/test-drivers/vicodec/vicodec-core.c b/drivers/media/test-drivers/vicodec/vicodec-core.c +index e879290727ef..8941d73f6611 100644 +--- a/drivers/media/test-drivers/vicodec/vicodec-core.c ++++ b/drivers/media/test-drivers/vicodec/vicodec-core.c +@@ -1442,7 +1442,7 @@ static void vicodec_buf_queue(struct vb2_buffer *vb) + .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION, + }; + +- if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type) && ++ if (V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type) && + vb2_is_streaming(vb->vb2_queue) && + v4l2_m2m_dst_buf_is_last(ctx->fh.m2m_ctx)) { + unsigned int i; +@@ -1479,7 +1479,7 @@ static void vicodec_buf_queue(struct vb2_buffer *vb) + * in the compressed stream + */ + if (ctx->is_stateless || ctx->is_enc || +- !V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { ++ V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type)) { + v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); + return; + } +@@ -1574,7 +1574,7 @@ static int vicodec_start_streaming(struct vb2_queue *q, + state->gop_cnt = 0; + + if ((V4L2_TYPE_IS_OUTPUT(q->type) && !ctx->is_enc) || +- (!V4L2_TYPE_IS_OUTPUT(q->type) && ctx->is_enc)) ++ (V4L2_TYPE_IS_CAPTURE(q->type) && ctx->is_enc)) + return 0; + + if (info->id == V4L2_PIX_FMT_FWHT || +diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c +index 62ac9424c92a..95a8f2dc5341 100644 +--- a/drivers/media/v4l2-core/v4l2-mem2mem.c ++++ b/drivers/media/v4l2-core/v4l2-mem2mem.c +@@ -556,7 +556,7 @@ int v4l2_m2m_querybuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, + ret = vb2_querybuf(vq, buf); + + /* Adjust MMAP memory offsets for the CAPTURE queue */ +- if (buf->memory == V4L2_MEMORY_MMAP && !V4L2_TYPE_IS_OUTPUT(vq->type)) { ++ if (buf->memory == V4L2_MEMORY_MMAP && V4L2_TYPE_IS_CAPTURE(vq->type)) { + if (V4L2_TYPE_IS_MULTIPLANAR(vq->type)) { + for (i = 0; i < buf->length; ++i) + buf->m.planes[i].m.mem_offset +@@ -712,7 +712,7 @@ int v4l2_m2m_qbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, + int ret; + + vq = v4l2_m2m_get_vq(m2m_ctx, buf->type); +- if (!V4L2_TYPE_IS_OUTPUT(vq->type) && ++ if (V4L2_TYPE_IS_CAPTURE(vq->type) && + (buf->flags & V4L2_BUF_FLAG_REQUEST_FD)) { + dprintk("%s: requests cannot be used with capture buffers\n", + __func__); +@@ -729,7 +729,7 @@ int v4l2_m2m_qbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, + * buffer as DONE with LAST flag since it won't be queued on the + * device. + */ +- if (!V4L2_TYPE_IS_OUTPUT(vq->type) && ++ if (V4L2_TYPE_IS_CAPTURE(vq->type) && + vb2_is_streaming(vq) && !vb2_start_streaming_called(vq) && + (v4l2_m2m_has_stopped(m2m_ctx) || v4l2_m2m_dst_buf_is_last(m2m_ctx))) + v4l2_m2m_force_last_buf_done(m2m_ctx, vq); +diff --git a/drivers/staging/media/hantro/hantro_v4l2.c b/drivers/staging/media/hantro/hantro_v4l2.c +index f28a94e2fa93..63859e8a0923 100644 +--- a/drivers/staging/media/hantro/hantro_v4l2.c ++++ b/drivers/staging/media/hantro/hantro_v4l2.c +@@ -237,7 +237,7 @@ static int hantro_try_fmt(const struct hantro_ctx *ctx, + enum v4l2_buf_type type) + { + const struct hantro_fmt *fmt, *vpu_fmt; +- bool capture = !V4L2_TYPE_IS_OUTPUT(type); ++ bool capture = V4L2_TYPE_IS_CAPTURE(type); + bool coded; + + coded = capture == hantro_is_encoder_ctx(ctx); +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index 225eeca73356..fd68671f0286 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -489,7 +489,7 @@ static int rkvdec_start_streaming(struct vb2_queue *q, unsigned int count) + const struct rkvdec_coded_fmt_desc *desc; + int ret; + +- if (!V4L2_TYPE_IS_OUTPUT(q->type)) ++ if (V4L2_TYPE_IS_CAPTURE(q->type)) + return 0; + + desc = ctx->coded_fmt_desc; +diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h +index c3a1cf1c507f..6fe8822d2cb4 100644 +--- a/include/uapi/linux/videodev2.h ++++ b/include/uapi/linux/videodev2.h +@@ -171,6 +171,8 @@ enum v4l2_buf_type { + || (type) == V4L2_BUF_TYPE_SDR_OUTPUT \ + || (type) == V4L2_BUF_TYPE_META_OUTPUT) + ++#define V4L2_TYPE_IS_CAPTURE(type) (!V4L2_TYPE_IS_OUTPUT(type)) ++ + enum v4l2_tuner_type { + V4L2_TUNER_RADIO = 1, + V4L2_TUNER_ANALOG_TV = 2, + +From 728f96ea31862791706eb9390cb865e4fd8fa09d Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Wed, 1 Jul 2020 15:16:02 +0200 +Subject: [PATCH] hantro: h264: Remove unused macro definition + +The generic H264 reference list builder moved all +the users of this macro, but left the macro. + +Remove it. + +Signed-off-by: Ezequiel Garcia +Reviewed-by: Philipp Zabel +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +(cherry picked from commit 3ebf271b1dee6df816bd8f2135218640c478dedd) +--- + drivers/staging/media/hantro/hantro_h264.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/staging/media/hantro/hantro_h264.c b/drivers/staging/media/hantro/hantro_h264.c +index d561f125085a..dd935d7009bf 100644 +--- a/drivers/staging/media/hantro/hantro_h264.c ++++ b/drivers/staging/media/hantro/hantro_h264.c +@@ -22,8 +22,6 @@ + #define POC_BUFFER_SIZE 34 + #define SCALING_LIST_SIZE (6 * 16 + 2 * 64) + +-#define HANTRO_CMP(a, b) ((a) < (b) ? -1 : 1) +- + /* Data structure describing auxiliary buffer format. */ + struct hantro_h264_dec_priv_tbl { + u32 cabac_table[CABAC_INIT_BUFFER_SIZE]; + +From ad6f6337541843af2f943f603636f64a6a55e215 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Wed, 1 Jul 2020 15:16:03 +0200 +Subject: [PATCH] hantro: h264: Rename scaling list handling function + +Commit e17f08e31666 ("media: hantro: Do not reorder +H264 scaling list") removed the scaling list reordering, +which was wrong and not needed. + +However, the name of the function stayed, which is +confusing for anyone reading the code. Rename +from "reorder" to "assemble" which is cleaner. + +This is just a cosmetic cleanup. + +Signed-off-by: Ezequiel Garcia +Reviewed-by: Philipp Zabel +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +(cherry picked from commit 4df3a47e3422a9de1f3ce1a4ba8a0447a73e7567) +--- + drivers/staging/media/hantro/hantro_h264.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/staging/media/hantro/hantro_h264.c b/drivers/staging/media/hantro/hantro_h264.c +index dd935d7009bf..194d05848077 100644 +--- a/drivers/staging/media/hantro/hantro_h264.c ++++ b/drivers/staging/media/hantro/hantro_h264.c +@@ -193,7 +193,7 @@ static const u32 h264_cabac_table[] = { + }; + + static void +-reorder_scaling_list(struct hantro_ctx *ctx) ++assemble_scaling_list(struct hantro_ctx *ctx) + { + const struct hantro_h264_dec_ctrls *ctrls = &ctx->h264_dec.ctrls; + const struct v4l2_ctrl_h264_scaling_matrix *scaling = ctrls->scaling; +@@ -235,7 +235,7 @@ static void prepare_table(struct hantro_ctx *ctx) + tbl->poc[32] = dec_param->top_field_order_cnt; + tbl->poc[33] = dec_param->bottom_field_order_cnt; + +- reorder_scaling_list(ctx); ++ assemble_scaling_list(ctx); + } + + static bool dpb_entry_match(const struct v4l2_h264_dpb_entry *a, + +From 63c05ac390a6fb9d4930804931732630dd0e20ac Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Wed, 1 Jul 2020 15:16:04 +0200 +Subject: [PATCH] hantro: Rework how encoder and decoder are identified + +So far we've been using the .buf_finish hook to distinguish +decoder from encoder. This is unnecessarily obfuscated. + +Moreover, we want to move the buf_finish, so use a cleaner +scheme to distinguish the driver decoder/encoder type. + +Signed-off-by: Ezequiel Garcia +Reviewed-by: Philipp Zabel +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +(cherry picked from commit 21f0315b7b3ee6ca909d81a963744671fb27bf71) +--- + drivers/staging/media/hantro/hantro.h | 6 ++--- + drivers/staging/media/hantro/hantro_drv.c | 9 +++---- + drivers/staging/media/hantro/hantro_v4l2.c | 28 +++++++++++----------- + 3 files changed, 20 insertions(+), 23 deletions(-) + +diff --git a/drivers/staging/media/hantro/hantro.h b/drivers/staging/media/hantro/hantro.h +index 3005207fc6fb..2284e23d8500 100644 +--- a/drivers/staging/media/hantro/hantro.h ++++ b/drivers/staging/media/hantro/hantro.h +@@ -199,6 +199,7 @@ struct hantro_dev { + * + * @dev: VPU driver data to which the context belongs. + * @fh: V4L2 file handler. ++ * @is_encoder: Decoder or encoder context? + * + * @sequence_cap: Sequence counter for capture queue + * @sequence_out: Sequence counter for output queue +@@ -223,6 +224,7 @@ struct hantro_dev { + struct hantro_ctx { + struct hantro_dev *dev; + struct v4l2_fh fh; ++ bool is_encoder; + + u32 sequence_cap; + u32 sequence_out; +@@ -399,8 +401,6 @@ static inline void hantro_reg_write_s(struct hantro_dev *vpu, + vdpu_write(vpu, vdpu_read_mask(vpu, reg, val), reg->base); + } + +-bool hantro_is_encoder_ctx(const struct hantro_ctx *ctx); +- + void *hantro_get_ctrl(struct hantro_ctx *ctx, u32 id); + dma_addr_t hantro_get_ref(struct hantro_ctx *ctx, u64 ts); + +@@ -420,7 +420,7 @@ static inline bool + hantro_needs_postproc(const struct hantro_ctx *ctx, + const struct hantro_fmt *fmt) + { +- return !hantro_is_encoder_ctx(ctx) && fmt->fourcc != V4L2_PIX_FMT_NV12; ++ return !ctx->is_encoder && fmt->fourcc != V4L2_PIX_FMT_NV12; + } + + static inline dma_addr_t +diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c +index 0db8ad455160..9145d02e5d3c 100644 +--- a/drivers/staging/media/hantro/hantro_drv.c ++++ b/drivers/staging/media/hantro/hantro_drv.c +@@ -195,11 +195,6 @@ static void device_run(void *priv) + hantro_job_finish(ctx->dev, ctx, 0, VB2_BUF_STATE_ERROR); + } + +-bool hantro_is_encoder_ctx(const struct hantro_ctx *ctx) +-{ +- return ctx->buf_finish == hantro_enc_buf_finish; +-} +- + static struct v4l2_m2m_ops vpu_m2m_ops = { + .device_run = device_run, + }; +@@ -240,7 +235,7 @@ queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq) + * + * For the DMA destination buffer, we use a bounce buffer. + */ +- if (hantro_is_encoder_ctx(ctx)) { ++ if (ctx->is_encoder) { + dst_vq->mem_ops = &vb2_vmalloc_memops; + } else { + dst_vq->bidirectional = true; +@@ -420,8 +415,10 @@ static int hantro_open(struct file *filp) + if (func->id == MEDIA_ENT_F_PROC_VIDEO_ENCODER) { + allowed_codecs = vpu->variant->codec & HANTRO_ENCODERS; + ctx->buf_finish = hantro_enc_buf_finish; ++ ctx->is_encoder = true; + } else if (func->id == MEDIA_ENT_F_PROC_VIDEO_DECODER) { + allowed_codecs = vpu->variant->codec & HANTRO_DECODERS; ++ ctx->is_encoder = false; + } else { + ret = -ENODEV; + goto err_ctx_free; +diff --git a/drivers/staging/media/hantro/hantro_v4l2.c b/drivers/staging/media/hantro/hantro_v4l2.c +index 63859e8a0923..b668a82d40ad 100644 +--- a/drivers/staging/media/hantro/hantro_v4l2.c ++++ b/drivers/staging/media/hantro/hantro_v4l2.c +@@ -40,7 +40,7 @@ hantro_get_formats(const struct hantro_ctx *ctx, unsigned int *num_fmts) + { + const struct hantro_fmt *formats; + +- if (hantro_is_encoder_ctx(ctx)) { ++ if (ctx->is_encoder) { + formats = ctx->dev->variant->enc_fmts; + *num_fmts = ctx->dev->variant->num_enc_fmts; + } else { +@@ -55,7 +55,7 @@ static const struct hantro_fmt * + hantro_get_postproc_formats(const struct hantro_ctx *ctx, + unsigned int *num_fmts) + { +- if (hantro_is_encoder_ctx(ctx)) { ++ if (ctx->is_encoder) { + *num_fmts = 0; + return NULL; + } +@@ -158,7 +158,7 @@ static int vidioc_enum_fmt(struct file *file, void *priv, + * not MODE_NONE. + * - on the output side we want to filter out all MODE_NONE formats. + */ +- skip_mode_none = capture == hantro_is_encoder_ctx(ctx); ++ skip_mode_none = capture == ctx->is_encoder; + + formats = hantro_get_formats(ctx, &num_fmts); + for (i = 0; i < num_fmts; i++) { +@@ -240,7 +240,7 @@ static int hantro_try_fmt(const struct hantro_ctx *ctx, + bool capture = V4L2_TYPE_IS_CAPTURE(type); + bool coded; + +- coded = capture == hantro_is_encoder_ctx(ctx); ++ coded = capture == ctx->is_encoder; + + vpu_debug(4, "trying format %c%c%c%c\n", + (pix_mp->pixelformat & 0x7f), +@@ -257,7 +257,7 @@ static int hantro_try_fmt(const struct hantro_ctx *ctx, + if (coded) { + pix_mp->num_planes = 1; + vpu_fmt = fmt; +- } else if (hantro_is_encoder_ctx(ctx)) { ++ } else if (ctx->is_encoder) { + vpu_fmt = ctx->vpu_dst_fmt; + } else { + vpu_fmt = ctx->vpu_src_fmt; +@@ -330,7 +330,7 @@ hantro_reset_encoded_fmt(struct hantro_ctx *ctx) + + vpu_fmt = hantro_get_default_fmt(ctx, true); + +- if (hantro_is_encoder_ctx(ctx)) { ++ if (ctx->is_encoder) { + ctx->vpu_dst_fmt = vpu_fmt; + fmt = &ctx->dst_fmt; + } else { +@@ -341,7 +341,7 @@ hantro_reset_encoded_fmt(struct hantro_ctx *ctx) + hantro_reset_fmt(fmt, vpu_fmt); + fmt->width = vpu_fmt->frmsize.min_width; + fmt->height = vpu_fmt->frmsize.min_height; +- if (hantro_is_encoder_ctx(ctx)) ++ if (ctx->is_encoder) + hantro_set_fmt_cap(ctx, fmt); + else + hantro_set_fmt_out(ctx, fmt); +@@ -355,7 +355,7 @@ hantro_reset_raw_fmt(struct hantro_ctx *ctx) + + raw_vpu_fmt = hantro_get_default_fmt(ctx, false); + +- if (hantro_is_encoder_ctx(ctx)) { ++ if (ctx->is_encoder) { + ctx->vpu_src_fmt = raw_vpu_fmt; + raw_fmt = &ctx->src_fmt; + encoded_fmt = &ctx->dst_fmt; +@@ -368,7 +368,7 @@ hantro_reset_raw_fmt(struct hantro_ctx *ctx) + hantro_reset_fmt(raw_fmt, raw_vpu_fmt); + raw_fmt->width = encoded_fmt->width; + raw_fmt->width = encoded_fmt->width; +- if (hantro_is_encoder_ctx(ctx)) ++ if (ctx->is_encoder) + hantro_set_fmt_out(ctx, raw_fmt); + else + hantro_set_fmt_cap(ctx, raw_fmt); +@@ -409,7 +409,7 @@ static int hantro_set_fmt_out(struct hantro_ctx *ctx, + if (ret) + return ret; + +- if (!hantro_is_encoder_ctx(ctx)) { ++ if (!ctx->is_encoder) { + struct vb2_queue *peer_vq; + + /* +@@ -450,7 +450,7 @@ static int hantro_set_fmt_out(struct hantro_ctx *ctx, + * Note that hantro_reset_raw_fmt() also propagates size + * changes to the raw format. + */ +- if (!hantro_is_encoder_ctx(ctx)) ++ if (!ctx->is_encoder) + hantro_reset_raw_fmt(ctx); + + /* Colorimetry information are always propagated. */ +@@ -479,7 +479,7 @@ static int hantro_set_fmt_cap(struct hantro_ctx *ctx, + if (vb2_is_busy(vq)) + return -EBUSY; + +- if (hantro_is_encoder_ctx(ctx)) { ++ if (ctx->is_encoder) { + struct vb2_queue *peer_vq; + + /* +@@ -512,7 +512,7 @@ static int hantro_set_fmt_cap(struct hantro_ctx *ctx, + * Note that hantro_reset_raw_fmt() also propagates size + * changes to the raw format. + */ +- if (hantro_is_encoder_ctx(ctx)) ++ if (ctx->is_encoder) + hantro_reset_raw_fmt(ctx); + + /* Colorimetry information are always propagated. */ +@@ -655,7 +655,7 @@ static bool hantro_vq_is_coded(struct vb2_queue *q) + { + struct hantro_ctx *ctx = vb2_get_drv_priv(q); + +- return hantro_is_encoder_ctx(ctx) != V4L2_TYPE_IS_OUTPUT(q->type); ++ return ctx->is_encoder != V4L2_TYPE_IS_OUTPUT(q->type); + } + + static int hantro_start_streaming(struct vb2_queue *q, unsigned int count) + +From 9067e59021400f6924e6fe593585bb6a561ef251 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Wed, 1 Jul 2020 15:16:05 +0200 +Subject: [PATCH] hantro: Move hantro_enc_buf_finish to JPEG codec_ops.done + +hantro_enc_buf_finish is used only for JPEG, and so should +be moved to JPEG codec_ops.done. + +This cleanup is also taking care of addressing +a subtle issue: checking the non-NULL bounce buffer +using ctx->jpeg_enc, which is a member of a union is +confusing and error-prone. + +Note that the issue is currently innocuous because an +encoder context only supports JPEG. + +The codec_ops.done has an argument that codec-specific code +shouldn't need, so drop that as well. + +Signed-off-by: Ezequiel Garcia +Reviewed-by: Philipp Zabel +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +(cherry picked from commit e765dba11ec26d7ea42974ec4d470b5ce00be3de) +--- + drivers/staging/media/hantro/hantro.h | 7 ---- + drivers/staging/media/hantro/hantro_drv.c | 37 ++----------------- + .../staging/media/hantro/hantro_h1_jpeg_enc.c | 17 +++++++++ + drivers/staging/media/hantro/hantro_hw.h | 3 +- + drivers/staging/media/hantro/rk3288_vpu_hw.c | 1 + + 5 files changed, 24 insertions(+), 41 deletions(-) + +diff --git a/drivers/staging/media/hantro/hantro.h b/drivers/staging/media/hantro/hantro.h +index 2284e23d8500..65f9f7ea7dcf 100644 +--- a/drivers/staging/media/hantro/hantro.h ++++ b/drivers/staging/media/hantro/hantro.h +@@ -212,9 +212,6 @@ struct hantro_dev { + * @ctrl_handler: Control handler used to register controls. + * @jpeg_quality: User-specified JPEG compression quality. + * +- * @buf_finish: Buffer finish. This depends on encoder or decoder +- * context, and it's called right before +- * calling v4l2_m2m_job_finish. + * @codec_ops: Set of operations related to codec mode. + * @postproc: Post-processing context. + * @jpeg_enc: JPEG-encoding context. +@@ -237,10 +234,6 @@ struct hantro_ctx { + struct v4l2_ctrl_handler ctrl_handler; + int jpeg_quality; + +- int (*buf_finish)(struct hantro_ctx *ctx, +- struct vb2_buffer *buf, +- unsigned int bytesused); +- + const struct hantro_codec_ops *codec_ops; + struct hantro_postproc_ctx postproc; + +diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c +index 9145d02e5d3c..88b5c5989d83 100644 +--- a/drivers/staging/media/hantro/hantro_drv.c ++++ b/drivers/staging/media/hantro/hantro_drv.c +@@ -56,37 +56,12 @@ dma_addr_t hantro_get_ref(struct hantro_ctx *ctx, u64 ts) + return hantro_get_dec_buf_addr(ctx, buf); + } + +-static int +-hantro_enc_buf_finish(struct hantro_ctx *ctx, struct vb2_buffer *buf, +- unsigned int bytesused) +-{ +- size_t avail_size; +- +- avail_size = vb2_plane_size(buf, 0) - ctx->vpu_dst_fmt->header_size; +- if (bytesused > avail_size) +- return -EINVAL; +- /* +- * The bounce buffer is only for the JPEG encoder. +- * TODO: Rework the JPEG encoder to eliminate the need +- * for a bounce buffer. +- */ +- if (ctx->jpeg_enc.bounce_buffer.cpu) { +- memcpy(vb2_plane_vaddr(buf, 0) + +- ctx->vpu_dst_fmt->header_size, +- ctx->jpeg_enc.bounce_buffer.cpu, bytesused); +- } +- buf->planes[0].bytesused = +- ctx->vpu_dst_fmt->header_size + bytesused; +- return 0; +-} +- + static void hantro_job_finish(struct hantro_dev *vpu, + struct hantro_ctx *ctx, + unsigned int bytesused, + enum vb2_buffer_state result) + { + struct vb2_v4l2_buffer *src, *dst; +- int ret; + + pm_runtime_mark_last_busy(vpu->dev); + pm_runtime_put_autosuspend(vpu->dev); +@@ -103,12 +78,6 @@ static void hantro_job_finish(struct hantro_dev *vpu, + src->sequence = ctx->sequence_out++; + dst->sequence = ctx->sequence_cap++; + +- if (ctx->buf_finish) { +- ret = ctx->buf_finish(ctx, &dst->vb2_buf, bytesused); +- if (ret) +- result = VB2_BUF_STATE_ERROR; +- } +- + v4l2_m2m_buf_done_and_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx, + result); + } +@@ -124,8 +93,11 @@ void hantro_irq_done(struct hantro_dev *vpu, unsigned int bytesused, + * the timeout expired. The watchdog is running, + * and will take care of finishing the job. + */ +- if (cancel_delayed_work(&vpu->watchdog_work)) ++ if (cancel_delayed_work(&vpu->watchdog_work)) { ++ if (result == VB2_BUF_STATE_DONE && ctx->codec_ops->done) ++ ctx->codec_ops->done(ctx); + hantro_job_finish(vpu, ctx, bytesused, result); ++ } + } + + void hantro_watchdog(struct work_struct *work) +@@ -414,7 +386,6 @@ static int hantro_open(struct file *filp) + ctx->dev = vpu; + if (func->id == MEDIA_ENT_F_PROC_VIDEO_ENCODER) { + allowed_codecs = vpu->variant->codec & HANTRO_ENCODERS; +- ctx->buf_finish = hantro_enc_buf_finish; + ctx->is_encoder = true; + } else if (func->id == MEDIA_ENT_F_PROC_VIDEO_DECODER) { + allowed_codecs = vpu->variant->codec & HANTRO_DECODERS; +diff --git a/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c b/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c +index b22418436823..b88dc4ed06db 100644 +--- a/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c ++++ b/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c +@@ -137,3 +137,20 @@ void hantro_h1_jpeg_enc_run(struct hantro_ctx *ctx) + + vepu_write(vpu, reg, H1_REG_ENC_CTRL); + } ++ ++void hantro_jpeg_enc_done(struct hantro_ctx *ctx) ++{ ++ struct hantro_dev *vpu = ctx->dev; ++ u32 bytesused = vepu_read(vpu, H1_REG_STR_BUF_LIMIT) / 8; ++ struct vb2_v4l2_buffer *dst_buf = hantro_get_dst_buf(ctx); ++ ++ /* ++ * TODO: Rework the JPEG encoder to eliminate the need ++ * for a bounce buffer. ++ */ ++ memcpy(vb2_plane_vaddr(&dst_buf->vb2_buf, 0) + ++ ctx->vpu_dst_fmt->header_size, ++ ctx->jpeg_enc.bounce_buffer.cpu, bytesused); ++ vb2_set_plane_payload(&dst_buf->vb2_buf, 0, ++ ctx->vpu_dst_fmt->header_size + bytesused); ++} +diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h +index 4053d8710e04..2d6323cd6732 100644 +--- a/drivers/staging/media/hantro/hantro_hw.h ++++ b/drivers/staging/media/hantro/hantro_hw.h +@@ -138,7 +138,7 @@ struct hantro_codec_ops { + int (*init)(struct hantro_ctx *ctx); + void (*exit)(struct hantro_ctx *ctx); + void (*run)(struct hantro_ctx *ctx); +- void (*done)(struct hantro_ctx *ctx, enum vb2_buffer_state); ++ void (*done)(struct hantro_ctx *ctx); + void (*reset)(struct hantro_ctx *ctx); + }; + +@@ -172,6 +172,7 @@ void hantro_h1_jpeg_enc_run(struct hantro_ctx *ctx); + void rk3399_vpu_jpeg_enc_run(struct hantro_ctx *ctx); + int hantro_jpeg_enc_init(struct hantro_ctx *ctx); + void hantro_jpeg_enc_exit(struct hantro_ctx *ctx); ++void hantro_jpeg_enc_done(struct hantro_ctx *ctx); + + dma_addr_t hantro_h264_get_ref_buf(struct hantro_ctx *ctx, + unsigned int dpb_idx); +diff --git a/drivers/staging/media/hantro/rk3288_vpu_hw.c b/drivers/staging/media/hantro/rk3288_vpu_hw.c +index 2f914b37b9e5..b1cf2abb972f 100644 +--- a/drivers/staging/media/hantro/rk3288_vpu_hw.c ++++ b/drivers/staging/media/hantro/rk3288_vpu_hw.c +@@ -180,6 +180,7 @@ static const struct hantro_codec_ops rk3288_vpu_codec_ops[] = { + .run = hantro_h1_jpeg_enc_run, + .reset = rk3288_vpu_enc_reset, + .init = hantro_jpeg_enc_init, ++ .done = hantro_jpeg_enc_done, + .exit = hantro_jpeg_enc_exit, + }, + [HANTRO_MODE_H264_DEC] = { + +From 7d3bf1fa2170bacf99bd02ccd7dc0f5fdc1fbc45 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Wed, 1 Jul 2020 15:16:06 +0200 +Subject: [PATCH] hantro: Remove unused bytesused argument + +The driver doesn't need the bytesused argument. + +For decoders, the plane bytesused is known and therefore, +buf_prepare is used to set it. For encoders, it's +handled by the codec_ops.done hook. + +Signed-off-by: Ezequiel Garcia +Reviewed-by: Philipp Zabel +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +(cherry picked from commit b72a6342dd240ce8e15b7acf1c38c67a0c56092b) +--- + drivers/staging/media/hantro/hantro_drv.c | 9 ++++----- + drivers/staging/media/hantro/hantro_hw.h | 2 +- + drivers/staging/media/hantro/imx8m_vpu_hw.c | 2 +- + drivers/staging/media/hantro/rk3288_vpu_hw.c | 7 +++---- + drivers/staging/media/hantro/rk3399_vpu_hw.c | 7 +++---- + 5 files changed, 12 insertions(+), 15 deletions(-) + +diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c +index 88b5c5989d83..34367b169011 100644 +--- a/drivers/staging/media/hantro/hantro_drv.c ++++ b/drivers/staging/media/hantro/hantro_drv.c +@@ -58,7 +58,6 @@ dma_addr_t hantro_get_ref(struct hantro_ctx *ctx, u64 ts) + + static void hantro_job_finish(struct hantro_dev *vpu, + struct hantro_ctx *ctx, +- unsigned int bytesused, + enum vb2_buffer_state result) + { + struct vb2_v4l2_buffer *src, *dst; +@@ -82,7 +81,7 @@ static void hantro_job_finish(struct hantro_dev *vpu, + result); + } + +-void hantro_irq_done(struct hantro_dev *vpu, unsigned int bytesused, ++void hantro_irq_done(struct hantro_dev *vpu, + enum vb2_buffer_state result) + { + struct hantro_ctx *ctx = +@@ -96,7 +95,7 @@ void hantro_irq_done(struct hantro_dev *vpu, unsigned int bytesused, + if (cancel_delayed_work(&vpu->watchdog_work)) { + if (result == VB2_BUF_STATE_DONE && ctx->codec_ops->done) + ctx->codec_ops->done(ctx); +- hantro_job_finish(vpu, ctx, bytesused, result); ++ hantro_job_finish(vpu, ctx, result); + } + } + +@@ -111,7 +110,7 @@ void hantro_watchdog(struct work_struct *work) + if (ctx) { + vpu_err("frame processing timed out!\n"); + ctx->codec_ops->reset(ctx); +- hantro_job_finish(vpu, ctx, 0, VB2_BUF_STATE_ERROR); ++ hantro_job_finish(vpu, ctx, VB2_BUF_STATE_ERROR); + } + } + +@@ -164,7 +163,7 @@ static void device_run(void *priv) + return; + + err_cancel_job: +- hantro_job_finish(ctx->dev, ctx, 0, VB2_BUF_STATE_ERROR); ++ hantro_job_finish(ctx->dev, ctx, VB2_BUF_STATE_ERROR); + } + + static struct v4l2_m2m_ops vpu_m2m_ops = { +diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h +index 2d6323cd6732..f066de6b592d 100644 +--- a/drivers/staging/media/hantro/hantro_hw.h ++++ b/drivers/staging/media/hantro/hantro_hw.h +@@ -163,7 +163,7 @@ extern const u32 hantro_vp8_dec_mc_filter[8][6]; + + void hantro_watchdog(struct work_struct *work); + void hantro_run(struct hantro_ctx *ctx); +-void hantro_irq_done(struct hantro_dev *vpu, unsigned int bytesused, ++void hantro_irq_done(struct hantro_dev *vpu, + enum vb2_buffer_state result); + void hantro_start_prepare_run(struct hantro_ctx *ctx); + void hantro_end_prepare_run(struct hantro_ctx *ctx); +diff --git a/drivers/staging/media/hantro/imx8m_vpu_hw.c b/drivers/staging/media/hantro/imx8m_vpu_hw.c +index cb2420c5526e..c222de075ef4 100644 +--- a/drivers/staging/media/hantro/imx8m_vpu_hw.c ++++ b/drivers/staging/media/hantro/imx8m_vpu_hw.c +@@ -143,7 +143,7 @@ static irqreturn_t imx8m_vpu_g1_irq(int irq, void *dev_id) + vdpu_write(vpu, 0, G1_REG_INTERRUPT); + vdpu_write(vpu, G1_REG_CONFIG_DEC_CLK_GATE_E, G1_REG_CONFIG); + +- hantro_irq_done(vpu, 0, state); ++ hantro_irq_done(vpu, state); + + return IRQ_HANDLED; + } +diff --git a/drivers/staging/media/hantro/rk3288_vpu_hw.c b/drivers/staging/media/hantro/rk3288_vpu_hw.c +index b1cf2abb972f..7b299ee3e93d 100644 +--- a/drivers/staging/media/hantro/rk3288_vpu_hw.c ++++ b/drivers/staging/media/hantro/rk3288_vpu_hw.c +@@ -113,17 +113,16 @@ static irqreturn_t rk3288_vepu_irq(int irq, void *dev_id) + { + struct hantro_dev *vpu = dev_id; + enum vb2_buffer_state state; +- u32 status, bytesused; ++ u32 status; + + status = vepu_read(vpu, H1_REG_INTERRUPT); +- bytesused = vepu_read(vpu, H1_REG_STR_BUF_LIMIT) / 8; + state = (status & H1_REG_INTERRUPT_FRAME_RDY) ? + VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR; + + vepu_write(vpu, 0, H1_REG_INTERRUPT); + vepu_write(vpu, 0, H1_REG_AXI_CTRL); + +- hantro_irq_done(vpu, bytesused, state); ++ hantro_irq_done(vpu, state); + + return IRQ_HANDLED; + } +@@ -141,7 +140,7 @@ static irqreturn_t rk3288_vdpu_irq(int irq, void *dev_id) + vdpu_write(vpu, 0, G1_REG_INTERRUPT); + vdpu_write(vpu, G1_REG_CONFIG_DEC_CLK_GATE_E, G1_REG_CONFIG); + +- hantro_irq_done(vpu, 0, state); ++ hantro_irq_done(vpu, state); + + return IRQ_HANDLED; + } +diff --git a/drivers/staging/media/hantro/rk3399_vpu_hw.c b/drivers/staging/media/hantro/rk3399_vpu_hw.c +index 9ac1f2cb6a16..7a7962cf771e 100644 +--- a/drivers/staging/media/hantro/rk3399_vpu_hw.c ++++ b/drivers/staging/media/hantro/rk3399_vpu_hw.c +@@ -92,17 +92,16 @@ static irqreturn_t rk3399_vepu_irq(int irq, void *dev_id) + { + struct hantro_dev *vpu = dev_id; + enum vb2_buffer_state state; +- u32 status, bytesused; ++ u32 status; + + status = vepu_read(vpu, VEPU_REG_INTERRUPT); +- bytesused = vepu_read(vpu, VEPU_REG_STR_BUF_LIMIT) / 8; + state = (status & VEPU_REG_INTERRUPT_FRAME_READY) ? + VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR; + + vepu_write(vpu, 0, VEPU_REG_INTERRUPT); + vepu_write(vpu, 0, VEPU_REG_AXI_CTRL); + +- hantro_irq_done(vpu, bytesused, state); ++ hantro_irq_done(vpu, state); + + return IRQ_HANDLED; + } +@@ -120,7 +119,7 @@ static irqreturn_t rk3399_vdpu_irq(int irq, void *dev_id) + vdpu_write(vpu, 0, VDPU_REG_INTERRUPT); + vdpu_write(vpu, 0, VDPU_REG_AXI_CTRL); + +- hantro_irq_done(vpu, 0, state); ++ hantro_irq_done(vpu, state); + + return IRQ_HANDLED; + } + +From 7e6a3bfc6d6ac30204d5ad0fc6496f1c263f809b Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Wed, 1 Jul 2020 15:16:07 +0200 +Subject: [PATCH] hantro: Make sure we don't use post-processor on an encoder + +Commit 986eee3a5234 ("media: hantro: Prevent encoders from using +post-processing") fixed hantro_needs_postproc condition, +but missed one case. Encoders don't have any post-processor +hardware block, so also can't be disabled. + +Fix it. + +Fixes: 986eee3a5234 ("media: hantro: Prevent encoders from using post-processing") +Signed-off-by: Ezequiel Garcia +Reviewed-by: Philipp Zabel +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +(cherry picked from commit 46d7aaebbe441d5381e35d8e16df784690e65ef3) +--- + drivers/staging/media/hantro/hantro_drv.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c +index 34367b169011..d32b6b1ab70b 100644 +--- a/drivers/staging/media/hantro/hantro_drv.c ++++ b/drivers/staging/media/hantro/hantro_drv.c +@@ -122,10 +122,12 @@ void hantro_start_prepare_run(struct hantro_ctx *ctx) + v4l2_ctrl_request_setup(src_buf->vb2_buf.req_obj.req, + &ctx->ctrl_handler); + +- if (hantro_needs_postproc(ctx, ctx->vpu_dst_fmt)) +- hantro_postproc_enable(ctx); +- else +- hantro_postproc_disable(ctx); ++ if (!ctx->is_encoder) { ++ if (hantro_needs_postproc(ctx, ctx->vpu_dst_fmt)) ++ hantro_postproc_enable(ctx); ++ else ++ hantro_postproc_disable(ctx); ++ } + } + + void hantro_end_prepare_run(struct hantro_ctx *ctx) + +From 1f833bbde61660aabc0320b314bab5a2f7e42d10 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Thu, 9 Jul 2020 18:36:34 +0200 +Subject: [PATCH] rkvdec: h264: Refuse to decode unsupported bitstream + +The hardware only supports 4:2:2, 4:2:0 or 4:0:0 (monochrome), +8-bit or 10-bit depth content. + +Verify that the SPS refers to a supported bitstream, and refuse +unsupported bitstreams by failing at TRY_EXT_CTRLS time. + +The driver is currently broken on 10-bit and 4:2:2 +so disallow those as well. + +Signed-off-by: Ezequiel Garcia +Reviewed-by: Jonas Karlman +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +(cherry picked from commit 9363aa33f6a9acfd16f98c749f17f6c65d184670) +--- + drivers/staging/media/rkvdec/rkvdec.c | 27 +++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index fd68671f0286..c8151328fb70 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -27,6 +27,32 @@ + #include "rkvdec.h" + #include "rkvdec-regs.h" + ++static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_SPS) { ++ const struct v4l2_ctrl_h264_sps *sps = ctrl->p_new.p_h264_sps; ++ /* ++ * TODO: The hardware supports 10-bit and 4:2:2 profiles, ++ * but it's currently broken in the driver. ++ * Reject them for now, until it's fixed. ++ */ ++ if (sps->chroma_format_idc > 1) ++ /* Only 4:0:0 and 4:2:0 are supported */ ++ return -EINVAL; ++ if (sps->bit_depth_luma_minus8 != sps->bit_depth_chroma_minus8) ++ /* Luma and chroma bit depth mismatch */ ++ return -EINVAL; ++ if (sps->bit_depth_luma_minus8 != 0) ++ /* Only 8-bit is supported */ ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static const struct v4l2_ctrl_ops rkvdec_ctrl_ops = { ++ .try_ctrl = rkvdec_try_ctrl, ++}; ++ + static const struct rkvdec_ctrl_desc rkvdec_h264_ctrl_descs[] = { + { + .per_request = true, +@@ -42,6 +68,7 @@ static const struct rkvdec_ctrl_desc rkvdec_h264_ctrl_descs[] = { + .per_request = true, + .mandatory = true, + .cfg.id = V4L2_CID_MPEG_VIDEO_H264_SPS, ++ .cfg.ops = &rkvdec_ctrl_ops, + }, + { + .per_request = true, + +From c09155eb49e230da5fa16f188677120f967bbb36 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Thu, 9 Jul 2020 18:36:35 +0200 +Subject: [PATCH] hantro: h264: Refuse to decode unsupported bitstream + +The hardware only supports 4:2:0 or 4:0:0 (monochrome), +8-bit depth content. + +Verify that the SPS refers to a supported bitstream, and refuse +unsupported bitstreams by failing at TRY_EXT_CTRLS time. + +Given the JPEG compression level control is the only one +that needs setting, a specific ops is provided. + +Signed-off-by: Ezequiel Garcia +Reviewed-by: Philipp Zabel +Reviewed-by: Jonas Karlman +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +(cherry picked from commit d70cca7323442026e20c474314518c446cb4766f) +--- + drivers/staging/media/hantro/hantro_drv.c | 29 ++++++++++++++++++++--- + 1 file changed, 26 insertions(+), 3 deletions(-) + +diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c +index d32b6b1ab70b..34797507f214 100644 +--- a/drivers/staging/media/hantro/hantro_drv.c ++++ b/drivers/staging/media/hantro/hantro_drv.c +@@ -229,7 +229,25 @@ queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq) + return vb2_queue_init(dst_vq); + } + +-static int hantro_s_ctrl(struct v4l2_ctrl *ctrl) ++static int hantro_try_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_SPS) { ++ const struct v4l2_ctrl_h264_sps *sps = ctrl->p_new.p_h264_sps; ++ ++ if (sps->chroma_format_idc > 1) ++ /* Only 4:0:0 and 4:2:0 are supported */ ++ return -EINVAL; ++ if (sps->bit_depth_luma_minus8 != sps->bit_depth_chroma_minus8) ++ /* Luma and chroma bit depth mismatch */ ++ return -EINVAL; ++ if (sps->bit_depth_luma_minus8 != 0) ++ /* Only 8-bit is supported */ ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int hantro_jpeg_s_ctrl(struct v4l2_ctrl *ctrl) + { + struct hantro_ctx *ctx; + +@@ -250,7 +268,11 @@ static int hantro_s_ctrl(struct v4l2_ctrl *ctrl) + } + + static const struct v4l2_ctrl_ops hantro_ctrl_ops = { +- .s_ctrl = hantro_s_ctrl, ++ .try_ctrl = hantro_try_ctrl, ++}; ++ ++static const struct v4l2_ctrl_ops hantro_jpeg_ctrl_ops = { ++ .s_ctrl = hantro_jpeg_s_ctrl, + }; + + static const struct hantro_ctrl controls[] = { +@@ -262,7 +284,7 @@ static const struct hantro_ctrl controls[] = { + .max = 100, + .step = 1, + .def = 50, +- .ops = &hantro_ctrl_ops, ++ .ops = &hantro_jpeg_ctrl_ops, + }, + }, { + .codec = HANTRO_MPEG2_DECODER, +@@ -293,6 +315,7 @@ static const struct hantro_ctrl controls[] = { + .codec = HANTRO_H264_DECODER, + .cfg = { + .id = V4L2_CID_MPEG_VIDEO_H264_SPS, ++ .ops = &hantro_ctrl_ops, + }, + }, { + .codec = HANTRO_H264_DECODER, diff --git a/patch/kernel/rk322x-current/01-linux-0012-v4l2-from-next-from-list.patch b/patch/kernel/rk322x-current/01-linux-0012-v4l2-from-next-from-list.patch new file mode 100644 index 000000000..c06b7447b --- /dev/null +++ b/patch/kernel/rk322x-current/01-linux-0012-v4l2-from-next-from-list.patch @@ -0,0 +1,7852 @@ +From 337af64a63b5d8d5a60ad8302cca0bfa4d0cc4ad Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Fri, 17 Jul 2020 16:53:16 +0200 +Subject: [PATCH] media: i2c: Use the new get_mbus_config pad op + +Move the existing users of the g_mbus_config video operation to use the +newly introduced get_mbus_config pad operations. + +All the ported drivers report a static media bus configuration and do no +support s_mbus_config so the operation implementation has not changed. + +Bridge drivers needs to call the new pad operation and will receive an +-ENOICTLCMD when calling the old g_mbus_config video operation + +Signed-off-by: Jacopo Mondi +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/i2c/adv7180.c | 7 ++++--- + drivers/media/i2c/ml86v7667.c | 7 ++++--- + drivers/media/i2c/mt9m001.c | 7 ++++--- + drivers/media/i2c/mt9m111.c | 7 ++++--- + drivers/media/i2c/ov9640.c | 7 ++++--- + drivers/media/i2c/tc358743.c | 7 ++++--- + drivers/media/i2c/tvp5150.c | 7 ++++--- + 7 files changed, 28 insertions(+), 21 deletions(-) + +diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c +index 00159daa6fcd..e8744efe3cf0 100644 +--- a/drivers/media/i2c/adv7180.c ++++ b/drivers/media/i2c/adv7180.c +@@ -760,8 +760,9 @@ static int adv7180_init_cfg(struct v4l2_subdev *sd, + return adv7180_set_pad_format(sd, cfg, &fmt); + } + +-static int adv7180_g_mbus_config(struct v4l2_subdev *sd, +- struct v4l2_mbus_config *cfg) ++static int adv7180_get_mbus_config(struct v4l2_subdev *sd, ++ unsigned int pad, ++ struct v4l2_mbus_config *cfg) + { + struct adv7180_state *state = to_state(sd); + +@@ -852,7 +853,6 @@ static const struct v4l2_subdev_video_ops adv7180_video_ops = { + .querystd = adv7180_querystd, + .g_input_status = adv7180_g_input_status, + .s_routing = adv7180_s_routing, +- .g_mbus_config = adv7180_g_mbus_config, + .g_pixelaspect = adv7180_g_pixelaspect, + .g_tvnorms = adv7180_g_tvnorms, + .s_stream = adv7180_s_stream, +@@ -869,6 +869,7 @@ static const struct v4l2_subdev_pad_ops adv7180_pad_ops = { + .enum_mbus_code = adv7180_enum_mbus_code, + .set_fmt = adv7180_set_pad_format, + .get_fmt = adv7180_get_pad_format, ++ .get_mbus_config = adv7180_get_mbus_config, + }; + + static const struct v4l2_subdev_sensor_ops adv7180_sensor_ops = { +diff --git a/drivers/media/i2c/ml86v7667.c b/drivers/media/i2c/ml86v7667.c +index c444bd6a0658..ff212335326a 100644 +--- a/drivers/media/i2c/ml86v7667.c ++++ b/drivers/media/i2c/ml86v7667.c +@@ -219,8 +219,9 @@ static int ml86v7667_fill_fmt(struct v4l2_subdev *sd, + return 0; + } + +-static int ml86v7667_g_mbus_config(struct v4l2_subdev *sd, +- struct v4l2_mbus_config *cfg) ++static int ml86v7667_get_mbus_config(struct v4l2_subdev *sd, ++ unsigned int pad, ++ struct v4l2_mbus_config *cfg) + { + cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING | + V4L2_MBUS_DATA_ACTIVE_HIGH; +@@ -291,13 +292,13 @@ static const struct v4l2_subdev_video_ops ml86v7667_subdev_video_ops = { + .s_std = ml86v7667_s_std, + .querystd = ml86v7667_querystd, + .g_input_status = ml86v7667_g_input_status, +- .g_mbus_config = ml86v7667_g_mbus_config, + }; + + static const struct v4l2_subdev_pad_ops ml86v7667_subdev_pad_ops = { + .enum_mbus_code = ml86v7667_enum_mbus_code, + .get_fmt = ml86v7667_fill_fmt, + .set_fmt = ml86v7667_fill_fmt, ++ .get_mbus_config = ml86v7667_get_mbus_config, + }; + + static const struct v4l2_subdev_core_ops ml86v7667_subdev_core_ops = { +diff --git a/drivers/media/i2c/mt9m001.c b/drivers/media/i2c/mt9m001.c +index 210ea76adb53..3b0ba8ed5233 100644 +--- a/drivers/media/i2c/mt9m001.c ++++ b/drivers/media/i2c/mt9m001.c +@@ -689,8 +689,9 @@ static int mt9m001_enum_mbus_code(struct v4l2_subdev *sd, + return 0; + } + +-static int mt9m001_g_mbus_config(struct v4l2_subdev *sd, +- struct v4l2_mbus_config *cfg) ++static int mt9m001_get_mbus_config(struct v4l2_subdev *sd, ++ unsigned int pad, ++ struct v4l2_mbus_config *cfg) + { + /* MT9M001 has all capture_format parameters fixed */ + cfg->flags = V4L2_MBUS_PCLK_SAMPLE_FALLING | +@@ -703,7 +704,6 @@ static int mt9m001_g_mbus_config(struct v4l2_subdev *sd, + + static const struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = { + .s_stream = mt9m001_s_stream, +- .g_mbus_config = mt9m001_g_mbus_config, + }; + + static const struct v4l2_subdev_sensor_ops mt9m001_subdev_sensor_ops = { +@@ -717,6 +717,7 @@ static const struct v4l2_subdev_pad_ops mt9m001_subdev_pad_ops = { + .set_selection = mt9m001_set_selection, + .get_fmt = mt9m001_get_fmt, + .set_fmt = mt9m001_set_fmt, ++ .get_mbus_config = mt9m001_get_mbus_config, + }; + + static const struct v4l2_subdev_ops mt9m001_subdev_ops = { +diff --git a/drivers/media/i2c/mt9m111.c b/drivers/media/i2c/mt9m111.c +index 17e8253f5748..69697386ffcd 100644 +--- a/drivers/media/i2c/mt9m111.c ++++ b/drivers/media/i2c/mt9m111.c +@@ -1137,8 +1137,9 @@ static int mt9m111_init_cfg(struct v4l2_subdev *sd, + return 0; + } + +-static int mt9m111_g_mbus_config(struct v4l2_subdev *sd, +- struct v4l2_mbus_config *cfg) ++static int mt9m111_get_mbus_config(struct v4l2_subdev *sd, ++ unsigned int pad, ++ struct v4l2_mbus_config *cfg) + { + struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev); + +@@ -1155,7 +1156,6 @@ static int mt9m111_g_mbus_config(struct v4l2_subdev *sd, + } + + static const struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = { +- .g_mbus_config = mt9m111_g_mbus_config, + .s_stream = mt9m111_s_stream, + .g_frame_interval = mt9m111_g_frame_interval, + .s_frame_interval = mt9m111_s_frame_interval, +@@ -1168,6 +1168,7 @@ static const struct v4l2_subdev_pad_ops mt9m111_subdev_pad_ops = { + .set_selection = mt9m111_set_selection, + .get_fmt = mt9m111_get_fmt, + .set_fmt = mt9m111_set_fmt, ++ .get_mbus_config = mt9m111_get_mbus_config, + }; + + static const struct v4l2_subdev_ops mt9m111_subdev_ops = { +diff --git a/drivers/media/i2c/ov9640.c b/drivers/media/i2c/ov9640.c +index 482609665305..0ef5af026d09 100644 +--- a/drivers/media/i2c/ov9640.c ++++ b/drivers/media/i2c/ov9640.c +@@ -648,8 +648,9 @@ static const struct v4l2_subdev_core_ops ov9640_core_ops = { + }; + + /* Request bus settings on camera side */ +-static int ov9640_g_mbus_config(struct v4l2_subdev *sd, +- struct v4l2_mbus_config *cfg) ++static int ov9640_get_mbus_config(struct v4l2_subdev *sd, ++ unsigned int pad, ++ struct v4l2_mbus_config *cfg) + { + cfg->flags = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER | + V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_HIGH | +@@ -661,13 +662,13 @@ static int ov9640_g_mbus_config(struct v4l2_subdev *sd, + + static const struct v4l2_subdev_video_ops ov9640_video_ops = { + .s_stream = ov9640_s_stream, +- .g_mbus_config = ov9640_g_mbus_config, + }; + + static const struct v4l2_subdev_pad_ops ov9640_pad_ops = { + .enum_mbus_code = ov9640_enum_mbus_code, + .get_selection = ov9640_get_selection, + .set_fmt = ov9640_set_fmt, ++ .get_mbus_config = ov9640_get_mbus_config, + }; + + static const struct v4l2_subdev_ops ov9640_subdev_ops = { +diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c +index dbbab75f135e..a03dcab5ce61 100644 +--- a/drivers/media/i2c/tc358743.c ++++ b/drivers/media/i2c/tc358743.c +@@ -1602,8 +1602,9 @@ static int tc358743_dv_timings_cap(struct v4l2_subdev *sd, + return 0; + } + +-static int tc358743_g_mbus_config(struct v4l2_subdev *sd, +- struct v4l2_mbus_config *cfg) ++static int tc358743_get_mbus_config(struct v4l2_subdev *sd, ++ unsigned int pad, ++ struct v4l2_mbus_config *cfg) + { + struct tc358743_state *state = to_state(sd); + +@@ -1836,7 +1837,6 @@ static const struct v4l2_subdev_video_ops tc358743_video_ops = { + .s_dv_timings = tc358743_s_dv_timings, + .g_dv_timings = tc358743_g_dv_timings, + .query_dv_timings = tc358743_query_dv_timings, +- .g_mbus_config = tc358743_g_mbus_config, + .s_stream = tc358743_s_stream, + }; + +@@ -1848,6 +1848,7 @@ static const struct v4l2_subdev_pad_ops tc358743_pad_ops = { + .set_edid = tc358743_s_edid, + .enum_dv_timings = tc358743_enum_dv_timings, + .dv_timings_cap = tc358743_dv_timings_cap, ++ .get_mbus_config = tc358743_get_mbus_config, + }; + + static const struct v4l2_subdev_ops tc358743_ops = { +diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c +index 9df575238952..1c2050944b92 100644 +--- a/drivers/media/i2c/tvp5150.c ++++ b/drivers/media/i2c/tvp5150.c +@@ -1191,8 +1191,9 @@ static int tvp5150_get_selection(struct v4l2_subdev *sd, + } + } + +-static int tvp5150_g_mbus_config(struct v4l2_subdev *sd, +- struct v4l2_mbus_config *cfg) ++static int tvp5150_get_mbus_config(struct v4l2_subdev *sd, ++ unsigned int pad, ++ struct v4l2_mbus_config *cfg) + { + struct tvp5150 *decoder = to_tvp5150(sd); + +@@ -1721,7 +1722,6 @@ static const struct v4l2_subdev_video_ops tvp5150_video_ops = { + .querystd = tvp5150_querystd, + .s_stream = tvp5150_s_stream, + .s_routing = tvp5150_s_routing, +- .g_mbus_config = tvp5150_g_mbus_config, + }; + + static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = { +@@ -1739,6 +1739,7 @@ static const struct v4l2_subdev_pad_ops tvp5150_pad_ops = { + .get_fmt = tvp5150_fill_fmt, + .get_selection = tvp5150_get_selection, + .set_selection = tvp5150_set_selection, ++ .get_mbus_config = tvp5150_get_mbus_config, + }; + + static const struct v4l2_subdev_ops tvp5150_ops = { + +From 4cc9a9a8b16549358ea377485df8fe21ea9e1bff Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Tue, 21 Jul 2020 09:53:17 +0200 +Subject: [PATCH] media: i2c: ov6650: Use new [get|set]_mbus_config ops + +Use the new get_mbus_config and set_mbus_config pad operations in place +of the video operations currently in use. + +Compared to other drivers where the same conversion has been performed, +ov6650 proved to be a bit more tricky, as the existing g_mbus_config +implementation did not report the currently applied configuration but +the set of all possible configuration options. + +Adapt the driver to support the semantic of the two newly introduced +operations: +- get_mbus_config reports the current media bus configuration +- set_mbus_config applies only changes explicitly requested and updates + the provided cfg parameter to report what has actually been applied to + the hardware. + +Compile-tested only. + +Signed-off-by: Jacopo Mondi +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/i2c/ov6650.c | 53 ++++++++++++++++++++++++++------------ + 1 file changed, 37 insertions(+), 16 deletions(-) + +diff --git a/drivers/media/i2c/ov6650.c b/drivers/media/i2c/ov6650.c +index 91906b94f978..48493af81198 100644 +--- a/drivers/media/i2c/ov6650.c ++++ b/drivers/media/i2c/ov6650.c +@@ -921,55 +921,74 @@ static const struct v4l2_subdev_core_ops ov6650_core_ops = { + }; + + /* Request bus settings on camera side */ +-static int ov6650_g_mbus_config(struct v4l2_subdev *sd, +- struct v4l2_mbus_config *cfg) ++static int ov6650_get_mbus_config(struct v4l2_subdev *sd, ++ unsigned int pad, ++ struct v4l2_mbus_config *cfg) + { ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ u8 comj, comf; ++ int ret; ++ ++ ret = ov6650_reg_read(client, REG_COMJ, &comj); ++ if (ret) ++ return ret; + +- cfg->flags = V4L2_MBUS_MASTER | +- V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING | +- V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_LOW | +- V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_LOW | +- V4L2_MBUS_DATA_ACTIVE_HIGH; ++ ret = ov6650_reg_read(client, REG_COMF, &comf); ++ if (ret) ++ return ret; ++ ++ cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_DATA_ACTIVE_HIGH ++ | ((comj & COMJ_VSYNC_HIGH) ? V4L2_MBUS_VSYNC_ACTIVE_HIGH ++ : V4L2_MBUS_VSYNC_ACTIVE_LOW) ++ | ((comf & COMF_HREF_LOW) ? V4L2_MBUS_HSYNC_ACTIVE_LOW ++ : V4L2_MBUS_HSYNC_ACTIVE_HIGH) ++ | ((comj & COMJ_PCLK_RISING) ? V4L2_MBUS_PCLK_SAMPLE_RISING ++ : V4L2_MBUS_PCLK_SAMPLE_FALLING); + cfg->type = V4L2_MBUS_PARALLEL; + + return 0; + } + + /* Alter bus settings on camera side */ +-static int ov6650_s_mbus_config(struct v4l2_subdev *sd, +- const struct v4l2_mbus_config *cfg) ++static int ov6650_set_mbus_config(struct v4l2_subdev *sd, ++ unsigned int pad, ++ struct v4l2_mbus_config *cfg) + { + struct i2c_client *client = v4l2_get_subdevdata(sd); +- int ret; ++ int ret = 0; + + if (cfg->flags & V4L2_MBUS_PCLK_SAMPLE_RISING) + ret = ov6650_reg_rmw(client, REG_COMJ, COMJ_PCLK_RISING, 0); +- else ++ else if (cfg->flags & V4L2_MBUS_PCLK_SAMPLE_FALLING) + ret = ov6650_reg_rmw(client, REG_COMJ, 0, COMJ_PCLK_RISING); + if (ret) + return ret; + + if (cfg->flags & V4L2_MBUS_HSYNC_ACTIVE_LOW) + ret = ov6650_reg_rmw(client, REG_COMF, COMF_HREF_LOW, 0); +- else ++ else if (cfg->flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) + ret = ov6650_reg_rmw(client, REG_COMF, 0, COMF_HREF_LOW); + if (ret) + return ret; + + if (cfg->flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) + ret = ov6650_reg_rmw(client, REG_COMJ, COMJ_VSYNC_HIGH, 0); +- else ++ else if (cfg->flags & V4L2_MBUS_VSYNC_ACTIVE_LOW) + ret = ov6650_reg_rmw(client, REG_COMJ, 0, COMJ_VSYNC_HIGH); ++ if (ret) ++ return ret; + +- return ret; ++ /* ++ * Update the configuration to report what is actually applied to ++ * the hardware. ++ */ ++ return ov6650_get_mbus_config(sd, pad, cfg); + } + + static const struct v4l2_subdev_video_ops ov6650_video_ops = { + .s_stream = ov6650_s_stream, + .g_frame_interval = ov6650_g_frame_interval, + .s_frame_interval = ov6650_s_frame_interval, +- .g_mbus_config = ov6650_g_mbus_config, +- .s_mbus_config = ov6650_s_mbus_config, + }; + + static const struct v4l2_subdev_pad_ops ov6650_pad_ops = { +@@ -978,6 +997,8 @@ static const struct v4l2_subdev_pad_ops ov6650_pad_ops = { + .set_selection = ov6650_set_selection, + .get_fmt = ov6650_get_fmt, + .set_fmt = ov6650_set_fmt, ++ .get_mbus_config = ov6650_get_mbus_config, ++ .set_mbus_config = ov6650_set_mbus_config, + }; + + static const struct v4l2_subdev_ops ov6650_subdev_ops = { + +From 9b55924aa37a4ba85f84b8c4e382efffdf2b73df Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Fri, 17 Jul 2020 16:53:18 +0200 +Subject: [PATCH] media: pxa_camera: Use the new set_mbus_config op + +Move the PXA camera driver to use the new set_mbus_config pad operation. +For this platform the change is not only cosmetic, as the pxa driver is +currently the only driver in mainline to make use of the g_mbus_config +and s_mbus_config video operations. + +The existing driver semantic is the following: +- Collect all supported mbus config flags from the remote end +- Match them with the supported PXA mbus configuration flags +- If the remote subdevice allows multiple options for for VSYNC, HSYNC + and PCLK polarity, use platform data requested settings + +The semantic of the new get_mbus_config and set_mbus_config differs from +the corresponding video ops, particularly in the fact get_mbus_config +reports the current mbus configuration and not the set of supported +configuration options, with set_mbus_config always reporting the actual +mbus configuration applied to the remote subdevice. + +Adapt the driver to perform the following +- Set the remote subdevice mbus configuration according to the PXA + platform data preferences. +- If the applied configuration differs from the requested one (i.e. the + remote subdevice does not allow changing one setting) make sure that + - The remote end does not claim for DATA_ACTIVE_LOW, which seems not + supported by the platform + - The bus mastering roles match + +While at there remove a few checks performed on the media bus +configuration at get_format() time as they do not belong there. + +Compile-tested only. + +Signed-off-by: Jacopo Mondi +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/platform/pxa_camera.c | 189 ++++++++-------------------- + 1 file changed, 51 insertions(+), 138 deletions(-) + +diff --git a/drivers/media/platform/pxa_camera.c b/drivers/media/platform/pxa_camera.c +index 3c5fe737d36f..3a2cd28178da 100644 +--- a/drivers/media/platform/pxa_camera.c ++++ b/drivers/media/platform/pxa_camera.c +@@ -605,42 +605,6 @@ static const struct pxa_mbus_pixelfmt *pxa_mbus_get_fmtdesc( + return pxa_mbus_find_fmtdesc(code, mbus_fmt, ARRAY_SIZE(mbus_fmt)); + } + +-static unsigned int pxa_mbus_config_compatible(const struct v4l2_mbus_config *cfg, +- unsigned int flags) +-{ +- unsigned long common_flags; +- bool hsync = true, vsync = true, pclk, data, mode; +- bool mipi_lanes, mipi_clock; +- +- common_flags = cfg->flags & flags; +- +- switch (cfg->type) { +- case V4L2_MBUS_PARALLEL: +- hsync = common_flags & (V4L2_MBUS_HSYNC_ACTIVE_HIGH | +- V4L2_MBUS_HSYNC_ACTIVE_LOW); +- vsync = common_flags & (V4L2_MBUS_VSYNC_ACTIVE_HIGH | +- V4L2_MBUS_VSYNC_ACTIVE_LOW); +- /* fall through */ +- case V4L2_MBUS_BT656: +- pclk = common_flags & (V4L2_MBUS_PCLK_SAMPLE_RISING | +- V4L2_MBUS_PCLK_SAMPLE_FALLING); +- data = common_flags & (V4L2_MBUS_DATA_ACTIVE_HIGH | +- V4L2_MBUS_DATA_ACTIVE_LOW); +- mode = common_flags & (V4L2_MBUS_MASTER | V4L2_MBUS_SLAVE); +- return (!hsync || !vsync || !pclk || !data || !mode) ? +- 0 : common_flags; +- case V4L2_MBUS_CSI2_DPHY: +- mipi_lanes = common_flags & V4L2_MBUS_CSI2_LANES; +- mipi_clock = common_flags & (V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK | +- V4L2_MBUS_CSI2_CONTINUOUS_CLOCK); +- return (!mipi_lanes || !mipi_clock) ? 0 : common_flags; +- default: +- WARN_ON(1); +- return -EINVAL; +- } +- return 0; +-} +- + /** + * struct pxa_camera_format_xlate - match between host and sensor formats + * @code: code of a sensor provided format +@@ -1231,31 +1195,6 @@ static irqreturn_t pxa_camera_irq(int irq, void *data) + return IRQ_HANDLED; + } + +-static int test_platform_param(struct pxa_camera_dev *pcdev, +- unsigned char buswidth, unsigned long *flags) +-{ +- /* +- * Platform specified synchronization and pixel clock polarities are +- * only a recommendation and are only used during probing. The PXA270 +- * quick capture interface supports both. +- */ +- *flags = (pcdev->platform_flags & PXA_CAMERA_MASTER ? +- V4L2_MBUS_MASTER : V4L2_MBUS_SLAVE) | +- V4L2_MBUS_HSYNC_ACTIVE_HIGH | +- V4L2_MBUS_HSYNC_ACTIVE_LOW | +- V4L2_MBUS_VSYNC_ACTIVE_HIGH | +- V4L2_MBUS_VSYNC_ACTIVE_LOW | +- V4L2_MBUS_DATA_ACTIVE_HIGH | +- V4L2_MBUS_PCLK_SAMPLE_RISING | +- V4L2_MBUS_PCLK_SAMPLE_FALLING; +- +- /* If requested data width is supported by the platform, use it */ +- if ((1 << (buswidth - 1)) & pcdev->width_flags) +- return 0; +- +- return -EINVAL; +-} +- + static void pxa_camera_setup_cicr(struct pxa_camera_dev *pcdev, + unsigned long flags, __u32 pixfmt) + { +@@ -1598,99 +1537,78 @@ static int pxa_camera_init_videobuf2(struct pxa_camera_dev *pcdev) + */ + static int pxa_camera_set_bus_param(struct pxa_camera_dev *pcdev) + { ++ unsigned int bus_width = pcdev->current_fmt->host_fmt->bits_per_sample; + struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,}; + u32 pixfmt = pcdev->current_fmt->host_fmt->fourcc; +- unsigned long bus_flags, common_flags; ++ int mbus_config; + int ret; + +- ret = test_platform_param(pcdev, +- pcdev->current_fmt->host_fmt->bits_per_sample, +- &bus_flags); +- if (ret < 0) +- return ret; +- +- ret = sensor_call(pcdev, video, g_mbus_config, &cfg); +- if (!ret) { +- common_flags = pxa_mbus_config_compatible(&cfg, +- bus_flags); +- if (!common_flags) { +- dev_warn(pcdev_to_dev(pcdev), +- "Flags incompatible: camera 0x%x, host 0x%lx\n", +- cfg.flags, bus_flags); +- return -EINVAL; +- } +- } else if (ret != -ENOIOCTLCMD) { +- return ret; +- } else { +- common_flags = bus_flags; ++ if (!((1 << (bus_width - 1)) & pcdev->width_flags)) { ++ dev_err(pcdev_to_dev(pcdev), "Unsupported bus width %u", ++ bus_width); ++ return -EINVAL; + } + + pcdev->channels = 1; + + /* Make choices, based on platform preferences */ +- if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) && +- (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) { +- if (pcdev->platform_flags & PXA_CAMERA_HSP) +- common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH; +- else +- common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW; +- } ++ mbus_config = 0; ++ if (pcdev->platform_flags & PXA_CAMERA_MASTER) ++ mbus_config |= V4L2_MBUS_MASTER; ++ else ++ mbus_config |= V4L2_MBUS_SLAVE; + +- if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) && +- (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) { +- if (pcdev->platform_flags & PXA_CAMERA_VSP) +- common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH; +- else +- common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW; +- } ++ if (pcdev->platform_flags & PXA_CAMERA_HSP) ++ mbus_config |= V4L2_MBUS_HSYNC_ACTIVE_HIGH; ++ else ++ mbus_config |= V4L2_MBUS_HSYNC_ACTIVE_LOW; + +- if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) && +- (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) { +- if (pcdev->platform_flags & PXA_CAMERA_PCP) +- common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING; +- else +- common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING; +- } ++ if (pcdev->platform_flags & PXA_CAMERA_VSP) ++ mbus_config |= V4L2_MBUS_VSYNC_ACTIVE_HIGH; ++ else ++ mbus_config |= V4L2_MBUS_VSYNC_ACTIVE_LOW; + +- cfg.flags = common_flags; +- ret = sensor_call(pcdev, video, s_mbus_config, &cfg); ++ if (pcdev->platform_flags & PXA_CAMERA_PCP) ++ mbus_config |= V4L2_MBUS_PCLK_SAMPLE_RISING; ++ else ++ mbus_config |= V4L2_MBUS_PCLK_SAMPLE_FALLING; ++ mbus_config |= V4L2_MBUS_DATA_ACTIVE_HIGH; ++ ++ cfg.flags = mbus_config; ++ ret = sensor_call(pcdev, pad, set_mbus_config, 0, &cfg); + if (ret < 0 && ret != -ENOIOCTLCMD) { +- dev_dbg(pcdev_to_dev(pcdev), +- "camera s_mbus_config(0x%lx) returned %d\n", +- common_flags, ret); ++ dev_err(pcdev_to_dev(pcdev), ++ "Failed to call set_mbus_config: %d\n", ret); + return ret; + } + +- pxa_camera_setup_cicr(pcdev, common_flags, pixfmt); +- +- return 0; +-} +- +-static int pxa_camera_try_bus_param(struct pxa_camera_dev *pcdev, +- unsigned char buswidth) +-{ +- struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,}; +- unsigned long bus_flags, common_flags; +- int ret = test_platform_param(pcdev, buswidth, &bus_flags); +- +- if (ret < 0) +- return ret; ++ /* ++ * If the requested media bus configuration has not been fully applied ++ * make sure it is supported by the platform. ++ * ++ * PXA does not support V4L2_MBUS_DATA_ACTIVE_LOW and the bus mastering ++ * roles should match. ++ */ ++ if (cfg.flags != mbus_config) { ++ unsigned int pxa_mbus_role = mbus_config & (V4L2_MBUS_MASTER | ++ V4L2_MBUS_SLAVE); ++ if (pxa_mbus_role != (cfg.flags & (V4L2_MBUS_MASTER | ++ V4L2_MBUS_SLAVE))) { ++ dev_err(pcdev_to_dev(pcdev), ++ "Unsupported mbus configuration: bus mastering\n"); ++ return -EINVAL; ++ } + +- ret = sensor_call(pcdev, video, g_mbus_config, &cfg); +- if (!ret) { +- common_flags = pxa_mbus_config_compatible(&cfg, +- bus_flags); +- if (!common_flags) { +- dev_warn(pcdev_to_dev(pcdev), +- "Flags incompatible: camera 0x%x, host 0x%lx\n", +- cfg.flags, bus_flags); ++ if (cfg.flags & V4L2_MBUS_DATA_ACTIVE_LOW) { ++ dev_err(pcdev_to_dev(pcdev), ++ "Unsupported mbus configuration: DATA_ACTIVE_LOW\n"); + return -EINVAL; + } +- } else if (ret == -ENOIOCTLCMD) { +- ret = 0; + } + +- return ret; ++ pxa_camera_setup_cicr(pcdev, cfg.flags, pixfmt); ++ ++ return 0; + } + + static const struct pxa_mbus_pixelfmt pxa_camera_formats[] = { +@@ -1738,11 +1656,6 @@ static int pxa_camera_get_formats(struct v4l2_device *v4l2_dev, + return 0; + } + +- /* This also checks support for the requested bits-per-sample */ +- ret = pxa_camera_try_bus_param(pcdev, fmt->bits_per_sample); +- if (ret < 0) +- return 0; +- + switch (code.code) { + case MEDIA_BUS_FMT_UYVY8_2X8: + formats++; + +From 562b1d8a78c8367d9809491277a6c60441565aa4 Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Fri, 17 Jul 2020 16:53:19 +0200 +Subject: [PATCH] media: v4l2-subdev: Remove [s|g]_mbus_config video ops + +With all sensor and platform drivers now converted to use the new +get_mbus_config and set_mbus_config pad operations, remove the +deprecated video operations g_mbus_config and s_mbus_config. + +Signed-off-by: Jacopo Mondi +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + include/media/v4l2-subdev.h | 10 ---------- + 1 file changed, 10 deletions(-) + +diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h +index f7fe78a6f65a..90098fb1d770 100644 +--- a/include/media/v4l2-subdev.h ++++ b/include/media/v4l2-subdev.h +@@ -402,12 +402,6 @@ struct v4l2_mbus_frame_desc { + * + * @query_dv_timings: callback for VIDIOC_QUERY_DV_TIMINGS() ioctl handler code. + * +- * @g_mbus_config: get supported mediabus configurations +- * +- * @s_mbus_config: set a certain mediabus configuration. This operation is added +- * for compatibility with soc-camera drivers and should not be used by new +- * software. +- * + * @s_rx_buffer: set a host allocated memory buffer for the subdev. The subdev + * can adjust @size to a lower value and must not write more data to the + * buffer starting at @data than the original value of @size. +@@ -435,10 +429,6 @@ struct v4l2_subdev_video_ops { + struct v4l2_dv_timings *timings); + int (*query_dv_timings)(struct v4l2_subdev *sd, + struct v4l2_dv_timings *timings); +- int (*g_mbus_config)(struct v4l2_subdev *sd, +- struct v4l2_mbus_config *cfg); +- int (*s_mbus_config)(struct v4l2_subdev *sd, +- const struct v4l2_mbus_config *cfg); + int (*s_rx_buffer)(struct v4l2_subdev *sd, void *buf, + unsigned int *size); + }; + +From 1ea27db9eaddf1eb44e533e4baa49b5b3a50900f Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Fri, 17 Jul 2020 16:53:20 +0200 +Subject: [PATCH] media: v4l2- mediabus: Add usage note for V4L2_MBUS_* + +With the removal of the legacy g_mbus_config and s_mbus_config video +operations, the sole users of V4L2_MBUS_* flags are now the newly +introduced get_mbus_config and set_mbus_config pad operations. + +As the semantic of the new operations differs from the semantic of +the legacy ones, add a usage note in the v4l2-mediabus.h header to +specify how to use the flags. + +Also add a TODO note to record that we intend to replace the existing +flags with fields, to prevent users from mixing conflicting values +in a single operation call. + +Signed-off-by: Jacopo Mondi +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + include/media/v4l2-mediabus.h | 33 +++++++++++++++++++++++++++++---- + 1 file changed, 29 insertions(+), 4 deletions(-) + +diff --git a/include/media/v4l2-mediabus.h b/include/media/v4l2-mediabus.h +index 45f88f0248c4..59b1de197114 100644 +--- a/include/media/v4l2-mediabus.h ++++ b/include/media/v4l2-mediabus.h +@@ -11,9 +11,34 @@ + #include + #include + ++/* ++ * How to use the V4L2_MBUS_* flags: ++ * Flags are defined for each of the possible states and values of a media ++ * bus configuration parameter. One and only one bit of each group of flags ++ * shall be set by the users of the v4l2_subdev_pad_ops.get_mbus_config and ++ * v4l2_subdev_pad_ops.set_mbus_config operations to ensure that no ++ * conflicting settings are specified when reporting and setting the media bus ++ * configuration with the two operations respectively. For example, it is ++ * invalid to set or clear both the V4L2_MBUS_HSYNC_ACTIVE_HIGH and the ++ * V4L2_MBUS_HSYNC_ACTIVE_LOW flag at the same time. Instead either flag ++ * V4L2_MBUS_HSYNC_ACTIVE_HIGH or flag V4L2_MBUS_HSYNC_ACTIVE_LOW shall be ++ * set. The same is true for the V4L2_MBUS_CSI2_1/2/3/4_LANE flags group: only ++ * one of these four bits shall be set. ++ * ++ * TODO: replace the existing V4L2_MBUS_* flags with structures of fields ++ * to avoid conflicting settings. ++ * ++ * In example: ++ * #define V4L2_MBUS_HSYNC_ACTIVE_HIGH BIT(2) ++ * #define V4L2_MBUS_HSYNC_ACTIVE_LOW BIT(3) ++ * will be replaced by a field whose value reports the intended active state of ++ * the signal: ++ * unsigned int v4l2_mbus_hsync_active : 1; ++ */ ++ + /* Parallel flags */ + /* +- * Can the client run in master or in slave mode. By "Master mode" an operation ++ * The client runs in master or in slave mode. By "Master mode" an operation + * mode is meant, when the client (e.g., a camera sensor) is producing + * horizontal and vertical synchronisation. In "Slave mode" the host is + * providing these signals to the slave. +@@ -45,17 +70,17 @@ + #define V4L2_MBUS_DATA_ENABLE_LOW BIT(15) + + /* Serial flags */ +-/* How many lanes the client can use */ ++/* CSI-2 D-PHY number of data lanes. */ + #define V4L2_MBUS_CSI2_1_LANE BIT(0) + #define V4L2_MBUS_CSI2_2_LANE BIT(1) + #define V4L2_MBUS_CSI2_3_LANE BIT(2) + #define V4L2_MBUS_CSI2_4_LANE BIT(3) +-/* On which channels it can send video data */ ++/* CSI-2 Virtual Channel identifiers. */ + #define V4L2_MBUS_CSI2_CHANNEL_0 BIT(4) + #define V4L2_MBUS_CSI2_CHANNEL_1 BIT(5) + #define V4L2_MBUS_CSI2_CHANNEL_2 BIT(6) + #define V4L2_MBUS_CSI2_CHANNEL_3 BIT(7) +-/* Does it support only continuous or also non-continuous clock mode */ ++/* Clock non-continuous mode support. */ + #define V4L2_MBUS_CSI2_CONTINUOUS_CLOCK BIT(8) + #define V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK BIT(9) + + +From 9aae063d84435edfb0212c7613f887105dd58009 Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Fri, 17 Jul 2020 16:53:21 +0200 +Subject: [PATCH] media: staging: media: imx: Update TODO entry + +Update the TODO entry that mentioned a potential use case for the now +removed g_mbus_config video operation. + +Signed-off-by: Jacopo Mondi +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/staging/media/imx/TODO | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/staging/media/imx/TODO b/drivers/staging/media/imx/TODO +index a371cdedcdb0..9cfc1c1e78dc 100644 +--- a/drivers/staging/media/imx/TODO ++++ b/drivers/staging/media/imx/TODO +@@ -10,6 +10,10 @@ + driver uses the parsed DT bus config method until this issue is + resolved. + ++ 2020-06: g_mbus has been removed in favour of the get_mbus_config pad ++ operation which should be used to avoid parsing the remote endpoint ++ configuration. ++ + - This media driver supports inheriting V4L2 controls to the + video capture devices, from the subdevices in the capture device's + pipeline. The controls for each capture device are updated in the + +From 33a781840365c6b8a2b86b1c6cb4aaa86941a5d6 Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Fri, 17 Jul 2020 16:53:22 +0200 +Subject: [PATCH] media: i2c: adv748x: Adjust TXA data lanes number +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When outputting SD-Core output through the TXA MIPI CSI-2 interface, +the number of enabled data lanes should be reduced in order to guarantee +that the two video formats produced by the SD-Core (480i and 576i) +generate a MIPI CSI-2 link clock frequency compatible with the MIPI D-PHY +specifications. + +Limit the number of enabled data lanes to 2, which is guaranteed to +support 480i and 576i formats. + +Cache the number of enabled data lanes to be able to report it through +the new get_mbus_config operation. + +Reviewed-by: Kieran Bingham +Reviewed-by: Laurent Pinchart +Reviewed-by: Niklas Söderlund +Signed-off-by: Jacopo Mondi +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/i2c/adv748x/adv748x-core.c | 31 ++++++++++++++++++------ + drivers/media/i2c/adv748x/adv748x.h | 1 + + 2 files changed, 25 insertions(+), 7 deletions(-) + +diff --git a/drivers/media/i2c/adv748x/adv748x-core.c b/drivers/media/i2c/adv748x/adv748x-core.c +index 23e02ff27b17..1fe7f97c6d52 100644 +--- a/drivers/media/i2c/adv748x/adv748x-core.c ++++ b/drivers/media/i2c/adv748x/adv748x-core.c +@@ -241,10 +241,10 @@ static int adv748x_power_up_tx(struct adv748x_csi2 *tx) + int ret = 0; + + /* Enable n-lane MIPI */ +- adv748x_write_check(state, page, 0x00, 0x80 | tx->num_lanes, &ret); ++ adv748x_write_check(state, page, 0x00, 0x80 | tx->active_lanes, &ret); + + /* Set Auto DPHY Timing */ +- adv748x_write_check(state, page, 0x00, 0xa0 | tx->num_lanes, &ret); ++ adv748x_write_check(state, page, 0x00, 0xa0 | tx->active_lanes, &ret); + + /* ADI Required Write */ + if (tx->src == &state->hdmi.sd) { +@@ -270,7 +270,7 @@ static int adv748x_power_up_tx(struct adv748x_csi2 *tx) + usleep_range(2000, 2500); + + /* Power-up CSI-TX */ +- adv748x_write_check(state, page, 0x00, 0x20 | tx->num_lanes, &ret); ++ adv748x_write_check(state, page, 0x00, 0x20 | tx->active_lanes, &ret); + usleep_range(1000, 1500); + + /* ADI Required Writes */ +@@ -292,7 +292,7 @@ static int adv748x_power_down_tx(struct adv748x_csi2 *tx) + adv748x_write_check(state, page, 0x1e, 0x00, &ret); + + /* Enable n-lane MIPI */ +- adv748x_write_check(state, page, 0x00, 0x80 | tx->num_lanes, &ret); ++ adv748x_write_check(state, page, 0x00, 0x80 | tx->active_lanes, &ret); + + /* i2c_mipi_pll_en - 1'b1 */ + adv748x_write_check(state, page, 0xda, 0x01, &ret); +@@ -357,14 +357,29 @@ static int adv748x_link_setup(struct media_entity *entity, + if (state->afe.tx) { + /* AFE Requires TXA enabled, even when output to TXB */ + io10 |= ADV748X_IO_10_CSI4_EN; +- if (is_txa(tx)) ++ if (is_txa(tx)) { ++ /* ++ * Output from the SD-core (480i and 576i) from the TXA ++ * interface requires reducing the number of enabled ++ * data lanes in order to guarantee a valid link ++ * frequency. ++ */ ++ tx->active_lanes = min(tx->num_lanes, 2U); + io10 |= ADV748X_IO_10_CSI4_IN_SEL_AFE; +- else ++ } else { ++ /* TXB has a single data lane, no need to adjust. */ + io10 |= ADV748X_IO_10_CSI1_EN; ++ } + } + +- if (state->hdmi.tx) ++ if (state->hdmi.tx) { ++ /* ++ * Restore the number of active lanes, in case we have gone ++ * through an AFE->TXA streaming sessions. ++ */ ++ tx->active_lanes = tx->num_lanes; + io10 |= ADV748X_IO_10_CSI4_EN; ++ } + + return io_clrset(state, ADV748X_IO_10, io10_mask, io10); + } +@@ -596,6 +611,7 @@ static int adv748x_parse_csi2_lanes(struct adv748x_state *state, + } + + state->txa.num_lanes = num_lanes; ++ state->txa.active_lanes = num_lanes; + adv_dbg(state, "TXA: using %u lanes\n", state->txa.num_lanes); + } + +@@ -607,6 +623,7 @@ static int adv748x_parse_csi2_lanes(struct adv748x_state *state, + } + + state->txb.num_lanes = num_lanes; ++ state->txb.active_lanes = num_lanes; + adv_dbg(state, "TXB: using %u lanes\n", state->txb.num_lanes); + } + +diff --git a/drivers/media/i2c/adv748x/adv748x.h b/drivers/media/i2c/adv748x/adv748x.h +index fccb388ce179..1061f425ece5 100644 +--- a/drivers/media/i2c/adv748x/adv748x.h ++++ b/drivers/media/i2c/adv748x/adv748x.h +@@ -79,6 +79,7 @@ struct adv748x_csi2 { + unsigned int page; + unsigned int port; + unsigned int num_lanes; ++ unsigned int active_lanes; + + struct media_pad pads[ADV748X_CSI2_NR_PADS]; + struct v4l2_ctrl_handler ctrl_hdl; + +From 5ccfd4f056cc53beef915bd24985449b7d20affc Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Fri, 17 Jul 2020 16:53:23 +0200 +Subject: [PATCH] media: i2c: adv748x: Implement get_mbus_config +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Implement the newly introduced get_mbus_config operation to report the +number of currently used data lanes on the MIPI CSI-2 interface. + +Reviewed-by: Kieran Bingham +Reviewed-by: Niklas Söderlund +Signed-off-by: Jacopo Mondi +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/i2c/adv748x/adv748x-csi2.c | 31 ++++++++++++++++++++++++ + 1 file changed, 31 insertions(+) + +diff --git a/drivers/media/i2c/adv748x/adv748x-csi2.c b/drivers/media/i2c/adv748x/adv748x-csi2.c +index 2091cda50935..99bb63d05eef 100644 +--- a/drivers/media/i2c/adv748x/adv748x-csi2.c ++++ b/drivers/media/i2c/adv748x/adv748x-csi2.c +@@ -214,9 +214,40 @@ static int adv748x_csi2_set_format(struct v4l2_subdev *sd, + return ret; + } + ++static int adv748x_csi2_get_mbus_config(struct v4l2_subdev *sd, unsigned int pad, ++ struct v4l2_mbus_config *config) ++{ ++ struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd); ++ ++ if (pad != ADV748X_CSI2_SOURCE) ++ return -EINVAL; ++ ++ config->type = V4L2_MBUS_CSI2_DPHY; ++ switch (tx->active_lanes) { ++ case 1: ++ config->flags = V4L2_MBUS_CSI2_1_LANE; ++ break; ++ ++ case 2: ++ config->flags = V4L2_MBUS_CSI2_2_LANE; ++ break; ++ ++ case 3: ++ config->flags = V4L2_MBUS_CSI2_3_LANE; ++ break; ++ ++ case 4: ++ config->flags = V4L2_MBUS_CSI2_4_LANE; ++ break; ++ } ++ ++ return 0; ++} ++ + static const struct v4l2_subdev_pad_ops adv748x_csi2_pad_ops = { + .get_fmt = adv748x_csi2_get_format, + .set_fmt = adv748x_csi2_set_format, ++ .get_mbus_config = adv748x_csi2_get_mbus_config, + }; + + /* ----------------------------------------------------------------------------- + +From a7053f425fb6140bdf72c009cab1730e9d3094af Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Fri, 17 Jul 2020 16:53:24 +0200 +Subject: [PATCH] media: rcar-csi2: Negotiate data lanes number +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use the newly introduced get_mbus_config() subdevice pad operation to +retrieve the remote subdevice MIPI CSI-2 bus configuration and configure +the number of active data lanes accordingly. + +In order to be able to call the remote subdevice operation cache the +index of the remote pad connected to the single CSI-2 input port. + +Reviewed-by: Niklas Söderlund +Signed-off-by: Jacopo Mondi +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/platform/rcar-vin/rcar-csi2.c | 75 +++++++++++++++++++-- + 1 file changed, 68 insertions(+), 7 deletions(-) + +diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c +index 151e6a90c5fb..fe99ae00e690 100644 +--- a/drivers/media/platform/rcar-vin/rcar-csi2.c ++++ b/drivers/media/platform/rcar-vin/rcar-csi2.c +@@ -363,6 +363,7 @@ struct rcar_csi2 { + struct v4l2_async_notifier notifier; + struct v4l2_async_subdev asd; + struct v4l2_subdev *remote; ++ unsigned int remote_pad; + + struct v4l2_mbus_framefmt mf; + +@@ -408,13 +409,14 @@ static void rcsi2_exit_standby(struct rcar_csi2 *priv) + reset_control_deassert(priv->rstc); + } + +-static int rcsi2_wait_phy_start(struct rcar_csi2 *priv) ++static int rcsi2_wait_phy_start(struct rcar_csi2 *priv, ++ unsigned int lanes) + { + unsigned int timeout; + + /* Wait for the clock and data lanes to enter LP-11 state. */ + for (timeout = 0; timeout <= 20; timeout++) { +- const u32 lane_mask = (1 << priv->lanes) - 1; ++ const u32 lane_mask = (1 << lanes) - 1; + + if ((rcsi2_read(priv, PHCLM_REG) & PHCLM_STOPSTATECKL) && + (rcsi2_read(priv, PHDLM_REG) & lane_mask) == lane_mask) +@@ -446,7 +448,8 @@ static int rcsi2_set_phypll(struct rcar_csi2 *priv, unsigned int mbps) + return 0; + } + +-static int rcsi2_calc_mbps(struct rcar_csi2 *priv, unsigned int bpp) ++static int rcsi2_calc_mbps(struct rcar_csi2 *priv, unsigned int bpp, ++ unsigned int lanes) + { + struct v4l2_subdev *source; + struct v4l2_ctrl *ctrl; +@@ -471,15 +474,64 @@ static int rcsi2_calc_mbps(struct rcar_csi2 *priv, unsigned int bpp) + * bps = link_freq * 2 + */ + mbps = v4l2_ctrl_g_ctrl_int64(ctrl) * bpp; +- do_div(mbps, priv->lanes * 1000000); ++ do_div(mbps, lanes * 1000000); + + return mbps; + } + ++static int rcsi2_get_active_lanes(struct rcar_csi2 *priv, ++ unsigned int *lanes) ++{ ++ struct v4l2_mbus_config mbus_config = { 0 }; ++ unsigned int num_lanes = UINT_MAX; ++ int ret; ++ ++ *lanes = priv->lanes; ++ ++ ret = v4l2_subdev_call(priv->remote, pad, get_mbus_config, ++ priv->remote_pad, &mbus_config); ++ if (ret == -ENOIOCTLCMD) { ++ dev_dbg(priv->dev, "No remote mbus configuration available\n"); ++ return 0; ++ } ++ ++ if (ret) { ++ dev_err(priv->dev, "Failed to get remote mbus configuration\n"); ++ return ret; ++ } ++ ++ if (mbus_config.type != V4L2_MBUS_CSI2_DPHY) { ++ dev_err(priv->dev, "Unsupported media bus type %u\n", ++ mbus_config.type); ++ return -EINVAL; ++ } ++ ++ if (mbus_config.flags & V4L2_MBUS_CSI2_1_LANE) ++ num_lanes = 1; ++ else if (mbus_config.flags & V4L2_MBUS_CSI2_2_LANE) ++ num_lanes = 2; ++ else if (mbus_config.flags & V4L2_MBUS_CSI2_3_LANE) ++ num_lanes = 3; ++ else if (mbus_config.flags & V4L2_MBUS_CSI2_4_LANE) ++ num_lanes = 4; ++ ++ if (num_lanes > priv->lanes) { ++ dev_err(priv->dev, ++ "Unsupported mbus config: too many data lanes %u\n", ++ num_lanes); ++ return -EINVAL; ++ } ++ ++ *lanes = num_lanes; ++ ++ return 0; ++} ++ + static int rcsi2_start_receiver(struct rcar_csi2 *priv) + { + const struct rcar_csi2_format *format; + u32 phycnt, vcdt = 0, vcdt2 = 0, fld = 0; ++ unsigned int lanes; + unsigned int i; + int mbps, ret; + +@@ -521,10 +573,18 @@ static int rcsi2_start_receiver(struct rcar_csi2 *priv) + fld |= FLD_FLD_NUM(1); + } + ++ /* ++ * Get the number of active data lanes inspecting the remote mbus ++ * configuration. ++ */ ++ ret = rcsi2_get_active_lanes(priv, &lanes); ++ if (ret) ++ return ret; ++ + phycnt = PHYCNT_ENABLECLK; +- phycnt |= (1 << priv->lanes) - 1; ++ phycnt |= (1 << lanes) - 1; + +- mbps = rcsi2_calc_mbps(priv, format->bpp); ++ mbps = rcsi2_calc_mbps(priv, format->bpp, lanes); + if (mbps < 0) + return mbps; + +@@ -571,7 +631,7 @@ static int rcsi2_start_receiver(struct rcar_csi2 *priv) + rcsi2_write(priv, PHYCNT_REG, phycnt | PHYCNT_SHUTDOWNZ); + rcsi2_write(priv, PHYCNT_REG, phycnt | PHYCNT_SHUTDOWNZ | PHYCNT_RSTZ); + +- ret = rcsi2_wait_phy_start(priv); ++ ret = rcsi2_wait_phy_start(priv, lanes); + if (ret) + return ret; + +@@ -748,6 +808,7 @@ static int rcsi2_notify_bound(struct v4l2_async_notifier *notifier, + } + + priv->remote = subdev; ++ priv->remote_pad = pad; + + dev_dbg(priv->dev, "Bound %s pad: %d\n", subdev->name, pad); + + +From ed9092fbdad008ed58e0bd8079b6d6484839d811 Mon Sep 17 00:00:00 2001 +From: Dinghao Liu +Date: Sun, 28 Jun 2020 07:55:23 +0200 +Subject: [PATCH] media: venus: core: Fix runtime PM imbalance in venus_probe + +pm_runtime_get_sync() increments the runtime PM usage counter even +when it returns an error code. Thus a pairing decrement is needed on +the error handling path to keep the counter balanced. For other error +paths after this call, things are the same. + +Fix this by adding pm_runtime_put_noidle() after 'err_runtime_disable' +label. But in this case, the error path after pm_runtime_put_sync() +will decrease PM usage counter twice. Thus add an extra +pm_runtime_get_noresume() in this path to balance PM counter. + +Signed-off-by: Dinghao Liu +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/platform/qcom/venus/core.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c +index 203c6538044f..b0b932bf8c02 100644 +--- a/drivers/media/platform/qcom/venus/core.c ++++ b/drivers/media/platform/qcom/venus/core.c +@@ -287,8 +287,10 @@ static int venus_probe(struct platform_device *pdev) + goto err_core_deinit; + + ret = pm_runtime_put_sync(dev); +- if (ret) ++ if (ret) { ++ pm_runtime_get_noresume(dev); + goto err_dev_unregister; ++ } + + return 0; + +@@ -299,6 +301,7 @@ static int venus_probe(struct platform_device *pdev) + err_venus_shutdown: + venus_shutdown(core); + err_runtime_disable: ++ pm_runtime_put_noidle(dev); + pm_runtime_set_suspended(dev); + pm_runtime_disable(dev); + hfi_destroy(core); + +From 757449d0037dd11f6b783bc31b27c76c5fa636c8 Mon Sep 17 00:00:00 2001 +From: Rajendra Nayak +Date: Wed, 29 Jul 2020 09:16:42 +0200 +Subject: [PATCH] media: venus: core: Fix error handling in probe + +Post a successful pm_ops->core_get, an error in probe +should exit by doing a pm_ops->core_put which seems +to be missing. So fix it. + +Signed-off-by: Rajendra Nayak +Reviewed-by: Bjorn Andersson +Signed-off-by: Stanimir Varbanov +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/platform/qcom/venus/core.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c +index b0b932bf8c02..321ad77cb6cf 100644 +--- a/drivers/media/platform/qcom/venus/core.c ++++ b/drivers/media/platform/qcom/venus/core.c +@@ -224,13 +224,15 @@ static int venus_probe(struct platform_device *pdev) + + ret = dma_set_mask_and_coherent(dev, core->res->dma_mask); + if (ret) +- return ret; ++ goto err_core_put; + + if (!dev->dma_parms) { + dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms), + GFP_KERNEL); +- if (!dev->dma_parms) +- return -ENOMEM; ++ if (!dev->dma_parms) { ++ ret = -ENOMEM; ++ goto err_core_put; ++ } + } + dma_set_max_seg_size(dev, DMA_BIT_MASK(32)); + +@@ -242,11 +244,11 @@ static int venus_probe(struct platform_device *pdev) + IRQF_TRIGGER_HIGH | IRQF_ONESHOT, + "venus", core); + if (ret) +- return ret; ++ goto err_core_put; + + ret = hfi_create(core, &venus_core_ops); + if (ret) +- return ret; ++ goto err_core_put; + + pm_runtime_enable(dev); + +@@ -305,6 +307,9 @@ static int venus_probe(struct platform_device *pdev) + pm_runtime_set_suspended(dev); + pm_runtime_disable(dev); + hfi_destroy(core); ++err_core_put: ++ if (core->pm_ops->core_put) ++ core->pm_ops->core_put(dev); + return ret; + } + + +From 207ffb881dd2058c1a86022671817cef37a9d273 Mon Sep 17 00:00:00 2001 +From: Rajendra Nayak +Date: Wed, 29 Jul 2020 09:16:43 +0200 +Subject: [PATCH] media: venus: core: Add support for opp tables/perf voting + +Add support to add OPP tables and perf voting on the OPP powerdomain. +This is needed so venus votes on the corresponding performance state +for the OPP powerdomain along with setting the core clock rate. + +Signed-off-by: Rajendra Nayak +Reviewed-by: Matthias Kaehlcke +Reviewed-by: Bjorn Andersson +Signed-off-by: Stanimir Varbanov +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/platform/qcom/venus/core.c | 2 + + drivers/media/platform/qcom/venus/core.h | 5 + + .../media/platform/qcom/venus/pm_helpers.c | 92 +++++++++++++++++-- + 3 files changed, 92 insertions(+), 7 deletions(-) + +diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c +index 321ad77cb6cf..5fd70f8cf857 100644 +--- a/drivers/media/platform/qcom/venus/core.c ++++ b/drivers/media/platform/qcom/venus/core.c +@@ -528,6 +528,7 @@ static const struct venus_resources sdm845_res_v2 = { + .vcodec_clks_num = 2, + .vcodec_pmdomains = { "venus", "vcodec0", "vcodec1" }, + .vcodec_pmdomains_num = 3, ++ .opp_pmdomain = (const char *[]) { "cx", NULL }, + .vcodec_num = 2, + .max_load = 3110400, /* 4096x2160@90 */ + .hfi_version = HFI_VERSION_4XX, +@@ -573,6 +574,7 @@ static const struct venus_resources sc7180_res = { + .vcodec_clks_num = 2, + .vcodec_pmdomains = { "venus", "vcodec0" }, + .vcodec_pmdomains_num = 2, ++ .opp_pmdomain = (const char *[]) { "cx", NULL }, + .vcodec_num = 1, + .hfi_version = HFI_VERSION_4XX, + .vmem_id = VIDC_RESOURCE_NONE, +diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h +index 7118612673c9..b0cc544ad39f 100644 +--- a/drivers/media/platform/qcom/venus/core.h ++++ b/drivers/media/platform/qcom/venus/core.h +@@ -62,6 +62,7 @@ struct venus_resources { + unsigned int vcodec_clks_num; + const char * const vcodec_pmdomains[VIDC_PMDOMAINS_NUM_MAX]; + unsigned int vcodec_pmdomains_num; ++ const char **opp_pmdomain; + unsigned int vcodec_num; + enum hfi_version hfi_version; + u32 max_load; +@@ -145,8 +146,12 @@ struct venus_core { + struct clk *vcodec1_clks[VIDC_VCODEC_CLKS_NUM_MAX]; + struct icc_path *video_path; + struct icc_path *cpucfg_path; ++ struct opp_table *opp_table; ++ bool has_opp_table; + struct device_link *pd_dl_venus; + struct device *pmdomains[VIDC_PMDOMAINS_NUM_MAX]; ++ struct device_link *opp_dl_venus; ++ struct device *opp_pmdomain; + struct video_device *vdev_dec; + struct video_device *vdev_enc; + struct v4l2_device v4l2_dev; +diff --git a/drivers/media/platform/qcom/venus/pm_helpers.c b/drivers/media/platform/qcom/venus/pm_helpers.c +index 531e7a41658f..3127af8985cf 100644 +--- a/drivers/media/platform/qcom/venus/pm_helpers.c ++++ b/drivers/media/platform/qcom/venus/pm_helpers.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -66,10 +67,9 @@ static void core_clks_disable(struct venus_core *core) + + static int core_clks_set_rate(struct venus_core *core, unsigned long freq) + { +- struct clk *clk = core->clks[0]; + int ret; + +- ret = clk_set_rate(clk, freq); ++ ret = dev_pm_opp_set_rate(core->dev, freq); + if (ret) + return ret; + +@@ -744,13 +744,16 @@ static int venc_power_v4(struct device *dev, int on) + + static int vcodec_domains_get(struct device *dev) + { ++ int ret; ++ struct opp_table *opp_table; ++ struct device **opp_virt_dev; + struct venus_core *core = dev_get_drvdata(dev); + const struct venus_resources *res = core->res; + struct device *pd; + unsigned int i; + + if (!res->vcodec_pmdomains_num) +- return -ENODEV; ++ goto skip_pmdomains; + + for (i = 0; i < res->vcodec_pmdomains_num; i++) { + pd = dev_pm_domain_attach_by_name(dev, +@@ -767,7 +770,41 @@ static int vcodec_domains_get(struct device *dev) + if (!core->pd_dl_venus) + return -ENODEV; + ++skip_pmdomains: ++ if (!core->has_opp_table) ++ return 0; ++ ++ /* Attach the power domain for setting performance state */ ++ opp_table = dev_pm_opp_attach_genpd(dev, res->opp_pmdomain, &opp_virt_dev); ++ if (IS_ERR(opp_table)) { ++ ret = PTR_ERR(opp_table); ++ goto opp_attach_err; ++ } ++ ++ core->opp_pmdomain = *opp_virt_dev; ++ core->opp_dl_venus = device_link_add(dev, core->opp_pmdomain, ++ DL_FLAG_RPM_ACTIVE | ++ DL_FLAG_PM_RUNTIME | ++ DL_FLAG_STATELESS); ++ if (!core->opp_dl_venus) { ++ ret = -ENODEV; ++ goto opp_dl_add_err; ++ } ++ + return 0; ++ ++opp_dl_add_err: ++ dev_pm_domain_detach(core->opp_pmdomain, true); ++opp_attach_err: ++ if (core->pd_dl_venus) { ++ device_link_del(core->pd_dl_venus); ++ for (i = 0; i < res->vcodec_pmdomains_num; i++) { ++ if (IS_ERR_OR_NULL(core->pmdomains[i])) ++ continue; ++ dev_pm_domain_detach(core->pmdomains[i], true); ++ } ++ } ++ return ret; + } + + static void vcodec_domains_put(struct device *dev) +@@ -777,7 +814,7 @@ static void vcodec_domains_put(struct device *dev) + unsigned int i; + + if (!res->vcodec_pmdomains_num) +- return; ++ goto skip_pmdomains; + + if (core->pd_dl_venus) + device_link_del(core->pd_dl_venus); +@@ -787,6 +824,15 @@ static void vcodec_domains_put(struct device *dev) + continue; + dev_pm_domain_detach(core->pmdomains[i], true); + } ++ ++skip_pmdomains: ++ if (!core->has_opp_table) ++ return; ++ ++ if (core->opp_dl_venus) ++ device_link_del(core->opp_dl_venus); ++ ++ dev_pm_domain_detach(core->opp_pmdomain, true); + } + + static int core_get_v4(struct device *dev) +@@ -815,19 +861,46 @@ static int core_get_v4(struct device *dev) + if (legacy_binding) + return 0; + ++ core->opp_table = dev_pm_opp_set_clkname(dev, "core"); ++ if (IS_ERR(core->opp_table)) ++ return PTR_ERR(core->opp_table); ++ ++ if (core->res->opp_pmdomain) { ++ ret = dev_pm_opp_of_add_table(dev); ++ if (!ret) { ++ core->has_opp_table = true; ++ } else if (ret != -ENODEV) { ++ dev_err(dev, "invalid OPP table in device tree\n"); ++ dev_pm_opp_put_clkname(core->opp_table); ++ return ret; ++ } ++ } ++ + ret = vcodec_domains_get(dev); +- if (ret) ++ if (ret) { ++ if (core->has_opp_table) ++ dev_pm_opp_of_remove_table(dev); ++ dev_pm_opp_put_clkname(core->opp_table); + return ret; ++ } + + return 0; + } + + static void core_put_v4(struct device *dev) + { ++ struct venus_core *core = dev_get_drvdata(dev); ++ + if (legacy_binding) + return; + + vcodec_domains_put(dev); ++ ++ if (core->has_opp_table) ++ dev_pm_opp_of_remove_table(dev); ++ if (core->opp_table) ++ dev_pm_opp_put_clkname(core->opp_table); ++ + } + + static int core_power_v4(struct device *dev, int on) +@@ -835,10 +908,15 @@ static int core_power_v4(struct device *dev, int on) + struct venus_core *core = dev_get_drvdata(dev); + int ret = 0; + +- if (on == POWER_ON) ++ if (on == POWER_ON) { + ret = core_clks_enable(core); +- else ++ } else { ++ /* Drop the performance state vote */ ++ if (core->opp_pmdomain) ++ dev_pm_opp_set_rate(dev, 0); ++ + core_clks_disable(core); ++ } + + return ret; + } + +From 3bf1ba10b6ac9cfff7ecd329c38dc31213e88ce1 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Mon, 27 Jul 2020 14:05:37 -0300 +Subject: [PATCH] hantro: h264: Get the correct fallback reference buffer + +If the bitstream and the application are incorrectly configuring +the reference pictures, the hardware will need to fallback +to using some other reference picture. + +When the post-processor is enabled, the fallback buffer +should be a shadow buffer (postproc.dec_q), and not a +CAPTURE queue buffer, since the latter is post-processed +and not really the output of the decoder core. + +Fixes: 8c2d66b036c77 ("media: hantro: Support color conversion via post-processing") +Signed-off-by: Ezequiel Garcia +--- + drivers/staging/media/hantro/hantro_h264.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/staging/media/hantro/hantro_h264.c b/drivers/staging/media/hantro/hantro_h264.c +index 194d05848077..6dcd47bd9ed3 100644 +--- a/drivers/staging/media/hantro/hantro_h264.c ++++ b/drivers/staging/media/hantro/hantro_h264.c +@@ -325,7 +325,7 @@ dma_addr_t hantro_h264_get_ref_buf(struct hantro_ctx *ctx, + */ + dst_buf = hantro_get_dst_buf(ctx); + buf = &dst_buf->vb2_buf; +- dma_addr = vb2_dma_contig_plane_dma_addr(buf, 0); ++ dma_addr = hantro_get_dec_buf_addr(ctx, buf); + } + + return dma_addr; + +From 28bebe4b9396ef9d2e4ae2a179abdb840ceddb03 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Mon, 27 Jul 2020 14:05:38 -0300 +Subject: [PATCH] hantro: postproc: Fix motion vector space allocation + +When the post-processor is enabled, the driver allocates +"shadow buffers" which are used for the decoder core, +and exposes the post-processed buffers to userspace. + +For this reason, extra motion vector space has to +be allocated on the shadow buffers, which the driver +wasn't doing. Fix it. + +This fix should address artifacts on high profile bitstreams. + +Fixes: 8c2d66b036c77 ("media: hantro: Support color conversion via post-processing") +Signed-off-by: Ezequiel Garcia +--- + drivers/staging/media/hantro/hantro_postproc.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/staging/media/hantro/hantro_postproc.c b/drivers/staging/media/hantro/hantro_postproc.c +index 44062ffceaea..6d2a8f2a8f0b 100644 +--- a/drivers/staging/media/hantro/hantro_postproc.c ++++ b/drivers/staging/media/hantro/hantro_postproc.c +@@ -118,7 +118,9 @@ int hantro_postproc_alloc(struct hantro_ctx *ctx) + unsigned int num_buffers = cap_queue->num_buffers; + unsigned int i, buf_size; + +- buf_size = ctx->dst_fmt.plane_fmt[0].sizeimage; ++ buf_size = ctx->dst_fmt.plane_fmt[0].sizeimage + ++ hantro_h264_mv_size(ctx->dst_fmt.width, ++ ctx->dst_fmt.height); + + for (i = 0; i < num_buffers; ++i) { + struct hantro_aux_buf *priv = &ctx->postproc.dec_q[i]; + +From be1ec3a445d13ab0bac45fd84edb30a11a2c0b8c Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Fri, 14 Aug 2020 10:36:16 -0300 +Subject: [PATCH] media: uapi: h264: Update reference lists + +When dealing with with interlaced frames, reference lists must tell if +each particular reference is meant for top or bottom field. This info +is currently not provided at all in the H264 related controls. + +Make reference lists hold a structure which will also hold an +enumerator type along index into DPB array. The enumerator must +be used to specify if reference is for top or bottom field. + +Currently the only user of these lists is Cedrus which is just compile +fixed here. Actual usage of will come in a following commit. + +Signed-off-by: Jernej Skrabec +Signed-off-by: Ezequiel Garcia +--- + .../media/v4l/ext-ctrls-codec.rst | 44 ++++++++++++++++++- + .../staging/media/sunxi/cedrus/cedrus_h264.c | 6 +-- + include/media/h264-ctrls.h | 23 +++++++--- + 3 files changed, 62 insertions(+), 11 deletions(-) + +diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +index d0d506a444b1..b9b2617c3bda 100644 +--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst ++++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +@@ -1843,10 +1843,10 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + * - __u32 + - ``slice_group_change_cycle`` + - +- * - __u8 ++ * - struct :c:type:`v4l2_h264_reference` + - ``ref_pic_list0[32]`` + - Reference picture list after applying the per-slice modifications +- * - __u8 ++ * - struct :c:type:`v4l2_h264_reference` + - ``ref_pic_list1[32]`` + - Reference picture list after applying the per-slice modifications + * - __u32 +@@ -1926,6 +1926,46 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + - ``chroma_offset[32][2]`` + - + ++``Picture Reference`` ++ ++.. c:type:: v4l2_h264_reference ++ ++.. cssclass:: longtable ++ ++.. flat-table:: struct v4l2_h264_reference ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - enum :c:type:`v4l2_h264_field_reference` ++ - ``reference`` ++ - Specifies how the picture is referenced. ++ * - __u8 ++ - ``index`` ++ - Index into the :c:type:`v4l2_ctrl_h264_decode_params`.dpb array. ++ ++.. c:type:: v4l2_h264_field_reference ++ ++.. cssclass:: longtable ++ ++.. flat-table:: ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - ``V4L2_H264_TOP_FIELD_REF`` ++ - 0x1 ++ - The top field in field pair is used for ++ short-term reference. ++ * - ``V4L2_H264_BOTTOM_FIELD_REF`` ++ - 0x2 ++ - The bottom field in field pair is used for ++ short-term reference. ++ * - ``V4L2_H264_FRAME_REF`` ++ - 0x3 ++ - The frame (or the top/bottom fields, if it's a field pair) ++ is used for short-term reference. ++ + ``V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS (struct)`` + Specifies the decode parameters (as extracted from the bitstream) + for the associated H264 slice data. This includes the necessary +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +index 54ee2aa423e2..cce527bbdf86 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +@@ -166,8 +166,8 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx, + + static void _cedrus_write_ref_list(struct cedrus_ctx *ctx, + struct cedrus_run *run, +- const u8 *ref_list, u8 num_ref, +- enum cedrus_h264_sram_off sram) ++ const struct v4l2_h264_reference *ref_list, ++ u8 num_ref, enum cedrus_h264_sram_off sram) + { + const struct v4l2_ctrl_h264_decode_params *decode = run->h264.decode_params; + struct vb2_queue *cap_q; +@@ -188,7 +188,7 @@ static void _cedrus_write_ref_list(struct cedrus_ctx *ctx, + int buf_idx; + u8 dpb_idx; + +- dpb_idx = ref_list[i]; ++ dpb_idx = ref_list[i].index; + dpb = &decode->dpb[dpb_idx]; + + if (!(dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)) +diff --git a/include/media/h264-ctrls.h b/include/media/h264-ctrls.h +index 080fd1293c42..5f635e8d25e2 100644 +--- a/include/media/h264-ctrls.h ++++ b/include/media/h264-ctrls.h +@@ -19,6 +19,8 @@ + */ + #define V4L2_H264_NUM_DPB_ENTRIES 16 + ++#define V4L2_H264_REF_LIST_LEN (2 * V4L2_H264_NUM_DPB_ENTRIES) ++ + /* Our pixel format isn't stable at the moment */ + #define V4L2_PIX_FMT_H264_SLICE v4l2_fourcc('S', '2', '6', '4') /* H264 parsed slices */ + +@@ -140,6 +142,19 @@ struct v4l2_h264_pred_weight_table { + #define V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED 0x04 + #define V4L2_H264_SLICE_FLAG_SP_FOR_SWITCH 0x08 + ++enum v4l2_h264_field_reference { ++ V4L2_H264_TOP_FIELD_REF = 0x1, ++ V4L2_H264_BOTTOM_FIELD_REF = 0x2, ++ V4L2_H264_FRAME_REF = 0x3, ++}; ++ ++struct v4l2_h264_reference { ++ enum v4l2_h264_field_reference fields; ++ ++ /* Index into v4l2_ctrl_h264_decode_params.dpb[] */ ++ __u8 index; ++}; ++ + struct v4l2_ctrl_h264_slice_params { + /* Size in bytes, including header */ + __u32 size; +@@ -178,12 +193,8 @@ struct v4l2_ctrl_h264_slice_params { + __u8 num_ref_idx_l1_active_minus1; + __u32 slice_group_change_cycle; + +- /* +- * Entries on each list are indices into +- * v4l2_ctrl_h264_decode_params.dpb[]. +- */ +- __u8 ref_pic_list0[32]; +- __u8 ref_pic_list1[32]; ++ struct v4l2_h264_reference ref_pic_list0[V4L2_H264_REF_LIST_LEN]; ++ struct v4l2_h264_reference ref_pic_list1[V4L2_H264_REF_LIST_LEN]; + + __u32 flags; + }; + +From 9e30508e5834c1a37aa07836bf7fc78f96559f82 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Fri, 14 Aug 2020 10:36:17 -0300 +Subject: [PATCH] media: uapi: h264: Further clarify scaling lists order + +Commit 0b0393d59eb4a ("media: uapi: h264: clarify +expected scaling_list_4x4/8x8 order") improved the +documentation on H264 scaling lists order. + +This commit improves the documentation by clarifying +that the lists themselves are expected in raster scan order. + +Signed-off-by: Ezequiel Garcia +--- + Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +index b9b2617c3bda..694037ce888a 100644 +--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst ++++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +@@ -1725,12 +1725,14 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + - ``scaling_list_4x4[6][16]`` + - Scaling matrix after applying the inverse scanning process. + Expected list order is Intra Y, Intra Cb, Intra Cr, Inter Y, +- Inter Cb, Inter Cr. ++ Inter Cb, Inter Cr. The values on each scaling list are ++ expected in raster scan order. + * - __u8 + - ``scaling_list_8x8[6][64]`` + - Scaling matrix after applying the inverse scanning process. + Expected list order is Intra Y, Inter Y, Intra Cb, Inter Cb, +- Intra Cr, Inter Cr. ++ Intra Cr, Inter Cr. The values on each scaling list are ++ expected in raster scan order. + + ``V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS (struct)`` + Specifies the slice parameters (as extracted from the bitstream) + +From da0e200cf7bd3c42b97c8fa8e941a756ffdbfb26 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Fri, 14 Aug 2020 10:36:18 -0300 +Subject: [PATCH] media: uapi: h264: Split prediction weight parameters + +The prediction weight parameters are only required under +certain conditions, which depend on slice header parameters. + +As specified in section 7.3.3 Slice header syntax, the prediction +weight table is present if: + +((weighted_pred_flag && (slice_type == P || slice_type == SP)) || \ +(weighted_bipred_idc == 1 && slice_type == B)) + +Given its size, it makes sense to move this table to its control, +so applications can avoid passing it if the slice doesn't specify it. + +Before this change struct v4l2_ctrl_h264_slice_params was 960 bytes. +With this change, it's 188 bytes and struct v4l2_ctrl_h264_pred_weight +is 772 bytes. + +Signed-off-by: Ezequiel Garcia +--- + .../media/v4l/ext-ctrls-codec.rst | 19 ++++++++++++------- + drivers/media/v4l2-core/v4l2-ctrls.c | 8 ++++++++ + drivers/staging/media/sunxi/cedrus/cedrus.c | 7 +++++++ + drivers/staging/media/sunxi/cedrus/cedrus.h | 1 + + .../staging/media/sunxi/cedrus/cedrus_dec.c | 2 ++ + .../staging/media/sunxi/cedrus/cedrus_h264.c | 12 +++--------- + include/media/h264-ctrls.h | 12 ++++++++++-- + include/media/v4l2-ctrls.h | 2 ++ + 8 files changed, 45 insertions(+), 18 deletions(-) + +diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +index 694037ce888a..ddf9c6af7d0a 100644 +--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst ++++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +@@ -1879,18 +1879,23 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + - 0x00000008 + - + +-``Prediction Weight Table`` ++``V4L2_CID_MPEG_VIDEO_H264_PRED_WEIGHTS (struct)`` ++ Prediction weight table defined according to :ref:`h264`, ++ section 7.4.3.2 "Prediction Weight Table Semantics". ++ The prediction weight table must be passed by applications ++ under the conditions explained in section 7.3.3 "Slice header ++ syntax". + +- The bitstream parameters are defined according to :ref:`h264`, +- section 7.4.3.2 "Prediction Weight Table Semantics". For further +- documentation, refer to the above specification, unless there is +- an explicit comment stating otherwise. ++ .. note:: ++ ++ This compound control is not yet part of the public kernel API and ++ it is expected to change. + +-.. c:type:: v4l2_h264_pred_weight_table ++.. c:type:: v4l2_ctrl_h264_pred_weights + + .. cssclass:: longtable + +-.. flat-table:: struct v4l2_h264_pred_weight_table ++.. flat-table:: struct v4l2_ctrl_h264_pred_weights + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 +diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c +index 3f3fbcd60cc6..76c8dc8fb31c 100644 +--- a/drivers/media/v4l2-core/v4l2-ctrls.c ++++ b/drivers/media/v4l2-core/v4l2-ctrls.c +@@ -897,6 +897,7 @@ const char *v4l2_ctrl_get_name(u32 id) + case V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS: return "H264 Decode Parameters"; + case V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE: return "H264 Decode Mode"; + case V4L2_CID_MPEG_VIDEO_H264_START_CODE: return "H264 Start Code"; ++ case V4L2_CID_MPEG_VIDEO_H264_PRED_WEIGHTS: return "H264 Prediction Weight Table"; + case V4L2_CID_MPEG_VIDEO_MPEG2_LEVEL: return "MPEG2 Level"; + case V4L2_CID_MPEG_VIDEO_MPEG2_PROFILE: return "MPEG2 Profile"; + case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP: return "MPEG4 I-Frame QP Value"; +@@ -1412,6 +1413,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, + case V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS: + *type = V4L2_CTRL_TYPE_H264_DECODE_PARAMS; + break; ++ case V4L2_CID_MPEG_VIDEO_H264_PRED_WEIGHTS: ++ *type = V4L2_CTRL_TYPE_H264_PRED_WEIGHTS; ++ break; + case V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER: + *type = V4L2_CTRL_TYPE_VP8_FRAME_HEADER; + break; +@@ -1790,6 +1794,7 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, + case V4L2_CTRL_TYPE_H264_SPS: + case V4L2_CTRL_TYPE_H264_PPS: + case V4L2_CTRL_TYPE_H264_SCALING_MATRIX: ++ case V4L2_CTRL_TYPE_H264_PRED_WEIGHTS: + case V4L2_CTRL_TYPE_H264_SLICE_PARAMS: + case V4L2_CTRL_TYPE_H264_DECODE_PARAMS: + break; +@@ -2553,6 +2558,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, + case V4L2_CTRL_TYPE_H264_DECODE_PARAMS: + elem_size = sizeof(struct v4l2_ctrl_h264_decode_params); + break; ++ case V4L2_CTRL_TYPE_H264_PRED_WEIGHTS: ++ elem_size = sizeof(struct v4l2_ctrl_h264_pred_weights); ++ break; + case V4L2_CTRL_TYPE_VP8_FRAME_HEADER: + elem_size = sizeof(struct v4l2_ctrl_vp8_frame_header); + break; +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c +index bc27f9430eeb..826324faad7e 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.c +@@ -78,6 +78,13 @@ static const struct cedrus_control cedrus_controls[] = { + .codec = CEDRUS_CODEC_H264, + .required = true, + }, ++ { ++ .cfg = { ++ .id = V4L2_CID_MPEG_VIDEO_H264_PRED_WEIGHTS, ++ }, ++ .codec = CEDRUS_CODEC_H264, ++ .required = false, ++ }, + { + .cfg = { + .id = V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE, +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h +index 96765555ab8a..93c843ae14bb 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.h +@@ -62,6 +62,7 @@ struct cedrus_h264_run { + const struct v4l2_ctrl_h264_scaling_matrix *scaling_matrix; + const struct v4l2_ctrl_h264_slice_params *slice_params; + const struct v4l2_ctrl_h264_sps *sps; ++ const struct v4l2_ctrl_h264_pred_weights *pred_weights; + }; + + struct cedrus_mpeg2_run { +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c +index 58c48e4fdfe9..6385026d1b6b 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c +@@ -57,6 +57,8 @@ void cedrus_device_run(void *priv) + V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS); + run.h264.sps = cedrus_find_control_data(ctx, + V4L2_CID_MPEG_VIDEO_H264_SPS); ++ run.h264.pred_weights = cedrus_find_control_data(ctx, ++ V4L2_CID_MPEG_VIDEO_H264_PRED_WEIGHTS); + break; + + case V4L2_PIX_FMT_HEVC_SLICE: +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +index cce527bbdf86..d5636dbbb622 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +@@ -256,10 +256,8 @@ static void cedrus_write_scaling_lists(struct cedrus_ctx *ctx, + static void cedrus_write_pred_weight_table(struct cedrus_ctx *ctx, + struct cedrus_run *run) + { +- const struct v4l2_ctrl_h264_slice_params *slice = +- run->h264.slice_params; +- const struct v4l2_h264_pred_weight_table *pred_weight = +- &slice->pred_weight_table; ++ const struct v4l2_ctrl_h264_pred_weights *pred_weight = ++ run->h264.pred_weights; + struct cedrus_dev *dev = ctx->dev; + int i, j, k; + +@@ -367,11 +365,7 @@ static void cedrus_set_params(struct cedrus_ctx *ctx, + + cedrus_skip_bits(dev, slice->header_bit_size); + +- if (((pps->flags & V4L2_H264_PPS_FLAG_WEIGHTED_PRED) && +- (slice->slice_type == V4L2_H264_SLICE_TYPE_P || +- slice->slice_type == V4L2_H264_SLICE_TYPE_SP)) || +- (pps->weighted_bipred_idc == 1 && +- slice->slice_type == V4L2_H264_SLICE_TYPE_B)) ++ if (V4L2_H264_CTRL_PRED_WEIGHTS_REQUIRED(pps, slice)) + cedrus_write_pred_weight_table(ctx, run); + + if ((slice->slice_type == V4L2_H264_SLICE_TYPE_P) || +diff --git a/include/media/h264-ctrls.h b/include/media/h264-ctrls.h +index 5f635e8d25e2..d995614be159 100644 +--- a/include/media/h264-ctrls.h ++++ b/include/media/h264-ctrls.h +@@ -36,6 +36,7 @@ + #define V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS (V4L2_CID_MPEG_BASE+1004) + #define V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE (V4L2_CID_MPEG_BASE+1005) + #define V4L2_CID_MPEG_VIDEO_H264_START_CODE (V4L2_CID_MPEG_BASE+1006) ++#define V4L2_CID_MPEG_VIDEO_H264_PRED_WEIGHTS (V4L2_CID_MPEG_BASE+1007) + + /* enum v4l2_ctrl_type type values */ + #define V4L2_CTRL_TYPE_H264_SPS 0x0110 +@@ -43,6 +44,7 @@ + #define V4L2_CTRL_TYPE_H264_SCALING_MATRIX 0x0112 + #define V4L2_CTRL_TYPE_H264_SLICE_PARAMS 0x0113 + #define V4L2_CTRL_TYPE_H264_DECODE_PARAMS 0x0114 ++#define V4L2_CTRL_TYPE_H264_PRED_WEIGHTS 0x0115 + + enum v4l2_mpeg_video_h264_decode_mode { + V4L2_MPEG_VIDEO_H264_DECODE_MODE_SLICE_BASED, +@@ -125,7 +127,14 @@ struct v4l2_h264_weight_factors { + __s16 chroma_offset[32][2]; + }; + +-struct v4l2_h264_pred_weight_table { ++#define V4L2_H264_CTRL_PRED_WEIGHTS_REQUIRED(pps, slice) \ ++ ((((pps)->flags & V4L2_H264_PPS_FLAG_WEIGHTED_PRED) && \ ++ ((slice)->slice_type == V4L2_H264_SLICE_TYPE_P || \ ++ (slice)->slice_type == V4L2_H264_SLICE_TYPE_SP)) || \ ++ ((pps)->weighted_bipred_idc == 1 && \ ++ (slice)->slice_type == V4L2_H264_SLICE_TYPE_B)) ++ ++struct v4l2_ctrl_h264_pred_weights { + __u16 luma_log2_weight_denom; + __u16 chroma_log2_weight_denom; + struct v4l2_h264_weight_factors weight_factors[2]; +@@ -177,7 +186,6 @@ struct v4l2_ctrl_h264_slice_params { + __s32 delta_pic_order_cnt0; + __s32 delta_pic_order_cnt1; + +- struct v4l2_h264_pred_weight_table pred_weight_table; + /* Size in bits of dec_ref_pic_marking() syntax element. */ + __u32 dec_ref_pic_marking_bit_size; + /* Size in bits of pic order count syntax. */ +diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h +index f40e2cbb21d3..cb25f345e9ad 100644 +--- a/include/media/v4l2-ctrls.h ++++ b/include/media/v4l2-ctrls.h +@@ -51,6 +51,7 @@ struct video_device; + * @p_h264_scaling_matrix: Pointer to a struct v4l2_ctrl_h264_scaling_matrix. + * @p_h264_slice_params: Pointer to a struct v4l2_ctrl_h264_slice_params. + * @p_h264_decode_params: Pointer to a struct v4l2_ctrl_h264_decode_params. ++ * @p_h264_pred_weights: Pointer to a struct v4l2_ctrl_h264_pred_weights. + * @p_vp8_frame_header: Pointer to a VP8 frame header structure. + * @p_hevc_sps: Pointer to an HEVC sequence parameter set structure. + * @p_hevc_pps: Pointer to an HEVC picture parameter set structure. +@@ -74,6 +75,7 @@ union v4l2_ctrl_ptr { + struct v4l2_ctrl_h264_scaling_matrix *p_h264_scaling_matrix; + struct v4l2_ctrl_h264_slice_params *p_h264_slice_params; + struct v4l2_ctrl_h264_decode_params *p_h264_decode_params; ++ struct v4l2_ctrl_h264_pred_weights *p_h264_pred_weights; + struct v4l2_ctrl_vp8_frame_header *p_vp8_frame_header; + struct v4l2_ctrl_hevc_sps *p_hevc_sps; + struct v4l2_ctrl_hevc_pps *p_hevc_pps; + +From 82c12e79f57d0b51b81efb2bb87a91288988d958 Mon Sep 17 00:00:00 2001 +From: Philipp Zabel +Date: Fri, 14 Aug 2020 10:36:19 -0300 +Subject: [PATCH] media: uapi: h264: Clarify pic_order_cnt_bit_size field + +Since pic_order_cnt_bit_size is not a syntax element itself, explicitly +state that it is the total size in bits of the pic_order_cnt_lsb, +delta_pic_order_cnt_bottom, delta_pic_order_cnt[0], and +delta_pic_order_cnt[1] syntax elements contained in the slice. + +Signed-off-by: Philipp Zabel +[Ezequiel: rebase] +Signed-off-by: Ezequiel Garcia +Reviewed-by: Nicolas Dufresne +--- + Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +index ddf9c6af7d0a..32f3cebf16e5 100644 +--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst ++++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +@@ -1815,7 +1815,9 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + - Size in bits of the dec_ref_pic_marking() syntax element. + * - __u32 + - ``pic_order_cnt_bit_size`` +- - ++ - Combined size in bits of the picture order count related syntax ++ elements: pic_order_cnt_lsb, delta_pic_order_cnt_bottom, ++ delta_pic_order_cnt0, and delta_pic_order_cnt1. + * - __u8 + - ``cabac_init_idc`` + - + +From fced897398d6228473f01df99fd09fd4410f623d Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Fri, 14 Aug 2020 10:36:20 -0300 +Subject: [PATCH] media: uapi: h264: Increase size of 'first_mb_in_slice' field + +Slice header syntax element 'first_mb_in_slice' can point +to the last macroblock, currently the field can only reference +65536 macroblocks which is insufficient for 8K videos. + +Although unlikely, a 8192x4320 video (where macroblocks are 16x16), +would contain 138240 macroblocks on a frame. + +As per the H264 specification, 'first_mb_in_slice' can be up to +PicSizeInMbs - 1, so increase the size of the field to 32-bits. + +Note that v4l2_ctrl_h264_slice_params struct will be modified +in a follow-up commit, and so we defer its 64-bit padding. + +Signed-off-by: Ezequiel Garcia +--- + Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst | 2 +- + include/media/h264-ctrls.h | 3 ++- + 2 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +index 32f3cebf16e5..714a8d9ae6a0 100644 +--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst ++++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +@@ -1774,7 +1774,7 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + * - __u32 + - ``header_bit_size`` + - +- * - __u16 ++ * - __u32 + - ``first_mb_in_slice`` + - + * - __u8 +diff --git a/include/media/h264-ctrls.h b/include/media/h264-ctrls.h +index d995614be159..9ff085fdc9ab 100644 +--- a/include/media/h264-ctrls.h ++++ b/include/media/h264-ctrls.h +@@ -174,7 +174,8 @@ struct v4l2_ctrl_h264_slice_params { + /* Offset in bits to slice_data() from the beginning of this slice. */ + __u32 header_bit_size; + +- __u16 first_mb_in_slice; ++ __u32 first_mb_in_slice; ++ + __u8 slice_type; + __u8 pic_parameter_set_id; + __u8 colour_plane_id; + +From 52266e3675e9359f13aa4d44a4ab392fd1f079c0 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Fri, 14 Aug 2020 10:36:21 -0300 +Subject: [PATCH] media: uapi: h264: Clean DPB entry interface + +As discussed recently, the current interface for the +Decoded Picture Buffer is not enough to properly +support field coding. + +This commit introduces enough semantics to support +frame and field coding, and to signal how DPB entries +are "used for reference". + +Signed-off-by: Ezequiel Garcia +--- + .../media/v4l/ext-ctrls-codec.rst | 24 ++++++------------- + drivers/media/v4l2-core/v4l2-h264.c | 4 ++-- + drivers/staging/media/rkvdec/rkvdec-h264.c | 17 ++++++------- + include/media/h264-ctrls.h | 2 +- + 4 files changed, 19 insertions(+), 28 deletions(-) + +diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +index 714a8d9ae6a0..d14da8325382 100644 +--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst ++++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +@@ -2063,6 +2063,9 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + * - __s32 + - ``bottom_field_order_cnt`` + - ++ * - enum :c:type:`v4l2_h264_field_reference` ++ - ``reference`` ++ - Specifies how the DPB entry is referenced. + * - __u32 + - ``flags`` + - See :ref:`DPB Entry Flags ` +@@ -2080,29 +2083,16 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + + * - ``V4L2_H264_DPB_ENTRY_FLAG_VALID`` + - 0x00000001 +- - The DPB entry is valid and should be considered ++ - The DPB entry is valid (non-empty) and should be considered. + * - ``V4L2_H264_DPB_ENTRY_FLAG_ACTIVE`` + - 0x00000002 +- - The DPB entry is currently being used as a reference frame ++ - The DPB entry is used for reference. + * - ``V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM`` + - 0x00000004 +- - The DPB entry is a long term reference frame ++ - The DPB entry is used for long-term reference. + * - ``V4L2_H264_DPB_ENTRY_FLAG_FIELD`` + - 0x00000008 +- - The DPB entry is a field reference, which means only one of the field +- will be used when decoding the new frame/field. When not set the DPB +- entry is a frame reference (both fields will be used). Note that this +- flag does not say anything about the number of fields contained in the +- reference frame, it just describes the one used to decode the new +- field/frame +- * - ``V4L2_H264_DPB_ENTRY_FLAG_BOTTOM_FIELD`` +- - 0x00000010 +- - The DPB entry is a bottom field reference (only the bottom field of the +- reference frame is needed to decode the new frame/field). Only valid if +- V4L2_H264_DPB_ENTRY_FLAG_FIELD is set. When +- V4L2_H264_DPB_ENTRY_FLAG_FIELD is set but +- V4L2_H264_DPB_ENTRY_FLAG_BOTTOM_FIELD is not, that means the +- DPB entry is a top field reference ++ - The DPB entry is a single field or a complementary field pair. + + ``V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE (enum)`` + Specifies the decoding mode to use. Currently exposes slice-based and +diff --git a/drivers/media/v4l2-core/v4l2-h264.c b/drivers/media/v4l2-core/v4l2-h264.c +index edf6225f0522..12b751c09016 100644 +--- a/drivers/media/v4l2-core/v4l2-h264.c ++++ b/drivers/media/v4l2-core/v4l2-h264.c +@@ -66,10 +66,10 @@ v4l2_h264_init_reflist_builder(struct v4l2_h264_reflist_builder *b, + else + b->refs[i].frame_num = dpb[i].frame_num; + +- if (!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_FIELD)) ++ if (dpb[i].reference == V4L2_H264_FRAME_REF) + pic_order_count = min(dpb[i].top_field_order_cnt, + dpb[i].bottom_field_order_cnt); +- else if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_BOTTOM_FIELD) ++ else if (dpb[i].reference & V4L2_H264_BOTTOM_FIELD_REF) + pic_order_count = dpb[i].bottom_field_order_cnt; + else + pic_order_count = dpb[i].top_field_order_cnt; +diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c +index 7b66e2743a4f..07a80e9a9df2 100644 +--- a/drivers/staging/media/rkvdec/rkvdec-h264.c ++++ b/drivers/staging/media/rkvdec/rkvdec-h264.c +@@ -949,16 +949,17 @@ static void config_registers(struct rkvdec_ctx *ctx, + for (i = 0; i < ARRAY_SIZE(dec_params->dpb); i++) { + struct vb2_buffer *vb_buf = get_ref_buf(ctx, run, i); + +- refer_addr = vb2_dma_contig_plane_dma_addr(vb_buf, 0) | +- RKVDEC_COLMV_USED_FLAG_REF; ++ refer_addr = vb2_dma_contig_plane_dma_addr(vb_buf, 0); + +- if (!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_FIELD)) +- refer_addr |= RKVDEC_TOPFIELD_USED_REF | +- RKVDEC_BOTFIELD_USED_REF; +- else if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_BOTTOM_FIELD) +- refer_addr |= RKVDEC_BOTFIELD_USED_REF; +- else ++ if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE) ++ refer_addr |= RKVDEC_COLMV_USED_FLAG_REF; ++ if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_FIELD) ++ refer_addr |= RKVDEC_FIELD_REF; ++ ++ if (dpb[i].reference & V4L2_H264_TOP_FIELD_REF) + refer_addr |= RKVDEC_TOPFIELD_USED_REF; ++ if (dpb[i].reference & V4L2_H264_BOTTOM_FIELD_REF) ++ refer_addr |= RKVDEC_BOTFIELD_USED_REF; + + writel_relaxed(dpb[i].top_field_order_cnt, + rkvdec->regs + poc_reg_tbl_top_field[i]); +diff --git a/include/media/h264-ctrls.h b/include/media/h264-ctrls.h +index 9ff085fdc9ab..4447697e9465 100644 +--- a/include/media/h264-ctrls.h ++++ b/include/media/h264-ctrls.h +@@ -212,7 +212,6 @@ struct v4l2_ctrl_h264_slice_params { + #define V4L2_H264_DPB_ENTRY_FLAG_ACTIVE 0x02 + #define V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM 0x04 + #define V4L2_H264_DPB_ENTRY_FLAG_FIELD 0x08 +-#define V4L2_H264_DPB_ENTRY_FLAG_BOTTOM_FIELD 0x10 + + struct v4l2_h264_dpb_entry { + __u64 reference_ts; +@@ -221,6 +220,7 @@ struct v4l2_h264_dpb_entry { + /* Note that field is indicated by v4l2_buffer.field */ + __s32 top_field_order_cnt; + __s32 bottom_field_order_cnt; ++ enum v4l2_h264_field_reference reference; + __u32 flags; /* V4L2_H264_DPB_ENTRY_FLAG_* */ + }; + + +From cd2980d0ab75400656f854ac48a147ef07b9f9ba Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Fri, 14 Aug 2020 10:36:22 -0300 +Subject: [PATCH] media: uapi: h264: Increase size of DPB entry pic_num + +DPB entry PicNum maximum value is 2*MaxFrameNum for interlaced +content (field_pic_flag=1). + +As specified, MaxFrameNum is 2^(log2_max_frame_num_minus4 + 4) +and log2_max_frame_num_minus4 is in the range of 0 to 12, +which means pic_num should be a 32-bit field. + +The v4l2_h264_dpb_entry struct needs to be padded to avoid a hole, +which might be also useful to allow future uAPI extensions. + +Signed-off-by: Ezequiel Garcia +--- + .../userspace-api/media/v4l/ext-ctrls-codec.rst | 5 ++++- + drivers/media/v4l2-core/v4l2-ctrls.c | 13 +++++++++++++ + include/media/h264-ctrls.h | 3 ++- + include/media/v4l2-h264.h | 2 +- + 4 files changed, 20 insertions(+), 3 deletions(-) + +diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +index d14da8325382..c0ae7fda803e 100644 +--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst ++++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +@@ -2054,7 +2054,10 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + * - __u16 + - ``frame_num`` + - +- * - __u16 ++ * - __u8 ++ - ``reserved[2]`` ++ - Applications and drivers must set this to zero. ++ * - __u32 + - ``pic_num`` + - + * - __s32 +diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c +index 76c8dc8fb31c..b9457789fa55 100644 +--- a/drivers/media/v4l2-core/v4l2-ctrls.c ++++ b/drivers/media/v4l2-core/v4l2-ctrls.c +@@ -1725,6 +1725,8 @@ static void std_log(const struct v4l2_ctrl *ctrl) + + #define zero_padding(s) \ + memset(&(s).padding, 0, sizeof((s).padding)) ++#define zero_reserved(s) \ ++ memset(&(s).reserved, 0, sizeof((s).reserved)) + + /* + * Compound controls validation requires setting unused fields/flags to zero +@@ -1735,6 +1737,7 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, + { + struct v4l2_ctrl_mpeg2_slice_params *p_mpeg2_slice_params; + struct v4l2_ctrl_vp8_frame_header *p_vp8_frame_header; ++ struct v4l2_ctrl_h264_decode_params *p_h264_dec_params; + struct v4l2_ctrl_hevc_sps *p_hevc_sps; + struct v4l2_ctrl_hevc_pps *p_hevc_pps; + struct v4l2_ctrl_hevc_slice_params *p_hevc_slice_params; +@@ -1796,7 +1799,17 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, + case V4L2_CTRL_TYPE_H264_SCALING_MATRIX: + case V4L2_CTRL_TYPE_H264_PRED_WEIGHTS: + case V4L2_CTRL_TYPE_H264_SLICE_PARAMS: ++ break; ++ + case V4L2_CTRL_TYPE_H264_DECODE_PARAMS: ++ p_h264_dec_params = p; ++ ++ for (i = 0; i < V4L2_H264_NUM_DPB_ENTRIES; i++) { ++ struct v4l2_h264_dpb_entry *dpb_entry = ++ &p_h264_dec_params->dpb[i]; ++ ++ zero_reserved(*dpb_entry); ++ } + break; + + case V4L2_CTRL_TYPE_VP8_FRAME_HEADER: +diff --git a/include/media/h264-ctrls.h b/include/media/h264-ctrls.h +index 4447697e9465..d178d7ad53b6 100644 +--- a/include/media/h264-ctrls.h ++++ b/include/media/h264-ctrls.h +@@ -216,7 +216,8 @@ struct v4l2_ctrl_h264_slice_params { + struct v4l2_h264_dpb_entry { + __u64 reference_ts; + __u16 frame_num; +- __u16 pic_num; ++ __u8 reserved[2]; ++ __u32 pic_num; + /* Note that field is indicated by v4l2_buffer.field */ + __s32 top_field_order_cnt; + __s32 bottom_field_order_cnt; +diff --git a/include/media/v4l2-h264.h b/include/media/v4l2-h264.h +index bc9ebb560ccf..1a5f26fc2a9a 100644 +--- a/include/media/v4l2-h264.h ++++ b/include/media/v4l2-h264.h +@@ -33,7 +33,7 @@ struct v4l2_h264_reflist_builder { + struct { + s32 pic_order_count; + int frame_num; +- u16 pic_num; ++ u32 pic_num; + u16 longterm : 1; + } refs[V4L2_H264_NUM_DPB_ENTRIES]; + s32 cur_pic_order_count; + +From c380a6c41ab18183ff5d6342d8dc6cf7f22e6ed5 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Fri, 14 Aug 2020 10:36:23 -0300 +Subject: [PATCH] media: uapi: h264: Drop SLICE_PARAMS 'size' field + +The SLICE_PARAMS control is intended for slice-based +devices. In this mode, the OUTPUT buffer contains +a single slice, and so the buffer's plane payload size +can be used to query the slice size. + +To reduce the API surface drop the size from the +SLICE_PARAMS control. + +A follow-up change will remove other members in SLICE_PARAMS +so we don't need to add padding fields here. + +Signed-off-by: Ezequiel Garcia +--- + Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst | 3 --- + drivers/staging/media/sunxi/cedrus/cedrus_h264.c | 7 +++---- + include/media/h264-ctrls.h | 3 --- + 3 files changed, 3 insertions(+), 10 deletions(-) + +diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +index c0ae7fda803e..e88c207d945b 100644 +--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst ++++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +@@ -1760,9 +1760,6 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + :stub-columns: 0 + :widths: 1 1 2 + +- * - __u32 +- - ``size`` +- - + * - __u32 + - ``start_byte_offset`` + Offset (in bytes) from the beginning of the OUTPUT buffer to the start +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +index d5636dbbb622..7d9bd5860a1b 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +@@ -324,17 +324,16 @@ static void cedrus_set_params(struct cedrus_ctx *ctx, + struct vb2_buffer *src_buf = &run->src->vb2_buf; + struct cedrus_dev *dev = ctx->dev; + dma_addr_t src_buf_addr; +- u32 len = slice->size * 8; ++ size_t slice_bytes = vb2_get_plane_payload(src_buf, 0); + unsigned int pic_width_in_mbs; + bool mbaff_pic; + u32 reg; + +- cedrus_write(dev, VE_H264_VLD_LEN, len); ++ cedrus_write(dev, VE_H264_VLD_LEN, slice_bytes * 8); + cedrus_write(dev, VE_H264_VLD_OFFSET, 0); + + src_buf_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0); +- cedrus_write(dev, VE_H264_VLD_END, +- src_buf_addr + vb2_get_plane_payload(src_buf, 0)); ++ cedrus_write(dev, VE_H264_VLD_END, src_buf_addr + slice_bytes); + cedrus_write(dev, VE_H264_VLD_ADDR, + VE_H264_VLD_ADDR_VAL(src_buf_addr) | + VE_H264_VLD_ADDR_FIRST | VE_H264_VLD_ADDR_VALID | +diff --git a/include/media/h264-ctrls.h b/include/media/h264-ctrls.h +index d178d7ad53b6..afcae3052085 100644 +--- a/include/media/h264-ctrls.h ++++ b/include/media/h264-ctrls.h +@@ -165,9 +165,6 @@ struct v4l2_h264_reference { + }; + + struct v4l2_ctrl_h264_slice_params { +- /* Size in bytes, including header */ +- __u32 size; +- + /* Offset in bytes to the start of slice in the OUTPUT buffer. */ + __u32 start_byte_offset; + + +From 37293295255bb5ad4063fe1ca6945a6890c65cd4 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Fri, 14 Aug 2020 10:36:24 -0300 +Subject: [PATCH] media: uapi: h264: Clarify SLICE_BASED mode + +Currently, the SLICE_BASED and FRAME_BASED modes documentation +is misleading and not matching the intended use-cases. + +Drop non-required fields SLICE_PARAMS 'start_byte_offset' and +DECODE_PARAMS 'num_slices' and clarify the decoding modes in the +documentation. + +On SLICE_BASED mode, a single slice is expected per OUTPUT buffer, +and therefore 'start_byte_offset' is not needed (since the offset +to the slice is the start of the buffer). + +This mode requires the use of CAPTURE buffer holding, and so +the number of slices shall not be required. + +On FRAME_BASED mode, the devices are expected to take care of slice +parsing. Neither SLICE_PARAMS are required (and shouldn't be +exposed by frame-based drivers), nor the number of slices. + +Signed-off-by: Ezequiel Garcia +--- + .../media/v4l/ext-ctrls-codec.rst | 39 +++++-------------- + include/media/h264-ctrls.h | 4 -- + 2 files changed, 10 insertions(+), 33 deletions(-) + +diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +index e88c207d945b..90caf6a0d5a0 100644 +--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst ++++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +@@ -1748,9 +1748,6 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + This compound control is not yet part of the public kernel API + and it is expected to change. + +- This structure is expected to be passed as an array, with one +- entry for each slice included in the bitstream buffer. +- + .. c:type:: v4l2_ctrl_h264_slice_params + + .. cssclass:: longtable +@@ -1760,17 +1757,9 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + :stub-columns: 0 + :widths: 1 1 2 + +- * - __u32 +- - ``start_byte_offset`` +- Offset (in bytes) from the beginning of the OUTPUT buffer to the start +- of the slice. If the slice starts with a start code, then this is the +- offset to such start code. When operating in slice-based decoding mode +- (see :c:type:`v4l2_mpeg_video_h264_decode_mode`), this field should +- be set to 0. When operating in frame-based decoding mode, this field +- should be 0 for the first slice. + * - __u32 + - ``header_bit_size`` +- - ++ - Offset in bits to slice_data() from the beginning of this slice. + * - __u32 + - ``first_mb_in_slice`` + - +@@ -1998,12 +1987,6 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + * - struct :c:type:`v4l2_h264_dpb_entry` + - ``dpb[16]`` + - +- * - __u16 +- - ``num_slices`` +- - Number of slices needed to decode the current frame/field. When +- operating in slice-based decoding mode (see +- :c:type:`v4l2_mpeg_video_h264_decode_mode`), this field +- should always be set to one. + * - __u16 + - ``nal_ref_idc`` + - NAL reference ID value coming from the NAL Unit header +@@ -2121,22 +2104,20 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + * - ``V4L2_MPEG_VIDEO_H264_DECODE_MODE_SLICE_BASED`` + - 0 + - Decoding is done at the slice granularity. +- In this mode, ``num_slices`` field in struct +- :c:type:`v4l2_ctrl_h264_decode_params` should be set to 1, +- and ``start_byte_offset`` in struct +- :c:type:`v4l2_ctrl_h264_slice_params` should be set to 0. + The OUTPUT buffer must contain a single slice. ++ When this mode is selected, the ``V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS`` ++ control shall be set. When multiple slices compose a frame, ++ use of ``V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF`` flag ++ is required. + * - ``V4L2_MPEG_VIDEO_H264_DECODE_MODE_FRAME_BASED`` + - 1 +- - Decoding is done at the frame granularity. +- In this mode, ``num_slices`` field in struct +- :c:type:`v4l2_ctrl_h264_decode_params` should be set to the number +- of slices in the frame, and ``start_byte_offset`` in struct +- :c:type:`v4l2_ctrl_h264_slice_params` should be set accordingly +- for each slice. For the first slice, ``start_byte_offset`` should +- be zero. ++ - Decoding is done at the frame granularity, + The OUTPUT buffer must contain all slices needed to decode the + frame. The OUTPUT buffer must also contain both fields. ++ This mode will be supported by devices that ++ parse the slice(s) header(s) in hardware. When this mode is ++ selected, the ``V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS`` ++ control shall not be set. + + ``V4L2_CID_MPEG_VIDEO_H264_START_CODE (enum)`` + Specifies the H264 slice start code expected for each slice. +diff --git a/include/media/h264-ctrls.h b/include/media/h264-ctrls.h +index afcae3052085..e180501e6385 100644 +--- a/include/media/h264-ctrls.h ++++ b/include/media/h264-ctrls.h +@@ -165,9 +165,6 @@ struct v4l2_h264_reference { + }; + + struct v4l2_ctrl_h264_slice_params { +- /* Offset in bytes to the start of slice in the OUTPUT buffer. */ +- __u32 start_byte_offset; +- + /* Offset in bits to slice_data() from the beginning of this slice. */ + __u32 header_bit_size; + +@@ -226,7 +223,6 @@ struct v4l2_h264_dpb_entry { + + struct v4l2_ctrl_h264_decode_params { + struct v4l2_h264_dpb_entry dpb[V4L2_H264_NUM_DPB_ENTRIES]; +- __u16 num_slices; + __u16 nal_ref_idc; + __s32 top_field_order_cnt; + __s32 bottom_field_order_cnt; + +From ff81175260cd33feaa7d0407ef50186422215fae Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Fri, 14 Aug 2020 10:36:25 -0300 +Subject: [PATCH] media: uapi: h264: Clean slice invariants syntax elements + +The H.264 specification requires in section 7.4.3 "Slice header semantics", +that the following values shall be the same in all slice headers: + + pic_parameter_set_id + frame_num + field_pic_flag + bottom_field_flag + idr_pic_id + pic_order_cnt_lsb + delta_pic_order_cnt_bottom + delta_pic_order_cnt[ 0 ] + delta_pic_order_cnt[ 1 ] + sp_for_switch_flag + slice_group_change_cycle + +These bitstream fields are part of the slice header, and therefore +passed redundantly on each slice. The purpose of the redundancy +is to make the codec fault-tolerant in network scenarios. + +This is of course not needed to be reflected in the V4L2 controls, +given the bitstream has already been parsed by applications. +Therefore, move the redundant fields to the per-frame decode +parameters control (DECODE_PARAMS). + +Field 'pic_parameter_set_id' is simply removed in this case, +because the PPS control must currently contain the active PPS. + +Syntax elements dec_ref_pic_marking() and those related +to pic order count, remain invariant as well, and therefore, +the fields dec_ref_pic_marking_bit_size and pic_order_cnt_bit_size +are also common to all slices. + +Signed-off-by: Ezequiel Garcia +Reviewed-by: Nicolas Dufresne +--- + .../media/v4l/ext-ctrls-codec.rst | 86 +++++++++---------- + drivers/media/v4l2-core/v4l2-ctrls.c | 7 ++ + drivers/media/v4l2-core/v4l2-h264.c | 8 +- + .../staging/media/hantro/hantro_g1_h264_dec.c | 21 +++-- + drivers/staging/media/hantro/hantro_h264.c | 3 +- + drivers/staging/media/rkvdec/rkvdec-h264.c | 6 +- + .../staging/media/sunxi/cedrus/cedrus_h264.c | 9 +- + include/media/h264-ctrls.h | 39 +++++---- + include/media/v4l2-h264.h | 1 - + 9 files changed, 90 insertions(+), 90 deletions(-) + +diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +index 90caf6a0d5a0..69dd3961b99b 100644 +--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst ++++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +@@ -1766,44 +1766,12 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + * - __u8 + - ``slice_type`` + - +- * - __u8 +- - ``pic_parameter_set_id`` +- - + * - __u8 + - ``colour_plane_id`` + - + * - __u8 + - ``redundant_pic_cnt`` + - +- * - __u16 +- - ``frame_num`` +- - +- * - __u16 +- - ``idr_pic_id`` +- - +- * - __u16 +- - ``pic_order_cnt_lsb`` +- - +- * - __s32 +- - ``delta_pic_order_cnt_bottom`` +- - +- * - __s32 +- - ``delta_pic_order_cnt0`` +- - +- * - __s32 +- - ``delta_pic_order_cnt1`` +- - +- * - struct :c:type:`v4l2_h264_pred_weight_table` +- - ``pred_weight_table`` +- - +- * - __u32 +- - ``dec_ref_pic_marking_bit_size`` +- - Size in bits of the dec_ref_pic_marking() syntax element. +- * - __u32 +- - ``pic_order_cnt_bit_size`` +- - Combined size in bits of the picture order count related syntax +- elements: pic_order_cnt_lsb, delta_pic_order_cnt_bottom, +- delta_pic_order_cnt0, and delta_pic_order_cnt1. + * - __u8 + - ``cabac_init_idc`` + - +@@ -1830,9 +1798,9 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + - ``num_ref_idx_l1_active_minus1`` + - If num_ref_idx_active_override_flag is not set, this field must be + set to the value of num_ref_idx_l1_default_active_minus1. +- * - __u32 +- - ``slice_group_change_cycle`` +- - ++ * - __u8 ++ - ``reserved`` ++ - Applications and drivers must set this to zero. + * - struct :c:type:`v4l2_h264_reference` + - ``ref_pic_list0[32]`` + - Reference picture list after applying the per-slice modifications +@@ -1854,17 +1822,11 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + :stub-columns: 0 + :widths: 1 1 2 + +- * - ``V4L2_H264_SLICE_FLAG_FIELD_PIC`` +- - 0x00000001 +- - +- * - ``V4L2_H264_SLICE_FLAG_BOTTOM_FIELD`` +- - 0x00000002 +- - + * - ``V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED`` +- - 0x00000004 ++ - 0x00000001 + - + * - ``V4L2_H264_SLICE_FLAG_SP_FOR_SWITCH`` +- - 0x00000008 ++ - 0x00000002 + - + + ``V4L2_CID_MPEG_VIDEO_H264_PRED_WEIGHTS (struct)`` +@@ -1990,12 +1952,44 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + * - __u16 + - ``nal_ref_idc`` + - NAL reference ID value coming from the NAL Unit header ++ * - __u16 ++ - ``frame_num`` ++ - + * - __s32 + - ``top_field_order_cnt`` + - Picture Order Count for the coded top field + * - __s32 + - ``bottom_field_order_cnt`` + - Picture Order Count for the coded bottom field ++ * - __u16 ++ - ``idr_pic_id`` ++ - ++ * - __u16 ++ - ``pic_order_cnt_lsb`` ++ - ++ * - __s32 ++ - ``delta_pic_order_cnt_bottom`` ++ - ++ * - __s32 ++ - ``delta_pic_order_cnt0`` ++ - ++ * - __s32 ++ - ``delta_pic_order_cnt1`` ++ - ++ * - __u32 ++ - ``dec_ref_pic_marking_bit_size`` ++ - Size in bits of the dec_ref_pic_marking() syntax element. ++ * - __u32 ++ - ``pic_order_cnt_bit_size`` ++ - Combined size in bits of the picture order count related syntax ++ elements: pic_order_cnt_lsb, delta_pic_order_cnt_bottom, ++ delta_pic_order_cnt0, and delta_pic_order_cnt1. ++ * - __u32 ++ - ``slice_group_change_cycle`` ++ - ++ * - __u32 ++ - ``reserved`` ++ - Applications and drivers must set this to zero. + * - __u32 + - ``flags`` + - See :ref:`Decode Parameters Flags ` +@@ -2014,6 +2008,12 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + * - ``V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC`` + - 0x00000001 + - That picture is an IDR picture ++ * - ``V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC`` ++ - 0x00000002 ++ - ++ * - ``V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD`` ++ - 0x00000004 ++ - + + .. c:type:: v4l2_h264_dpb_entry + +diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c +index b9457789fa55..b846f5b089c9 100644 +--- a/drivers/media/v4l2-core/v4l2-ctrls.c ++++ b/drivers/media/v4l2-core/v4l2-ctrls.c +@@ -1737,6 +1737,7 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, + { + struct v4l2_ctrl_mpeg2_slice_params *p_mpeg2_slice_params; + struct v4l2_ctrl_vp8_frame_header *p_vp8_frame_header; ++ struct v4l2_ctrl_h264_slice_params *p_h264_slice_params; + struct v4l2_ctrl_h264_decode_params *p_h264_dec_params; + struct v4l2_ctrl_hevc_sps *p_hevc_sps; + struct v4l2_ctrl_hevc_pps *p_hevc_pps; +@@ -1798,7 +1799,12 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, + case V4L2_CTRL_TYPE_H264_PPS: + case V4L2_CTRL_TYPE_H264_SCALING_MATRIX: + case V4L2_CTRL_TYPE_H264_PRED_WEIGHTS: ++ break; ++ + case V4L2_CTRL_TYPE_H264_SLICE_PARAMS: ++ p_h264_slice_params = p; ++ ++ zero_reserved(*p_h264_slice_params); + break; + + case V4L2_CTRL_TYPE_H264_DECODE_PARAMS: +@@ -1810,6 +1816,7 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, + + zero_reserved(*dpb_entry); + } ++ zero_reserved(*p_h264_dec_params); + break; + + case V4L2_CTRL_TYPE_VP8_FRAME_HEADER: +diff --git a/drivers/media/v4l2-core/v4l2-h264.c b/drivers/media/v4l2-core/v4l2-h264.c +index 12b751c09016..101fdeabfb06 100644 +--- a/drivers/media/v4l2-core/v4l2-h264.c ++++ b/drivers/media/v4l2-core/v4l2-h264.c +@@ -18,14 +18,12 @@ + * + * @b: the builder context to initialize + * @dec_params: decode parameters control +- * @slice_params: first slice parameters control + * @sps: SPS control + * @dpb: DPB to use when creating the reference list + */ + void + v4l2_h264_init_reflist_builder(struct v4l2_h264_reflist_builder *b, + const struct v4l2_ctrl_h264_decode_params *dec_params, +- const struct v4l2_ctrl_h264_slice_params *slice_params, + const struct v4l2_ctrl_h264_sps *sps, + const struct v4l2_h264_dpb_entry dpb[V4L2_H264_NUM_DPB_ENTRIES]) + { +@@ -33,13 +31,13 @@ v4l2_h264_init_reflist_builder(struct v4l2_h264_reflist_builder *b, + unsigned int i; + + max_frame_num = 1 << (sps->log2_max_frame_num_minus4 + 4); +- cur_frame_num = slice_params->frame_num; ++ cur_frame_num = dec_params->frame_num; + + memset(b, 0, sizeof(*b)); +- if (!(slice_params->flags & V4L2_H264_SLICE_FLAG_FIELD_PIC)) ++ if (!(dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC)) + b->cur_pic_order_count = min(dec_params->bottom_field_order_cnt, + dec_params->top_field_order_cnt); +- else if (slice_params->flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD) ++ else if (dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD) + b->cur_pic_order_count = dec_params->bottom_field_order_cnt; + else + b->cur_pic_order_count = dec_params->top_field_order_cnt; +diff --git a/drivers/staging/media/hantro/hantro_g1_h264_dec.c b/drivers/staging/media/hantro/hantro_g1_h264_dec.c +index 424c648ce9fc..f9839e9c6da5 100644 +--- a/drivers/staging/media/hantro/hantro_g1_h264_dec.c ++++ b/drivers/staging/media/hantro/hantro_g1_h264_dec.c +@@ -23,7 +23,6 @@ static void set_params(struct hantro_ctx *ctx) + { + const struct hantro_h264_dec_ctrls *ctrls = &ctx->h264_dec.ctrls; + const struct v4l2_ctrl_h264_decode_params *dec_param = ctrls->decode; +- const struct v4l2_ctrl_h264_slice_params *slices = ctrls->slices; + const struct v4l2_ctrl_h264_sps *sps = ctrls->sps; + const struct v4l2_ctrl_h264_pps *pps = ctrls->pps; + struct vb2_v4l2_buffer *src_buf = hantro_get_src_buf(ctx); +@@ -42,11 +41,11 @@ static void set_params(struct hantro_ctx *ctx) + + if (!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY) && + (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD || +- slices[0].flags & V4L2_H264_SLICE_FLAG_FIELD_PIC)) ++ dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC)) + reg |= G1_REG_DEC_CTRL0_PIC_INTERLACE_E; +- if (slices[0].flags & V4L2_H264_SLICE_FLAG_FIELD_PIC) ++ if (dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC) + reg |= G1_REG_DEC_CTRL0_PIC_FIELDMODE_E; +- if (!(slices[0].flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD)) ++ if (!(dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD)) + reg |= G1_REG_DEC_CTRL0_PIC_TOPFIELD_E; + vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL0); + +@@ -75,7 +74,7 @@ static void set_params(struct hantro_ctx *ctx) + + /* Decoder control register 4. */ + reg = G1_REG_DEC_CTRL4_FRAMENUM_LEN(sps->log2_max_frame_num_minus4 + 4) | +- G1_REG_DEC_CTRL4_FRAMENUM(slices[0].frame_num) | ++ G1_REG_DEC_CTRL4_FRAMENUM(dec_param->frame_num) | + G1_REG_DEC_CTRL4_WEIGHT_BIPR_IDC(pps->weighted_bipred_idc); + if (pps->flags & V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE) + reg |= G1_REG_DEC_CTRL4_CABAC_E; +@@ -88,8 +87,8 @@ static void set_params(struct hantro_ctx *ctx) + vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL4); + + /* Decoder control register 5. */ +- reg = G1_REG_DEC_CTRL5_REFPIC_MK_LEN(slices[0].dec_ref_pic_marking_bit_size) | +- G1_REG_DEC_CTRL5_IDR_PIC_ID(slices[0].idr_pic_id); ++ reg = G1_REG_DEC_CTRL5_REFPIC_MK_LEN(dec_param->dec_ref_pic_marking_bit_size) | ++ G1_REG_DEC_CTRL5_IDR_PIC_ID(dec_param->idr_pic_id); + if (pps->flags & V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED) + reg |= G1_REG_DEC_CTRL5_CONST_INTRA_E; + if (pps->flags & V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT) +@@ -103,10 +102,10 @@ static void set_params(struct hantro_ctx *ctx) + vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL5); + + /* Decoder control register 6. */ +- reg = G1_REG_DEC_CTRL6_PPS_ID(slices[0].pic_parameter_set_id) | ++ reg = G1_REG_DEC_CTRL6_PPS_ID(pps->pic_parameter_set_id) | + G1_REG_DEC_CTRL6_REFIDX0_ACTIVE(pps->num_ref_idx_l0_default_active_minus1 + 1) | + G1_REG_DEC_CTRL6_REFIDX1_ACTIVE(pps->num_ref_idx_l1_default_active_minus1 + 1) | +- G1_REG_DEC_CTRL6_POC_LENGTH(slices[0].pic_order_cnt_bit_size); ++ G1_REG_DEC_CTRL6_POC_LENGTH(dec_param->pic_order_cnt_bit_size); + vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL6); + + /* Error concealment register. */ +@@ -246,7 +245,7 @@ static void set_buffers(struct hantro_ctx *ctx) + /* Destination (decoded frame) buffer. */ + dst_dma = hantro_get_dec_buf_addr(ctx, &dst_buf->vb2_buf); + /* Adjust dma addr to start at second line for bottom field */ +- if (ctrls->slices[0].flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD) ++ if (ctrls->decode->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD) + offset = ALIGN(ctx->src_fmt.width, MB_DIM); + vdpu_write_relaxed(vpu, dst_dma + offset, G1_REG_ADDR_DST); + +@@ -265,7 +264,7 @@ static void set_buffers(struct hantro_ctx *ctx) + * DMV buffer is split in two for field encoded frames, + * adjust offset for bottom field + */ +- if (ctrls->slices[0].flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD) ++ if (ctrls->decode->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD) + offset += 32 * MB_WIDTH(ctx->src_fmt.width) * + MB_HEIGHT(ctx->src_fmt.height); + vdpu_write_relaxed(vpu, dst_dma + offset, G1_REG_ADDR_DIR_MV); +diff --git a/drivers/staging/media/hantro/hantro_h264.c b/drivers/staging/media/hantro/hantro_h264.c +index 6dcd47bd9ed3..7578a4fc1b16 100644 +--- a/drivers/staging/media/hantro/hantro_h264.c ++++ b/drivers/staging/media/hantro/hantro_h264.c +@@ -372,8 +372,7 @@ int hantro_h264_dec_prepare_run(struct hantro_ctx *ctx) + + /* Build the P/B{0,1} ref lists. */ + v4l2_h264_init_reflist_builder(&reflist_builder, ctrls->decode, +- &ctrls->slices[0], ctrls->sps, +- ctx->h264_dec.dpb); ++ ctrls->sps, ctx->h264_dec.dpb); + v4l2_h264_build_p_ref_list(&reflist_builder, h264_ctx->reflists.p); + v4l2_h264_build_b_ref_lists(&reflist_builder, h264_ctx->reflists.b0, + h264_ctx->reflists.b1); +diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c +index 07a80e9a9df2..70752e30b3a3 100644 +--- a/drivers/staging/media/rkvdec/rkvdec-h264.c ++++ b/drivers/staging/media/rkvdec/rkvdec-h264.c +@@ -730,7 +730,6 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx, + struct rkvdec_h264_run *run) + { + const struct v4l2_ctrl_h264_decode_params *dec_params = run->decode_params; +- const struct v4l2_ctrl_h264_slice_params *sl_params = &run->slices_params[0]; + const struct v4l2_h264_dpb_entry *dpb = dec_params->dpb; + struct rkvdec_h264_ctx *h264_ctx = ctx->priv; + const struct v4l2_ctrl_h264_sps *sps = run->sps; +@@ -754,7 +753,7 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx, + continue; + + if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM || +- dpb[i].frame_num < sl_params->frame_num) { ++ dpb[i].frame_num < dec_params->frame_num) { + p[i] = dpb[i].frame_num; + continue; + } +@@ -1094,8 +1093,7 @@ static int rkvdec_h264_run(struct rkvdec_ctx *ctx) + + /* Build the P/B{0,1} ref lists. */ + v4l2_h264_init_reflist_builder(&reflist_builder, run.decode_params, +- &run.slices_params[0], run.sps, +- run.decode_params->dpb); ++ run.sps, run.decode_params->dpb); + h264_ctx->reflists.num_valid = reflist_builder.num_valid; + v4l2_h264_build_p_ref_list(&reflist_builder, h264_ctx->reflists.p); + v4l2_h264_build_b_ref_lists(&reflist_builder, h264_ctx->reflists.b0, +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +index 7d9bd5860a1b..c8f626fdd3dd 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +@@ -95,7 +95,6 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx, + { + struct cedrus_h264_sram_ref_pic pic_list[CEDRUS_H264_FRAME_NUM]; + const struct v4l2_ctrl_h264_decode_params *decode = run->h264.decode_params; +- const struct v4l2_ctrl_h264_slice_params *slice = run->h264.slice_params; + const struct v4l2_ctrl_h264_sps *sps = run->h264.sps; + struct vb2_queue *cap_q; + struct cedrus_buffer *output_buf; +@@ -144,7 +143,7 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx, + output_buf = vb2_to_cedrus_buffer(&run->dst->vb2_buf); + output_buf->codec.h264.position = position; + +- if (slice->flags & V4L2_H264_SLICE_FLAG_FIELD_PIC) ++ if (decode->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC) + output_buf->codec.h264.pic_type = CEDRUS_H264_PIC_TYPE_FIELD; + else if (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD) + output_buf->codec.h264.pic_type = CEDRUS_H264_PIC_TYPE_MBAFF; +@@ -407,7 +406,7 @@ static void cedrus_set_params(struct cedrus_ctx *ctx, + reg |= VE_H264_SPS_DIRECT_8X8_INFERENCE; + cedrus_write(dev, VE_H264_SPS, reg); + +- mbaff_pic = !(slice->flags & V4L2_H264_SLICE_FLAG_FIELD_PIC) && ++ mbaff_pic = !(decode->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC) && + (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD); + pic_width_in_mbs = sps->pic_width_in_mbs_minus1 + 1; + +@@ -421,9 +420,9 @@ static void cedrus_set_params(struct cedrus_ctx *ctx, + reg |= slice->cabac_init_idc & 0x3; + if (ctx->fh.m2m_ctx->new_frame) + reg |= VE_H264_SHS_FIRST_SLICE_IN_PIC; +- if (slice->flags & V4L2_H264_SLICE_FLAG_FIELD_PIC) ++ if (decode->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC) + reg |= VE_H264_SHS_FIELD_PIC; +- if (slice->flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD) ++ if (decode->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD) + reg |= VE_H264_SHS_BOTTOM_FIELD; + if (slice->flags & V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED) + reg |= VE_H264_SHS_DIRECT_SPATIAL_MV_PRED; +diff --git a/include/media/h264-ctrls.h b/include/media/h264-ctrls.h +index e180501e6385..1217b706128e 100644 +--- a/include/media/h264-ctrls.h ++++ b/include/media/h264-ctrls.h +@@ -146,10 +146,8 @@ struct v4l2_ctrl_h264_pred_weights { + #define V4L2_H264_SLICE_TYPE_SP 3 + #define V4L2_H264_SLICE_TYPE_SI 4 + +-#define V4L2_H264_SLICE_FLAG_FIELD_PIC 0x01 +-#define V4L2_H264_SLICE_FLAG_BOTTOM_FIELD 0x02 +-#define V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED 0x04 +-#define V4L2_H264_SLICE_FLAG_SP_FOR_SWITCH 0x08 ++#define V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED 0x01 ++#define V4L2_H264_SLICE_FLAG_SP_FOR_SWITCH 0x02 + + enum v4l2_h264_field_reference { + V4L2_H264_TOP_FIELD_REF = 0x1, +@@ -171,21 +169,8 @@ struct v4l2_ctrl_h264_slice_params { + __u32 first_mb_in_slice; + + __u8 slice_type; +- __u8 pic_parameter_set_id; + __u8 colour_plane_id; + __u8 redundant_pic_cnt; +- __u16 frame_num; +- __u16 idr_pic_id; +- __u16 pic_order_cnt_lsb; +- __s32 delta_pic_order_cnt_bottom; +- __s32 delta_pic_order_cnt0; +- __s32 delta_pic_order_cnt1; +- +- /* Size in bits of dec_ref_pic_marking() syntax element. */ +- __u32 dec_ref_pic_marking_bit_size; +- /* Size in bits of pic order count syntax. */ +- __u32 pic_order_cnt_bit_size; +- + __u8 cabac_init_idc; + __s8 slice_qp_delta; + __s8 slice_qs_delta; +@@ -194,7 +179,8 @@ struct v4l2_ctrl_h264_slice_params { + __s8 slice_beta_offset_div2; + __u8 num_ref_idx_l0_active_minus1; + __u8 num_ref_idx_l1_active_minus1; +- __u32 slice_group_change_cycle; ++ ++ __u8 reserved; + + struct v4l2_h264_reference ref_pic_list0[V4L2_H264_REF_LIST_LEN]; + struct v4l2_h264_reference ref_pic_list1[V4L2_H264_REF_LIST_LEN]; +@@ -219,13 +205,28 @@ struct v4l2_h264_dpb_entry { + __u32 flags; /* V4L2_H264_DPB_ENTRY_FLAG_* */ + }; + +-#define V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC 0x01 ++#define V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC 0x01 ++#define V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC 0x02 ++#define V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD 0x04 + + struct v4l2_ctrl_h264_decode_params { + struct v4l2_h264_dpb_entry dpb[V4L2_H264_NUM_DPB_ENTRIES]; + __u16 nal_ref_idc; ++ __u16 frame_num; + __s32 top_field_order_cnt; + __s32 bottom_field_order_cnt; ++ __u16 idr_pic_id; ++ __u16 pic_order_cnt_lsb; ++ __s32 delta_pic_order_cnt_bottom; ++ __s32 delta_pic_order_cnt0; ++ __s32 delta_pic_order_cnt1; ++ /* Size in bits of dec_ref_pic_marking() syntax element. */ ++ __u32 dec_ref_pic_marking_bit_size; ++ /* Size in bits of pic order count syntax. */ ++ __u32 pic_order_cnt_bit_size; ++ __u32 slice_group_change_cycle; ++ ++ __u32 reserved; + __u32 flags; /* V4L2_H264_DECODE_PARAM_FLAG_* */ + }; + +diff --git a/include/media/v4l2-h264.h b/include/media/v4l2-h264.h +index 1a5f26fc2a9a..f08ba181263d 100644 +--- a/include/media/v4l2-h264.h ++++ b/include/media/v4l2-h264.h +@@ -44,7 +44,6 @@ struct v4l2_h264_reflist_builder { + void + v4l2_h264_init_reflist_builder(struct v4l2_h264_reflist_builder *b, + const struct v4l2_ctrl_h264_decode_params *dec_params, +- const struct v4l2_ctrl_h264_slice_params *slice_params, + const struct v4l2_ctrl_h264_sps *sps, + const struct v4l2_h264_dpb_entry dpb[V4L2_H264_NUM_DPB_ENTRIES]); + + +From c94048bd00c4faa5bf1be0b3b01d3cc41cb475bb Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Fri, 14 Aug 2020 10:36:26 -0300 +Subject: [PATCH] media: uapi: h264: Rename and clarify + PPS_FLAG_SCALING_MATRIX_PRESENT + +Applications are expected to fill V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX +if a non-flat scaling matrix applies to the picture. This is the case if +SPS scaling_matrix_present_flag or PPS pic_scaling_matrix_present_flag +are set, and should be handled by applications. + +On one hand, the PPS bitstream syntax element signals the presence of a +Picture scaling matrix modifying the Sequence (SPS) scaling matrix. +On the other hand, our flag should indicate if the scaling matrix +V4L2 control is applicable to this request. + +Rename the flag from PPS_FLAG_PIC_SCALING_MATRIX_PRESENT to +PPS_FLAG_SCALING_MATRIX_PRESENT, to avoid mixing this flag with +bitstream syntax element pic_scaling_matrix_present_flag, +and clarify the meaning of our flag. + +Signed-off-by: Ezequiel Garcia +--- + Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst | 5 +++-- + include/media/h264-ctrls.h | 2 +- + 2 files changed, 4 insertions(+), 3 deletions(-) + +diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +index 69dd3961b99b..03ce87aa5488 100644 +--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst ++++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +@@ -1695,9 +1695,10 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + * - ``V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE`` + - 0x00000040 + - +- * - ``V4L2_H264_PPS_FLAG_PIC_SCALING_MATRIX_PRESENT`` ++ * - ``V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT`` + - 0x00000080 +- - ++ - Indicates that ``V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX`` ++ must be used for this picture. + + ``V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX (struct)`` + Specifies the scaling matrix (as extracted from the bitstream) for +diff --git a/include/media/h264-ctrls.h b/include/media/h264-ctrls.h +index 1217b706128e..070b9499d7bc 100644 +--- a/include/media/h264-ctrls.h ++++ b/include/media/h264-ctrls.h +@@ -99,7 +99,7 @@ struct v4l2_ctrl_h264_sps { + #define V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED 0x0010 + #define V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT 0x0020 + #define V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE 0x0040 +-#define V4L2_H264_PPS_FLAG_PIC_SCALING_MATRIX_PRESENT 0x0080 ++#define V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT 0x0080 + + struct v4l2_ctrl_h264_pps { + __u8 pic_parameter_set_id; + +From 2344f270ec7a9f9559e6d1e57a124c6a89ce0602 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Fri, 14 Aug 2020 10:36:27 -0300 +Subject: [PATCH] media: hantro: Don't require unneeded H264_SLICE_PARAMS + +Now that slice invariant parameters have been moved, +the driver no longer needs this control, so drop it. + +Signed-off-by: Ezequiel Garcia +--- + drivers/staging/media/hantro/hantro_drv.c | 5 ----- + drivers/staging/media/hantro/hantro_h264.c | 5 ----- + drivers/staging/media/hantro/hantro_hw.h | 2 -- + 3 files changed, 12 deletions(-) + +diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c +index 34797507f214..3cd00cc0a364 100644 +--- a/drivers/staging/media/hantro/hantro_drv.c ++++ b/drivers/staging/media/hantro/hantro_drv.c +@@ -306,11 +306,6 @@ static const struct hantro_ctrl controls[] = { + .cfg = { + .id = V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS, + }, +- }, { +- .codec = HANTRO_H264_DECODER, +- .cfg = { +- .id = V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS, +- }, + }, { + .codec = HANTRO_H264_DECODER, + .cfg = { +diff --git a/drivers/staging/media/hantro/hantro_h264.c b/drivers/staging/media/hantro/hantro_h264.c +index 7578a4fc1b16..089bfa9c625b 100644 +--- a/drivers/staging/media/hantro/hantro_h264.c ++++ b/drivers/staging/media/hantro/hantro_h264.c +@@ -349,11 +349,6 @@ int hantro_h264_dec_prepare_run(struct hantro_ctx *ctx) + if (WARN_ON(!ctrls->decode)) + return -EINVAL; + +- ctrls->slices = +- hantro_get_ctrl(ctx, V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS); +- if (WARN_ON(!ctrls->slices)) +- return -EINVAL; +- + ctrls->sps = + hantro_get_ctrl(ctx, V4L2_CID_MPEG_VIDEO_H264_SPS); + if (WARN_ON(!ctrls->sps)) +diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h +index f066de6b592d..219283a06f52 100644 +--- a/drivers/staging/media/hantro/hantro_hw.h ++++ b/drivers/staging/media/hantro/hantro_hw.h +@@ -56,14 +56,12 @@ struct hantro_jpeg_enc_hw_ctx { + * struct hantro_h264_dec_ctrls + * @decode: Decode params + * @scaling: Scaling info +- * @slice: Slice params + * @sps: SPS info + * @pps: PPS info + */ + struct hantro_h264_dec_ctrls { + const struct v4l2_ctrl_h264_decode_params *decode; + const struct v4l2_ctrl_h264_scaling_matrix *scaling; +- const struct v4l2_ctrl_h264_slice_params *slices; + const struct v4l2_ctrl_h264_sps *sps; + const struct v4l2_ctrl_h264_pps *pps; + }; + +From 419ccc9852409f2553c92ee3be909afa53d24d1d Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Fri, 14 Aug 2020 10:36:28 -0300 +Subject: [PATCH] media: rkvdec: Don't require unneeded H264_SLICE_PARAMS + +Now that slice invariant parameters have been moved, +the driver no longer needs this control, so drop it. + +Signed-off-by: Ezequiel Garcia +Reviewed-by: Jonas Karlman +--- + drivers/staging/media/rkvdec/rkvdec-h264.c | 4 ---- + drivers/staging/media/rkvdec/rkvdec.c | 5 ----- + 2 files changed, 9 deletions(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c +index 70752e30b3a3..584e0d5c493b 100644 +--- a/drivers/staging/media/rkvdec/rkvdec-h264.c ++++ b/drivers/staging/media/rkvdec/rkvdec-h264.c +@@ -109,7 +109,6 @@ struct rkvdec_h264_reflists { + struct rkvdec_h264_run { + struct rkvdec_run base; + const struct v4l2_ctrl_h264_decode_params *decode_params; +- const struct v4l2_ctrl_h264_slice_params *slices_params; + const struct v4l2_ctrl_h264_sps *sps; + const struct v4l2_ctrl_h264_pps *pps; + const struct v4l2_ctrl_h264_scaling_matrix *scaling_matrix; +@@ -1066,9 +1065,6 @@ static void rkvdec_h264_run_preamble(struct rkvdec_ctx *ctx, + ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, + V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS); + run->decode_params = ctrl ? ctrl->p_cur.p : NULL; +- ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, +- V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS); +- run->slices_params = ctrl ? ctrl->p_cur.p : NULL; + ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, + V4L2_CID_MPEG_VIDEO_H264_SPS); + run->sps = ctrl ? ctrl->p_cur.p : NULL; +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index c8151328fb70..7c5129593921 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -59,11 +59,6 @@ static const struct rkvdec_ctrl_desc rkvdec_h264_ctrl_descs[] = { + .mandatory = true, + .cfg.id = V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS, + }, +- { +- .per_request = true, +- .mandatory = true, +- .cfg.id = V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS, +- }, + { + .per_request = true, + .mandatory = true, + +From 85567a00727331d7a3269bd76319a048ef1ed505 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Fri, 14 Aug 2020 10:36:29 -0300 +Subject: [PATCH] media: cedrus: h264: Properly configure reference field + +When interlaced H264 content is being decoded, references must indicate +which field is being referenced. Currently this was done by checking +capture buffer flags. However, that is not correct because capture +buffer may hold both fields. + +Fix this by checking newly introduced flags in reference lists. + +Signed-off-by: Jernej Skrabec +Reviewed-by: Nicolas Dufresne +--- + drivers/staging/media/sunxi/cedrus/cedrus_h264.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +index c8f626fdd3dd..1e89a8438f36 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +@@ -182,7 +182,6 @@ static void _cedrus_write_ref_list(struct cedrus_ctx *ctx, + for (i = 0; i < num_ref; i++) { + const struct v4l2_h264_dpb_entry *dpb; + const struct cedrus_buffer *cedrus_buf; +- const struct vb2_v4l2_buffer *ref_buf; + unsigned int position; + int buf_idx; + u8 dpb_idx; +@@ -197,12 +196,11 @@ static void _cedrus_write_ref_list(struct cedrus_ctx *ctx, + if (buf_idx < 0) + continue; + +- ref_buf = to_vb2_v4l2_buffer(cap_q->bufs[buf_idx]); +- cedrus_buf = vb2_v4l2_to_cedrus_buffer(ref_buf); ++ cedrus_buf = vb2_to_cedrus_buffer(cap_q->bufs[buf_idx]); + position = cedrus_buf->codec.h264.position; + + sram_array[i] |= position << 1; +- if (ref_buf->field == V4L2_FIELD_BOTTOM) ++ if (ref_list[i].fields & V4L2_H264_BOTTOM_FIELD_REF) + sram_array[i] |= BIT(0); + } + + +From 102efa220abfcf3c08ceaf0a7c3ac5f88db5bc0c Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Fri, 14 Aug 2020 10:36:30 -0300 +Subject: [PATCH] media: cedrus: h264: Fix frame list construction + +Current frame list construction algorithm assumes that decoded image +will be output into its own buffer. That is true for progressive content +but not for interlaced where each field is decoded separately into same +buffer. + +Fix that by checking if capture buffer is listed in DPB. If it is, reuse +it. + +Signed-off-by: Jernej Skrabec +--- + drivers/staging/media/sunxi/cedrus/cedrus_h264.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +index 1e89a8438f36..fe041b444385 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +@@ -101,7 +101,7 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx, + struct cedrus_dev *dev = ctx->dev; + unsigned long used_dpbs = 0; + unsigned int position; +- unsigned int output = 0; ++ int output = -1; + unsigned int i; + + cap_q = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); +@@ -124,6 +124,11 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx, + position = cedrus_buf->codec.h264.position; + used_dpbs |= BIT(position); + ++ if (run->dst->vb2_buf.timestamp == dpb->reference_ts) { ++ output = position; ++ continue; ++ } ++ + if (!(dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)) + continue; + +@@ -131,13 +136,11 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx, + dpb->top_field_order_cnt, + dpb->bottom_field_order_cnt, + &pic_list[position]); +- +- output = max(position, output); + } + +- position = find_next_zero_bit(&used_dpbs, CEDRUS_H264_FRAME_NUM, +- output); +- if (position >= CEDRUS_H264_FRAME_NUM) ++ if (output >= 0) ++ position = output; ++ else + position = find_first_zero_bit(&used_dpbs, CEDRUS_H264_FRAME_NUM); + + output_buf = vb2_to_cedrus_buffer(&run->dst->vb2_buf); + +From 47f1224e5d7f2d3d566d1da9df0f72ee0564a0d1 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Wed, 19 Aug 2020 11:37:55 -0300 +Subject: [PATCH] media: rkvdec: Drop unneeded per_request driver-specific + control flag + +Currently, the drivers makes no distinction between per_request +and mandatory, as both are used in the same request validate check. + +The driver only cares to know if a given control is +required to be part of a request, so only one flag is needed. + +Signed-off-by: Ezequiel Garcia +--- + drivers/staging/media/rkvdec/rkvdec.c | 8 +------- + drivers/staging/media/rkvdec/rkvdec.h | 1 - + 2 files changed, 1 insertion(+), 8 deletions(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index 7c5129593921..9f59dfb62d3f 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -55,35 +55,29 @@ static const struct v4l2_ctrl_ops rkvdec_ctrl_ops = { + + static const struct rkvdec_ctrl_desc rkvdec_h264_ctrl_descs[] = { + { +- .per_request = true, + .mandatory = true, + .cfg.id = V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS, + }, + { +- .per_request = true, + .mandatory = true, + .cfg.id = V4L2_CID_MPEG_VIDEO_H264_SPS, + .cfg.ops = &rkvdec_ctrl_ops, + }, + { +- .per_request = true, + .mandatory = true, + .cfg.id = V4L2_CID_MPEG_VIDEO_H264_PPS, + }, + { +- .per_request = true, + .mandatory = true, + .cfg.id = V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX, + }, + { +- .mandatory = true, + .cfg.id = V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE, + .cfg.min = V4L2_MPEG_VIDEO_H264_DECODE_MODE_FRAME_BASED, + .cfg.max = V4L2_MPEG_VIDEO_H264_DECODE_MODE_FRAME_BASED, + .cfg.def = V4L2_MPEG_VIDEO_H264_DECODE_MODE_FRAME_BASED, + }, + { +- .mandatory = true, + .cfg.id = V4L2_CID_MPEG_VIDEO_H264_START_CODE, + .cfg.min = V4L2_MPEG_VIDEO_H264_START_CODE_ANNEX_B, + .cfg.def = V4L2_MPEG_VIDEO_H264_START_CODE_ANNEX_B, +@@ -615,7 +609,7 @@ static int rkvdec_request_validate(struct media_request *req) + u32 id = ctrls->ctrls[i].cfg.id; + struct v4l2_ctrl *ctrl; + +- if (!ctrls->ctrls[i].per_request || !ctrls->ctrls[i].mandatory) ++ if (!ctrls->ctrls[i].mandatory) + continue; + + ctrl = v4l2_ctrl_request_hdl_ctrl_find(hdl, id); +diff --git a/drivers/staging/media/rkvdec/rkvdec.h b/drivers/staging/media/rkvdec/rkvdec.h +index 2fc9f46b6910..77a137cca88e 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.h ++++ b/drivers/staging/media/rkvdec/rkvdec.h +@@ -25,7 +25,6 @@ + struct rkvdec_ctx; + + struct rkvdec_ctrl_desc { +- u32 per_request : 1; + u32 mandatory : 1; + struct v4l2_ctrl_config cfg; + }; + +From 90ea71bc465216778ac6fda4ca151f324df4d516 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Fri, 14 Aug 2020 10:36:32 -0300 +Subject: [PATCH] media: rkvdec: Use H264_SCALING_MATRIX only when required + +Baseline, Main and Extended profiles are specified to +not support a scaling matrix. Also, High profiles +can optionally specify a scaling matrix, using +SPS and PPS NAL units. + +To meet this expectation, applications are required to +set the V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX control +and set the V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT +flag only when a scaling matrix is specified for a picture. + +Implement this on rkvdec, which has hardware support for this +case. + +Signed-off-by: Ezequiel Garcia +--- + drivers/staging/media/rkvdec/rkvdec-h264.c | 10 +++++++--- + drivers/staging/media/rkvdec/rkvdec.c | 1 - + 2 files changed, 7 insertions(+), 4 deletions(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c +index 584e0d5c493b..9233260e14c1 100644 +--- a/drivers/staging/media/rkvdec/rkvdec-h264.c ++++ b/drivers/staging/media/rkvdec/rkvdec-h264.c +@@ -708,9 +708,9 @@ static void assemble_hw_pps(struct rkvdec_ctx *ctx, + WRITE_PPS(pps->second_chroma_qp_index_offset, + SECOND_CHROMA_QP_INDEX_OFFSET); + +- /* always use the matrix sent from userspace */ +- WRITE_PPS(1, SCALING_LIST_ENABLE_FLAG); +- ++ WRITE_PPS(!!(pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT), ++ SCALING_LIST_ENABLE_FLAG); ++ /* To be on the safe side, program the scaling matrix address */ + scaling_distance = offsetof(struct rkvdec_h264_priv_tbl, scaling_list); + scaling_list_address = h264_ctx->priv_tbl.dma + scaling_distance; + WRITE_PPS(scaling_list_address, SCALING_LIST_ADDRESS); +@@ -792,9 +792,13 @@ static void assemble_hw_scaling_list(struct rkvdec_ctx *ctx, + struct rkvdec_h264_run *run) + { + const struct v4l2_ctrl_h264_scaling_matrix *scaling = run->scaling_matrix; ++ const struct v4l2_ctrl_h264_pps *pps = run->pps; + struct rkvdec_h264_ctx *h264_ctx = ctx->priv; + struct rkvdec_h264_priv_tbl *tbl = h264_ctx->priv_tbl.cpu; + ++ if (!(pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT)) ++ return; ++ + BUILD_BUG_ON(sizeof(tbl->scaling_list.scaling_list_4x4) != + sizeof(scaling->scaling_list_4x4)); + BUILD_BUG_ON(sizeof(tbl->scaling_list.scaling_list_8x8) != +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index 9f59dfb62d3f..d25c4a37e2af 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -68,7 +68,6 @@ static const struct rkvdec_ctrl_desc rkvdec_h264_ctrl_descs[] = { + .cfg.id = V4L2_CID_MPEG_VIDEO_H264_PPS, + }, + { +- .mandatory = true, + .cfg.id = V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX, + }, + { + +From 70d39439f485d511c9c929934a26341ef3b736ef Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Fri, 14 Aug 2020 10:36:33 -0300 +Subject: [PATCH] media: hantro: Use H264_SCALING_MATRIX only when required + +Baseline, Main and Extended profiles are specified to +not support a scaling matrix. Also, High profiles +can optionally specify a scaling matrix, using +SPS and PPS NAL units. + +To meet this expectation, applications are required to +set the V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX control +and set the V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT +flag only when a scaling matrix is specified for a picture. + +Implement this on hantro, which has hardware support for this +case. + +Signed-off-by: Ezequiel Garcia +--- + drivers/staging/media/hantro/hantro_g1_h264_dec.c | 5 ++--- + drivers/staging/media/hantro/hantro_h264.c | 4 ++++ + 2 files changed, 6 insertions(+), 3 deletions(-) + +diff --git a/drivers/staging/media/hantro/hantro_g1_h264_dec.c b/drivers/staging/media/hantro/hantro_g1_h264_dec.c +index f9839e9c6da5..845bef73d218 100644 +--- a/drivers/staging/media/hantro/hantro_g1_h264_dec.c ++++ b/drivers/staging/media/hantro/hantro_g1_h264_dec.c +@@ -59,9 +59,8 @@ static void set_params(struct hantro_ctx *ctx) + reg = G1_REG_DEC_CTRL2_CH_QP_OFFSET(pps->chroma_qp_index_offset) | + G1_REG_DEC_CTRL2_CH_QP_OFFSET2(pps->second_chroma_qp_index_offset); + +- /* always use the matrix sent from userspace */ +- reg |= G1_REG_DEC_CTRL2_TYPE1_QUANT_E; +- ++ if (pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT) ++ reg |= G1_REG_DEC_CTRL2_TYPE1_QUANT_E; + if (!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY)) + reg |= G1_REG_DEC_CTRL2_FIELDPIC_FLAG_E; + vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL2); +diff --git a/drivers/staging/media/hantro/hantro_h264.c b/drivers/staging/media/hantro/hantro_h264.c +index 089bfa9c625b..b1bdc00ac262 100644 +--- a/drivers/staging/media/hantro/hantro_h264.c ++++ b/drivers/staging/media/hantro/hantro_h264.c +@@ -197,6 +197,7 @@ assemble_scaling_list(struct hantro_ctx *ctx) + { + const struct hantro_h264_dec_ctrls *ctrls = &ctx->h264_dec.ctrls; + const struct v4l2_ctrl_h264_scaling_matrix *scaling = ctrls->scaling; ++ const struct v4l2_ctrl_h264_pps *pps = ctrls->pps; + const size_t num_list_4x4 = ARRAY_SIZE(scaling->scaling_list_4x4); + const size_t list_len_4x4 = ARRAY_SIZE(scaling->scaling_list_4x4[0]); + const size_t list_len_8x8 = ARRAY_SIZE(scaling->scaling_list_8x8[0]); +@@ -205,6 +206,9 @@ assemble_scaling_list(struct hantro_ctx *ctx) + const u32 *src; + int i, j; + ++ if (!(pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT)) ++ return; ++ + for (i = 0; i < num_list_4x4; i++) { + src = (u32 *)&scaling->scaling_list_4x4[i]; + for (j = 0; j < list_len_4x4 / 4; j++) + +From 6390458815944ce231b6282771e2a6c3fc6f2fa6 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Fri, 14 Aug 2020 10:36:34 -0300 +Subject: [PATCH] media: cedrus: Use H264_SCALING_MATRIX only when required + +Baseline, Main and Extended profiles are specified to +not support a scaling matrix. Also, High profiles +can optionally specify a scaling matrix, using +SPS and PPS NAL units. + +To meet this expectation, applications are required to +set the V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX control +and set the V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT +flag only when a scaling matrix is specified for a picture. + +Implement this on cedrus, which has hardware support for this +case. + +Signed-off-by: Ezequiel Garcia +--- + drivers/staging/media/sunxi/cedrus/cedrus.c | 2 +- + drivers/staging/media/sunxi/cedrus/cedrus_h264.c | 6 ++++++ + 2 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c +index 826324faad7e..6ebb39e0c0ce 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.c +@@ -76,7 +76,7 @@ static const struct cedrus_control cedrus_controls[] = { + .id = V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX, + }, + .codec = CEDRUS_CODEC_H264, +- .required = true, ++ .required = false, + }, + { + .cfg = { +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +index fe041b444385..28319351e909 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +@@ -238,8 +238,12 @@ static void cedrus_write_scaling_lists(struct cedrus_ctx *ctx, + { + const struct v4l2_ctrl_h264_scaling_matrix *scaling = + run->h264.scaling_matrix; ++ const struct v4l2_ctrl_h264_pps *pps = run->h264.pps; + struct cedrus_dev *dev = ctx->dev; + ++ if (!(pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT)) ++ return; ++ + cedrus_h264_write_sram(dev, CEDRUS_SRAM_H264_SCALING_LIST_8x8_0, + scaling->scaling_list_8x8[0], + sizeof(scaling->scaling_list_8x8[0])); +@@ -442,6 +446,8 @@ static void cedrus_set_params(struct cedrus_ctx *ctx, + reg |= (pps->second_chroma_qp_index_offset & 0x3f) << 16; + reg |= (pps->chroma_qp_index_offset & 0x3f) << 8; + reg |= (pps->pic_init_qp_minus26 + 26 + slice->slice_qp_delta) & 0x3f; ++ if (pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT) ++ reg |= VE_H264_SHS_QP_SCALING_MATRIX_DEFAULT; + cedrus_write(dev, VE_H264_SHS_QP, reg); + + // clear status flags + +From 711f57301ef4368ba23f70f6596994b7242803cc Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 6 Jul 2020 21:54:33 +0000 +Subject: [PATCH] media: rkvdec: h264: Fix reference frame_num wrap for second + field + +When decoding the second field in a complementary field pair the second +field is sharing the same frame_num with the first field. + +Currently the frame_num for the first field is wrapped when it matches the +field being decoded, this cause issues to decode the second field in a +complementary field pair. + +Fix this by using inclusive comparison, less than or equal. + +Signed-off-by: Jonas Karlman +Reviewed-by: Ezequiel Garcia +--- + drivers/staging/media/rkvdec/rkvdec-h264.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c +index 9233260e14c1..8fab0151b884 100644 +--- a/drivers/staging/media/rkvdec/rkvdec-h264.c ++++ b/drivers/staging/media/rkvdec/rkvdec-h264.c +@@ -752,7 +752,7 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx, + continue; + + if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM || +- dpb[i].frame_num < dec_params->frame_num) { ++ dpb[i].frame_num <= dec_params->frame_num) { + p[i] = dpb[i].frame_num; + continue; + } + +From a957b522403e98c67b8c184fa3b7709c6e874d40 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 6 Jul 2020 21:54:34 +0000 +Subject: [PATCH] media: rkvdec: Ensure decoded resolution fit coded resolution + +Ensure decoded CAPTURE buffer resolution is larger or equal to the coded +OPTUPT buffer resolution. + +Signed-off-by: Jonas Karlman +--- + drivers/staging/media/rkvdec/rkvdec.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index d25c4a37e2af..b3e067031c83 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -223,6 +223,8 @@ static int rkvdec_try_capture_fmt(struct file *file, void *priv, + pix_mp->pixelformat = coded_desc->decoded_fmts[0]; + + /* Always apply the frmsize constraint of the coded end. */ ++ pix_mp->width = max(pix_mp->width, ctx->coded_fmt.fmt.pix_mp.width); ++ pix_mp->height = max(pix_mp->height, ctx->coded_fmt.fmt.pix_mp.height); + v4l2_apply_frmsize_constraints(&pix_mp->width, + &pix_mp->height, + &coded_desc->frmsize); + +From 7c3bb86b8d315c1939a35c4dfe31e120758e5395 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 6 Jul 2020 21:54:34 +0000 +Subject: [PATCH] media: rkvdec: h264: Validate and use pic width and height in + mbs + +The width and height in mbs is currently configured based on OUTPUT buffer +resolution, this works for frame pictures but can cause issues for field +pictures. + +When frame_mbs_only_flag is 0 the height in mbs should be height of +the field instead of height of frame. + +Validate pic_width_in_mbs_minus1 and pic_height_in_map_units_minus1 +against OUTPUT buffer resolution and use these values to configure HW. + +Signed-off-by: Jonas Karlman +--- + drivers/staging/media/rkvdec/rkvdec-h264.c | 4 ++-- + drivers/staging/media/rkvdec/rkvdec.c | 10 ++++++++++ + 2 files changed, 12 insertions(+), 2 deletions(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c +index 8fab0151b884..20a783a1bcc7 100644 +--- a/drivers/staging/media/rkvdec/rkvdec-h264.c ++++ b/drivers/staging/media/rkvdec/rkvdec-h264.c +@@ -671,8 +671,8 @@ static void assemble_hw_pps(struct rkvdec_ctx *ctx, + LOG2_MAX_PIC_ORDER_CNT_LSB_MINUS4); + WRITE_PPS(!!(sps->flags & V4L2_H264_SPS_FLAG_DELTA_PIC_ORDER_ALWAYS_ZERO), + DELTA_PIC_ORDER_ALWAYS_ZERO_FLAG); +- WRITE_PPS(DIV_ROUND_UP(ctx->coded_fmt.fmt.pix_mp.width, 16), PIC_WIDTH_IN_MBS); +- WRITE_PPS(DIV_ROUND_UP(ctx->coded_fmt.fmt.pix_mp.height, 16), PIC_HEIGHT_IN_MBS); ++ WRITE_PPS(sps->pic_width_in_mbs_minus1 + 1, PIC_WIDTH_IN_MBS); ++ WRITE_PPS(sps->pic_height_in_map_units_minus1 + 1, PIC_HEIGHT_IN_MBS); + WRITE_PPS(!!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY), + FRAME_MBS_ONLY_FLAG); + WRITE_PPS(!!(sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD), +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index b3e067031c83..06fc58440cd3 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -29,8 +29,11 @@ + + static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl) + { ++ struct rkvdec_ctx *ctx = container_of(ctrl->handler, struct rkvdec_ctx, ctrl_hdl); ++ + if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_SPS) { + const struct v4l2_ctrl_h264_sps *sps = ctrl->p_new.p_h264_sps; ++ unsigned int width, height; + /* + * TODO: The hardware supports 10-bit and 4:2:2 profiles, + * but it's currently broken in the driver. +@@ -45,6 +48,13 @@ static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl) + if (sps->bit_depth_luma_minus8 != 0) + /* Only 8-bit is supported */ + return -EINVAL; ++ ++ width = (sps->pic_width_in_mbs_minus1 + 1) * 16; ++ height = (sps->pic_height_in_map_units_minus1 + 1) * 16; ++ ++ if (width > ctx->coded_fmt.fmt.pix_mp.width || ++ height > ctx->coded_fmt.fmt.pix_mp.height) ++ return -EINVAL; + } + return 0; + } + +From f28529ac6fd75419e2b1806777158b5912ea0cb4 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 6 Jul 2020 21:54:35 +0000 +Subject: [PATCH] media: rkvdec: h264: Fix bit depth wrap in pps packet + +The luma and chroma bit depth fields in the pps packet is 3 bits wide. +8 is wrongly added to the bit depth value written to these 3-bit fields. +Because only the 3 LSB is written the hardware is configured correctly. + +Correct this by not adding 8 to the luma and chroma bit depth value. + +Signed-off-by: Jonas Karlman +Reviewed-by: Ezequiel Garcia +--- + drivers/staging/media/rkvdec/rkvdec-h264.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c +index 20a783a1bcc7..f4b61dd45e7f 100644 +--- a/drivers/staging/media/rkvdec/rkvdec-h264.c ++++ b/drivers/staging/media/rkvdec/rkvdec-h264.c +@@ -661,8 +661,8 @@ static void assemble_hw_pps(struct rkvdec_ctx *ctx, + WRITE_PPS(0xff, PROFILE_IDC); + WRITE_PPS(1, CONSTRAINT_SET3_FLAG); + WRITE_PPS(sps->chroma_format_idc, CHROMA_FORMAT_IDC); +- WRITE_PPS(sps->bit_depth_luma_minus8 + 8, BIT_DEPTH_LUMA); +- WRITE_PPS(sps->bit_depth_chroma_minus8 + 8, BIT_DEPTH_CHROMA); ++ WRITE_PPS(sps->bit_depth_luma_minus8, BIT_DEPTH_LUMA); ++ WRITE_PPS(sps->bit_depth_chroma_minus8, BIT_DEPTH_CHROMA); + WRITE_PPS(0, QPPRIME_Y_ZERO_TRANSFORM_BYPASS_FLAG); + WRITE_PPS(sps->log2_max_frame_num_minus4, LOG2_MAX_FRAME_NUM_MINUS4); + WRITE_PPS(sps->max_num_ref_frames, MAX_NUM_REF_FRAMES); + +From a0de7efadd3058c3837714fd1c71e31dd00b9eac Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 6 Jul 2020 21:54:35 +0000 +Subject: [PATCH] media: rkvdec: h264: Do not override output buffer sizeimage + +The output buffer sizeimage is currently forced to 2 bytes per pixel, this +can lead to high memory usage for 4K content when multiple output buffers +is created by userspace. + +Do not override output buffer sizeimage and let userspace have control of +output buffer sizeimage by only setting sizeimage if none is provided. + +Signed-off-by: Jonas Karlman +--- + drivers/staging/media/rkvdec/rkvdec-h264.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c +index f4b61dd45e7f..2e7749bac417 100644 +--- a/drivers/staging/media/rkvdec/rkvdec-h264.c ++++ b/drivers/staging/media/rkvdec/rkvdec-h264.c +@@ -1015,8 +1015,9 @@ static int rkvdec_h264_adjust_fmt(struct rkvdec_ctx *ctx, + struct v4l2_pix_format_mplane *fmt = &f->fmt.pix_mp; + + fmt->num_planes = 1; +- fmt->plane_fmt[0].sizeimage = fmt->width * fmt->height * +- RKVDEC_H264_MAX_DEPTH_IN_BYTES; ++ if (!fmt->plane_fmt[0].sizeimage) ++ fmt->plane_fmt[0].sizeimage = fmt->width * fmt->height * ++ RKVDEC_H264_MAX_DEPTH_IN_BYTES; + return 0; + } + + +From 2fd027124722012155dda6bf4af57d978ce0655c Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 6 Jul 2020 21:54:35 +0000 +Subject: [PATCH] media: v4l2-common: Add helpers to calculate bytesperline and + sizeimage + +Add helper functions to calculate plane bytesperline and sizeimage, these +new helpers consider block width and height when calculating plane +bytesperline and sizeimage. + +This prepare support for new pixel formats added in next patch that make +use of block width and height. + +Signed-off-by: Jonas Karlman +--- + drivers/media/v4l2-core/v4l2-common.c | 77 +++++++++++++-------------- + 1 file changed, 38 insertions(+), 39 deletions(-) + +diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c +index 3dc17ebe14fa..4102c373b48a 100644 +--- a/drivers/media/v4l2-core/v4l2-common.c ++++ b/drivers/media/v4l2-core/v4l2-common.c +@@ -333,6 +333,33 @@ static inline unsigned int v4l2_format_block_height(const struct v4l2_format_inf + return info->block_h[plane]; + } + ++static inline unsigned int v4l2_format_plane_width(const struct v4l2_format_info *info, int plane, ++ unsigned int width) ++{ ++ unsigned int hdiv = plane ? info->hdiv : 1; ++ unsigned int bytes = DIV_ROUND_UP(width * info->bpp[plane], ++ v4l2_format_block_width(info, plane) * ++ v4l2_format_block_height(info, plane)); ++ ++ return DIV_ROUND_UP(bytes, hdiv); ++} ++ ++static inline unsigned int v4l2_format_plane_height(const struct v4l2_format_info *info, int plane, ++ unsigned int height) ++{ ++ unsigned int vdiv = plane ? info->vdiv : 1; ++ unsigned int lines = ALIGN(height, v4l2_format_block_height(info, plane)); ++ ++ return DIV_ROUND_UP(lines, vdiv); ++} ++ ++static inline unsigned int v4l2_format_plane_size(const struct v4l2_format_info *info, int plane, ++ unsigned int width, unsigned int height) ++{ ++ return v4l2_format_plane_width(info, plane, width) * ++ v4l2_format_plane_height(info, plane, height); ++} ++ + void v4l2_apply_frmsize_constraints(u32 *width, u32 *height, + const struct v4l2_frmsize_stepwise *frmsize) + { +@@ -368,37 +395,19 @@ int v4l2_fill_pixfmt_mp(struct v4l2_pix_format_mplane *pixfmt, + + if (info->mem_planes == 1) { + plane = &pixfmt->plane_fmt[0]; +- plane->bytesperline = ALIGN(width, v4l2_format_block_width(info, 0)) * info->bpp[0]; ++ plane->bytesperline = v4l2_format_plane_width(info, 0, width); + plane->sizeimage = 0; + +- for (i = 0; i < info->comp_planes; i++) { +- unsigned int hdiv = (i == 0) ? 1 : info->hdiv; +- unsigned int vdiv = (i == 0) ? 1 : info->vdiv; +- unsigned int aligned_width; +- unsigned int aligned_height; +- +- aligned_width = ALIGN(width, v4l2_format_block_width(info, i)); +- aligned_height = ALIGN(height, v4l2_format_block_height(info, i)); +- +- plane->sizeimage += info->bpp[i] * +- DIV_ROUND_UP(aligned_width, hdiv) * +- DIV_ROUND_UP(aligned_height, vdiv); +- } ++ for (i = 0; i < info->comp_planes; i++) ++ plane->sizeimage += ++ v4l2_format_plane_size(info, i, width, height); + } else { + for (i = 0; i < info->comp_planes; i++) { +- unsigned int hdiv = (i == 0) ? 1 : info->hdiv; +- unsigned int vdiv = (i == 0) ? 1 : info->vdiv; +- unsigned int aligned_width; +- unsigned int aligned_height; +- +- aligned_width = ALIGN(width, v4l2_format_block_width(info, i)); +- aligned_height = ALIGN(height, v4l2_format_block_height(info, i)); +- + plane = &pixfmt->plane_fmt[i]; + plane->bytesperline = +- info->bpp[i] * DIV_ROUND_UP(aligned_width, hdiv); +- plane->sizeimage = +- plane->bytesperline * DIV_ROUND_UP(aligned_height, vdiv); ++ v4l2_format_plane_width(info, i, width); ++ plane->sizeimage = plane->bytesperline * ++ v4l2_format_plane_height(info, i, height); + } + } + return 0; +@@ -422,22 +431,12 @@ int v4l2_fill_pixfmt(struct v4l2_pix_format *pixfmt, u32 pixelformat, + pixfmt->width = width; + pixfmt->height = height; + pixfmt->pixelformat = pixelformat; +- pixfmt->bytesperline = ALIGN(width, v4l2_format_block_width(info, 0)) * info->bpp[0]; ++ pixfmt->bytesperline = v4l2_format_plane_width(info, 0, width); + pixfmt->sizeimage = 0; + +- for (i = 0; i < info->comp_planes; i++) { +- unsigned int hdiv = (i == 0) ? 1 : info->hdiv; +- unsigned int vdiv = (i == 0) ? 1 : info->vdiv; +- unsigned int aligned_width; +- unsigned int aligned_height; +- +- aligned_width = ALIGN(width, v4l2_format_block_width(info, i)); +- aligned_height = ALIGN(height, v4l2_format_block_height(info, i)); +- +- pixfmt->sizeimage += info->bpp[i] * +- DIV_ROUND_UP(aligned_width, hdiv) * +- DIV_ROUND_UP(aligned_height, vdiv); +- } ++ for (i = 0; i < info->comp_planes; i++) ++ pixfmt->sizeimage += ++ v4l2_format_plane_size(info, i, width, height); + return 0; + } + EXPORT_SYMBOL_GPL(v4l2_fill_pixfmt); + +From 889f4693a0947c22188ca643ed9ba3579f0abc66 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 6 Jul 2020 21:54:36 +0000 +Subject: [PATCH] media: v4l2: Add NV15 and NV20 pixel formats + +Add NV15 and NV20 pixel formats used by the Rockchip Video Decoder for +10-bit buffers. + +NV15 and NV20 is a packed 10-bit 4:2:0/4:2:2 semi-planar Y/CbCr format +similar to P010 and P210 but has no padding between components. Instead, +luminance and chrominance samples are grouped into 4s so that each group is +packed into an integer number of bytes: + +YYYY = UVUV = 4 * 10 bits = 40 bits = 5 bytes + +The '15' and '20' suffix refers to the optimum effective bits per pixel +which is achieved when the total number of luminance samples is a multiple +of 8 for NV15 and 4 for NV20. + +Signed-off-by: Jonas Karlman +--- + .../userspace-api/media/v4l/pixfmt-nv15.rst | 101 ++++++++++++++++++ + .../userspace-api/media/v4l/pixfmt-nv20.rst | 99 +++++++++++++++++ + .../userspace-api/media/v4l/yuv-formats.rst | 2 + + drivers/media/v4l2-core/v4l2-common.c | 3 + + drivers/media/v4l2-core/v4l2-ioctl.c | 2 + + include/uapi/linux/videodev2.h | 3 + + 6 files changed, 210 insertions(+) + create mode 100644 Documentation/userspace-api/media/v4l/pixfmt-nv15.rst + create mode 100644 Documentation/userspace-api/media/v4l/pixfmt-nv20.rst + +diff --git a/Documentation/userspace-api/media/v4l/pixfmt-nv15.rst b/Documentation/userspace-api/media/v4l/pixfmt-nv15.rst +new file mode 100644 +index 000000000000..d059db58c6e0 +--- /dev/null ++++ b/Documentation/userspace-api/media/v4l/pixfmt-nv15.rst +@@ -0,0 +1,101 @@ ++.. Permission is granted to copy, distribute and/or modify this ++.. document under the terms of the GNU Free Documentation License, ++.. Version 1.1 or any later version published by the Free Software ++.. Foundation, with no Invariant Sections, no Front-Cover Texts ++.. and no Back-Cover Texts. A copy of the license is included at ++.. Documentation/userspace-api/media/fdl-appendix.rst. ++.. ++.. TODO: replace it to GFDL-1.1-or-later WITH no-invariant-sections ++ ++.. _V4L2-PIX-FMT-NV15: ++ ++************************** ++V4L2_PIX_FMT_NV15 ('NV15') ++************************** ++ ++Format with ½ horizontal and vertical chroma resolution, also known as ++YUV 4:2:0. One luminance and one chrominance plane with alternating ++chroma samples similar to ``V4L2_PIX_FMT_NV12`` but with 10-bit samples ++that are grouped into four and packed into five bytes. ++ ++The '15' suffix refers to the optimum effective bits per pixel which is ++achieved when the total number of luminance samples is a multiple of 8. ++ ++ ++Description ++=========== ++ ++This is a packed 10-bit two-plane version of the YUV 4:2:0 format. The ++three components are separated into two sub-images or planes. The Y plane ++is first. The Y plane has five bytes per each group of four pixels. A ++combined CbCr plane immediately follows the Y plane in memory. The CbCr ++plane is the same width, in bytes, as the Y plane (and of the image), but ++is half as tall in pixels. Each CbCr pair belongs to four pixels. For ++example, Cb\ :sub:`00`/Cr\ :sub:`00` belongs to Y'\ :sub:`00`, ++Y'\ :sub:`01`, Y'\ :sub:`10`, Y'\ :sub:`11`. ++ ++If the Y plane has pad bytes after each row, then the CbCr plane has as ++many pad bytes after its rows. ++ ++**Byte Order.** ++Little endian. Each cell is one byte. Pixels cross the byte boundary. ++ ++ ++.. flat-table:: ++ :header-rows: 0 ++ :stub-columns: 0 ++ ++ * - start + 0: ++ - Y'\ :sub:`00[7:0]` ++ - Y'\ :sub:`01[5:0]`\ Y'\ :sub:`00[9:8]` ++ - Y'\ :sub:`02[3:0]`\ Y'\ :sub:`01[9:6]` ++ - Y'\ :sub:`03[1:0]`\ Y'\ :sub:`02[9:4]` ++ - Y'\ :sub:`03[9:2]` ++ * - start + 5: ++ - Y'\ :sub:`10[7:0]` ++ - Y'\ :sub:`11[5:0]`\ Y'\ :sub:`10[9:8]` ++ - Y'\ :sub:`12[3:0]`\ Y'\ :sub:`11[9:6]` ++ - Y'\ :sub:`13[1:0]`\ Y'\ :sub:`12[9:4]` ++ - Y'\ :sub:`13[9:2]` ++ * - start + 10: ++ - Cb'\ :sub:`00[7:0]` ++ - Cr'\ :sub:`00[5:0]`\ Cb'\ :sub:`00[9:8]` ++ - Cb'\ :sub:`01[3:0]`\ Cr'\ :sub:`00[9:6]` ++ - Cr'\ :sub:`01[1:0]`\ Cb'\ :sub:`01[9:4]` ++ - Cr'\ :sub:`01[9:2]` ++ ++ ++**Color Sample Location:** ++ ++.. flat-table:: ++ :header-rows: 0 ++ :stub-columns: 0 ++ ++ * - ++ - 0 ++ - ++ - 1 ++ - 2 ++ - ++ - 3 ++ * - 0 ++ - Y ++ - ++ - Y ++ - Y ++ - ++ - Y ++ * - ++ - ++ - C ++ - ++ - ++ - C ++ - ++ * - 1 ++ - Y ++ - ++ - Y ++ - Y ++ - ++ - Y +diff --git a/Documentation/userspace-api/media/v4l/pixfmt-nv20.rst b/Documentation/userspace-api/media/v4l/pixfmt-nv20.rst +new file mode 100644 +index 000000000000..a8123be0baa3 +--- /dev/null ++++ b/Documentation/userspace-api/media/v4l/pixfmt-nv20.rst +@@ -0,0 +1,99 @@ ++.. Permission is granted to copy, distribute and/or modify this ++.. document under the terms of the GNU Free Documentation License, ++.. Version 1.1 or any later version published by the Free Software ++.. Foundation, with no Invariant Sections, no Front-Cover Texts ++.. and no Back-Cover Texts. A copy of the license is included at ++.. Documentation/userspace-api/media/fdl-appendix.rst. ++.. ++.. TODO: replace it to GFDL-1.1-or-later WITH no-invariant-sections ++ ++.. _V4L2-PIX-FMT-NV20: ++ ++************************** ++V4L2_PIX_FMT_NV20 ('NV20') ++************************** ++ ++Format with ½ horizontal chroma resolution, also known as YUV 4:2:2. ++One luminance and one chrominance plane with alternating chroma samples ++similar to ``V4L2_PIX_FMT_NV16`` but with 10-bit samples ++that are grouped into four and packed into five bytes. ++ ++The '20' suffix refers to the optimum effective bits per pixel which is ++achieved when the total number of luminance samples is a multiple of 4. ++ ++ ++Description ++=========== ++ ++This is a packed 10-bit two-plane version of the YUV 4:2:2 format. The ++three components are separated into two sub-images or planes. The Y plane ++is first. The Y plane has five bytes per each group of four pixels. A ++combined CbCr plane immediately follows the Y plane in memory. The CbCr ++plane is the same width and height, in bytes, as the Y plane (and of the ++image). Each CbCr pair belongs to two pixels. For example, ++Cb\ :sub:`00`/Cr\ :sub:`00` belongs to Y'\ :sub:`00`, Y'\ :sub:`01`. ++ ++If the Y plane has pad bytes after each row, then the CbCr plane has as ++many pad bytes after its rows. ++ ++**Byte Order.** ++Little endian. Each cell is one byte. Pixels cross the byte boundary. ++ ++ ++.. flat-table:: ++ :header-rows: 0 ++ :stub-columns: 0 ++ ++ * - start + 0: ++ - Y'\ :sub:`00[7:0]` ++ - Y'\ :sub:`01[5:0]`\ Y'\ :sub:`00[9:8]` ++ - Y'\ :sub:`02[3:0]`\ Y'\ :sub:`01[9:6]` ++ - Y'\ :sub:`03[1:0]`\ Y'\ :sub:`02[9:4]` ++ - Y'\ :sub:`03[9:2]` ++ * - start + 5: ++ - Y'\ :sub:`10[7:0]` ++ - Y'\ :sub:`11[5:0]`\ Y'\ :sub:`10[9:8]` ++ - Y'\ :sub:`12[3:0]`\ Y'\ :sub:`11[9:6]` ++ - Y'\ :sub:`13[1:0]`\ Y'\ :sub:`12[9:4]` ++ - Y'\ :sub:`13[9:2]` ++ * - start + 10: ++ - Cb'\ :sub:`00[7:0]` ++ - Cr'\ :sub:`00[5:0]`\ Cb'\ :sub:`00[9:8]` ++ - Cb'\ :sub:`01[3:0]`\ Cr'\ :sub:`00[9:6]` ++ - Cr'\ :sub:`01[1:0]`\ Cb'\ :sub:`01[9:4]` ++ - Cr'\ :sub:`01[9:2]` ++ * - start + 15: ++ - Cb'\ :sub:`10[7:0]` ++ - Cr'\ :sub:`10[5:0]`\ Cb'\ :sub:`10[9:8]` ++ - Cb'\ :sub:`11[3:0]`\ Cr'\ :sub:`10[9:6]` ++ - Cr'\ :sub:`11[1:0]`\ Cb'\ :sub:`11[9:4]` ++ - Cr'\ :sub:`11[9:2]` ++ ++ ++**Color Sample Location:** ++ ++.. flat-table:: ++ :header-rows: 0 ++ :stub-columns: 0 ++ ++ * - ++ - 0 ++ - ++ - 1 ++ - 2 ++ - ++ - 3 ++ * - 0 ++ - Y ++ - C ++ - Y ++ - Y ++ - C ++ - Y ++ * - 1 ++ - Y ++ - C ++ - Y ++ - Y ++ - C ++ - Y +diff --git a/Documentation/userspace-api/media/v4l/yuv-formats.rst b/Documentation/userspace-api/media/v4l/yuv-formats.rst +index 8ee92d0cd769..7cca883f178a 100644 +--- a/Documentation/userspace-api/media/v4l/yuv-formats.rst ++++ b/Documentation/userspace-api/media/v4l/yuv-formats.rst +@@ -61,4 +61,6 @@ to brightness information. + pixfmt-nv16 + pixfmt-nv16m + pixfmt-nv24 ++ pixfmt-nv15 ++ pixfmt-nv20 + pixfmt-m420 +diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c +index 4102c373b48a..0caac755d303 100644 +--- a/drivers/media/v4l2-core/v4l2-common.c ++++ b/drivers/media/v4l2-core/v4l2-common.c +@@ -267,6 +267,9 @@ const struct v4l2_format_info *v4l2_format_info(u32 format) + { .format = V4L2_PIX_FMT_NV24, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_NV42, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + ++ { .format = V4L2_PIX_FMT_NV15, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 5, 5, 0, 0 }, .hdiv = 2, .vdiv = 2, .block_w = { 4, 2, 0, 0 }, .block_h = { 1, 1, 0, 0 } }, ++ { .format = V4L2_PIX_FMT_NV20, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 5, 5, 0, 0 }, .hdiv = 2, .vdiv = 1, .block_w = { 4, 2, 0, 0 }, .block_h = { 1, 1, 0, 0 } }, ++ + { .format = V4L2_PIX_FMT_YUV410, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 4 }, + { .format = V4L2_PIX_FMT_YVU410, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 4 }, + { .format = V4L2_PIX_FMT_YUV411P, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 1 }, +diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c +index ccf947632a3b..53de49087938 100644 +--- a/drivers/media/v4l2-core/v4l2-ioctl.c ++++ b/drivers/media/v4l2-core/v4l2-ioctl.c +@@ -1321,6 +1321,8 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) + case V4L2_PIX_FMT_NV61: descr = "Y/CrCb 4:2:2"; break; + case V4L2_PIX_FMT_NV24: descr = "Y/CbCr 4:4:4"; break; + case V4L2_PIX_FMT_NV42: descr = "Y/CrCb 4:4:4"; break; ++ case V4L2_PIX_FMT_NV15: descr = "10-bit Y/CbCr 4:2:0 (Packed)"; break; ++ case V4L2_PIX_FMT_NV20: descr = "10-bit Y/CbCr 4:2:2 (Packed)"; break; + case V4L2_PIX_FMT_NV12M: descr = "Y/CbCr 4:2:0 (N-C)"; break; + case V4L2_PIX_FMT_NV21M: descr = "Y/CrCb 4:2:0 (N-C)"; break; + case V4L2_PIX_FMT_NV16M: descr = "Y/CbCr 4:2:2 (N-C)"; break; +diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h +index 6fe8822d2cb4..c8d7148cd9ae 100644 +--- a/include/uapi/linux/videodev2.h ++++ b/include/uapi/linux/videodev2.h +@@ -610,6 +610,9 @@ struct v4l2_pix_format { + #define V4L2_PIX_FMT_NV24 v4l2_fourcc('N', 'V', '2', '4') /* 24 Y/CbCr 4:4:4 */ + #define V4L2_PIX_FMT_NV42 v4l2_fourcc('N', 'V', '4', '2') /* 24 Y/CrCb 4:4:4 */ + ++#define V4L2_PIX_FMT_NV15 v4l2_fourcc('N', 'V', '1', '5') /* 15 Y/CbCr 4:2:0 10-bit packed */ ++#define V4L2_PIX_FMT_NV20 v4l2_fourcc('N', 'V', '2', '0') /* 20 Y/CbCr 4:2:2 10-bit packed */ ++ + /* two non contiguous planes - one Y, one Cr + Cb interleaved */ + #define V4L2_PIX_FMT_NV12M v4l2_fourcc('N', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 */ + #define V4L2_PIX_FMT_NV21M v4l2_fourcc('N', 'M', '2', '1') /* 21 Y/CrCb 4:2:0 */ + +From d09e5dfbcc096eddf5c5d11744d53bae5f1f7d00 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 6 Jul 2020 21:54:36 +0000 +Subject: [PATCH] media: rkvdec: h264: Use bytesperline and buffer height to + calculate stride + +Use bytesperline and buffer height to calculate the strides configured. + +This does not really change anything other than ensuring the bytesperline +that is signaled to userspace matches what is configured in HW. + +Signed-off-by: Jonas Karlman +--- + drivers/staging/media/rkvdec/rkvdec-h264.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c +index 2e7749bac417..d33fccc92205 100644 +--- a/drivers/staging/media/rkvdec/rkvdec-h264.c ++++ b/drivers/staging/media/rkvdec/rkvdec-h264.c +@@ -893,9 +893,9 @@ static void config_registers(struct rkvdec_ctx *ctx, + dma_addr_t rlc_addr; + dma_addr_t refer_addr; + u32 rlc_len; +- u32 hor_virstride = 0; +- u32 ver_virstride = 0; +- u32 y_virstride = 0; ++ u32 hor_virstride; ++ u32 ver_virstride; ++ u32 y_virstride; + u32 yuv_virstride = 0; + u32 offset; + dma_addr_t dst_addr; +@@ -906,8 +906,8 @@ static void config_registers(struct rkvdec_ctx *ctx, + + f = &ctx->decoded_fmt; + dst_fmt = &f->fmt.pix_mp; +- hor_virstride = (sps->bit_depth_luma_minus8 + 8) * dst_fmt->width / 8; +- ver_virstride = round_up(dst_fmt->height, 16); ++ hor_virstride = dst_fmt->plane_fmt[0].bytesperline; ++ ver_virstride = dst_fmt->height; + y_virstride = hor_virstride * ver_virstride; + + if (sps->chroma_format_idc == 0) + +From f0e873d66825fcd9ea314dcdab0d214226b2b8b4 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 6 Jul 2020 21:54:37 +0000 +Subject: [PATCH] media: rkvdec: Extract rkvdec_fill_decoded_pixfmt helper + method + +This extract setting decoded pixfmt into a helper method, current code is +replaced with a call to the new helper method. + +The helper method is also called from a new function in next patch. + +Signed-off-by: Jonas Karlman +--- + drivers/staging/media/rkvdec/rkvdec.c | 29 ++++++++++++++------------- + 1 file changed, 15 insertions(+), 14 deletions(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index 06fc58440cd3..dc16bf8d57a9 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -27,6 +27,17 @@ + #include "rkvdec.h" + #include "rkvdec-regs.h" + ++static void rkvdec_fill_decoded_pixfmt(struct rkvdec_ctx *ctx, ++ struct v4l2_pix_format_mplane *pix_mp) ++{ ++ v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat, ++ pix_mp->width, pix_mp->height); ++ pix_mp->plane_fmt[0].sizeimage += 128 * ++ DIV_ROUND_UP(pix_mp->width, 16) * ++ DIV_ROUND_UP(pix_mp->height, 16); ++ pix_mp->field = V4L2_FIELD_NONE; ++} ++ + static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl) + { + struct rkvdec_ctx *ctx = container_of(ctrl->handler, struct rkvdec_ctx, ctrl_hdl); +@@ -167,13 +178,9 @@ static void rkvdec_reset_decoded_fmt(struct rkvdec_ctx *ctx) + + rkvdec_reset_fmt(ctx, f, ctx->coded_fmt_desc->decoded_fmts[0]); + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; +- v4l2_fill_pixfmt_mp(&f->fmt.pix_mp, +- ctx->coded_fmt_desc->decoded_fmts[0], +- ctx->coded_fmt.fmt.pix_mp.width, +- ctx->coded_fmt.fmt.pix_mp.height); +- f->fmt.pix_mp.plane_fmt[0].sizeimage += 128 * +- DIV_ROUND_UP(f->fmt.pix_mp.width, 16) * +- DIV_ROUND_UP(f->fmt.pix_mp.height, 16); ++ f->fmt.pix_mp.width = ctx->coded_fmt.fmt.pix_mp.width; ++ f->fmt.pix_mp.height = ctx->coded_fmt.fmt.pix_mp.height; ++ rkvdec_fill_decoded_pixfmt(ctx, &f->fmt.pix_mp); + } + + static int rkvdec_enum_framesizes(struct file *file, void *priv, +@@ -239,13 +246,7 @@ static int rkvdec_try_capture_fmt(struct file *file, void *priv, + &pix_mp->height, + &coded_desc->frmsize); + +- v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat, +- pix_mp->width, pix_mp->height); +- pix_mp->plane_fmt[0].sizeimage += +- 128 * +- DIV_ROUND_UP(pix_mp->width, 16) * +- DIV_ROUND_UP(pix_mp->height, 16); +- pix_mp->field = V4L2_FIELD_NONE; ++ rkvdec_fill_decoded_pixfmt(ctx, pix_mp); + + return 0; + } + +From 7743a31004da67bfd0f6246deaa59e670230c84e Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 6 Jul 2020 21:54:37 +0000 +Subject: [PATCH] media: rkvdec: Lock capture pixel format in s_ctrl and s_fmt + +Add an optional valid_fmt operation that should return the valid +pixelformat of CAPTURE buffers. + +This is used in next patch to ensure correct pixelformat is used for 10-bit +and 4:2:2 content. + +Signed-off-by: Jonas Karlman +--- + drivers/staging/media/rkvdec/rkvdec.c | 59 ++++++++++++++++++++++++--- + drivers/staging/media/rkvdec/rkvdec.h | 2 + + 2 files changed, 55 insertions(+), 6 deletions(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index dc16bf8d57a9..6b2a2f4164b2 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -38,6 +38,16 @@ static void rkvdec_fill_decoded_pixfmt(struct rkvdec_ctx *ctx, + pix_mp->field = V4L2_FIELD_NONE; + } + ++static u32 rkvdec_valid_fmt(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl) ++{ ++ const struct rkvdec_coded_fmt_desc *coded_desc = ctx->coded_fmt_desc; ++ ++ if (coded_desc->ops->valid_fmt) ++ return coded_desc->ops->valid_fmt(ctx, ctrl); ++ ++ return ctx->valid_fmt; ++} ++ + static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl) + { + struct rkvdec_ctx *ctx = container_of(ctrl->handler, struct rkvdec_ctx, ctrl_hdl); +@@ -60,6 +70,10 @@ static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl) + /* Only 8-bit is supported */ + return -EINVAL; + ++ if (ctx->valid_fmt && ctx->valid_fmt != rkvdec_valid_fmt(ctx, ctrl)) ++ /* Only current valid format */ ++ return -EINVAL; ++ + width = (sps->pic_width_in_mbs_minus1 + 1) * 16; + height = (sps->pic_height_in_map_units_minus1 + 1) * 16; + +@@ -70,8 +84,27 @@ static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl) + return 0; + } + ++static int rkvdec_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct rkvdec_ctx *ctx = container_of(ctrl->handler, struct rkvdec_ctx, ctrl_hdl); ++ ++ if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_SPS && !ctx->valid_fmt) { ++ ctx->valid_fmt = rkvdec_valid_fmt(ctx, ctrl); ++ if (ctx->valid_fmt) { ++ struct v4l2_pix_format_mplane *pix_mp; ++ ++ pix_mp = &ctx->decoded_fmt.fmt.pix_mp; ++ pix_mp->pixelformat = ctx->valid_fmt; ++ rkvdec_fill_decoded_pixfmt(ctx, pix_mp); ++ } ++ } ++ ++ return 0; ++} ++ + static const struct v4l2_ctrl_ops rkvdec_ctrl_ops = { + .try_ctrl = rkvdec_try_ctrl, ++ .s_ctrl = rkvdec_s_ctrl, + }; + + static const struct rkvdec_ctrl_desc rkvdec_h264_ctrl_descs[] = { +@@ -176,6 +209,7 @@ static void rkvdec_reset_decoded_fmt(struct rkvdec_ctx *ctx) + { + struct v4l2_format *f = &ctx->decoded_fmt; + ++ ctx->valid_fmt = 0; + rkvdec_reset_fmt(ctx, f, ctx->coded_fmt_desc->decoded_fmts[0]); + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + f->fmt.pix_mp.width = ctx->coded_fmt.fmt.pix_mp.width; +@@ -231,13 +265,17 @@ static int rkvdec_try_capture_fmt(struct file *file, void *priv, + if (WARN_ON(!coded_desc)) + return -EINVAL; + +- for (i = 0; i < coded_desc->num_decoded_fmts; i++) { +- if (coded_desc->decoded_fmts[i] == pix_mp->pixelformat) +- break; +- } ++ if (ctx->valid_fmt) { ++ pix_mp->pixelformat = ctx->valid_fmt; ++ } else { ++ for (i = 0; i < coded_desc->num_decoded_fmts; i++) { ++ if (coded_desc->decoded_fmts[i] == pix_mp->pixelformat) ++ break; ++ } + +- if (i == coded_desc->num_decoded_fmts) +- pix_mp->pixelformat = coded_desc->decoded_fmts[0]; ++ if (i == coded_desc->num_decoded_fmts) ++ pix_mp->pixelformat = coded_desc->decoded_fmts[0]; ++ } + + /* Always apply the frmsize constraint of the coded end. */ + pix_mp->width = max(pix_mp->width, ctx->coded_fmt.fmt.pix_mp.width); +@@ -312,6 +350,7 @@ static int rkvdec_s_capture_fmt(struct file *file, void *priv, + return ret; + + ctx->decoded_fmt = *f; ++ ctx->valid_fmt = f->fmt.pix_mp.pixelformat; + return 0; + } + +@@ -401,6 +440,14 @@ static int rkvdec_enum_capture_fmt(struct file *file, void *priv, + if (WARN_ON(!ctx->coded_fmt_desc)) + return -EINVAL; + ++ if (ctx->valid_fmt) { ++ if (f->index) ++ return -EINVAL; ++ ++ f->pixelformat = ctx->valid_fmt; ++ return 0; ++ } ++ + if (f->index >= ctx->coded_fmt_desc->num_decoded_fmts) + return -EINVAL; + +diff --git a/drivers/staging/media/rkvdec/rkvdec.h b/drivers/staging/media/rkvdec/rkvdec.h +index 77a137cca88e..e95c52e3168a 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.h ++++ b/drivers/staging/media/rkvdec/rkvdec.h +@@ -63,6 +63,7 @@ vb2_to_rkvdec_decoded_buf(struct vb2_buffer *buf) + struct rkvdec_coded_fmt_ops { + int (*adjust_fmt)(struct rkvdec_ctx *ctx, + struct v4l2_format *f); ++ u32 (*valid_fmt)(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl); + int (*start)(struct rkvdec_ctx *ctx); + void (*stop)(struct rkvdec_ctx *ctx); + int (*run)(struct rkvdec_ctx *ctx); +@@ -96,6 +97,7 @@ struct rkvdec_ctx { + struct v4l2_fh fh; + struct v4l2_format coded_fmt; + struct v4l2_format decoded_fmt; ++ u32 valid_fmt; + const struct rkvdec_coded_fmt_desc *coded_fmt_desc; + struct v4l2_ctrl_handler ctrl_hdl; + struct rkvdec_dev *dev; + +From 15bb8d006a05aecc371e530769f06bf52c2c65bc Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 6 Jul 2020 21:54:37 +0000 +Subject: [PATCH] media: rkvdec: h264: Support High 10 and 4:2:2 profiles + +Add support and enable decoding of H264 High 10 and 4:2:2 profiles. + +Decoded CAPTURE buffer width is aligned to 64 pixels to accommodate HW +requirement on 10-bit format buffers. + +The new valid_fmt operation is implemented and return a valid pixelformat +for the provided SPS control. + +Signed-off-by: Jonas Karlman +--- + drivers/staging/media/rkvdec/rkvdec-h264.c | 20 ++++++++++++++++++++ + drivers/staging/media/rkvdec/rkvdec.c | 19 +++++++++---------- + 2 files changed, 29 insertions(+), 10 deletions(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c +index d33fccc92205..afc695d32186 100644 +--- a/drivers/staging/media/rkvdec/rkvdec-h264.c ++++ b/drivers/staging/media/rkvdec/rkvdec-h264.c +@@ -1021,6 +1021,25 @@ static int rkvdec_h264_adjust_fmt(struct rkvdec_ctx *ctx, + return 0; + } + ++static u32 rkvdec_h264_valid_fmt(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl) ++{ ++ const struct v4l2_ctrl_h264_sps *sps = ctrl->p_new.p_h264_sps; ++ ++ if (sps->bit_depth_luma_minus8 == 0) { ++ if (sps->chroma_format_idc == 2) ++ return V4L2_PIX_FMT_NV16; ++ else ++ return V4L2_PIX_FMT_NV12; ++ } else if (sps->bit_depth_luma_minus8 == 2) { ++ if (sps->chroma_format_idc == 2) ++ return V4L2_PIX_FMT_NV20; ++ else ++ return V4L2_PIX_FMT_NV15; ++ } ++ ++ return 0; ++} ++ + static int rkvdec_h264_start(struct rkvdec_ctx *ctx) + { + struct rkvdec_dev *rkvdec = ctx->dev; +@@ -1124,6 +1143,7 @@ static int rkvdec_h264_run(struct rkvdec_ctx *ctx) + + const struct rkvdec_coded_fmt_ops rkvdec_h264_fmt_ops = { + .adjust_fmt = rkvdec_h264_adjust_fmt, ++ .valid_fmt = rkvdec_h264_valid_fmt, + .start = rkvdec_h264_start, + .stop = rkvdec_h264_stop, + .run = rkvdec_h264_run, +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index 6b2a2f4164b2..bd8ec2915fe9 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -31,7 +31,7 @@ static void rkvdec_fill_decoded_pixfmt(struct rkvdec_ctx *ctx, + struct v4l2_pix_format_mplane *pix_mp) + { + v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat, +- pix_mp->width, pix_mp->height); ++ ALIGN(pix_mp->width, 64), pix_mp->height); + pix_mp->plane_fmt[0].sizeimage += 128 * + DIV_ROUND_UP(pix_mp->width, 16) * + DIV_ROUND_UP(pix_mp->height, 16); +@@ -55,19 +55,15 @@ static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl) + if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_SPS) { + const struct v4l2_ctrl_h264_sps *sps = ctrl->p_new.p_h264_sps; + unsigned int width, height; +- /* +- * TODO: The hardware supports 10-bit and 4:2:2 profiles, +- * but it's currently broken in the driver. +- * Reject them for now, until it's fixed. +- */ +- if (sps->chroma_format_idc > 1) +- /* Only 4:0:0 and 4:2:0 are supported */ ++ ++ if (sps->chroma_format_idc > 2) ++ /* Only 4:0:0, 4:2:0 and 4:2:2 are supported */ + return -EINVAL; + if (sps->bit_depth_luma_minus8 != sps->bit_depth_chroma_minus8) + /* Luma and chroma bit depth mismatch */ + return -EINVAL; +- if (sps->bit_depth_luma_minus8 != 0) +- /* Only 8-bit is supported */ ++ if (sps->bit_depth_luma_minus8 != 0 && sps->bit_depth_luma_minus8 != 2) ++ /* Only 8-bit and 10-bit is supported */ + return -EINVAL; + + if (ctx->valid_fmt && ctx->valid_fmt != rkvdec_valid_fmt(ctx, ctrl)) +@@ -145,6 +141,9 @@ static const struct rkvdec_ctrls rkvdec_h264_ctrls = { + + static const u32 rkvdec_h264_decoded_fmts[] = { + V4L2_PIX_FMT_NV12, ++ V4L2_PIX_FMT_NV15, ++ V4L2_PIX_FMT_NV16, ++ V4L2_PIX_FMT_NV20, + }; + + static const struct rkvdec_coded_fmt_desc rkvdec_coded_fmts[] = { + +From 26aca7fda4117f4bff16e3fb5349878fb322410b Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 6 Jul 2020 21:54:38 +0000 +Subject: [PATCH] media: rkvdec: h264: Support profile and level controls + +The Rockchip Video Decoder used in RK3399 supports H.264 profiles from +Baseline to High 4:2:2 up to Level 5.1, except for the Extended profile. + +Expose the V4L2_CID_MPEG_VIDEO_H264_PROFILE and the +V4L2_CID_MPEG_VIDEO_H264_LEVEL control, so that userspace can query the +driver for the list of supported profiles and level. + +Signed-off-by: Jonas Karlman +Reviewed-by: Ezequiel Garcia +--- + drivers/staging/media/rkvdec/rkvdec.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index bd8ec2915fe9..87987a782d75 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -132,6 +132,19 @@ static const struct rkvdec_ctrl_desc rkvdec_h264_ctrl_descs[] = { + .cfg.def = V4L2_MPEG_VIDEO_H264_START_CODE_ANNEX_B, + .cfg.max = V4L2_MPEG_VIDEO_H264_START_CODE_ANNEX_B, + }, ++ { ++ .cfg.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE, ++ .cfg.min = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE, ++ .cfg.max = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422, ++ .cfg.menu_skip_mask = ++ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED), ++ .cfg.def = V4L2_MPEG_VIDEO_H264_PROFILE_MAIN, ++ }, ++ { ++ .cfg.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL, ++ .cfg.min = V4L2_MPEG_VIDEO_H264_LEVEL_1_0, ++ .cfg.max = V4L2_MPEG_VIDEO_H264_LEVEL_5_1, ++ }, + }; + + static const struct rkvdec_ctrls rkvdec_h264_ctrls = { + +From 272e8a34d1803cc88e74de99b10330cd57d18f26 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Mon, 18 May 2020 14:40:09 -0300 +Subject: [PATCH] media: rkvdec: Fix .buf_prepare + +The driver should only set the payload on .buf_prepare +if the buffer is CAPTURE type, or if an OUTPUT buffer +has a zeroed payload. + +Fix it. + +Fixes: cd33c830448ba ("media: rkvdec: Add the rkvdec driver") +Signed-off-by: Ezequiel Garcia +--- + drivers/staging/media/rkvdec/rkvdec.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index 87987a782d75..91f8a1bb6176 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -543,7 +543,15 @@ static int rkvdec_buf_prepare(struct vb2_buffer *vb) + if (vb2_plane_size(vb, i) < sizeimage) + return -EINVAL; + } +- vb2_set_plane_payload(vb, 0, f->fmt.pix_mp.plane_fmt[0].sizeimage); ++ ++ /* ++ * Buffer's bytesused is written by the driver for CAPTURE buffers, ++ * or if the application passed zero bytesused on an OUTPUT buffer. ++ */ ++ if (!V4L2_TYPE_IS_OUTPUT(vq->type) || ++ (V4L2_TYPE_IS_OUTPUT(vq->type) && !vb2_get_plane_payload(vb, 0))) ++ vb2_set_plane_payload(vb, 0, ++ f->fmt.pix_mp.plane_fmt[0].sizeimage); + return 0; + } + + +From 6e771db436797df6146b1fe0ec94d4138bdaa2bc Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Mon, 18 May 2020 14:40:10 -0300 +Subject: [PATCH] media: uapi: Add VP9 stateless decoder controls + +Add the VP9 stateless decoder controls plus the documentation that goes +with it. + +Signed-off-by: Boris Brezillon +Signed-off-by: Ezequiel Garcia +--- + .../userspace-api/media/v4l/biblio.rst | 10 + + .../media/v4l/ext-ctrls-codec.rst | 550 ++++++++++++++++++ + drivers/media/v4l2-core/v4l2-ctrls.c | 239 ++++++++ + drivers/media/v4l2-core/v4l2-ioctl.c | 1 + + include/media/v4l2-ctrls.h | 1 + + include/media/vp9-ctrls.h | 485 +++++++++++++++ + 6 files changed, 1286 insertions(+) + create mode 100644 include/media/vp9-ctrls.h + +diff --git a/Documentation/userspace-api/media/v4l/biblio.rst b/Documentation/userspace-api/media/v4l/biblio.rst +index 3c9634173e82..e09102e572fd 100644 +--- a/Documentation/userspace-api/media/v4l/biblio.rst ++++ b/Documentation/userspace-api/media/v4l/biblio.rst +@@ -414,3 +414,13 @@ VP8 + :title: RFC 6386: "VP8 Data Format and Decoding Guide" + + :author: J. Bankoski et al. ++ ++.. _vp9: ++ ++VP9 ++=== ++ ++ ++:title: VP9 Bitstream & Decoding Process Specification ++ ++:author: Adrian Grange (Google), Peter de Rivaz (Argon Design), Jonathan Hunt (Argon Design) +diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +index 03ce87aa5488..ca13b141d8c2 100644 +--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst ++++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +@@ -2689,6 +2689,556 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + - ``padding[3]`` + - Applications and drivers must set this to zero. + ++.. _v4l2-mpeg-vp9: ++ ++``V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(0..3) (struct)`` ++ Stores VP9 probabilities attached to a specific frame context. The VP9 ++ specification allows using a maximum of 4 contexts. Each frame being ++ decoded refers to one of those context. See section '7.1.2 Refresh ++ probs semantics' section of :ref:`vp9` for more details about these ++ contexts. ++ ++ This control is bi-directional: ++ ++ * all 4 contexts must be initialized by userspace just after the ++ stream is started and before the first decoding request is submitted. ++ * the referenced context might be read by the kernel when a decoding ++ request is submitted, and will be updated after the decoder is done ++ decoding the frame if the `V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX` flag ++ is set. ++ * contexts will be read back by user space before each decoding request ++ to retrieve the updated probabilities. ++ * userspace will re-initialize the context to their default values when ++ a reset context is required. ++ ++ .. note:: ++ ++ This compound control is not yet part of the public kernel API and ++ it is expected to change. ++ ++.. c:type:: v4l2_ctrl_vp9_frame_ctx ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{5.8cm}|p{4.8cm}|p{6.6cm}| ++ ++.. flat-table:: struct v4l2_ctrl_vp9_frame_ctx ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - struct :c:type:`v4l2_vp9_probabilities` ++ - ``probs`` ++ - Structure with VP9 probabilities attached to the context. ++ ++.. c:type:: v4l2_vp9_probabilities ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: struct v4l2_vp9_probabilities ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - __u8 ++ - ``tx8[2][1]`` ++ - TX 8x8 probabilities. ++ * - __u8 ++ - ``tx16[2][2]`` ++ - TX 16x16 probabilities. ++ * - __u8 ++ - ``tx32[2][3]`` ++ - TX 32x32 probabilities. ++ * - __u8 ++ - ``coef[4][2][2][6][6][3]`` ++ - Coefficient probabilities. ++ * - __u8 ++ - ``skip[3]`` ++ - Skip probabilities. ++ * - __u8 ++ - ``inter_mode[7][3]`` ++ - Inter prediction mode probabilities. ++ * - __u8 ++ - ``interp_filter[4][2]`` ++ - Interpolation filter probabilities. ++ * - __u8 ++ - ``is_inter[4]`` ++ - Is inter-block probabilities. ++ * - __u8 ++ - ``comp_mode[5]`` ++ - Compound prediction mode probabilities. ++ * - __u8 ++ - ``single_ref[5][2]`` ++ - Single reference probabilities. ++ * - __u8 ++ - ``comp_mode[5]`` ++ - Compound reference probabilities. ++ * - __u8 ++ - ``y_mode[4][9]`` ++ - Y prediction mode probabilities. ++ * - __u8 ++ - ``uv_mode[10][9]`` ++ - UV prediction mode probabilities. ++ * - __u8 ++ - ``partition[16][3]`` ++ - Partition probabilities. ++ * - __u8 ++ - ``mv.joint[3]`` ++ - Motion vector joint probabilities. ++ * - __u8 ++ - ``mv.sign[2]`` ++ - Motion vector sign probabilities. ++ * - __u8 ++ - ``mv.class[2][10]`` ++ - Motion vector class probabilities. ++ * - __u8 ++ - ``mv.class0_bit[2]`` ++ - Motion vector class0 bit probabilities. ++ * - __u8 ++ - ``mv.bits[2][10]`` ++ - Motion vector bits probabilities. ++ * - __u8 ++ - ``mv.class0_fr[2][2][3]`` ++ - Motion vector class0 fractional bit probabilities. ++ * - __u8 ++ - ``mv.fr[2][3]`` ++ - Motion vector fractional bit probabilities. ++ * - __u8 ++ - ``mv.class0_hp[2]`` ++ - Motion vector class0 high precision fractional bit probabilities. ++ * - __u8 ++ - ``mv.hp[2]`` ++ - Motion vector high precision fractional bit probabilities. ++ ++``V4L2_CID_MPEG_VIDEO_VP9_FRAME_DECODE_PARAMS (struct)`` ++ Specifies the frame parameters for the associated VP9 frame decode request. ++ This includes the necessary parameters for configuring a stateless hardware ++ decoding pipeline for VP9. The bitstream parameters are defined according ++ to :ref:`vp9`. ++ ++ .. note:: ++ ++ This compound control is not yet part of the public kernel API and ++ it is expected to change. ++ ++.. c:type:: v4l2_ctrl_vp9_frame_decode_params ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: struct v4l2_ctrl_vp9_frame_decode_params ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - __u32 ++ - ``flags`` ++ - Combination of V4L2_VP9_FRAME_FLAG_* flags. See ++ :c:type:`v4l2_vp9_frame_flags`. ++ * - __u16 ++ - ``compressed_header_size`` ++ - Compressed header size in bytes. ++ * - __u16 ++ - ``uncompressed_header_size`` ++ - Uncompressed header size in bytes. ++ * - __u8 ++ - ``profile`` ++ - VP9 profile. Can be 0, 1, 2 or 3. ++ * - __u8 ++ - ``reset_frame_context`` ++ - Frame context that should be used/updated when decoding the frame. ++ * - __u8 ++ - ``bit_depth`` ++ - Component depth in bits. Must be 8 for profile 0 and 1. Must 10 or 12 ++ for profile 2 and 3. ++ * - __u8 ++ - ``interpolation_filter`` ++ - Specifies the filter selection used for performing inter prediction. See ++ :c:type:`v4l2_vp9_interpolation_filter`. ++ * - __u8 ++ - ``tile_cols_log2`` ++ - Specifies the base 2 logarithm of the width of each tile (where the ++ width is measured in units of 8x8 blocks). Shall be less than or equal ++ to 6. ++ * - __u8 ++ - ``tile_rows_log2`` ++ - Specifies the base 2 logarithm of the height of each tile (where the ++ height is measured in units of 8x8 blocks) ++ * - __u8 ++ - ``tx_mode`` ++ - Specifies the TX mode. See :c:type:`v4l2_vp9_tx_mode`. ++ * - __u8 ++ - ``reference_mode`` ++ - Specifies the type of inter prediction to be used. See ++ :c:type:`v4l2_vp9_reference_mode`. ++ * - __u8 ++ - ``padding`` ++ - Needed to make this struct 64 bit aligned. Shall be filled with zeroes. ++ * - __u16 ++ - ``frame_width_minus_1`` ++ - Add 1 to get the frame width expressed in pixels. ++ * - __u16 ++ - ``frame_height_minus_1`` ++ - Add 1 to to get the frame height expressed in pixels. ++ * - __u16 ++ - ``frame_width_minus_1`` ++ - Add 1 to to get the expected render width expressed in pixels. This is ++ not used during the decoding process but might be used by HW scalers to ++ prepare a frame that's ready for scanout. ++ * - __u16 ++ - frame_height_minus_1 ++ - Add 1 to get the expected render height expressed in pixels. This is ++ not used during the decoding process but might be used by HW scalers to ++ prepare a frame that's ready for scanout. ++ * - __u64 ++ - ``refs[3]`` ++ - Array of reference frame timestamps. ++ * - struct :c:type:`v4l2_vp9_loop_filter` ++ - ``lf`` ++ - Loop filter parameters. See struct :c:type:`v4l2_vp9_loop_filter`. ++ * - struct :c:type:`v4l2_vp9_quantization` ++ - ``quant`` ++ - Quantization parameters. See :c:type:`v4l2_vp9_quantization`. ++ * - struct :c:type:`v4l2_vp9_segmentation` ++ - ``seg`` ++ - Segmentation parameters. See :c:type:`v4l2_vp9_segmentation`. ++ * - struct :c:type:`v4l2_vp9_probabilities` ++ - ``probs`` ++ - Probabilities. See :c:type:`v4l2_vp9_probabilities`. ++ ++.. c:type:: v4l2_vp9_frame_flags ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: enum v4l2_vp9_frame_flags ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 2 ++ ++ * - ``V4L2_VP9_FRAME_FLAG_KEY_FRAME`` ++ - The frame is a key frame. ++ * - ``V4L2_VP9_FRAME_FLAG_SHOW_FRAME`` ++ - The frame should be displayed. ++ * - ``V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT`` ++ - The decoding should be error resilient. ++ * - ``V4L2_VP9_FRAME_FLAG_INTRA_ONLY`` ++ - The frame does not reference other frames. ++ * - ``V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV`` ++ - the frame might can high precision motion vectors. ++ * - ``V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX`` ++ - Frame context should be updated after decoding. ++ * - ``V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE`` ++ - Parallel decoding is used. ++ * - ``V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING`` ++ - Vertical subsampling is enabled. ++ * - ``V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING`` ++ - Horizontal subsampling is enabled. ++ * - ``V4L2_VP9_FRAME_FLAG_COLOR_RANGE_FULL_SWING`` ++ - The full UV range is used. ++ ++.. c:type:: v4l2_vp9_ref_id ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: enum v4l2_vp9_ref_id ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 2 ++ ++ * - ``V4L2_REF_ID_LAST`` ++ - Last reference frame. ++ * - ``V4L2_REF_ID_GOLDEN`` ++ - Golden reference frame. ++ * - ``V4L2_REF_ID_ALTREF`` ++ - Alternative reference frame. ++ * - ``V4L2_REF_ID_CNT`` ++ - Number of reference frames. ++ ++.. c:type:: v4l2_vp9_tx_mode ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: enum v4l2_vp9_tx_mode ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 2 ++ ++ * - ``V4L2_VP9_TX_MODE_ONLY_4X4`` ++ - Transform size is 4x4. ++ * - ``V4L2_VP9_TX_MODE_ALLOW_8X8`` ++ - Transform size can be up to 8x8. ++ * - ``V4L2_VP9_TX_MODE_ALLOW_16X16`` ++ - Transform size can be up to 16x16. ++ * - ``V4L2_VP9_TX_MODE_ALLOW_32X32`` ++ - transform size can be up to 32x32. ++ * - ``V4L2_VP9_TX_MODE_SELECT`` ++ - Bitstream contains transform size for each block. ++ ++.. c:type:: v4l2_vp9_reference_mode ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: enum v4l2_vp9_reference_mode ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 2 ++ ++ * - ``V4L2_VP9_REF_MODE_SINGLE`` ++ - Indicates that all the inter blocks use only a single reference frame ++ to generate motion compensated prediction. ++ * - ``V4L2_VP9_REF_MODE_COMPOUND`` ++ - Requires all the inter blocks to use compound mode. Single reference ++ frame prediction is not allowed. ++ * - ``V4L2_VP9_REF_MODE_SELECT`` ++ - Allows each individual inter block to select between single and ++ compound prediction modes. ++ ++.. c:type:: v4l2_vp9_interpolation_filter ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: enum v4l2_vp9_interpolation_filter ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 2 ++ ++ * - ``V4L2_VP9_INTERP_FILTER_8TAP`` ++ - Height tap filter. ++ * - ``V4L2_VP9_INTERP_FILTER_8TAP_SMOOTH`` ++ - Height tap smooth filter. ++ * - ``V4L2_VP9_INTERP_FILTER_8TAP_SHARP`` ++ - Height tap sharp filter. ++ * - ``V4L2_VP9_INTERP_FILTER_BILINEAR`` ++ - Bilinear filter. ++ * - ``V4L2_VP9_INTERP_FILTER_SWITCHABLE`` ++ - Filter selection is signaled at the block level. ++ ++.. c:type:: v4l2_vp9_reset_frame_context ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: enum v4l2_vp9_reset_frame_context ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 2 ++ ++ * - ``V4L2_VP9_RESET_FRAME_CTX_NONE`` ++ - Do not reset any frame context. ++ * - ``V4L2_VP9_RESET_FRAME_CTX_SPEC`` ++ - Reset the frame context pointed by ++ :c:type:`v4l2_ctrl_vp9_frame_decode_params`.frame_context_idx. ++ * - ``V4L2_VP9_RESET_FRAME_CTX_ALL`` ++ - Reset all frame contexts. ++ ++.. c:type:: v4l2_vp9_intra_prediction_mode ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: enum v4l2_vp9_intra_prediction_mode ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 2 ++ ++ * - ``V4L2_VP9_INTRA_PRED_DC`` ++ - DC intra prediction. ++ * - ``V4L2_VP9_INTRA_PRED_MODE_V`` ++ - Vertical intra prediction. ++ * - ``V4L2_VP9_INTRA_PRED_MODE_H`` ++ - Horizontal intra prediction. ++ * - ``V4L2_VP9_INTRA_PRED_MODE_D45`` ++ - D45 intra prediction. ++ * - ``V4L2_VP9_INTRA_PRED_MODE_D135`` ++ - D135 intra prediction. ++ * - ``V4L2_VP9_INTRA_PRED_MODE_D117`` ++ - D117 intra prediction. ++ * - ``V4L2_VP9_INTRA_PRED_MODE_D153`` ++ - D153 intra prediction. ++ * - ``V4L2_VP9_INTRA_PRED_MODE_D207`` ++ - D207 intra prediction. ++ * - ``V4L2_VP9_INTRA_PRED_MODE_D63`` ++ - D63 intra prediction. ++ * - ``V4L2_VP9_INTRA_PRED_MODE_TM`` ++ - True motion intra prediction. ++ ++.. c:type:: v4l2_vp9_segmentation ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: struct v4l2_vp9_segmentation ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - __u8 ++ - ``flags`` ++ - Combination of V4L2_VP9_SEGMENTATION_FLAG_* flags. See ++ :c:type:`v4l2_vp9_segmentation_flags`. ++ * - __u8 ++ - ``tree_probs[7]`` ++ - Specifies the probability values to be used when decoding a Segment-ID. ++ See '5.15. Segmentation map' section of :ref:`vp9` for more details. ++ * - __u8 ++ - ``pred_prob[3]`` ++ - Specifies the probability values to be used when decoding a ++ Predicted-Segment-ID. See '6.4.14. Get segment id syntax' ++ section of :ref:`vp9` for more details. ++ * - __u8 ++ - ``padding[5]`` ++ - Used to align this struct on 64 bit. Shall be filled with zeroes. ++ * - __u8 ++ - ``feature_enabled[8]`` ++ - Bitmask defining which features are enabled in each segment. ++ * - __u8 ++ - ``feature_data[8][4]`` ++ - Data attached to each feature. Data entry is only valid if the feature ++ is enabled. ++ ++.. c:type:: v4l2_vp9_segment_feature ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: enum v4l2_vp9_segment_feature ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 2 ++ ++ * - ``V4L2_VP9_SEGMENT_FEATURE_QP_DELTA`` ++ - QP delta segment feature. ++ * - ``V4L2_VP9_SEGMENT_FEATURE_LF`` ++ - Loop filter segment feature. ++ * - ``V4L2_VP9_SEGMENT_FEATURE_REF_FRAME`` ++ - Reference frame segment feature. ++ * - ``V4L2_VP9_SEGMENT_FEATURE_SKIP`` ++ - Skip segment feature. ++ * - ``V4L2_VP9_SEGMENT_FEATURE_CNT`` ++ - Number of segment features. ++ ++.. c:type:: v4l2_vp9_segmentation_flags ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: enum v4l2_vp9_segmentation_flags ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 2 ++ ++ * - ``V4L2_VP9_SEGMENTATION_FLAG_ENABLED`` ++ - Indicates that this frame makes use of the segmentation tool. ++ * - ``V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP`` ++ - Indicates that the segmentation map should be updated during the ++ decoding of this frame. ++ * - ``V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE`` ++ - Indicates that the updates to the segmentation map are coded ++ relative to the existing segmentation map. ++ * - ``V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA`` ++ - Indicates that new parameters are about to be specified for each ++ segment. ++ * - ``V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE`` ++ - Indicates that the segmentation parameters represent the actual values ++ to be used. ++ ++.. c:type:: v4l2_vp9_quantization ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: struct v4l2_vp9_quantization ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - __u8 ++ - ``base_q_idx`` ++ - Indicates the base frame qindex. ++ * - __s8 ++ - ``delta_q_y_dc`` ++ - Indicates the Y DC quantizer relative to base_q_idx. ++ * - __s8 ++ - ``delta_q_uv_dc`` ++ - Indicates the UV DC quantizer relative to base_q_idx. ++ * - __s8 ++ - ``delta_q_uv_ac`` ++ - Indicates the UV AC quantizer relative to base_q_idx. ++ * - __u8 ++ - ``padding[4]`` ++ - Padding bytes used to align this struct on 64 bit. Must be set to 0. ++ ++.. c:type:: v4l2_vp9_loop_filter ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: struct v4l2_vp9_loop_filter ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - __u8 ++ - ``flags`` ++ - Combination of V4L2_VP9_LOOP_FILTER_FLAG_* flags. ++ See :c:type:`v4l2_vp9_loop_filter_flags`. ++ * - __u8 ++ - ``level`` ++ - Indicates the loop filter strength. ++ * - __u8 ++ - ``sharpness`` ++ - Indicates the sharpness level. ++ * - __s8 ++ - ``ref_deltas[4]`` ++ - Contains the adjustment needed for the filter level based on the chosen ++ reference frame. ++ * - __s8 ++ - ``mode_deltas[2]`` ++ - Contains the adjustment needed for the filter level based on the chosen ++ mode ++ * - __u8 ++ - ``level_lookup[8][4][2]`` ++ - Level lookup table. ++ ++ ++.. c:type:: v4l2_vp9_loop_filter_flags ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: enum v4l2_vp9_loop_filter_flags ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 2 ++ ++ * - ``V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED`` ++ - When set, the filter level depends on the mode and reference frame used ++ to predict a block. ++ * - ``V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE`` ++ - When set, the bitstream contains additional syntax elements that ++ specify which mode and reference frame deltas are to be updated. ++ + .. raw:: latex + + \normalsize +diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c +index b846f5b089c9..5913088cbc6f 100644 +--- a/drivers/media/v4l2-core/v4l2-ctrls.c ++++ b/drivers/media/v4l2-core/v4l2-ctrls.c +@@ -940,6 +940,11 @@ const char *v4l2_ctrl_get_name(u32 id) + case V4L2_CID_MPEG_VIDEO_VP8_PROFILE: return "VP8 Profile"; + case V4L2_CID_MPEG_VIDEO_VP9_PROFILE: return "VP9 Profile"; + case V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER: return "VP8 Frame Header"; ++ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_DECODE_PARAMS: return "VP9 Frame Decode Parameters"; ++ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(0): return "VP9 Frame Context 0"; ++ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(1): return "VP9 Frame Context 1"; ++ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(2): return "VP9 Frame Context 2"; ++ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(3): return "VP9 Frame Context 3"; + + /* HEVC controls */ + case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP: return "HEVC I-Frame QP Value"; +@@ -1419,6 +1424,15 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, + case V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER: + *type = V4L2_CTRL_TYPE_VP8_FRAME_HEADER; + break; ++ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_DECODE_PARAMS: ++ *type = V4L2_CTRL_TYPE_VP9_FRAME_DECODE_PARAMS; ++ break; ++ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(0): ++ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(1): ++ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(2): ++ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(3): ++ *type = V4L2_CTRL_TYPE_VP9_FRAME_CONTEXT; ++ break; + case V4L2_CID_MPEG_VIDEO_HEVC_SPS: + *type = V4L2_CTRL_TYPE_HEVC_SPS; + break; +@@ -1721,6 +1735,219 @@ static void std_log(const struct v4l2_ctrl *ctrl) + 0; \ + }) + ++static int ++validate_vp9_lf_params(struct v4l2_vp9_loop_filter *lf) ++{ ++ unsigned int i, j, k; ++ ++ if (lf->flags & ++ ~(V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED | ++ V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE)) ++ return -EINVAL; ++ ++ /* ++ * V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED implies ++ * V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE. ++ */ ++ if (lf->flags & V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE && ++ !(lf->flags & V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED)) ++ return -EINVAL; ++ ++ /* That all values are in the accepted range. */ ++ if (lf->level > GENMASK(5, 0)) ++ return -EINVAL; ++ ++ if (lf->sharpness > GENMASK(2, 0)) ++ return -EINVAL; ++ ++ for (i = 0; i < ARRAY_SIZE(lf->ref_deltas); i++) { ++ if (lf->ref_deltas[i] < -63 || lf->ref_deltas[i] > 63) ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(lf->mode_deltas); i++) { ++ if (lf->mode_deltas[i] < -63 || lf->mode_deltas[i] > 63) ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(lf->level_lookup); i++) { ++ for (j = 0; j < ARRAY_SIZE(lf->level_lookup[0]); j++) { ++ for (k = 0; k < ARRAY_SIZE(lf->level_lookup[0][0]); k++) { ++ if (lf->level_lookup[i][j][k] > 63) ++ return -EINVAL; ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++static int ++validate_vp9_quant_params(struct v4l2_vp9_quantization *quant) ++{ ++ if (quant->delta_q_y_dc < -15 || quant->delta_q_y_dc > 15 || ++ quant->delta_q_uv_dc < -15 || quant->delta_q_uv_dc > 15 || ++ quant->delta_q_uv_ac < -15 || quant->delta_q_uv_ac > 15) ++ return -EINVAL; ++ ++ memset(quant->padding, 0, sizeof(quant->padding)); ++ return 0; ++} ++ ++static int ++validate_vp9_seg_params(struct v4l2_vp9_segmentation *seg) ++{ ++ unsigned int i, j; ++ ++ if (seg->flags & ++ ~(V4L2_VP9_SEGMENTATION_FLAG_ENABLED | ++ V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP | ++ V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE | ++ V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA | ++ V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE)) ++ return -EINVAL; ++ ++ /* ++ * V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP and ++ * V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA imply ++ * V4L2_VP9_SEGMENTATION_FLAG_ENABLED. ++ */ ++ if ((seg->flags & ++ (V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP | ++ V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA)) && ++ !(seg->flags & V4L2_VP9_SEGMENTATION_FLAG_ENABLED)) ++ return -EINVAL; ++ ++ /* ++ * V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE implies ++ * V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP. ++ */ ++ if (seg->flags & V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE && ++ !(seg->flags & V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP)) ++ return -EINVAL; ++ ++ /* ++ * V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE implies ++ * V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA. ++ */ ++ if (seg->flags & V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE && ++ !(seg->flags & V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA)) ++ return -EINVAL; ++ ++ for (i = 0; i < ARRAY_SIZE(seg->feature_enabled); i++) { ++ if (seg->feature_enabled[i] & ++ ~(V4L2_VP9_SEGMENT_FEATURE_QP_DELTA | ++ V4L2_VP9_SEGMENT_FEATURE_LF | ++ V4L2_VP9_SEGMENT_FEATURE_REF_FRAME | ++ V4L2_VP9_SEGMENT_FEATURE_SKIP)) ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(seg->feature_data); i++) { ++ const int range[] = {255, 63, 3, 0}; ++ ++ for (j = 0; j < ARRAY_SIZE(seg->feature_data[j]); j++) { ++ if (seg->feature_data[i][j] < -range[j] || ++ seg->feature_data[i][j] > range[j]) ++ return -EINVAL; ++ } ++ } ++ ++ memset(seg->padding, 0, sizeof(seg->padding)); ++ return 0; ++} ++ ++static int ++validate_vp9_frame_decode_params(struct v4l2_ctrl_vp9_frame_decode_params *dec_params) ++{ ++ int ret; ++ ++ /* Make sure we're not passed invalid flags. */ ++ if (dec_params->flags & ++ ~(V4L2_VP9_FRAME_FLAG_KEY_FRAME | ++ V4L2_VP9_FRAME_FLAG_SHOW_FRAME | ++ V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT | ++ V4L2_VP9_FRAME_FLAG_INTRA_ONLY | ++ V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV | ++ V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX | ++ V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE | ++ V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING | ++ V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING | ++ V4L2_VP9_FRAME_FLAG_COLOR_RANGE_FULL_SWING)) ++ return -EINVAL; ++ ++ /* ++ * The refresh context and error resilient flags are mutually exclusive. ++ * Same goes for parallel decoding and error resilient modes. ++ */ ++ if (dec_params->flags & V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT && ++ dec_params->flags & ++ (V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX | ++ V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE)) ++ return -EINVAL; ++ ++ if (dec_params->profile > V4L2_VP9_PROFILE_MAX) ++ return -EINVAL; ++ ++ if (dec_params->reset_frame_context > V4L2_VP9_RESET_FRAME_CTX_ALL) ++ return -EINVAL; ++ ++ if (dec_params->frame_context_idx >= V4L2_VP9_NUM_FRAME_CTX) ++ return -EINVAL; ++ ++ /* ++ * Profiles 0 and 1 only support 8-bit depth, profiles 2 and 3 only 10 ++ * and 12 bit depths. ++ */ ++ if ((dec_params->profile < 2 && dec_params->bit_depth != 8) || ++ (dec_params->profile >= 2 && ++ (dec_params->bit_depth != 10 && dec_params->bit_depth != 12))) ++ return -EINVAL; ++ ++ /* Profile 0 and 2 only accept YUV 4:2:0. */ ++ if ((dec_params->profile == 0 || dec_params->profile == 2) && ++ (!(dec_params->flags & V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING) || ++ !(dec_params->flags & V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING))) ++ return -EINVAL; ++ ++ /* Profile 1 and 3 only accept YUV 4:2:2, 4:4:0 and 4:4:4. */ ++ if ((dec_params->profile == 1 || dec_params->profile == 3) && ++ ((dec_params->flags & V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING) && ++ (dec_params->flags & V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING))) ++ return -EINVAL; ++ ++ if (dec_params->interpolation_filter > V4L2_VP9_INTERP_FILTER_SWITCHABLE) ++ return -EINVAL; ++ ++ /* ++ * According to the spec, tile_cols_log2 shall be less than or equal ++ * to 6. ++ */ ++ if (dec_params->tile_cols_log2 > 6) ++ return -EINVAL; ++ ++ if (dec_params->tx_mode > V4L2_VP9_TX_MODE_SELECT) ++ return -EINVAL; ++ ++ if (dec_params->reference_mode > V4L2_VP9_REF_MODE_SELECT) ++ return -EINVAL; ++ ++ ret = validate_vp9_lf_params(&dec_params->lf); ++ if (ret) ++ return ret; ++ ++ ret = validate_vp9_quant_params(&dec_params->quant); ++ if (ret) ++ return ret; ++ ++ ret = validate_vp9_seg_params(&dec_params->seg); ++ if (ret) ++ return ret; ++ ++ memset(dec_params->padding, 0, sizeof(dec_params->padding)); ++ return 0; ++} ++ + /* Validate a new control */ + + #define zero_padding(s) \ +@@ -1838,6 +2065,12 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, + zero_padding(p_vp8_frame_header->coder_state); + break; + ++ case V4L2_CTRL_TYPE_VP9_FRAME_DECODE_PARAMS: ++ return validate_vp9_frame_decode_params(p); ++ ++ case V4L2_CTRL_TYPE_VP9_FRAME_CONTEXT: ++ break; ++ + case V4L2_CTRL_TYPE_HEVC_SPS: + p_hevc_sps = p; + +@@ -2584,6 +2817,12 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, + case V4L2_CTRL_TYPE_VP8_FRAME_HEADER: + elem_size = sizeof(struct v4l2_ctrl_vp8_frame_header); + break; ++ case V4L2_CTRL_TYPE_VP9_FRAME_CONTEXT: ++ elem_size = sizeof(struct v4l2_ctrl_vp9_frame_ctx); ++ break; ++ case V4L2_CTRL_TYPE_VP9_FRAME_DECODE_PARAMS: ++ elem_size = sizeof(struct v4l2_ctrl_vp9_frame_decode_params); ++ break; + case V4L2_CTRL_TYPE_HEVC_SPS: + elem_size = sizeof(struct v4l2_ctrl_hevc_sps); + break; +diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c +index 53de49087938..22eab942c8d4 100644 +--- a/drivers/media/v4l2-core/v4l2-ioctl.c ++++ b/drivers/media/v4l2-core/v4l2-ioctl.c +@@ -1431,6 +1431,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) + case V4L2_PIX_FMT_VP8: descr = "VP8"; break; + case V4L2_PIX_FMT_VP8_FRAME: descr = "VP8 Frame"; break; + case V4L2_PIX_FMT_VP9: descr = "VP9"; break; ++ case V4L2_PIX_FMT_VP9_FRAME: descr = "VP9 Frame"; break; + case V4L2_PIX_FMT_HEVC: descr = "HEVC"; break; /* aka H.265 */ + case V4L2_PIX_FMT_HEVC_SLICE: descr = "HEVC Parsed Slice Data"; break; + case V4L2_PIX_FMT_FWHT: descr = "FWHT"; break; /* used in vicodec */ +diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h +index cb25f345e9ad..c427acc964b9 100644 +--- a/include/media/v4l2-ctrls.h ++++ b/include/media/v4l2-ctrls.h +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + #include + + /* forward references */ +diff --git a/include/media/vp9-ctrls.h b/include/media/vp9-ctrls.h +new file mode 100644 +index 000000000000..0cdea8a18b72 +--- /dev/null ++++ b/include/media/vp9-ctrls.h +@@ -0,0 +1,485 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * These are the VP9 state controls for use with stateless VP9 ++ * codec drivers. ++ * ++ * It turns out that these structs are not stable yet and will undergo ++ * more changes. So keep them private until they are stable and ready to ++ * become part of the official public API. ++ */ ++ ++#ifndef _VP9_CTRLS_H_ ++#define _VP9_CTRLS_H_ ++ ++#include ++ ++#define V4L2_PIX_FMT_VP9_FRAME v4l2_fourcc('V', 'P', '9', 'F') ++ ++#define V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(i) (V4L2_CID_MPEG_BASE + 4000 + (i)) ++#define V4L2_CID_MPEG_VIDEO_VP9_FRAME_DECODE_PARAMS (V4L2_CID_MPEG_BASE + 4004) ++#define V4L2_CTRL_TYPE_VP9_FRAME_CONTEXT 0x400 ++#define V4L2_CTRL_TYPE_VP9_FRAME_DECODE_PARAMS 0x404 ++ ++/** ++ * enum v4l2_vp9_loop_filter_flags - VP9 loop filter flags ++ * ++ * @V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED: the filter level depends on ++ * the mode and reference frame used ++ * to predict a block ++ * @V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE: the bitstream contains additional ++ * syntax elements that specify which ++ * mode and reference frame deltas ++ * are to be updated ++ * ++ * Those are the flags you should pass to &v4l2_vp9_loop_filter.flags. See ++ * section '7.2.8 Loop filter semantics' of the VP9 specification for more ++ * details. ++ */ ++enum v4l2_vp9_loop_filter_flags { ++ V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED = 1 << 0, ++ V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE = 1 << 1, ++}; ++ ++/** ++ * struct v4l2_vp9_loop_filter - VP9 loop filter parameters ++ * ++ * @flags: combination of V4L2_VP9_LOOP_FILTER_FLAG_* flags ++ * @level: indicates the loop filter strength ++ * @sharpness: indicates the sharpness level ++ * @ref_deltas: contains the adjustment needed for the filter level based on ++ * the chosen reference frame ++ * @mode_deltas: contains the adjustment needed for the filter level based on ++ * the chosen mode ++ * @level_lookup: level lookup table ++ * ++ * This structure contains all loop filter related parameters. See sections ++ * '7.2.8 Loop filter semantics' and '8.8.1 Loop filter frame init process' ++ * of the VP9 specification for more details. ++ */ ++struct v4l2_vp9_loop_filter { ++ __u8 flags; ++ __u8 level; ++ __u8 sharpness; ++ __s8 ref_deltas[4]; ++ __s8 mode_deltas[2]; ++ __u8 level_lookup[8][4][2]; ++}; ++ ++/** ++ * struct v4l2_vp9_quantization - VP9 quantization parameters ++ * ++ * @base_q_idx: indicates the base frame qindex ++ * @delta_q_y_dc: indicates the Y DC quantizer relative to base_q_idx ++ * @delta_q_uv_dc: indicates the UV DC quantizer relative to base_q_idx ++ * @delta_q_uv_ac indicates the UV AC quantizer relative to base_q_idx ++ * @padding: padding bytes to align things on 64 bits. Must be set to 0 ++ * ++ * Encodes the quantization parameters. See section '7.2.9 Quantization params ++ * syntax' of the VP9 specification for more details. ++ */ ++struct v4l2_vp9_quantization { ++ __u8 base_q_idx; ++ __s8 delta_q_y_dc; ++ __s8 delta_q_uv_dc; ++ __s8 delta_q_uv_ac; ++ __u8 padding[4]; ++}; ++ ++/** ++ * enum v4l2_vp9_segmentation_flags - VP9 segmentation flags ++ * ++ * @V4L2_VP9_SEGMENTATION_FLAG_ENABLED: indicates that this frame makes use of ++ * the segmentation tool ++ * @V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP: indicates that the segmentation map ++ * should be updated during the ++ * decoding of this frame ++ * @V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE: indicates that the updates to ++ * the segmentation map are coded ++ * relative to the existing ++ * segmentation map ++ * @V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA: indicates that new parameters are ++ * about to be specified for each ++ * segment ++ * @V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE: indicates that the ++ * segmentation parameters ++ * represent the actual values ++ * to be used ++ * ++ * Those are the flags you should pass to &v4l2_vp9_segmentation.flags. See ++ * section '7.2.10 Segmentation params syntax' of the VP9 specification for ++ * more details. ++ */ ++enum v4l2_vp9_segmentation_flags { ++ V4L2_VP9_SEGMENTATION_FLAG_ENABLED = 1 << 0, ++ V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP = 1 << 1, ++ V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE = 1 << 2, ++ V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA = 1 << 3, ++ V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE = 1 << 4, ++}; ++ ++#define V4L2_VP9_SEGMENT_FEATURE_ENABLED(id) (1 << (id)) ++#define V4L2_VP9_SEGMENT_FEATURE_ENABLED_MASK 0xf ++ ++/** ++ * enum v4l2_vp9_segment_feature - VP9 segment feature IDs ++ * ++ * @V4L2_VP9_SEGMENT_FEATURE_QP_DELTA: QP delta segment feature ++ * @V4L2_VP9_SEGMENT_FEATURE_LF: loop filter segment feature ++ * @V4L2_VP9_SEGMENT_FEATURE_REF_FRAME: reference frame segment feature ++ * @V4L2_VP9_SEGMENT_FEATURE_SKIP: skip segment feature ++ * @V4L2_VP9_SEGMENT_FEATURE_CNT: number of segment features ++ * ++ * Segment feature IDs. See section '7.2.10 Segmentation params syntax' of the ++ * VP9 specification for more details. ++ */ ++enum v4l2_vp9_segment_feature { ++ V4L2_VP9_SEGMENT_FEATURE_QP_DELTA, ++ V4L2_VP9_SEGMENT_FEATURE_LF, ++ V4L2_VP9_SEGMENT_FEATURE_REF_FRAME, ++ V4L2_VP9_SEGMENT_FEATURE_SKIP, ++ V4L2_VP9_SEGMENT_FEATURE_CNT, ++}; ++ ++/** ++ * struct v4l2_vp9_segmentation - VP9 segmentation parameters ++ * ++ * @flags: combination of V4L2_VP9_SEGMENTATION_FLAG_* flags ++ * @tree_probs: specifies the probability values to be used when ++ * decoding a Segment-ID. See '5.15. Segmentation map' ++ * section of the VP9 specification for more details. ++ * @pred_prob: specifies the probability values to be used when decoding a ++ * Predicted-Segment-ID. See '6.4.14. Get segment id syntax' ++ * section of :ref:`vp9` for more details.. ++ * @padding: padding used to make things aligned on 64 bits. Shall be zero ++ * filled ++ * @feature_enabled: bitmask defining which features are enabled in each ++ * segment ++ * @feature_data: data attached to each feature. Data entry is only valid if ++ * the feature is enabled ++ * ++ * Encodes the quantization parameters. See section '7.2.10 Segmentation ++ * params syntax' of the VP9 specification for more details. ++ */ ++struct v4l2_vp9_segmentation { ++ __u8 flags; ++ __u8 tree_probs[7]; ++ __u8 pred_probs[3]; ++ __u8 padding[5]; ++ __u8 feature_enabled[8]; ++ __s16 feature_data[8][4]; ++}; ++ ++/** ++ * enum v4l2_vp9_intra_prediction_mode - VP9 Intra prediction modes ++ * ++ * @V4L2_VP9_INTRA_PRED_DC: DC intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_V: vertical intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_H: horizontal intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_D45: D45 intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_D135: D135 intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_D117: D117 intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_D153: D153 intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_D207: D207 intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_D63: D63 intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_TM: True Motion intra prediction ++ * ++ * See section '7.4.5 Intra frame mode info semantics' for more details. ++ */ ++enum v4l2_vp9_intra_prediction_mode { ++ V4L2_VP9_INTRA_PRED_MODE_DC, ++ V4L2_VP9_INTRA_PRED_MODE_V, ++ V4L2_VP9_INTRA_PRED_MODE_H, ++ V4L2_VP9_INTRA_PRED_MODE_D45, ++ V4L2_VP9_INTRA_PRED_MODE_D135, ++ V4L2_VP9_INTRA_PRED_MODE_D117, ++ V4L2_VP9_INTRA_PRED_MODE_D153, ++ V4L2_VP9_INTRA_PRED_MODE_D207, ++ V4L2_VP9_INTRA_PRED_MODE_D63, ++ V4L2_VP9_INTRA_PRED_MODE_TM, ++}; ++ ++/** ++ * struct v4l2_vp9_mv_probabilities - VP9 Motion vector probabilities ++ * @joint: motion vector joint probabilities ++ * @sign: motion vector sign probabilities ++ * @class: motion vector class probabilities ++ * @class0_bit: motion vector class0 bit probabilities ++ * @bits: motion vector bits probabilities ++ * @class0_fr: motion vector class0 fractional bit probabilities ++ * @fr: motion vector fractional bit probabilities ++ * @class0_hp: motion vector class0 high precision fractional bit probabilities ++ * @hp: motion vector high precision fractional bit probabilities ++ */ ++struct v4l2_vp9_mv_probabilities { ++ __u8 joint[3]; ++ __u8 sign[2]; ++ __u8 class[2][10]; ++ __u8 class0_bit[2]; ++ __u8 bits[2][10]; ++ __u8 class0_fr[2][2][3]; ++ __u8 fr[2][3]; ++ __u8 class0_hp[2]; ++ __u8 hp[2]; ++}; ++ ++/** ++ * struct v4l2_vp9_probabilities - VP9 Probabilities ++ * ++ * @tx8: TX 8x8 probabilities ++ * @tx16: TX 16x16 probabilities ++ * @tx32: TX 32x32 probabilities ++ * @coef: coefficient probabilities ++ * @skip: skip probabilities ++ * @inter_mode: inter mode probabilities ++ * @interp_filter: interpolation filter probabilities ++ * @is_inter: is inter-block probabilities ++ * @comp_mode: compound prediction mode probabilities ++ * @single_ref: single ref probabilities ++ * @comp_ref: compound ref probabilities ++ * @y_mode: Y prediction mode probabilities ++ * @uv_mode: UV prediction mode probabilities ++ * @partition: partition probabilities ++ * @mv: motion vector probabilities ++ * ++ * Structure containing most VP9 probabilities. See the VP9 specification ++ * for more details. ++ */ ++struct v4l2_vp9_probabilities { ++ __u8 tx8[2][1]; ++ __u8 tx16[2][2]; ++ __u8 tx32[2][3]; ++ __u8 coef[4][2][2][6][6][3]; ++ __u8 skip[3]; ++ __u8 inter_mode[7][3]; ++ __u8 interp_filter[4][2]; ++ __u8 is_inter[4]; ++ __u8 comp_mode[5]; ++ __u8 single_ref[5][2]; ++ __u8 comp_ref[5]; ++ __u8 y_mode[4][9]; ++ __u8 uv_mode[10][9]; ++ __u8 partition[16][3]; ++ ++ struct v4l2_vp9_mv_probabilities mv; ++}; ++ ++/** ++ * enum v4l2_vp9_reset_frame_context - Valid values for ++ * &v4l2_ctrl_vp9_frame_decode_params->reset_frame_context ++ * ++ * @V4L2_VP9_RESET_FRAME_CTX_NONE: don't reset any frame context ++ * @V4L2_VP9_RESET_FRAME_CTX_SPEC: reset the frame context pointed by ++ * &v4l2_ctrl_vp9_frame_decode_params.frame_context_idx ++ * @V4L2_VP9_RESET_FRAME_CTX_ALL: reset all frame contexts ++ * ++ * See section '7.2 Uncompressed header semantics' of the VP9 specification ++ * for more details. ++ */ ++enum v4l2_vp9_reset_frame_context { ++ V4L2_VP9_RESET_FRAME_CTX_NONE, ++ V4L2_VP9_RESET_FRAME_CTX_SPEC, ++ V4L2_VP9_RESET_FRAME_CTX_ALL, ++}; ++ ++/** ++ * enum v4l2_vp9_interpolation_filter - VP9 interpolation filter types ++ * ++ * @V4L2_VP9_INTERP_FILTER_8TAP: height tap filter ++ * @V4L2_VP9_INTERP_FILTER_8TAP_SMOOTH: height tap smooth filter ++ * @V4L2_VP9_INTERP_FILTER_8TAP_SHARP: height tap sharp filter ++ * @V4L2_VP9_INTERP_FILTER_BILINEAR: bilinear filter ++ * @V4L2_VP9_INTERP_FILTER_SWITCHABLE: filter selection is signaled at the ++ * block level ++ * ++ * See section '7.2.7 Interpolation filter semantics' of the VP9 specification ++ * for more details. ++ */ ++enum v4l2_vp9_interpolation_filter { ++ V4L2_VP9_INTERP_FILTER_8TAP, ++ V4L2_VP9_INTERP_FILTER_8TAP_SMOOTH, ++ V4L2_VP9_INTERP_FILTER_8TAP_SHARP, ++ V4L2_VP9_INTERP_FILTER_BILINEAR, ++ V4L2_VP9_INTERP_FILTER_SWITCHABLE, ++}; ++ ++/** ++ * enum v4l2_vp9_reference_mode - VP9 reference modes ++ * ++ * @V4L2_VP9_REF_MODE_SINGLE: indicates that all the inter blocks use only a ++ * single reference frame to generate motion ++ * compensated prediction ++ * @V4L2_VP9_REF_MODE_COMPOUND: requires all the inter blocks to use compound ++ * mode. Single reference frame prediction is not ++ * allowed ++ * @V4L2_VP9_REF_MODE_SELECT: allows each individual inter block to select ++ * between single and compound prediction modes ++ * ++ * See section '7.3.6 Frame reference mode semantics' of the VP9 specification ++ * for more details. ++ */ ++enum v4l2_vp9_reference_mode { ++ V4L2_VP9_REF_MODE_SINGLE, ++ V4L2_VP9_REF_MODE_COMPOUND, ++ V4L2_VP9_REF_MODE_SELECT, ++}; ++ ++/** ++ * enum v4l2_vp9_tx_mode - VP9 TX modes ++ * ++ * @V4L2_VP9_TX_MODE_ONLY_4X4: transform size is 4x4 ++ * @V4L2_VP9_TX_MODE_ALLOW_8X8: transform size can be up to 8x8 ++ * @V4L2_VP9_TX_MODE_ALLOW_16X16: transform size can be up to 16x16 ++ * @V4L2_VP9_TX_MODE_ALLOW_32X32: transform size can be up to 32x32 ++ * @V4L2_VP9_TX_MODE_SELECT: bitstream contains transform size for each block ++ * ++ * See section '7.3.1 Tx mode semantics' of the VP9 specification for more ++ * details. ++ */ ++enum v4l2_vp9_tx_mode { ++ V4L2_VP9_TX_MODE_ONLY_4X4, ++ V4L2_VP9_TX_MODE_ALLOW_8X8, ++ V4L2_VP9_TX_MODE_ALLOW_16X16, ++ V4L2_VP9_TX_MODE_ALLOW_32X32, ++ V4L2_VP9_TX_MODE_SELECT, ++}; ++ ++/** ++ * enum v4l2_vp9_ref_id - VP9 Reference frame IDs ++ * ++ * @V4L2_REF_ID_LAST: last reference frame ++ * @V4L2_REF_ID_GOLDEN: golden reference frame ++ * @V4L2_REF_ID_ALTREF: alternative reference frame ++ * @V4L2_REF_ID_CNT: number of reference frames ++ * ++ * See section '7.4.12 Ref frames semantics' of the VP9 specification for more ++ * details. ++ */ ++enum v4l2_vp9_ref_id { ++ V4L2_REF_ID_LAST, ++ V4L2_REF_ID_GOLDEN, ++ V4L2_REF_ID_ALTREF, ++ V4L2_REF_ID_CNT, ++}; ++ ++/** ++ * enum v4l2_vp9_frame_flags - VP9 frame flags ++ * @V4L2_VP9_FRAME_FLAG_KEY_FRAME: the frame is a key frame ++ * @V4L2_VP9_FRAME_FLAG_SHOW_FRAME: the frame should be displayed ++ * @V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT: the decoding should be error resilient ++ * @V4L2_VP9_FRAME_FLAG_INTRA_ONLY: the frame does not reference other frames ++ * @V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV: the frame might can high precision ++ * motion vectors ++ * @V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX: frame context should be updated ++ * after decoding ++ * @V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE: parallel decoding is used ++ * @V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING: vertical subsampling is enabled ++ * @V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING: horizontal subsampling is enabled ++ * @V4L2_VP9_FRAME_FLAG_COLOR_RANGE_FULL_SWING: full UV range is used ++ * ++ * Check the VP9 specification for more details. ++ */ ++enum v4l2_vp9_frame_flags { ++ V4L2_VP9_FRAME_FLAG_KEY_FRAME = 1 << 0, ++ V4L2_VP9_FRAME_FLAG_SHOW_FRAME = 1 << 1, ++ V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT = 1 << 2, ++ V4L2_VP9_FRAME_FLAG_INTRA_ONLY = 1 << 3, ++ V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV = 1 << 4, ++ V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX = 1 << 5, ++ V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE = 1 << 6, ++ V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING = 1 << 7, ++ V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING = 1 << 8, ++ V4L2_VP9_FRAME_FLAG_COLOR_RANGE_FULL_SWING = 1 << 9, ++}; ++ ++#define V4L2_VP9_PROFILE_MAX 3 ++ ++/** ++ * struct v4l2_ctrl_vp9_frame_decode_params - VP9 frame decoding control ++ * ++ * @flags: combination of V4L2_VP9_FRAME_FLAG_* flags ++ * @compressed_header_size: compressed header size in bytes ++ * @uncompressed_header_size: uncompressed header size in bytes ++ * @profile: VP9 profile. Can be 0, 1, 2 or 3 ++ * @reset_frame_context: specifies whether the frame context should be reset ++ * to default values. See &v4l2_vp9_reset_frame_context ++ * for more details ++ * @frame_context_idx: frame context that should be used/updated ++ * @bit_depth: bits per components. Can be 8, 10 or 12. Note that not all ++ * profiles support 10 and/or 12 bits depths ++ * @interpolation_filter: specifies the filter selection used for performing ++ * inter prediction. See &v4l2_vp9_interpolation_filter ++ * for more details ++ * @tile_cols_log2: specifies the base 2 logarithm of the width of each tile ++ * (where the width is measured in units of 8x8 blocks). ++ * Shall be less than or equal to 6 ++ * @tile_rows_log2: specifies the base 2 logarithm of the height of each tile ++ * (where the height is measured in units of 8x8 blocks) ++ * @tx_mode: specifies the TX mode. See &v4l2_vp9_tx_mode for more details ++ * @reference_mode: specifies the type of inter prediction to be used. See ++ * &v4l2_vp9_reference_mode for more details ++ * @padding: needed to make this struct 64 bit aligned. Shall be filled with ++ * zeros ++ * @frame_width_minus_1: add 1 to it and you'll get the frame width expressed ++ * in pixels ++ * @frame_height_minus_1: add 1 to it and you'll get the frame height expressed ++ * in pixels ++ * @frame_width_minus_1: add 1 to it and you'll get the expected render width ++ * expressed in pixels. This is not used during the ++ * decoding process but might be used by HW scalers to ++ * prepare a frame that's ready for scanout ++ * @frame_height_minus_1: add 1 to it and you'll get the expected render height ++ * expressed in pixels. This is not used during the ++ * decoding process but might be used by HW scalers to ++ * prepare a frame that's ready for scanout ++ * @refs: array of reference frames. See &v4l2_vp9_ref_id for more details ++ * @lf: loop filter parameters. See &v4l2_vp9_loop_filter for more details ++ * @quant: quantization parameters. See &v4l2_vp9_quantization for more details ++ * @seg: segmentation parameters. See &v4l2_vp9_segmentation for more details ++ * @probs: probabilities. See &v4l2_vp9_probabilities for more details ++ */ ++struct v4l2_ctrl_vp9_frame_decode_params { ++ __u32 flags; ++ __u16 compressed_header_size; ++ __u16 uncompressed_header_size; ++ __u8 profile; ++ __u8 reset_frame_context; ++ __u8 frame_context_idx; ++ __u8 bit_depth; ++ __u8 interpolation_filter; ++ __u8 tile_cols_log2; ++ __u8 tile_rows_log2; ++ __u8 tx_mode; ++ __u8 reference_mode; ++ __u8 padding[6]; ++ __u16 frame_width_minus_1; ++ __u16 frame_height_minus_1; ++ __u16 render_width_minus_1; ++ __u16 render_height_minus_1; ++ __u64 refs[V4L2_REF_ID_CNT]; ++ struct v4l2_vp9_loop_filter lf; ++ struct v4l2_vp9_quantization quant; ++ struct v4l2_vp9_segmentation seg; ++ struct v4l2_vp9_probabilities probs; ++}; ++ ++#define V4L2_VP9_NUM_FRAME_CTX 4 ++ ++/** ++ * struct v4l2_ctrl_vp9_frame_ctx - VP9 frame context control ++ * ++ * @probs: VP9 probabilities ++ * ++ * This control is accessed in both direction. The user should initialize the ++ * 4 contexts with default values just after starting the stream. Then before ++ * decoding a frame it should query the current frame context (the one passed ++ * through &v4l2_ctrl_vp9_frame_decode_params.frame_context_idx) to initialize ++ * &v4l2_ctrl_vp9_frame_decode_params.probs. The probs are then adjusted based ++ * on the bitstream info and passed to the kernel. The codec should update ++ * the frame context after the frame has been decoded, so that next time ++ * userspace query this context it contains the updated probabilities. ++ */ ++struct v4l2_ctrl_vp9_frame_ctx { ++ struct v4l2_vp9_probabilities probs; ++}; ++ ++#endif /* _VP9_CTRLS_H_ */ + +From 3e089d23e73a5eb2b070f875845ff423a492f3ba Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Mon, 18 May 2020 14:40:11 -0300 +Subject: [PATCH] media: rkvdec: Add the VP9 backend + +The Rockchip VDEC supports VP9 profile 0 up to 4096x2304@30fps. Add +a backend for this new format. + +Signed-off-by: Boris Brezillon +Signed-off-by: Ezequiel Garcia +--- + drivers/staging/media/rkvdec/Makefile | 2 +- + drivers/staging/media/rkvdec/rkvdec-vp9.c | 1577 +++++++++++++++++++++ + drivers/staging/media/rkvdec/rkvdec.c | 54 + + drivers/staging/media/rkvdec/rkvdec.h | 6 + + 4 files changed, 1638 insertions(+), 1 deletion(-) + create mode 100644 drivers/staging/media/rkvdec/rkvdec-vp9.c + +diff --git a/drivers/staging/media/rkvdec/Makefile b/drivers/staging/media/rkvdec/Makefile +index c08fed0a39f9..cb86b429cfaa 100644 +--- a/drivers/staging/media/rkvdec/Makefile ++++ b/drivers/staging/media/rkvdec/Makefile +@@ -1,3 +1,3 @@ + obj-$(CONFIG_VIDEO_ROCKCHIP_VDEC) += rockchip-vdec.o + +-rockchip-vdec-y += rkvdec.o rkvdec-h264.o ++rockchip-vdec-y += rkvdec.o rkvdec-h264.o rkvdec-vp9.o +diff --git a/drivers/staging/media/rkvdec/rkvdec-vp9.c b/drivers/staging/media/rkvdec/rkvdec-vp9.c +new file mode 100644 +index 000000000000..37d0ea4e3570 +--- /dev/null ++++ b/drivers/staging/media/rkvdec/rkvdec-vp9.c +@@ -0,0 +1,1577 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Rockchip Video Decoder VP9 backend ++ * ++ * Copyright (C) 2019 Collabora, Ltd. ++ * Boris Brezillon ++ * ++ * Copyright (C) 2016 Rockchip Electronics Co., Ltd. ++ * Alpha Lin ++ */ ++ ++#include ++#include ++#include ++ ++#include "rkvdec.h" ++#include "rkvdec-regs.h" ++ ++#define RKVDEC_VP9_PROBE_SIZE 4864 ++#define RKVDEC_VP9_COUNT_SIZE 13232 ++#define RKVDEC_VP9_MAX_SEGMAP_SIZE 73728 ++ ++struct rkvdec_vp9_intra_mode_probs { ++ u8 y_mode[105]; ++ u8 uv_mode[23]; ++}; ++ ++struct rkvdec_vp9_intra_only_frame_probs { ++ u8 coef_intra[4][2][128]; ++ struct rkvdec_vp9_intra_mode_probs intra_mode[10]; ++}; ++ ++struct rkvdec_vp9_inter_frame_probs { ++ u8 y_mode[4][9]; ++ u8 comp_mode[5]; ++ u8 comp_ref[5]; ++ u8 single_ref[5][2]; ++ u8 inter_mode[7][3]; ++ u8 interp_filter[4][2]; ++ u8 padding0[11]; ++ u8 coef[2][4][2][128]; ++ u8 uv_mode_0_2[3][9]; ++ u8 padding1[5]; ++ u8 uv_mode_3_5[3][9]; ++ u8 padding2[5]; ++ u8 uv_mode_6_8[3][9]; ++ u8 padding3[5]; ++ u8 uv_mode_9[9]; ++ u8 padding4[7]; ++ u8 padding5[16]; ++ struct { ++ u8 joint[3]; ++ u8 sign[2]; ++ u8 class[2][10]; ++ u8 class0_bit[2]; ++ u8 bits[2][10]; ++ u8 class0_fr[2][2][3]; ++ u8 fr[2][3]; ++ u8 class0_hp[2]; ++ u8 hp[2]; ++ } mv; ++}; ++ ++struct rkvdec_vp9_probs { ++ u8 partition[16][3]; ++ u8 pred[3]; ++ u8 tree[7]; ++ u8 skip[3]; ++ u8 tx32[2][3]; ++ u8 tx16[2][2]; ++ u8 tx8[2][1]; ++ u8 is_inter[4]; ++ /* 128 bit alignment */ ++ u8 padding0[3]; ++ union { ++ struct rkvdec_vp9_inter_frame_probs inter; ++ struct rkvdec_vp9_intra_only_frame_probs intra_only; ++ }; ++}; ++ ++/* Data structure describing auxiliary buffer format. */ ++struct rkvdec_vp9_priv_tbl { ++ struct rkvdec_vp9_probs probs; ++ u8 segmap[2][RKVDEC_VP9_MAX_SEGMAP_SIZE]; ++}; ++ ++struct rkvdec_vp9_refs_counts { ++ u32 eob[2]; ++ u32 coeff[3]; ++}; ++ ++struct rkvdec_vp9_inter_frame_symbol_counts { ++ u32 partition[16][4]; ++ u32 skip[3][2]; ++ u32 inter[4][2]; ++ u32 tx32p[2][4]; ++ u32 tx16p[2][4]; ++ u32 tx8p[2][2]; ++ u32 y_mode[4][10]; ++ u32 uv_mode[10][10]; ++ u32 comp[5][2]; ++ u32 comp_ref[5][2]; ++ u32 single_ref[5][2][2]; ++ u32 mv_mode[7][4]; ++ u32 filter[4][3]; ++ u32 mv_joint[4]; ++ u32 sign[2][2]; ++ /* add 1 element for align */ ++ u32 classes[2][11 + 1]; ++ u32 class0[2][2]; ++ u32 bits[2][10][2]; ++ u32 class0_fp[2][2][4]; ++ u32 fp[2][4]; ++ u32 class0_hp[2][2]; ++ u32 hp[2][2]; ++ struct rkvdec_vp9_refs_counts ref_cnt[2][4][2][6][6]; ++}; ++ ++struct rkvdec_vp9_intra_frame_symbol_counts { ++ u32 partition[4][4][4]; ++ u32 skip[3][2]; ++ u32 intra[4][2]; ++ u32 tx32p[2][4]; ++ u32 tx16p[2][4]; ++ u32 tx8p[2][2]; ++ struct rkvdec_vp9_refs_counts ref_cnt[2][4][2][6][6]; ++}; ++ ++struct rkvdec_vp9_run { ++ struct rkvdec_run base; ++ const struct v4l2_ctrl_vp9_frame_decode_params *decode_params; ++}; ++ ++struct rkvdec_vp9_frame_info { ++ u32 valid : 1; ++ u32 segmapid : 1; ++ u32 frame_context_idx : 2; ++ u32 reference_mode : 2; ++ u32 tx_mode : 3; ++ u32 interpolation_filter : 3; ++ u32 flags; ++ u64 timestamp; ++ struct v4l2_vp9_segmentation seg; ++ struct v4l2_vp9_loop_filter lf; ++}; ++ ++struct rkvdec_vp9_ctx { ++ struct rkvdec_aux_buf priv_tbl; ++ struct rkvdec_aux_buf count_tbl; ++ struct v4l2_ctrl_vp9_frame_ctx frame_context; ++ struct rkvdec_vp9_frame_info cur; ++ struct rkvdec_vp9_frame_info last; ++}; ++ ++static u32 rkvdec_fastdiv(u32 dividend, u16 divisor) ++{ ++#define DIV_INV(d) (u32)(((1ULL << 32) + ((d) - 1)) / (d)) ++#define DIVS_INV(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9) \ ++ DIV_INV(d0), DIV_INV(d1), DIV_INV(d2), DIV_INV(d3), \ ++ DIV_INV(d4), DIV_INV(d5), DIV_INV(d6), DIV_INV(d7), \ ++ DIV_INV(d8), DIV_INV(d9) ++ ++ static const u32 inv[] = { ++ DIV_INV(2), DIV_INV(3), DIV_INV(4), DIV_INV(5), ++ DIV_INV(6), DIV_INV(7), DIV_INV(8), DIV_INV(9), ++ DIVS_INV(10, 11, 12, 13, 14, 15, 16, 17, 18, 19), ++ DIVS_INV(20, 21, 22, 23, 24, 25, 26, 27, 28, 29), ++ DIVS_INV(30, 31, 32, 33, 34, 35, 36, 37, 38, 39), ++ DIVS_INV(40, 41, 42, 43, 44, 45, 46, 47, 48, 49), ++ DIVS_INV(50, 51, 52, 53, 54, 55, 56, 57, 58, 59), ++ DIVS_INV(60, 61, 62, 63, 64, 65, 66, 67, 68, 69), ++ DIVS_INV(70, 71, 72, 73, 74, 75, 76, 77, 78, 79), ++ DIVS_INV(80, 81, 82, 83, 84, 85, 86, 87, 88, 89), ++ DIVS_INV(90, 91, 92, 93, 94, 95, 96, 97, 98, 99), ++ DIVS_INV(100, 101, 102, 103, 104, 105, 106, 107, 108, 109), ++ DIVS_INV(110, 111, 112, 113, 114, 115, 116, 117, 118, 119), ++ DIVS_INV(120, 121, 122, 123, 124, 125, 126, 127, 128, 129), ++ DIVS_INV(130, 131, 132, 133, 134, 135, 136, 137, 138, 139), ++ DIVS_INV(140, 141, 142, 143, 144, 145, 146, 147, 148, 149), ++ DIVS_INV(150, 151, 152, 153, 154, 155, 156, 157, 158, 159), ++ DIVS_INV(160, 161, 162, 163, 164, 165, 166, 167, 168, 169), ++ DIVS_INV(170, 171, 172, 173, 174, 175, 176, 177, 178, 179), ++ DIVS_INV(180, 181, 182, 183, 184, 185, 186, 187, 188, 189), ++ DIVS_INV(190, 191, 192, 193, 194, 195, 196, 197, 198, 199), ++ DIVS_INV(200, 201, 202, 203, 204, 205, 206, 207, 208, 209), ++ DIVS_INV(210, 211, 212, 213, 214, 215, 216, 217, 218, 219), ++ DIVS_INV(220, 221, 222, 223, 224, 225, 226, 227, 228, 229), ++ DIVS_INV(230, 231, 232, 233, 234, 235, 236, 237, 238, 239), ++ DIVS_INV(240, 241, 242, 243, 244, 245, 246, 247, 248, 249), ++ DIV_INV(250), DIV_INV(251), DIV_INV(252), DIV_INV(253), ++ DIV_INV(254), DIV_INV(255), DIV_INV(256), ++ }; ++ ++ if (divisor == 0) ++ return 0; ++ else if (divisor == 1) ++ return dividend; ++ ++ if (WARN_ON(divisor - 2 >= ARRAY_SIZE(inv))) ++ return dividend; ++ ++ return ((u64)dividend * inv[divisor - 2]) >> 32; ++} ++ ++static const u8 vp9_kf_y_mode_prob[10][10][9] = { ++ { ++ /* above = dc */ ++ { 137, 30, 42, 148, 151, 207, 70, 52, 91 },/*left = dc */ ++ { 92, 45, 102, 136, 116, 180, 74, 90, 100 },/*left = v */ ++ { 73, 32, 19, 187, 222, 215, 46, 34, 100 },/*left = h */ ++ { 91, 30, 32, 116, 121, 186, 93, 86, 94 },/*left = d45 */ ++ { 72, 35, 36, 149, 68, 206, 68, 63, 105 },/*left = d135*/ ++ { 73, 31, 28, 138, 57, 124, 55, 122, 151 },/*left = d117*/ ++ { 67, 23, 21, 140, 126, 197, 40, 37, 171 },/*left = d153*/ ++ { 86, 27, 28, 128, 154, 212, 45, 43, 53 },/*left = d207*/ ++ { 74, 32, 27, 107, 86, 160, 63, 134, 102 },/*left = d63 */ ++ { 59, 67, 44, 140, 161, 202, 78, 67, 119 } /*left = tm */ ++ }, { /* above = v */ ++ { 63, 36, 126, 146, 123, 158, 60, 90, 96 },/*left = dc */ ++ { 43, 46, 168, 134, 107, 128, 69, 142, 92 },/*left = v */ ++ { 44, 29, 68, 159, 201, 177, 50, 57, 77 },/*left = h */ ++ { 58, 38, 76, 114, 97, 172, 78, 133, 92 },/*left = d45 */ ++ { 46, 41, 76, 140, 63, 184, 69, 112, 57 },/*left = d135*/ ++ { 38, 32, 85, 140, 46, 112, 54, 151, 133 },/*left = d117*/ ++ { 39, 27, 61, 131, 110, 175, 44, 75, 136 },/*left = d153*/ ++ { 52, 30, 74, 113, 130, 175, 51, 64, 58 },/*left = d207*/ ++ { 47, 35, 80, 100, 74, 143, 64, 163, 74 },/*left = d63 */ ++ { 36, 61, 116, 114, 128, 162, 80, 125, 82 } /*left = tm */ ++ }, { /* above = h */ ++ { 82, 26, 26, 171, 208, 204, 44, 32, 105 },/*left = dc */ ++ { 55, 44, 68, 166, 179, 192, 57, 57, 108 },/*left = v */ ++ { 42, 26, 11, 199, 241, 228, 23, 15, 85 },/*left = h */ ++ { 68, 42, 19, 131, 160, 199, 55, 52, 83 },/*left = d45 */ ++ { 58, 50, 25, 139, 115, 232, 39, 52, 118 },/*left = d135*/ ++ { 50, 35, 33, 153, 104, 162, 64, 59, 131 },/*left = d117*/ ++ { 44, 24, 16, 150, 177, 202, 33, 19, 156 },/*left = d153*/ ++ { 55, 27, 12, 153, 203, 218, 26, 27, 49 },/*left = d207*/ ++ { 53, 49, 21, 110, 116, 168, 59, 80, 76 },/*left = d63 */ ++ { 38, 72, 19, 168, 203, 212, 50, 50, 107 } /*left = tm */ ++ }, { /* above = d45 */ ++ { 103, 26, 36, 129, 132, 201, 83, 80, 93 },/*left = dc */ ++ { 59, 38, 83, 112, 103, 162, 98, 136, 90 },/*left = v */ ++ { 62, 30, 23, 158, 200, 207, 59, 57, 50 },/*left = h */ ++ { 67, 30, 29, 84, 86, 191, 102, 91, 59 },/*left = d45 */ ++ { 60, 32, 33, 112, 71, 220, 64, 89, 104 },/*left = d135*/ ++ { 53, 26, 34, 130, 56, 149, 84, 120, 103 },/*left = d117*/ ++ { 53, 21, 23, 133, 109, 210, 56, 77, 172 },/*left = d153*/ ++ { 77, 19, 29, 112, 142, 228, 55, 66, 36 },/*left = d207*/ ++ { 61, 29, 29, 93, 97, 165, 83, 175, 162 },/*left = d63 */ ++ { 47, 47, 43, 114, 137, 181, 100, 99, 95 } /*left = tm */ ++ }, { /* above = d135 */ ++ { 69, 23, 29, 128, 83, 199, 46, 44, 101 },/*left = dc */ ++ { 53, 40, 55, 139, 69, 183, 61, 80, 110 },/*left = v */ ++ { 40, 29, 19, 161, 180, 207, 43, 24, 91 },/*left = h */ ++ { 60, 34, 19, 105, 61, 198, 53, 64, 89 },/*left = d45 */ ++ { 52, 31, 22, 158, 40, 209, 58, 62, 89 },/*left = d135*/ ++ { 44, 31, 29, 147, 46, 158, 56, 102, 198 },/*left = d117*/ ++ { 35, 19, 12, 135, 87, 209, 41, 45, 167 },/*left = d153*/ ++ { 55, 25, 21, 118, 95, 215, 38, 39, 66 },/*left = d207*/ ++ { 51, 38, 25, 113, 58, 164, 70, 93, 97 },/*left = d63 */ ++ { 47, 54, 34, 146, 108, 203, 72, 103, 151 } /*left = tm */ ++ }, { /* above = d117 */ ++ { 64, 19, 37, 156, 66, 138, 49, 95, 133 },/*left = dc */ ++ { 46, 27, 80, 150, 55, 124, 55, 121, 135 },/*left = v */ ++ { 36, 23, 27, 165, 149, 166, 54, 64, 118 },/*left = h */ ++ { 53, 21, 36, 131, 63, 163, 60, 109, 81 },/*left = d45 */ ++ { 40, 26, 35, 154, 40, 185, 51, 97, 123 },/*left = d135*/ ++ { 35, 19, 34, 179, 19, 97, 48, 129, 124 },/*left = d117*/ ++ { 36, 20, 26, 136, 62, 164, 33, 77, 154 },/*left = d153*/ ++ { 45, 18, 32, 130, 90, 157, 40, 79, 91 },/*left = d207*/ ++ { 45, 26, 28, 129, 45, 129, 49, 147, 123 },/*left = d63 */ ++ { 38, 44, 51, 136, 74, 162, 57, 97, 121 } /*left = tm */ ++ }, { /* above = d153 */ ++ { 75, 17, 22, 136, 138, 185, 32, 34, 166 },/*left = dc */ ++ { 56, 39, 58, 133, 117, 173, 48, 53, 187 },/*left = v */ ++ { 35, 21, 12, 161, 212, 207, 20, 23, 145 },/*left = h */ ++ { 56, 29, 19, 117, 109, 181, 55, 68, 112 },/*left = d45 */ ++ { 47, 29, 17, 153, 64, 220, 59, 51, 114 },/*left = d135*/ ++ { 46, 16, 24, 136, 76, 147, 41, 64, 172 },/*left = d117*/ ++ { 34, 17, 11, 108, 152, 187, 13, 15, 209 },/*left = d153*/ ++ { 51, 24, 14, 115, 133, 209, 32, 26, 104 },/*left = d207*/ ++ { 55, 30, 18, 122, 79, 179, 44, 88, 116 },/*left = d63 */ ++ { 37, 49, 25, 129, 168, 164, 41, 54, 148 } /*left = tm */ ++ }, { /* above = d207 */ ++ { 82, 22, 32, 127, 143, 213, 39, 41, 70 },/*left = dc */ ++ { 62, 44, 61, 123, 105, 189, 48, 57, 64 },/*left = v */ ++ { 47, 25, 17, 175, 222, 220, 24, 30, 86 },/*left = h */ ++ { 68, 36, 17, 106, 102, 206, 59, 74, 74 },/*left = d45 */ ++ { 57, 39, 23, 151, 68, 216, 55, 63, 58 },/*left = d135*/ ++ { 49, 30, 35, 141, 70, 168, 82, 40, 115 },/*left = d117*/ ++ { 51, 25, 15, 136, 129, 202, 38, 35, 139 },/*left = d153*/ ++ { 68, 26, 16, 111, 141, 215, 29, 28, 28 },/*left = d207*/ ++ { 59, 39, 19, 114, 75, 180, 77, 104, 42 },/*left = d63 */ ++ { 40, 61, 26, 126, 152, 206, 61, 59, 93 } /*left = tm */ ++ }, { /* above = d63 */ ++ { 78, 23, 39, 111, 117, 170, 74, 124, 94 },/*left = dc */ ++ { 48, 34, 86, 101, 92, 146, 78, 179, 134 },/*left = v */ ++ { 47, 22, 24, 138, 187, 178, 68, 69, 59 },/*left = h */ ++ { 56, 25, 33, 105, 112, 187, 95, 177, 129 },/*left = d45 */ ++ { 48, 31, 27, 114, 63, 183, 82, 116, 56 },/*left = d135*/ ++ { 43, 28, 37, 121, 63, 123, 61, 192, 169 },/*left = d117*/ ++ { 42, 17, 24, 109, 97, 177, 56, 76, 122 },/*left = d153*/ ++ { 58, 18, 28, 105, 139, 182, 70, 92, 63 },/*left = d207*/ ++ { 46, 23, 32, 74, 86, 150, 67, 183, 88 },/*left = d63 */ ++ { 36, 38, 48, 92, 122, 165, 88, 137, 91 } /*left = tm */ ++ }, { /* above = tm */ ++ { 65, 70, 60, 155, 159, 199, 61, 60, 81 },/*left = dc */ ++ { 44, 78, 115, 132, 119, 173, 71, 112, 93 },/*left = v */ ++ { 39, 38, 21, 184, 227, 206, 42, 32, 64 },/*left = h */ ++ { 58, 47, 36, 124, 137, 193, 80, 82, 78 },/*left = d45 */ ++ { 49, 50, 35, 144, 95, 205, 63, 78, 59 },/*left = d135*/ ++ { 41, 53, 52, 148, 71, 142, 65, 128, 51 },/*left = d117*/ ++ { 40, 36, 28, 143, 143, 202, 40, 55, 137 },/*left = d153*/ ++ { 52, 34, 29, 129, 183, 227, 42, 35, 43 },/*left = d207*/ ++ { 42, 44, 44, 104, 105, 164, 64, 130, 80 },/*left = d63 */ ++ { 43, 81, 53, 140, 169, 204, 68, 84, 72 } /*left = tm */ ++ } ++}; ++ ++static const u8 kf_partition_probs[16][3] = { ++ /* 8x8 -> 4x4 */ ++ { 158, 97, 94 }, /* a/l both not split */ ++ { 93, 24, 99 }, /* a split, l not split */ ++ { 85, 119, 44 }, /* l split, a not split */ ++ { 62, 59, 67 }, /* a/l both split */ ++ /* 16x16 -> 8x8 */ ++ { 149, 53, 53 }, /* a/l both not split */ ++ { 94, 20, 48 }, /* a split, l not split */ ++ { 83, 53, 24 }, /* l split, a not split */ ++ { 52, 18, 18 }, /* a/l both split */ ++ /* 32x32 -> 16x16 */ ++ { 150, 40, 39 }, /* a/l both not split */ ++ { 78, 12, 26 }, /* a split, l not split */ ++ { 67, 33, 11 }, /* l split, a not split */ ++ { 24, 7, 5 }, /* a/l both split */ ++ /* 64x64 -> 32x32 */ ++ { 174, 35, 49 }, /* a/l both not split */ ++ { 68, 11, 27 }, /* a split, l not split */ ++ { 57, 15, 9 }, /* l split, a not split */ ++ { 12, 3, 3 }, /* a/l both split */ ++}; ++ ++static const u8 kf_uv_mode_prob[10][9] = { ++ { 144, 11, 54, 157, 195, 130, 46, 58, 108 }, /* y = dc */ ++ { 118, 15, 123, 148, 131, 101, 44, 93, 131 }, /* y = v */ ++ { 113, 12, 23, 188, 226, 142, 26, 32, 125 }, /* y = h */ ++ { 120, 11, 50, 123, 163, 135, 64, 77, 103 }, /* y = d45 */ ++ { 113, 9, 36, 155, 111, 157, 32, 44, 161 }, /* y = d135 */ ++ { 116, 9, 55, 176, 76, 96, 37, 61, 149 }, /* y = d117 */ ++ { 115, 9, 28, 141, 161, 167, 21, 25, 193 }, /* y = d153 */ ++ { 120, 12, 32, 145, 195, 142, 32, 38, 86 }, /* y = d207 */ ++ { 116, 12, 64, 120, 140, 125, 49, 115, 121 }, /* y = d63 */ ++ { 102, 19, 66, 162, 182, 122, 35, 59, 128 } /* y = tm */ ++}; ++ ++static void write_coeff_plane(const u8 coef[6][6][3], u8 *coeff_plane) ++{ ++ unsigned int idx = 0; ++ u8 byte_count = 0, p; ++ s32 k, m, n; ++ ++ for (k = 0; k < 6; k++) { ++ for (m = 0; m < 6; m++) { ++ for (n = 0; n < 3; n++) { ++ p = coef[k][m][n]; ++ coeff_plane[idx++] = p; ++ byte_count++; ++ if (byte_count == 27) { ++ idx += 5; ++ byte_count = 0; ++ } ++ } ++ } ++ } ++} ++ ++static void init_intra_only_probs(struct rkvdec_ctx *ctx, ++ const struct rkvdec_vp9_run *run) ++{ ++ const struct v4l2_ctrl_vp9_frame_decode_params *dec_params; ++ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; ++ struct rkvdec_vp9_priv_tbl *tbl = vp9_ctx->priv_tbl.cpu; ++ struct rkvdec_vp9_intra_only_frame_probs *rkprobs; ++ const struct v4l2_vp9_probabilities *probs; ++ unsigned int i, j, k, m; ++ ++ rkprobs = &tbl->probs.intra_only; ++ dec_params = run->decode_params; ++ probs = &dec_params->probs; ++ ++ /* ++ * intra only 149 x 128 bits ,aligned to 152 x 128 bits coeff related ++ * prob 64 x 128 bits ++ */ ++ for (i = 0; i < ARRAY_SIZE(probs->coef); i++) { ++ for (j = 0; j < ARRAY_SIZE(probs->coef[0]); j++) ++ write_coeff_plane(probs->coef[i][j][0], ++ rkprobs->coef_intra[i][j]); ++ } ++ ++ /* intra mode prob 80 x 128 bits */ ++ for (i = 0; i < ARRAY_SIZE(vp9_kf_y_mode_prob); i++) { ++ u32 byte_count = 0; ++ int idx = 0; ++ ++ /* vp9_kf_y_mode_prob */ ++ for (j = 0; j < ARRAY_SIZE(vp9_kf_y_mode_prob[0]); j++) { ++ for (k = 0; k < ARRAY_SIZE(vp9_kf_y_mode_prob[0][0]); ++ k++) { ++ u8 val = vp9_kf_y_mode_prob[i][j][k]; ++ ++ rkprobs->intra_mode[i].y_mode[idx++] = val; ++ byte_count++; ++ if (byte_count == 27) { ++ byte_count = 0; ++ idx += 5; ++ } ++ } ++ } ++ ++ idx = 0; ++ if (i < 4) { ++ for (m = 0; m < (i < 3 ? 23 : 21); m++) { ++ const u8 *ptr = (const u8 *)kf_uv_mode_prob; ++ ++ rkprobs->intra_mode[i].uv_mode[idx++] = ptr[i * 23 + m]; ++ } ++ } ++ } ++} ++ ++static void init_inter_probs(struct rkvdec_ctx *ctx, ++ const struct rkvdec_vp9_run *run) ++{ ++ const struct v4l2_ctrl_vp9_frame_decode_params *dec_params; ++ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; ++ struct rkvdec_vp9_priv_tbl *tbl = vp9_ctx->priv_tbl.cpu; ++ struct rkvdec_vp9_inter_frame_probs *rkprobs; ++ const struct v4l2_vp9_probabilities *probs; ++ unsigned int i, j, k; ++ ++ rkprobs = &tbl->probs.inter; ++ dec_params = run->decode_params; ++ probs = &dec_params->probs; ++ ++ /* ++ * inter probs ++ * 151 x 128 bits, aligned to 152 x 128 bits ++ * inter only ++ * intra_y_mode & inter_block info 6 x 128 bits ++ */ ++ ++ memcpy(rkprobs->y_mode, probs->y_mode, sizeof(rkprobs->y_mode)); ++ memcpy(rkprobs->comp_mode, probs->comp_mode, ++ sizeof(rkprobs->comp_mode)); ++ memcpy(rkprobs->comp_ref, probs->comp_ref, ++ sizeof(rkprobs->comp_ref)); ++ memcpy(rkprobs->single_ref, probs->single_ref, ++ sizeof(rkprobs->single_ref)); ++ memcpy(rkprobs->inter_mode, probs->inter_mode, ++ sizeof(rkprobs->inter_mode)); ++ memcpy(rkprobs->interp_filter, probs->interp_filter, ++ sizeof(rkprobs->interp_filter)); ++ ++ /* 128 x 128 bits coeff related */ ++ for (i = 0; i < ARRAY_SIZE(probs->coef); i++) { ++ for (j = 0; j < ARRAY_SIZE(probs->coef[0]); j++) { ++ for (k = 0; k < ARRAY_SIZE(probs->coef[0][0]); k++) ++ write_coeff_plane(probs->coef[i][j][k], ++ rkprobs->coef[k][i][j]); ++ } ++ } ++ ++ /* intra uv mode 6 x 128 */ ++ memcpy(rkprobs->uv_mode_0_2, &probs->uv_mode[0], ++ sizeof(rkprobs->uv_mode_0_2)); ++ memcpy(rkprobs->uv_mode_3_5, &probs->uv_mode[3], ++ sizeof(rkprobs->uv_mode_3_5)); ++ memcpy(rkprobs->uv_mode_6_8, &probs->uv_mode[6], ++ sizeof(rkprobs->uv_mode_6_8)); ++ memcpy(rkprobs->uv_mode_9, &probs->uv_mode[9], ++ sizeof(rkprobs->uv_mode_9)); ++ ++ /* mv related 6 x 128 */ ++ memcpy(rkprobs->mv.joint, probs->mv.joint, ++ sizeof(rkprobs->mv.joint)); ++ memcpy(rkprobs->mv.sign, probs->mv.sign, ++ sizeof(rkprobs->mv.sign)); ++ memcpy(rkprobs->mv.class, probs->mv.class, ++ sizeof(rkprobs->mv.class)); ++ memcpy(rkprobs->mv.class0_bit, probs->mv.class0_bit, ++ sizeof(rkprobs->mv.class0_bit)); ++ memcpy(rkprobs->mv.bits, probs->mv.bits, ++ sizeof(rkprobs->mv.bits)); ++ memcpy(rkprobs->mv.class0_fr, probs->mv.class0_fr, ++ sizeof(rkprobs->mv.class0_fr)); ++ memcpy(rkprobs->mv.fr, probs->mv.fr, ++ sizeof(rkprobs->mv.fr)); ++ memcpy(rkprobs->mv.class0_hp, probs->mv.class0_hp, ++ sizeof(rkprobs->mv.class0_hp)); ++ memcpy(rkprobs->mv.hp, probs->mv.hp, ++ sizeof(rkprobs->mv.hp)); ++} ++ ++static void init_probs(struct rkvdec_ctx *ctx, ++ const struct rkvdec_vp9_run *run) ++{ ++ const struct v4l2_ctrl_vp9_frame_decode_params *dec_params; ++ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; ++ struct rkvdec_vp9_priv_tbl *tbl = vp9_ctx->priv_tbl.cpu; ++ struct rkvdec_vp9_probs *rkprobs = &tbl->probs; ++ const struct v4l2_vp9_segmentation *seg; ++ const struct v4l2_vp9_probabilities *probs; ++ bool intra_only; ++ ++ dec_params = run->decode_params; ++ probs = &dec_params->probs; ++ seg = &dec_params->seg; ++ ++ memset(rkprobs, 0, sizeof(*rkprobs)); ++ ++ intra_only = !!(dec_params->flags & ++ (V4L2_VP9_FRAME_FLAG_KEY_FRAME | ++ V4L2_VP9_FRAME_FLAG_INTRA_ONLY)); ++ ++ /* sb info 5 x 128 bit */ ++ memcpy(rkprobs->partition, ++ intra_only ? kf_partition_probs : probs->partition, ++ sizeof(rkprobs->partition)); ++ ++ memcpy(rkprobs->pred, seg->pred_probs, sizeof(rkprobs->pred)); ++ memcpy(rkprobs->tree, seg->tree_probs, sizeof(rkprobs->tree)); ++ memcpy(rkprobs->skip, probs->skip, sizeof(rkprobs->skip)); ++ memcpy(rkprobs->tx32, probs->tx32, sizeof(rkprobs->tx32)); ++ memcpy(rkprobs->tx16, probs->tx16, sizeof(rkprobs->tx16)); ++ memcpy(rkprobs->tx8, probs->tx8, sizeof(rkprobs->tx8)); ++ memcpy(rkprobs->is_inter, probs->is_inter, sizeof(rkprobs->is_inter)); ++ ++ if (intra_only) ++ init_intra_only_probs(ctx, run); ++ else ++ init_inter_probs(ctx, run); ++} ++ ++struct vp9d_ref_config { ++ u32 reg_frm_size; ++ u32 reg_hor_stride; ++ u32 reg_y_stride; ++ u32 reg_yuv_stride; ++ u32 reg_ref_base; ++}; ++ ++static struct vp9d_ref_config ref_config[3] = { ++ { ++ .reg_frm_size = RKVDEC_REG_VP9_FRAME_SIZE(0), ++ .reg_hor_stride = RKVDEC_VP9_HOR_VIRSTRIDE(0), ++ .reg_y_stride = RKVDEC_VP9_LAST_FRAME_YSTRIDE, ++ .reg_yuv_stride = RKVDEC_VP9_LAST_FRAME_YUVSTRIDE, ++ .reg_ref_base = RKVDEC_REG_VP9_LAST_FRAME_BASE, ++ }, ++ { ++ .reg_frm_size = RKVDEC_REG_VP9_FRAME_SIZE(1), ++ .reg_hor_stride = RKVDEC_VP9_HOR_VIRSTRIDE(1), ++ .reg_y_stride = RKVDEC_VP9_GOLDEN_FRAME_YSTRIDE, ++ .reg_yuv_stride = 0, ++ .reg_ref_base = RKVDEC_REG_VP9_GOLDEN_FRAME_BASE, ++ }, ++ { ++ .reg_frm_size = RKVDEC_REG_VP9_FRAME_SIZE(2), ++ .reg_hor_stride = RKVDEC_VP9_HOR_VIRSTRIDE(2), ++ .reg_y_stride = RKVDEC_VP9_ALTREF_FRAME_YSTRIDE, ++ .reg_yuv_stride = 0, ++ .reg_ref_base = RKVDEC_REG_VP9_ALTREF_FRAME_BASE, ++ } ++}; ++ ++static struct rkvdec_decoded_buffer * ++get_ref_buf(struct rkvdec_ctx *ctx, struct vb2_v4l2_buffer *dst, u64 timestamp) ++{ ++ struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx; ++ struct vb2_queue *cap_q = &m2m_ctx->cap_q_ctx.q; ++ int buf_idx; ++ ++ /* ++ * If a ref is unused or invalid, address of current destination ++ * buffer is returned. ++ */ ++ buf_idx = vb2_find_timestamp(cap_q, timestamp, 0); ++ if (buf_idx < 0) ++ return vb2_to_rkvdec_decoded_buf(&dst->vb2_buf); ++ ++ return vb2_to_rkvdec_decoded_buf(vb2_get_buffer(cap_q, buf_idx)); ++} ++ ++static dma_addr_t get_mv_base_addr(struct rkvdec_decoded_buffer *buf) ++{ ++ u32 aligned_pitch, aligned_height, yuv_len; ++ ++ aligned_height = round_up(buf->vp9.height, 64); ++ aligned_pitch = round_up(buf->vp9.width * buf->vp9.bit_depth, 512) / 8; ++ yuv_len = (aligned_height * aligned_pitch * 3) / 2; ++ ++ return vb2_dma_contig_plane_dma_addr(&buf->base.vb.vb2_buf, 0) + ++ yuv_len; ++} ++ ++static void ++config_ref_registers(struct rkvdec_ctx *ctx, ++ const struct rkvdec_vp9_run *run, ++ struct rkvdec_decoded_buffer **ref_bufs, ++ enum v4l2_vp9_ref_id id) ++{ ++ u32 aligned_pitch, aligned_height, y_len, yuv_len; ++ struct rkvdec_decoded_buffer *buf = ref_bufs[id]; ++ struct rkvdec_dev *rkvdec = ctx->dev; ++ ++ aligned_height = round_up(buf->vp9.height, 64); ++ writel_relaxed(RKVDEC_VP9_FRAMEWIDTH(buf->vp9.width) | ++ RKVDEC_VP9_FRAMEHEIGHT(buf->vp9.height), ++ rkvdec->regs + ref_config[id].reg_frm_size); ++ ++ writel_relaxed(vb2_dma_contig_plane_dma_addr(&buf->base.vb.vb2_buf, 0), ++ rkvdec->regs + ref_config[id].reg_ref_base); ++ ++ if (&buf->base.vb == run->base.bufs.dst) ++ return; ++ ++ aligned_pitch = round_up(buf->vp9.width * buf->vp9.bit_depth, 512) / 8; ++ y_len = aligned_height * aligned_pitch; ++ yuv_len = (y_len * 3) / 2; ++ ++ writel_relaxed(RKVDEC_HOR_Y_VIRSTRIDE(aligned_pitch / 16) | ++ RKVDEC_HOR_UV_VIRSTRIDE(aligned_pitch / 16), ++ rkvdec->regs + ref_config[id].reg_hor_stride); ++ writel_relaxed(RKVDEC_VP9_REF_YSTRIDE(y_len / 16), ++ rkvdec->regs + ref_config[id].reg_y_stride); ++ ++ if (!ref_config[id].reg_yuv_stride) ++ return; ++ ++ writel_relaxed(RKVDEC_VP9_REF_YUVSTRIDE(yuv_len / 16), ++ rkvdec->regs + ref_config[id].reg_yuv_stride); ++} ++ ++static bool seg_featured_enabled(const struct v4l2_vp9_segmentation *seg, ++ enum v4l2_vp9_segment_feature feature, ++ unsigned int segid) ++{ ++ u8 mask = V4L2_VP9_SEGMENT_FEATURE_ENABLED(feature); ++ ++ return !!(seg->feature_enabled[segid] & mask); ++} ++ ++static void ++config_seg_registers(struct rkvdec_ctx *ctx, ++ unsigned int segid) ++{ ++ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; ++ const struct v4l2_vp9_segmentation *seg; ++ struct rkvdec_dev *rkvdec = ctx->dev; ++ s16 feature_val; ++ u8 feature_id; ++ u32 val = 0; ++ ++ seg = vp9_ctx->last.valid ? &vp9_ctx->last.seg : &vp9_ctx->cur.seg; ++ feature_id = V4L2_VP9_SEGMENT_FEATURE_QP_DELTA; ++ if (seg_featured_enabled(seg, feature_id, segid)) { ++ feature_val = seg->feature_data[segid][feature_id]; ++ val |= RKVDEC_SEGID_FRAME_QP_DELTA_EN(1) | ++ RKVDEC_SEGID_FRAME_QP_DELTA(feature_val); ++ } ++ ++ feature_id = V4L2_VP9_SEGMENT_FEATURE_LF; ++ if (seg_featured_enabled(seg, feature_id, segid)) { ++ feature_val = seg->feature_data[segid][feature_id]; ++ val |= RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE_EN(1) | ++ RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE(feature_val); ++ } ++ ++ feature_id = V4L2_VP9_SEGMENT_FEATURE_REF_FRAME; ++ if (seg_featured_enabled(seg, feature_id, segid)) { ++ feature_val = seg->feature_data[segid][feature_id]; ++ val |= RKVDEC_SEGID_REFERINFO_EN(1) | ++ RKVDEC_SEGID_REFERINFO(feature_val); ++ } ++ ++ feature_id = V4L2_VP9_SEGMENT_FEATURE_SKIP; ++ if (seg_featured_enabled(seg, feature_id, segid)) ++ val |= RKVDEC_SEGID_FRAME_SKIP_EN(1); ++ ++ if (!segid && ++ (seg->flags & V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE)) ++ val |= RKVDEC_SEGID_ABS_DELTA(1); ++ ++ writel_relaxed(val, rkvdec->regs + RKVDEC_VP9_SEGID_GRP(segid)); ++} ++ ++static void ++update_dec_buf_info(struct rkvdec_decoded_buffer *buf, ++ const struct v4l2_ctrl_vp9_frame_decode_params *dec_params) ++{ ++ buf->vp9.width = dec_params->frame_width_minus_1 + 1; ++ buf->vp9.height = dec_params->frame_height_minus_1 + 1; ++ buf->vp9.bit_depth = dec_params->bit_depth; ++} ++ ++static void ++update_ctx_cur_info(struct rkvdec_vp9_ctx *vp9_ctx, ++ struct rkvdec_decoded_buffer *buf, ++ const struct v4l2_ctrl_vp9_frame_decode_params *dec_params) ++{ ++ vp9_ctx->cur.valid = true; ++ vp9_ctx->cur.frame_context_idx = dec_params->frame_context_idx; ++ vp9_ctx->cur.reference_mode = dec_params->reference_mode; ++ vp9_ctx->cur.tx_mode = dec_params->tx_mode; ++ vp9_ctx->cur.interpolation_filter = dec_params->interpolation_filter; ++ vp9_ctx->cur.flags = dec_params->flags; ++ vp9_ctx->cur.timestamp = buf->base.vb.vb2_buf.timestamp; ++ vp9_ctx->cur.seg = dec_params->seg; ++ vp9_ctx->cur.lf = dec_params->lf; ++} ++ ++static void ++update_ctx_last_info(struct rkvdec_vp9_ctx *vp9_ctx) ++{ ++ vp9_ctx->last = vp9_ctx->cur; ++} ++ ++static void config_registers(struct rkvdec_ctx *ctx, ++ const struct rkvdec_vp9_run *run) ++{ ++ u32 y_len, uv_len, yuv_len, bit_depth, aligned_height, aligned_pitch; ++ const struct v4l2_ctrl_vp9_frame_decode_params *dec_params; ++ struct rkvdec_decoded_buffer *ref_bufs[V4L2_REF_ID_CNT]; ++ struct rkvdec_decoded_buffer *dst, *last, *mv_ref; ++ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; ++ u32 val, stream_len, last_frame_info = 0; ++ const struct v4l2_vp9_segmentation *seg; ++ struct rkvdec_dev *rkvdec = ctx->dev; ++ dma_addr_t addr; ++ bool intra_only; ++ unsigned int i; ++ ++ dec_params = run->decode_params; ++ dst = vb2_to_rkvdec_decoded_buf(&run->base.bufs.dst->vb2_buf); ++ for (i = 0; i < ARRAY_SIZE(ref_bufs); i++) ++ ref_bufs[i] = get_ref_buf(ctx, &dst->base.vb, ++ dec_params->refs[i]); ++ ++ if (vp9_ctx->last.valid) ++ last = get_ref_buf(ctx, &dst->base.vb, vp9_ctx->last.timestamp); ++ else ++ last = dst; ++ ++ update_dec_buf_info(dst, dec_params); ++ update_ctx_cur_info(vp9_ctx, dst, dec_params); ++ seg = &dec_params->seg; ++ ++ intra_only = !!(dec_params->flags & ++ (V4L2_VP9_FRAME_FLAG_KEY_FRAME | ++ V4L2_VP9_FRAME_FLAG_INTRA_ONLY)); ++ ++ writel_relaxed(RKVDEC_MODE(RKVDEC_MODE_VP9), ++ rkvdec->regs + RKVDEC_REG_SYSCTRL); ++ ++ bit_depth = dec_params->bit_depth; ++ aligned_height = round_up(ctx->decoded_fmt.fmt.pix_mp.height, 64); ++ ++ aligned_pitch = round_up(ctx->decoded_fmt.fmt.pix_mp.width * ++ bit_depth, ++ 512) / 8; ++ y_len = aligned_height * aligned_pitch; ++ uv_len = y_len / 2; ++ yuv_len = y_len + uv_len; ++ ++ writel_relaxed(RKVDEC_Y_HOR_VIRSTRIDE(aligned_pitch / 16) | ++ RKVDEC_UV_HOR_VIRSTRIDE(aligned_pitch / 16), ++ rkvdec->regs + RKVDEC_REG_PICPAR); ++ writel_relaxed(RKVDEC_Y_VIRSTRIDE(y_len / 16), ++ rkvdec->regs + RKVDEC_REG_Y_VIRSTRIDE); ++ writel_relaxed(RKVDEC_YUV_VIRSTRIDE(yuv_len / 16), ++ rkvdec->regs + RKVDEC_REG_YUV_VIRSTRIDE); ++ ++ stream_len = vb2_get_plane_payload(&run->base.bufs.src->vb2_buf, 0); ++ writel_relaxed(RKVDEC_STRM_LEN(stream_len), ++ rkvdec->regs + RKVDEC_REG_STRM_LEN); ++ ++ /* ++ * Reset count buffer, because decoder only output intra related syntax ++ * counts when decoding intra frame, but update entropy need to update ++ * all the probabilities. ++ */ ++ if (intra_only) ++ memset(vp9_ctx->count_tbl.cpu, 0, vp9_ctx->count_tbl.size); ++ ++ vp9_ctx->cur.segmapid = vp9_ctx->last.segmapid; ++ if (!intra_only && ++ !(dec_params->flags & V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT) && ++ (!(seg->flags & V4L2_VP9_SEGMENTATION_FLAG_ENABLED) || ++ (seg->flags & V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP))) ++ vp9_ctx->cur.segmapid++; ++ ++ for (i = 0; i < ARRAY_SIZE(ref_bufs); i++) ++ config_ref_registers(ctx, run, ref_bufs, i); ++ ++ for (i = 0; i < 8; i++) ++ config_seg_registers(ctx, i); ++ ++ writel_relaxed(RKVDEC_VP9_TX_MODE(dec_params->tx_mode) | ++ RKVDEC_VP9_FRAME_REF_MODE(dec_params->reference_mode), ++ rkvdec->regs + RKVDEC_VP9_CPRHEADER_CONFIG); ++ ++ if (!intra_only) { ++ const struct v4l2_vp9_loop_filter *lf; ++ s8 delta; ++ ++ if (vp9_ctx->last.valid) ++ lf = &vp9_ctx->last.lf; ++ else ++ lf = &vp9_ctx->cur.lf; ++ ++ val = 0; ++ for (i = 0; i < ARRAY_SIZE(lf->ref_deltas); i++) { ++ delta = lf->ref_deltas[i]; ++ val |= RKVDEC_REF_DELTAS_LASTFRAME(i, delta); ++ } ++ ++ writel_relaxed(val, ++ rkvdec->regs + RKVDEC_VP9_REF_DELTAS_LASTFRAME); ++ ++ for (i = 0; i < ARRAY_SIZE(lf->mode_deltas); i++) { ++ delta = lf->mode_deltas[i]; ++ last_frame_info |= RKVDEC_MODE_DELTAS_LASTFRAME(i, ++ delta); ++ } ++ } ++ ++ if (vp9_ctx->last.valid && !intra_only && ++ vp9_ctx->last.seg.flags & V4L2_VP9_SEGMENTATION_FLAG_ENABLED) ++ last_frame_info |= RKVDEC_SEG_EN_LASTFRAME; ++ ++ if (vp9_ctx->last.valid && ++ vp9_ctx->last.flags & V4L2_VP9_FRAME_FLAG_SHOW_FRAME) ++ last_frame_info |= RKVDEC_LAST_SHOW_FRAME; ++ ++ if (vp9_ctx->last.valid && ++ vp9_ctx->last.flags & ++ (V4L2_VP9_FRAME_FLAG_KEY_FRAME | V4L2_VP9_FRAME_FLAG_INTRA_ONLY)) ++ last_frame_info |= RKVDEC_LAST_INTRA_ONLY; ++ ++ if (vp9_ctx->last.valid && ++ last->vp9.width == dst->vp9.width && ++ last->vp9.height == dst->vp9.height) ++ last_frame_info |= RKVDEC_LAST_WIDHHEIGHT_EQCUR; ++ ++ writel_relaxed(last_frame_info, ++ rkvdec->regs + RKVDEC_VP9_INFO_LASTFRAME); ++ ++ writel_relaxed(stream_len - dec_params->compressed_header_size - ++ dec_params->uncompressed_header_size, ++ rkvdec->regs + RKVDEC_VP9_LASTTILE_SIZE); ++ ++ for (i = 0; !intra_only && i < ARRAY_SIZE(ref_bufs); i++) { ++ u32 refw = ref_bufs[i]->vp9.width; ++ u32 refh = ref_bufs[i]->vp9.height; ++ u32 hscale, vscale; ++ ++ hscale = (refw << 14) / dst->vp9.width; ++ vscale = (refh << 14) / dst->vp9.height; ++ writel_relaxed(RKVDEC_VP9_REF_HOR_SCALE(hscale) | ++ RKVDEC_VP9_REF_VER_SCALE(vscale), ++ rkvdec->regs + RKVDEC_VP9_REF_SCALE(i)); ++ } ++ ++ addr = vb2_dma_contig_plane_dma_addr(&dst->base.vb.vb2_buf, 0); ++ writel_relaxed(addr, rkvdec->regs + RKVDEC_REG_DECOUT_BASE); ++ addr = vb2_dma_contig_plane_dma_addr(&run->base.bufs.src->vb2_buf, 0); ++ writel_relaxed(addr, rkvdec->regs + RKVDEC_REG_STRM_RLC_BASE); ++ writel_relaxed(vp9_ctx->priv_tbl.dma + ++ offsetof(struct rkvdec_vp9_priv_tbl, probs), ++ rkvdec->regs + RKVDEC_REG_CABACTBL_PROB_BASE); ++ writel_relaxed(vp9_ctx->count_tbl.dma, ++ rkvdec->regs + RKVDEC_REG_VP9COUNT_BASE); ++ ++ writel_relaxed(vp9_ctx->priv_tbl.dma + ++ offsetof(struct rkvdec_vp9_priv_tbl, segmap) + ++ (RKVDEC_VP9_MAX_SEGMAP_SIZE * vp9_ctx->cur.segmapid), ++ rkvdec->regs + RKVDEC_REG_VP9_SEGIDCUR_BASE); ++ writel_relaxed(vp9_ctx->priv_tbl.dma + ++ offsetof(struct rkvdec_vp9_priv_tbl, segmap) + ++ (RKVDEC_VP9_MAX_SEGMAP_SIZE * (!vp9_ctx->cur.segmapid)), ++ rkvdec->regs + RKVDEC_REG_VP9_SEGIDLAST_BASE); ++ ++ if (!intra_only && ++ !(dec_params->flags & V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT) && ++ vp9_ctx->last.valid) ++ mv_ref = last; ++ else ++ mv_ref = dst; ++ ++ writel_relaxed(get_mv_base_addr(mv_ref), ++ rkvdec->regs + RKVDEC_VP9_REF_COLMV_BASE); ++ ++ writel_relaxed(ctx->decoded_fmt.fmt.pix_mp.width | ++ (ctx->decoded_fmt.fmt.pix_mp.height << 16), ++ rkvdec->regs + RKVDEC_REG_PERFORMANCE_CYCLE); ++} ++ ++static int ++validate_dec_params(struct rkvdec_ctx *ctx, ++ const struct v4l2_ctrl_vp9_frame_decode_params *dec_params) ++{ ++ unsigned int aligned_width, aligned_height; ++ ++ /* We only support profile 0. */ ++ if (dec_params->profile != 0) { ++ dev_err(ctx->dev->dev, "unsupported profile %d\n", ++ dec_params->profile); ++ return -EINVAL; ++ } ++ ++ aligned_width = round_up(dec_params->frame_width_minus_1 + 1, 64); ++ aligned_height = round_up(dec_params->frame_height_minus_1 + 1, 64); ++ ++ /* ++ * Userspace should update the capture/decoded format when the ++ * resolution changes. ++ */ ++ if (aligned_width != ctx->decoded_fmt.fmt.pix_mp.width || ++ aligned_height != ctx->decoded_fmt.fmt.pix_mp.height) { ++ dev_err(ctx->dev->dev, ++ "unexpected bitstream resolution %dx%d\n", ++ dec_params->frame_width_minus_1 + 1, ++ dec_params->frame_height_minus_1 +1); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int rkvdec_vp9_run_preamble(struct rkvdec_ctx *ctx, ++ struct rkvdec_vp9_run *run) ++{ ++ const struct v4l2_ctrl_vp9_frame_decode_params *dec_params; ++ const struct v4l2_ctrl_vp9_frame_ctx *fctx = NULL; ++ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; ++ struct v4l2_ctrl *ctrl; ++ u8 frm_ctx; ++ int ret; ++ ++ rkvdec_run_preamble(ctx, &run->base); ++ ++ ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, ++ V4L2_CID_MPEG_VIDEO_VP9_FRAME_DECODE_PARAMS); ++ WARN_ON(!ctrl); ++ ++ dec_params = ctrl ? ctrl->p_cur.p : NULL; ++ if (WARN_ON(!dec_params)) ++ return -EINVAL; ++ ++ ret = validate_dec_params(ctx, dec_params); ++ if (ret) ++ return ret; ++ ++ run->decode_params = dec_params; ++ ++ /* No need to load the frame context if we don't need to update it. */ ++ if (!(dec_params->flags & V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX)) ++ return 0; ++ ++ /* ++ * When a refresh context is requested in parallel mode, we should just ++ * update the context with the probs passed in the decode parameters. ++ */ ++ if (dec_params->flags & V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE) { ++ vp9_ctx->frame_context.probs = dec_params->probs; ++ return 0; ++ } ++ ++ frm_ctx = run->decode_params->frame_context_idx; ++ ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, ++ V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(frm_ctx)); ++ if (WARN_ON(!ctrl)) ++ return 0; ++ ++ fctx = ctrl->p_cur.p; ++ vp9_ctx->frame_context = *fctx; ++ ++ /* ++ * For intra-only frames, we must update the context TX and skip probs ++ * with the value passed in the decode params. ++ */ ++ if (dec_params->flags & ++ (V4L2_VP9_FRAME_FLAG_KEY_FRAME | V4L2_VP9_FRAME_FLAG_INTRA_ONLY)) { ++ struct v4l2_vp9_probabilities *probs; ++ ++ probs = &vp9_ctx->frame_context.probs; ++ memcpy(probs->skip, dec_params->probs.skip, ++ sizeof(probs->skip)); ++ memcpy(probs->tx8, dec_params->probs.tx8, ++ sizeof(probs->tx8)); ++ memcpy(probs->tx16, dec_params->probs.tx16, ++ sizeof(probs->tx16)); ++ memcpy(probs->tx32, dec_params->probs.tx32, ++ sizeof(probs->tx32)); ++ } ++ ++ return 0; ++} ++ ++static int rkvdec_vp9_run(struct rkvdec_ctx *ctx) ++{ ++ struct rkvdec_dev *rkvdec = ctx->dev; ++ struct rkvdec_vp9_run run = { }; ++ int ret; ++ ++ ret = rkvdec_vp9_run_preamble(ctx, &run); ++ if (ret) { ++ rkvdec_run_postamble(ctx, &run.base); ++ return ret; ++ } ++ ++ /* Prepare probs. */ ++ init_probs(ctx, &run); ++ ++ /* Configure hardware registers. */ ++ config_registers(ctx, &run); ++ ++ rkvdec_run_postamble(ctx, &run.base); ++ ++ schedule_delayed_work(&rkvdec->watchdog_work, msecs_to_jiffies(2000)); ++ ++ writel(1, rkvdec->regs + RKVDEC_REG_PREF_LUMA_CACHE_COMMAND); ++ writel(1, rkvdec->regs + RKVDEC_REG_PREF_CHR_CACHE_COMMAND); ++ ++ writel(0xe, rkvdec->regs + RKVDEC_REG_STRMD_ERR_EN); ++ /* Start decoding! */ ++ writel(RKVDEC_INTERRUPT_DEC_E | RKVDEC_CONFIG_DEC_CLK_GATE_E | ++ RKVDEC_TIMEOUT_E | RKVDEC_BUF_EMPTY_E, ++ rkvdec->regs + RKVDEC_REG_INTERRUPT); ++ ++ return 0; ++} ++ ++static u8 adapt_prob(u8 p1, u32 ct0, u32 ct1, u16 max_count, u32 update_factor) ++{ ++ u32 ct = ct0 + ct1, p2; ++ u32 lo = 1; ++ u32 hi = 255; ++ ++ if (!ct) ++ return p1; ++ ++ p2 = ((ct0 << 8) + (ct >> 1)) / ct; ++ p2 = clamp(p2, lo, hi); ++ ct = min_t(u32, ct, max_count); ++ ++ if (WARN_ON(max_count >= 257)) ++ return p1; ++ ++ update_factor = rkvdec_fastdiv(update_factor * ct, max_count); ++ ++ return p1 + (((p2 - p1) * update_factor + 128) >> 8); ++} ++ ++#define BAND_6(band) ((band) == 0 ? 3 : 6) ++ ++static void adapt_coeff(u8 coef[6][6][3], ++ const struct rkvdec_vp9_refs_counts ref_cnt[6][6], ++ u32 uf) ++{ ++ s32 l, m, n; ++ ++ for (l = 0; l < 6; l++) { ++ for (m = 0; m < BAND_6(l); m++) { ++ u8 *p = coef[l][m]; ++ const u32 n0 = ref_cnt[l][m].coeff[0]; ++ const u32 n1 = ref_cnt[l][m].coeff[1]; ++ const u32 n2 = ref_cnt[l][m].coeff[2]; ++ const u32 neob = ref_cnt[l][m].eob[1]; ++ const u32 eob_count = ref_cnt[l][m].eob[0]; ++ const u32 branch_ct[3][2] = { ++ { neob, eob_count - neob }, ++ { n0, n1 + n2 }, ++ { n1, n2 } ++ }; ++ ++ for (n = 0; n < 3; n++) ++ p[n] = adapt_prob(p[n], branch_ct[n][0], ++ branch_ct[n][1], 24, uf); ++ } ++ } ++} ++ ++static void ++adapt_coef_probs(struct v4l2_vp9_probabilities *probs, ++ const struct rkvdec_vp9_refs_counts ref_cnt[2][4][2][6][6], ++ unsigned int uf) ++{ ++ unsigned int i, j, k; ++ ++ for (i = 0; i < ARRAY_SIZE(probs->coef); i++) { ++ for (j = 0; j < ARRAY_SIZE(probs->coef[0]); j++) { ++ for (k = 0; k < ARRAY_SIZE(probs->coef[0][0]); ++ k++) { ++ adapt_coeff(probs->coef[i][j][k], ++ ref_cnt[k][i][j], ++ uf); ++ } ++ } ++ } ++} ++ ++static void adapt_intra_frame_probs(struct rkvdec_ctx *ctx) ++{ ++ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; ++ struct v4l2_vp9_probabilities *probs = &vp9_ctx->frame_context.probs; ++ const struct rkvdec_vp9_intra_frame_symbol_counts *sym_cnts; ++ ++ sym_cnts = vp9_ctx->count_tbl.cpu; ++ adapt_coef_probs(probs, sym_cnts->ref_cnt, 112); ++} ++ ++static void ++adapt_skip_probs(struct v4l2_vp9_probabilities *probs, ++ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(probs->skip); i++) ++ probs->skip[i] = adapt_prob(probs->skip[i], ++ sym_cnts->skip[i][0], ++ sym_cnts->skip[i][1], ++ 20, 128); ++} ++ ++static void ++adapt_is_inter_probs(struct v4l2_vp9_probabilities *probs, ++ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(probs->is_inter); i++) ++ probs->is_inter[i] = adapt_prob(probs->is_inter[i], ++ sym_cnts->inter[i][0], ++ sym_cnts->inter[i][1], ++ 20, 128); ++} ++ ++static void ++adapt_comp_mode_probs(struct v4l2_vp9_probabilities *probs, ++ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(probs->comp_mode); i++) ++ probs->comp_mode[i] = adapt_prob(probs->comp_mode[i], ++ sym_cnts->comp[i][0], ++ sym_cnts->comp[i][1], ++ 20, 128); ++} ++ ++static void ++adapt_comp_ref_probs(struct v4l2_vp9_probabilities *probs, ++ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(probs->comp_ref); i++) ++ probs->comp_ref[i] = adapt_prob(probs->comp_ref[i], ++ sym_cnts->comp_ref[i][0], ++ sym_cnts->comp_ref[i][1], ++ 20, 128); ++} ++ ++static void ++adapt_single_ref_probs(struct v4l2_vp9_probabilities *probs, ++ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(probs->single_ref); i++) { ++ u8 *p = probs->single_ref[i]; ++ ++ p[0] = adapt_prob(p[0], sym_cnts->single_ref[i][0][0], ++ sym_cnts->single_ref[i][0][1], 20, 128); ++ p[1] = adapt_prob(p[1], sym_cnts->single_ref[i][1][0], ++ sym_cnts->single_ref[i][1][1], 20, 128); ++ } ++} ++ ++static void ++adapt_partition_probs(struct v4l2_vp9_probabilities *probs, ++ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(probs->partition); i++) { ++ const u32 *c = sym_cnts->partition[i]; ++ u8 *p = probs->partition[i]; ++ ++ p[0] = adapt_prob(p[0], c[0], c[1] + c[2] + c[3], 20, 128); ++ p[1] = adapt_prob(p[1], c[1], c[2] + c[3], 20, 128); ++ p[2] = adapt_prob(p[2], c[2], c[3], 20, 128); ++ } ++} ++ ++static void ++adapt_tx_probs(struct v4l2_vp9_probabilities *probs, ++ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(probs->tx8); i++) { ++ u8 *p16x16 = probs->tx16[i]; ++ u8 *p32x32 = probs->tx32[i]; ++ const u32 *c16 = sym_cnts->tx16p[i]; ++ const u32 *c32 = sym_cnts->tx32p[i]; ++ const u32 *c8 = sym_cnts->tx8p[i]; ++ u8 *p8x8 = probs->tx8[i]; ++ ++ p8x8[0] = adapt_prob(p8x8[0], c8[0], c8[1], 20, 128); ++ p16x16[0] = adapt_prob(p16x16[0], c16[0], c16[1] + c16[2], ++ 20, 128); ++ p16x16[1] = adapt_prob(p16x16[1], c16[1], c16[2], 20, 128); ++ p32x32[0] = adapt_prob(p32x32[0], c32[0], ++ c32[1] + c32[2] + c32[3], 20, 128); ++ p32x32[1] = adapt_prob(p32x32[1], c32[1], c32[2] + c32[3], ++ 20, 128); ++ p32x32[2] = adapt_prob(p32x32[2], c32[2], c32[3], 20, 128); ++ } ++} ++ ++static void ++adapt_interp_filter_probs(struct v4l2_vp9_probabilities *probs, ++ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(probs->interp_filter); i++) { ++ u8 *p = probs->interp_filter[i]; ++ const u32 *c = sym_cnts->filter[i]; ++ ++ p[0] = adapt_prob(p[0], c[0], c[1] + c[2], 20, 128); ++ p[1] = adapt_prob(p[1], c[1], c[2], 20, 128); ++ } ++} ++ ++static void ++adapt_inter_mode_probs(struct v4l2_vp9_probabilities *probs, ++ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(probs->inter_mode); i++) { ++ const u32 *c = sym_cnts->mv_mode[i]; ++ u8 *p = probs->inter_mode[i]; ++ ++ p[0] = adapt_prob(p[0], c[2], c[1] + c[0] + c[3], 20, 128); ++ p[1] = adapt_prob(p[1], c[0], c[1] + c[3], 20, 128); ++ p[2] = adapt_prob(p[2], c[1], c[3], 20, 128); ++ } ++} ++ ++static void ++adapt_mv_probs(struct v4l2_vp9_probabilities *probs, ++ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts, ++ bool high_prec_mv) ++{ ++ const u32 *c = sym_cnts->mv_joint; ++ u8 *p = probs->mv.joint; ++ unsigned int i, j; ++ u32 sum; ++ ++ p[0] = adapt_prob(p[0], c[0], c[1] + c[2] + c[3], 20, 128); ++ p[1] = adapt_prob(p[1], c[1], c[2] + c[3], 20, 128); ++ p[2] = adapt_prob(p[2], c[2], c[3], 20, 128); ++ ++ for (i = 0; i < ARRAY_SIZE(probs->mv.sign); i++) { ++ p = probs->mv.sign; ++ ++ p[i] = adapt_prob(p[i], sym_cnts->sign[i][0], ++ sym_cnts->sign[i][1], 20, 128); ++ ++ p = probs->mv.class[i]; ++ c = sym_cnts->classes[i]; ++ sum = c[1] + c[2] + c[3] + c[4] + c[5] + c[6] + c[7] + c[8] + ++ c[9] + c[10]; ++ p[0] = adapt_prob(p[0], c[0], sum, 20, 128); ++ sum -= c[1]; ++ p[1] = adapt_prob(p[1], c[1], sum, 20, 128); ++ sum -= c[2] + c[3]; ++ p[2] = adapt_prob(p[2], c[2] + c[3], sum, 20, 128); ++ p[3] = adapt_prob(p[3], c[2], c[3], 20, 128); ++ sum -= c[4] + c[5]; ++ p[4] = adapt_prob(p[4], c[4] + c[5], sum, 20, 128); ++ p[5] = adapt_prob(p[5], c[4], c[5], 20, 128); ++ sum -= c[6]; ++ p[6] = adapt_prob(p[6], c[6], sum, 20, 128); ++ p[7] = adapt_prob(p[7], c[7] + c[8], c[9] + c[10], 20, 128); ++ p[8] = adapt_prob(p[8], c[7], c[8], 20, 128); ++ p[9] = adapt_prob(p[9], c[9], c[10], 20, 128); ++ ++ p = probs->mv.class0_bit; ++ p[i] = adapt_prob(p[i], ++ sym_cnts->class0[i][0], ++ sym_cnts->class0[i][1], 20, 128); ++ ++ p = probs->mv.bits[i]; ++ for (j = 0; j < 10; j++) ++ p[j] = adapt_prob(p[j], sym_cnts->bits[i][j][0], ++ sym_cnts->bits[i][j][1], 20, 128); ++ ++ for (j = 0; j < 2; j++) { ++ p = probs->mv.class0_fr[i][j]; ++ c = sym_cnts->class0_fp[i][j]; ++ p[0] = adapt_prob(p[0], c[0], c[1] + c[2] + c[3], ++ 20, 128); ++ p[1] = adapt_prob(p[1], c[1], c[2] + c[3], 20, 128); ++ p[2] = adapt_prob(p[2], c[2], c[3], 20, 128); ++ } ++ ++ p = probs->mv.fr[i]; ++ c = sym_cnts->fp[i]; ++ p[0] = adapt_prob(p[0], c[0], c[1] + c[2] + c[3], 20, 128); ++ p[1] = adapt_prob(p[1], c[1], c[2] + c[3], 20, 128); ++ p[2] = adapt_prob(p[2], c[2], c[3], 20, 128); ++ ++ if (!high_prec_mv) ++ continue; ++ ++ p = probs->mv.class0_hp; ++ p[i] = adapt_prob(p[i], sym_cnts->class0_hp[i][0], ++ sym_cnts->class0_hp[i][1], 20, 128); ++ ++ p = probs->mv.hp; ++ p[i] = adapt_prob(p[i], sym_cnts->hp[i][0], ++ sym_cnts->hp[i][1], 20, 128); ++ } ++} ++ ++static void ++adapt_intra_mode_probs(u8 *p, const u32 *c) ++{ ++ u32 sum = 0, s2; ++ unsigned int i; ++ ++ for (i = V4L2_VP9_INTRA_PRED_MODE_V; i <= V4L2_VP9_INTRA_PRED_MODE_TM; ++ i++) ++ sum += c[i]; ++ ++ p[0] = adapt_prob(p[0], c[V4L2_VP9_INTRA_PRED_MODE_DC], sum, 20, 128); ++ sum -= c[V4L2_VP9_INTRA_PRED_MODE_TM]; ++ p[1] = adapt_prob(p[1], c[V4L2_VP9_INTRA_PRED_MODE_TM], sum, 20, 128); ++ sum -= c[V4L2_VP9_INTRA_PRED_MODE_V]; ++ p[2] = adapt_prob(p[2], c[V4L2_VP9_INTRA_PRED_MODE_V], sum, 20, 128); ++ s2 = c[V4L2_VP9_INTRA_PRED_MODE_H] + c[V4L2_VP9_INTRA_PRED_MODE_D135] + ++ c[V4L2_VP9_INTRA_PRED_MODE_D117]; ++ sum -= s2; ++ p[3] = adapt_prob(p[3], s2, sum, 20, 128); ++ s2 -= c[V4L2_VP9_INTRA_PRED_MODE_H]; ++ p[4] = adapt_prob(p[4], c[V4L2_VP9_INTRA_PRED_MODE_H], s2, 20, 128); ++ p[5] = adapt_prob(p[5], c[V4L2_VP9_INTRA_PRED_MODE_D135], ++ c[V4L2_VP9_INTRA_PRED_MODE_D117], 20, 128); ++ sum -= c[V4L2_VP9_INTRA_PRED_MODE_D45]; ++ p[6] = adapt_prob(p[6], c[V4L2_VP9_INTRA_PRED_MODE_D45], ++ sum, 20, 128); ++ sum -= c[V4L2_VP9_INTRA_PRED_MODE_D63]; ++ p[7] = adapt_prob(p[7], c[V4L2_VP9_INTRA_PRED_MODE_D63], sum, ++ 20, 128); ++ p[8] = adapt_prob(p[8], c[V4L2_VP9_INTRA_PRED_MODE_D153], ++ c[V4L2_VP9_INTRA_PRED_MODE_D207], 20, 128); ++} ++ ++static void ++adapt_y_intra_mode_probs(struct v4l2_vp9_probabilities *probs, ++ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(probs->y_mode); i++) ++ adapt_intra_mode_probs(probs->y_mode[i], sym_cnts->y_mode[i]); ++} ++ ++static void ++adapt_uv_intra_mode_probs(struct v4l2_vp9_probabilities *probs, ++ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(probs->uv_mode); i++) ++ adapt_intra_mode_probs(probs->uv_mode[i], ++ sym_cnts->uv_mode[i]); ++} ++ ++static void ++adapt_inter_frame_probs(struct rkvdec_ctx *ctx) ++{ ++ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; ++ struct v4l2_vp9_probabilities *probs = &vp9_ctx->frame_context.probs; ++ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts; ++ ++ sym_cnts = vp9_ctx->count_tbl.cpu; ++ /* coefficients */ ++ if (vp9_ctx->last.valid && ++ !(vp9_ctx->last.flags & V4L2_VP9_FRAME_FLAG_KEY_FRAME)) ++ adapt_coef_probs(probs, sym_cnts->ref_cnt, 112); ++ else ++ adapt_coef_probs(probs, sym_cnts->ref_cnt, 128); ++ ++ /* skip flag */ ++ adapt_skip_probs(probs, sym_cnts); ++ ++ /* intra/inter flag */ ++ adapt_is_inter_probs(probs, sym_cnts); ++ ++ /* comppred flag */ ++ adapt_comp_mode_probs(probs, sym_cnts); ++ ++ /* reference frames */ ++ adapt_comp_ref_probs(probs, sym_cnts); ++ ++ if (vp9_ctx->cur.reference_mode != V4L2_VP9_REF_MODE_COMPOUND) ++ adapt_single_ref_probs(probs, sym_cnts); ++ ++ /* block partitioning */ ++ adapt_partition_probs(probs, sym_cnts); ++ ++ /* tx size */ ++ if (vp9_ctx->cur.tx_mode == V4L2_VP9_TX_MODE_SELECT) ++ adapt_tx_probs(probs, sym_cnts); ++ ++ /* interpolation filter */ ++ if (vp9_ctx->cur.interpolation_filter == V4L2_VP9_INTERP_FILTER_SWITCHABLE) ++ adapt_interp_filter_probs(probs, sym_cnts); ++ ++ /* inter modes */ ++ adapt_inter_mode_probs(probs, sym_cnts); ++ ++ /* mv probs */ ++ adapt_mv_probs(probs, sym_cnts, ++ !!(vp9_ctx->cur.flags & ++ V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV)); ++ ++ /* y intra modes */ ++ adapt_y_intra_mode_probs(probs, sym_cnts); ++ ++ /* uv intra modes */ ++ adapt_uv_intra_mode_probs(probs, sym_cnts); ++} ++ ++static void adapt_probs(struct rkvdec_ctx *ctx) ++{ ++ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; ++ bool intra_only; ++ ++ intra_only = !!(vp9_ctx->cur.flags & ++ (V4L2_VP9_FRAME_FLAG_KEY_FRAME | ++ V4L2_VP9_FRAME_FLAG_INTRA_ONLY)); ++ ++ if (intra_only) ++ adapt_intra_frame_probs(ctx); ++ else ++ adapt_inter_frame_probs(ctx); ++} ++ ++static void rkvdec_vp9_done(struct rkvdec_ctx *ctx, ++ struct vb2_v4l2_buffer *src_buf, ++ struct vb2_v4l2_buffer *dst_buf, ++ enum vb2_buffer_state result) ++{ ++ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; ++ struct v4l2_ctrl *ctrl; ++ unsigned int fctx_idx; ++ ++ if (result == VB2_BUF_STATE_ERROR) ++ goto out_update_last; ++ ++ if (!(vp9_ctx->cur.flags & V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX)) ++ goto out_update_last; ++ ++ fctx_idx = vp9_ctx->cur.frame_context_idx; ++ ++ if (!(vp9_ctx->cur.flags & ++ (V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT | ++ V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE))) ++ adapt_probs(ctx); ++ ++ ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, ++ V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(fctx_idx)); ++ if (WARN_ON(!ctrl)) ++ goto out_update_last; ++ ++ v4l2_ctrl_s_ctrl_compound(ctrl, V4L2_CTRL_TYPE_VP9_FRAME_CONTEXT, ++ &vp9_ctx->frame_context); ++ ++out_update_last: ++ update_ctx_last_info(vp9_ctx); ++} ++ ++static int rkvdec_vp9_start(struct rkvdec_ctx *ctx) ++{ ++ struct rkvdec_dev *rkvdec = ctx->dev; ++ struct rkvdec_vp9_priv_tbl *priv_tbl; ++ struct rkvdec_vp9_ctx *vp9_ctx; ++ u8 *count_tbl; ++ int ret; ++ ++ vp9_ctx = kzalloc(sizeof(*vp9_ctx), GFP_KERNEL); ++ if (!vp9_ctx) ++ return -ENOMEM; ++ ++ ctx->priv = vp9_ctx; ++ ++ priv_tbl = dma_alloc_coherent(rkvdec->dev, sizeof(*priv_tbl), ++ &vp9_ctx->priv_tbl.dma, GFP_KERNEL); ++ if (!priv_tbl) { ++ ret = -ENOMEM; ++ goto err_free_ctx; ++ } ++ ++ vp9_ctx->priv_tbl.size = sizeof(*priv_tbl); ++ vp9_ctx->priv_tbl.cpu = priv_tbl; ++ memset(priv_tbl, 0, sizeof(*priv_tbl)); ++ ++ count_tbl = dma_alloc_coherent(rkvdec->dev, RKVDEC_VP9_COUNT_SIZE, ++ &vp9_ctx->count_tbl.dma, GFP_KERNEL); ++ if (!count_tbl) { ++ ret = -ENOMEM; ++ goto err_free_priv_tbl; ++ } ++ ++ vp9_ctx->count_tbl.size = RKVDEC_VP9_COUNT_SIZE; ++ vp9_ctx->count_tbl.cpu = count_tbl; ++ memset(count_tbl, 0, sizeof(*count_tbl)); ++ ++ return 0; ++ ++err_free_priv_tbl: ++ dma_free_coherent(rkvdec->dev, vp9_ctx->priv_tbl.size, ++ vp9_ctx->priv_tbl.cpu, vp9_ctx->priv_tbl.dma); ++ ++err_free_ctx: ++ kfree(vp9_ctx); ++ return ret; ++} ++ ++static void rkvdec_vp9_stop(struct rkvdec_ctx *ctx) ++{ ++ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; ++ struct rkvdec_dev *rkvdec = ctx->dev; ++ ++ dma_free_coherent(rkvdec->dev, vp9_ctx->count_tbl.size, ++ vp9_ctx->count_tbl.cpu, vp9_ctx->count_tbl.dma); ++ dma_free_coherent(rkvdec->dev, vp9_ctx->priv_tbl.size, ++ vp9_ctx->priv_tbl.cpu, vp9_ctx->priv_tbl.dma); ++ kfree(vp9_ctx); ++} ++ ++static int rkvdec_vp9_adjust_fmt(struct rkvdec_ctx *ctx, ++ struct v4l2_format *f) ++{ ++ struct v4l2_pix_format_mplane *fmt = &f->fmt.pix_mp; ++ ++ fmt->num_planes = 1; ++ if (!fmt->plane_fmt[0].sizeimage) ++ fmt->plane_fmt[0].sizeimage = fmt->width * fmt->height * 2; ++ return 0; ++} ++ ++const struct rkvdec_coded_fmt_ops rkvdec_vp9_fmt_ops = { ++ .adjust_fmt = rkvdec_vp9_adjust_fmt, ++ .start = rkvdec_vp9_start, ++ .stop = rkvdec_vp9_stop, ++ .run = rkvdec_vp9_run, ++ .done = rkvdec_vp9_done, ++}; +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index 91f8a1bb6176..f0f28f6a68cf 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -159,6 +159,45 @@ static const u32 rkvdec_h264_decoded_fmts[] = { + V4L2_PIX_FMT_NV20, + }; + ++static const struct rkvdec_ctrl_desc rkvdec_vp9_ctrl_descs[] = { ++ { ++ .per_request = true, ++ .mandatory = true, ++ .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_DECODE_PARAMS, ++ }, ++ { ++ .mandatory = true, ++ .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(0), ++ }, ++ { ++ .mandatory = true, ++ .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(1), ++ }, ++ { ++ .mandatory = true, ++ .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(2), ++ }, ++ { ++ .mandatory = true, ++ .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(3), ++ }, ++ { ++ .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_PROFILE, ++ .cfg.min = V4L2_MPEG_VIDEO_VP9_PROFILE_0, ++ .cfg.max = V4L2_MPEG_VIDEO_VP9_PROFILE_0, ++ .cfg.def = V4L2_MPEG_VIDEO_VP9_PROFILE_0, ++ }, ++}; ++ ++static const struct rkvdec_ctrls rkvdec_vp9_ctrls = { ++ .ctrls = rkvdec_vp9_ctrl_descs, ++ .num_ctrls = ARRAY_SIZE(rkvdec_vp9_ctrl_descs), ++}; ++ ++static const u32 rkvdec_vp9_decoded_fmts[] = { ++ V4L2_PIX_FMT_NV12, ++}; ++ + static const struct rkvdec_coded_fmt_desc rkvdec_coded_fmts[] = { + { + .fourcc = V4L2_PIX_FMT_H264_SLICE, +@@ -174,6 +213,21 @@ static const struct rkvdec_coded_fmt_desc rkvdec_coded_fmts[] = { + .ops = &rkvdec_h264_fmt_ops, + .num_decoded_fmts = ARRAY_SIZE(rkvdec_h264_decoded_fmts), + .decoded_fmts = rkvdec_h264_decoded_fmts, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_VP9_FRAME, ++ .frmsize = { ++ .min_width = 64, ++ .max_width = 4096, ++ .step_width = 64, ++ .min_height = 64, ++ .max_height = 2304, ++ .step_height = 64, ++ }, ++ .ctrls = &rkvdec_vp9_ctrls, ++ .ops = &rkvdec_vp9_fmt_ops, ++ .num_decoded_fmts = ARRAY_SIZE(rkvdec_vp9_decoded_fmts), ++ .decoded_fmts = rkvdec_vp9_decoded_fmts, + } + }; + +diff --git a/drivers/staging/media/rkvdec/rkvdec.h b/drivers/staging/media/rkvdec/rkvdec.h +index e95c52e3168a..5f66f07acac5 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.h ++++ b/drivers/staging/media/rkvdec/rkvdec.h +@@ -51,6 +51,10 @@ struct rkvdec_vp9_decoded_buffer_info { + struct rkvdec_decoded_buffer { + /* Must be the first field in this struct. */ + struct v4l2_m2m_buffer base; ++ ++ union { ++ struct rkvdec_vp9_decoded_buffer_info vp9; ++ }; + }; + + static inline struct rkvdec_decoded_buffer * +@@ -119,4 +123,6 @@ void rkvdec_run_preamble(struct rkvdec_ctx *ctx, struct rkvdec_run *run); + void rkvdec_run_postamble(struct rkvdec_ctx *ctx, struct rkvdec_run *run); + + extern const struct rkvdec_coded_fmt_ops rkvdec_h264_fmt_ops; ++extern const struct rkvdec_coded_fmt_ops rkvdec_vp9_fmt_ops; ++ + #endif /* RKVDEC_H_ */ diff --git a/patch/kernel/rk322x-current/01-linux-0013-v4l2-from-list.patch.disabled b/patch/kernel/rk322x-current/01-linux-0013-v4l2-from-list.patch.disabled deleted file mode 100644 index 44e7d191f..000000000 --- a/patch/kernel/rk322x-current/01-linux-0013-v4l2-from-list.patch.disabled +++ /dev/null @@ -1,319 +0,0 @@ -diff --git a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst -index 28313c0f4e7c..d472a54d1c4d 100644 ---- a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst -+++ b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst -@@ -2028,6 +2028,18 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - - * - ``V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM`` - - 0x00000004 - - The DPB entry is a long term reference frame -+ * - ``V4L2_H264_DPB_ENTRY_FLAG_FIELD_PICTURE`` -+ - 0x00000008 -+ - The DPB entry is a field picture -+ * - ``V4L2_H264_DPB_ENTRY_FLAG_REF_TOP`` -+ - 0x00000010 -+ - The DPB entry is a top field reference -+ * - ``V4L2_H264_DPB_ENTRY_FLAG_REF_BOTTOM`` -+ - 0x00000020 -+ - The DPB entry is a bottom field reference -+ * - ``V4L2_H264_DPB_ENTRY_FLAG_REF_FRAME`` -+ - 0x00000030 -+ - The DPB entry is a reference frame - - ``V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE (enum)`` - Specifies the decoding mode to use. Currently exposes slice-based and -diff --git a/include/media/h264-ctrls.h b/include/media/h264-ctrls.h -index e877bf1d537c..76020ebd1e6c 100644 ---- a/include/media/h264-ctrls.h -+++ b/include/media/h264-ctrls.h -@@ -185,6 +185,10 @@ struct v4l2_ctrl_h264_slice_params { - #define V4L2_H264_DPB_ENTRY_FLAG_VALID 0x01 - #define V4L2_H264_DPB_ENTRY_FLAG_ACTIVE 0x02 - #define V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM 0x04 -+#define V4L2_H264_DPB_ENTRY_FLAG_FIELD_PICTURE 0x08 -+#define V4L2_H264_DPB_ENTRY_FLAG_REF_TOP 0x10 -+#define V4L2_H264_DPB_ENTRY_FLAG_REF_BOTTOM 0x20 -+#define V4L2_H264_DPB_ENTRY_FLAG_REF_FRAME 0x30 - - struct v4l2_h264_dpb_entry { - __u64 reference_ts; --- -2.17.1 - - -From ef240de60cedea0264ca954a8e8e2fa25db097ae Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Tue, 29 Oct 2019 01:26:02 +0000 -Subject: [PATCH] RFC: media: hantro: Fix H264 decoding of field encoded - content - -This still need code cleanup and formatting - -Signed-off-by: Jonas Karlman ---- - .../staging/media/hantro/hantro_g1_h264_dec.c | 17 +-- - drivers/staging/media/hantro/hantro_h264.c | 122 ++++++++++++------ - drivers/staging/media/hantro/hantro_hw.h | 2 + - 3 files changed, 85 insertions(+), 56 deletions(-) - -diff --git a/drivers/staging/media/hantro/hantro_g1_h264_dec.c b/drivers/staging/media/hantro/hantro_g1_h264_dec.c -index 424c648ce9fc..89cf5741280e 100644 ---- a/drivers/staging/media/hantro/hantro_g1_h264_dec.c -+++ b/drivers/staging/media/hantro/hantro_g1_h264_dec.c -@@ -132,25 +132,12 @@ static void set_ref(struct hantro_ctx *ctx) - struct v4l2_h264_dpb_entry *dpb = ctx->h264_dec.dpb; - const u8 *b0_reflist, *b1_reflist, *p_reflist; - struct hantro_dev *vpu = ctx->dev; -- u32 dpb_longterm = 0; -- u32 dpb_valid = 0; - int reg_num; - u32 reg; - int i; - -- /* -- * Set up bit maps of valid and long term DPBs. -- * NOTE: The bits are reversed, i.e. MSb is DPB 0. -- */ -- for (i = 0; i < HANTRO_H264_DPB_SIZE; ++i) { -- if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE) -- dpb_valid |= BIT(HANTRO_H264_DPB_SIZE - 1 - i); -- -- if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM) -- dpb_longterm |= BIT(HANTRO_H264_DPB_SIZE - 1 - i); -- } -- vdpu_write_relaxed(vpu, dpb_valid << 16, G1_REG_VALID_REF); -- vdpu_write_relaxed(vpu, dpb_longterm << 16, G1_REG_LT_REF); -+ vdpu_write_relaxed(vpu, ctx->h264_dec.dpb_valid, G1_REG_VALID_REF); -+ vdpu_write_relaxed(vpu, ctx->h264_dec.dpb_longterm, G1_REG_LT_REF); - - /* - * Set up reference frame picture numbers. -diff --git a/drivers/staging/media/hantro/hantro_h264.c b/drivers/staging/media/hantro/hantro_h264.c -index f2d3e81fb6ce..4db779354e89 100644 ---- a/drivers/staging/media/hantro/hantro_h264.c -+++ b/drivers/staging/media/hantro/hantro_h264.c -@@ -225,17 +225,65 @@ static void prepare_table(struct hantro_ctx *ctx) - { - const struct hantro_h264_dec_ctrls *ctrls = &ctx->h264_dec.ctrls; - const struct v4l2_ctrl_h264_decode_params *dec_param = ctrls->decode; -+ const struct v4l2_ctrl_h264_slice_params *slices = ctrls->slices; - struct hantro_h264_dec_priv_tbl *tbl = ctx->h264_dec.priv.cpu; - const struct v4l2_h264_dpb_entry *dpb = ctx->h264_dec.dpb; -+ u32 dpb_longterm = 0; -+ u32 dpb_valid = 0; - int i; - -+ /* -+ * Set up bit maps of valid and long term DPBs. -+ * NOTE: The bits are reversed, i.e. MSb is DPB 0. -+ */ -+ if ((slices[0].flags & V4L2_H264_SLICE_FLAG_FIELD_PIC) || (slices[0].flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD)) { -+ for (i = 0; i < HANTRO_H264_DPB_SIZE * 2; ++i) { -+ // check for correct reference use -+ u32 flag = (i & 0x1) ? V4L2_H264_DPB_ENTRY_FLAG_REF_BOTTOM : V4L2_H264_DPB_ENTRY_FLAG_REF_TOP; -+ if (dpb[i / 2].flags & flag) -+ dpb_valid |= BIT(HANTRO_H264_DPB_SIZE * 2 - 1 - i); -+ -+ if (dpb[i / 2].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM) -+ dpb_longterm |= BIT(HANTRO_H264_DPB_SIZE * 2 - 1 - i); -+ } -+ -+ ctx->h264_dec.dpb_valid = dpb_valid; -+ ctx->h264_dec.dpb_longterm = dpb_longterm; -+ } else { -+ for (i = 0; i < HANTRO_H264_DPB_SIZE; ++i) { -+ if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE) -+ dpb_valid |= BIT(HANTRO_H264_DPB_SIZE - 1 - i); -+ -+ if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM) -+ dpb_longterm |= BIT(HANTRO_H264_DPB_SIZE - 1 - i); -+ } -+ -+ ctx->h264_dec.dpb_valid = dpb_valid << 16; -+ ctx->h264_dec.dpb_longterm = dpb_longterm << 16; -+ } -+ - for (i = 0; i < HANTRO_H264_DPB_SIZE; ++i) { -- tbl->poc[i * 2] = dpb[i].top_field_order_cnt; -- tbl->poc[i * 2 + 1] = dpb[i].bottom_field_order_cnt; -+ if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE) { -+ tbl->poc[i * 2] = dpb[i].top_field_order_cnt; -+ tbl->poc[i * 2 + 1] = dpb[i].bottom_field_order_cnt; -+ } else { -+ tbl->poc[i * 2] = 0; -+ tbl->poc[i * 2 + 1] = 0; -+ } - } - -- tbl->poc[32] = dec_param->top_field_order_cnt; -- tbl->poc[33] = dec_param->bottom_field_order_cnt; -+ if ((slices[0].flags & V4L2_H264_SLICE_FLAG_FIELD_PIC) || !(slices[0].flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD)) { -+ if ((slices[0].flags & V4L2_H264_SLICE_FLAG_FIELD_PIC)) -+ tbl->poc[32] = (slices[0].flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD) ? -+ dec_param->bottom_field_order_cnt : -+ dec_param->top_field_order_cnt; -+ else -+ tbl->poc[32] = min(dec_param->top_field_order_cnt, dec_param->bottom_field_order_cnt); -+ tbl->poc[33] = 0; -+ } else { -+ tbl->poc[32] = dec_param->top_field_order_cnt; -+ tbl->poc[33] = dec_param->bottom_field_order_cnt; -+ } - - reorder_scaling_list(ctx); - } -@@ -249,21 +297,6 @@ struct hantro_h264_reflist_builder { - u8 num_valid; - }; - --static s32 get_poc(enum v4l2_field field, s32 top_field_order_cnt, -- s32 bottom_field_order_cnt) --{ -- switch (field) { -- case V4L2_FIELD_TOP: -- return top_field_order_cnt; -- case V4L2_FIELD_BOTTOM: -- return bottom_field_order_cnt; -- default: -- break; -- } -- -- return min(top_field_order_cnt, bottom_field_order_cnt); --} -- - static void - init_reflist_builder(struct hantro_ctx *ctx, - struct hantro_h264_reflist_builder *b) -@@ -271,9 +304,7 @@ init_reflist_builder(struct hantro_ctx *ctx, - const struct v4l2_ctrl_h264_slice_params *slice_params; - const struct v4l2_ctrl_h264_decode_params *dec_param; - const struct v4l2_ctrl_h264_sps *sps; -- struct vb2_v4l2_buffer *buf = hantro_get_dst_buf(ctx); - const struct v4l2_h264_dpb_entry *dpb = ctx->h264_dec.dpb; -- struct vb2_queue *cap_q = &ctx->fh.m2m_ctx->cap_q_ctx.q; - int cur_frame_num, max_frame_num; - unsigned int i; - -@@ -285,21 +316,15 @@ init_reflist_builder(struct hantro_ctx *ctx, - - memset(b, 0, sizeof(*b)); - b->dpb = dpb; -- b->curpoc = get_poc(buf->field, dec_param->top_field_order_cnt, -- dec_param->bottom_field_order_cnt); -+ b->curpoc = (slice_params->flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD) ? -+ dec_param->bottom_field_order_cnt : -+ dec_param->top_field_order_cnt; - - for (i = 0; i < ARRAY_SIZE(ctx->h264_dec.dpb); i++) { -- int buf_idx; -- -- if (!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)) -+ u32 ref_flag = dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_REF_FRAME; -+ if (!ref_flag) - continue; - -- buf_idx = vb2_find_timestamp(cap_q, dpb[i].reference_ts, 0); -- if (buf_idx < 0) -- continue; -- -- buf = to_vb2_v4l2_buffer(vb2_get_buffer(cap_q, buf_idx)); -- - /* - * Handle frame_num wraparound as described in section - * '8.2.4.1 Decoding process for picture numbers' of the spec. -@@ -311,8 +336,13 @@ init_reflist_builder(struct hantro_ctx *ctx, - else - b->frame_nums[i] = dpb[i].frame_num; - -- b->pocs[i] = get_poc(buf->field, dpb[i].top_field_order_cnt, -- dpb[i].bottom_field_order_cnt); -+ if (ref_flag == V4L2_H264_DPB_ENTRY_FLAG_REF_FRAME) -+ b->pocs[i] = min(dpb[i].bottom_field_order_cnt, dpb[i].top_field_order_cnt); -+ else if (ref_flag == V4L2_H264_DPB_ENTRY_FLAG_REF_BOTTOM) -+ b->pocs[i] = dpb[i].bottom_field_order_cnt; -+ else if (ref_flag == V4L2_H264_DPB_ENTRY_FLAG_REF_TOP) -+ b->pocs[i] = dpb[i].top_field_order_cnt; -+ - b->unordered_reflist[b->num_valid] = i; - b->num_valid++; - } -@@ -466,8 +496,7 @@ build_b_ref_lists(const struct hantro_h264_reflist_builder *builder, - static bool dpb_entry_match(const struct v4l2_h264_dpb_entry *a, - const struct v4l2_h264_dpb_entry *b) - { -- return a->top_field_order_cnt == b->top_field_order_cnt && -- a->bottom_field_order_cnt == b->bottom_field_order_cnt; -+ return a->reference_ts == b->reference_ts; - } - - static void update_dpb(struct hantro_ctx *ctx) -@@ -481,13 +510,13 @@ static void update_dpb(struct hantro_ctx *ctx) - - /* Disable all entries by default. */ - for (i = 0; i < ARRAY_SIZE(ctx->h264_dec.dpb); i++) -- ctx->h264_dec.dpb[i].flags &= ~V4L2_H264_DPB_ENTRY_FLAG_ACTIVE; -+ ctx->h264_dec.dpb[i].flags = 0; - - /* Try to match new DPB entries with existing ones by their POCs. */ - for (i = 0; i < ARRAY_SIZE(dec_param->dpb); i++) { - const struct v4l2_h264_dpb_entry *ndpb = &dec_param->dpb[i]; - -- if (!(ndpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)) -+ if (!(ndpb->flags & V4L2_H264_DPB_ENTRY_FLAG_VALID)) - continue; - - /* -@@ -498,8 +527,7 @@ static void update_dpb(struct hantro_ctx *ctx) - struct v4l2_h264_dpb_entry *cdpb; - - cdpb = &ctx->h264_dec.dpb[j]; -- if (cdpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE || -- !dpb_entry_match(cdpb, ndpb)) -+ if (!dpb_entry_match(cdpb, ndpb)) - continue; - - *cdpb = *ndpb; -@@ -535,7 +563,11 @@ dma_addr_t hantro_h264_get_ref_buf(struct hantro_ctx *ctx, - unsigned int dpb_idx) - { - struct v4l2_h264_dpb_entry *dpb = ctx->h264_dec.dpb; -+ const struct v4l2_ctrl_h264_decode_params *dec_param = ctx->h264_dec.ctrls.decode; -+ const struct v4l2_ctrl_h264_slice_params *slices = ctx->h264_dec.ctrls.slices; - dma_addr_t dma_addr = 0; -+ s32 cur_poc; -+ u32 flags; - - if (dpb[dpb_idx].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE) - dma_addr = hantro_get_ref(ctx, dpb[dpb_idx].reference_ts); -@@ -553,7 +585,15 @@ dma_addr_t hantro_h264_get_ref_buf(struct hantro_ctx *ctx, - dma_addr = vb2_dma_contig_plane_dma_addr(buf, 0); - } - -- return dma_addr; -+ cur_poc = slices[0].flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD ? -+ dec_param->bottom_field_order_cnt : -+ dec_param->top_field_order_cnt; -+ flags = dpb[dpb_idx].flags & V4L2_H264_DPB_ENTRY_FLAG_FIELD_PICTURE ? 0x2 : 0; -+ flags |= abs(dpb[dpb_idx].top_field_order_cnt - cur_poc) < -+ abs(dpb[dpb_idx].bottom_field_order_cnt - cur_poc) ? -+ 0x1 : 0; -+ -+ return dma_addr | flags; - } - - int hantro_h264_dec_prepare_run(struct hantro_ctx *ctx) -diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h -index 2398d4c1f207..3dc7b8f27c32 100644 ---- a/drivers/staging/media/hantro/hantro_hw.h -+++ b/drivers/staging/media/hantro/hantro_hw.h -@@ -88,6 +88,8 @@ struct hantro_h264_dec_hw_ctx { - struct v4l2_h264_dpb_entry dpb[HANTRO_H264_DPB_SIZE]; - struct hantro_h264_dec_reflists reflists; - struct hantro_h264_dec_ctrls ctrls; -+ u32 dpb_longterm; -+ u32 dpb_valid; - }; - - /** --- -2.17.1 - diff --git a/patch/kernel/rk322x-current/01-linux-0014-v4l2-work-in-progress.patch.disabled b/patch/kernel/rk322x-current/01-linux-0014-v4l2-work-in-progress.patch.disabled deleted file mode 100644 index c032a8414..000000000 --- a/patch/kernel/rk322x-current/01-linux-0014-v4l2-work-in-progress.patch.disabled +++ /dev/null @@ -1,1525 +0,0 @@ -diff --git a/drivers/staging/media/hantro/rk3399_vpu_hw_mpeg2_dec.c b/drivers/staging/media/hantro/rk3399_vpu_hw_mpeg2_dec.c -index 7e9aad671489..b9b8194b42f2 100644 ---- a/drivers/staging/media/hantro/rk3399_vpu_hw_mpeg2_dec.c -+++ b/drivers/staging/media/hantro/rk3399_vpu_hw_mpeg2_dec.c -@@ -127,7 +127,7 @@ rk3399_vpu_mpeg2_dec_set_buffers(struct hantro_dev *vpu, - current_addr = addr; - - if (picture->picture_structure == PICT_BOTTOM_FIELD) -- addr += ALIGN(ctx->dst_fmt.width, 16); -+ addr += ALIGN(ctx->src_fmt.width, MB_DIM); - vdpu_write_relaxed(vpu, addr, VDPU_REG_DEC_OUT_BASE); - - if (!forward_addr) -@@ -220,8 +220,8 @@ void rk3399_vpu_mpeg2_dec_run(struct hantro_ctx *ctx) - VDPU_REG_DEC_CLK_GATE_E(1); - vdpu_write_relaxed(vpu, reg, VDPU_SWREG(57)); - -- reg = VDPU_REG_PIC_MB_WIDTH(MB_WIDTH(ctx->dst_fmt.width)) | -- VDPU_REG_PIC_MB_HEIGHT_P(MB_HEIGHT(ctx->dst_fmt.height)) | -+ reg = VDPU_REG_PIC_MB_WIDTH(MB_WIDTH(ctx->src_fmt.width)) | -+ VDPU_REG_PIC_MB_HEIGHT_P(MB_HEIGHT(ctx->src_fmt.height)) | - VDPU_REG_ALT_SCAN_E(picture->alternate_scan) | - VDPU_REG_TOPFIELDFIRST_E(picture->top_field_first); - vdpu_write_relaxed(vpu, reg, VDPU_SWREG(120)); --- -2.17.1 - - -From 3b87f8547b97f13afb8db289cc9974760e668b79 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Tue, 5 Nov 2019 23:06:34 +0000 -Subject: [PATCH] WIP: media: hantro: g1 mpeg2 src_fmt - -Fixes: ceaac6dc5b7a -Signed-off-by: Jonas Karlman ---- - drivers/staging/media/hantro/hantro_g1_mpeg2_dec.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/drivers/staging/media/hantro/hantro_g1_mpeg2_dec.c b/drivers/staging/media/hantro/hantro_g1_mpeg2_dec.c -index 24041849384a..44f7326aba32 100644 ---- a/drivers/staging/media/hantro/hantro_g1_mpeg2_dec.c -+++ b/drivers/staging/media/hantro/hantro_g1_mpeg2_dec.c -@@ -125,7 +125,7 @@ hantro_g1_mpeg2_dec_set_buffers(struct hantro_dev *vpu, struct hantro_ctx *ctx, - current_addr = addr; - - if (picture->picture_structure == PICT_BOTTOM_FIELD) -- addr += ALIGN(ctx->dst_fmt.width, 16); -+ addr += ALIGN(ctx->src_fmt.width, MB_DIM); - vdpu_write_relaxed(vpu, addr, G1_REG_DEC_OUT_BASE); - - if (!forward_addr) -@@ -204,8 +204,8 @@ void hantro_g1_mpeg2_dec_run(struct hantro_ctx *ctx) - G1_REG_DEC_AXI_WR_ID(0); - vdpu_write_relaxed(vpu, reg, G1_SWREG(3)); - -- reg = G1_REG_PIC_MB_WIDTH(MB_WIDTH(ctx->dst_fmt.width)) | -- G1_REG_PIC_MB_HEIGHT_P(MB_HEIGHT(ctx->dst_fmt.height)) | -+ reg = G1_REG_PIC_MB_WIDTH(MB_WIDTH(ctx->src_fmt.width)) | -+ G1_REG_PIC_MB_HEIGHT_P(MB_HEIGHT(ctx->src_fmt.height)) | - G1_REG_ALT_SCAN_E(picture->alternate_scan) | - G1_REG_TOPFIELDFIRST_E(picture->top_field_first); - vdpu_write_relaxed(vpu, reg, G1_SWREG(4)); --- -2.17.1 - - -From 10bf68403975d4fe3b383c7882d6a7d8a8bca64b Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Tue, 5 Nov 2019 23:09:18 +0000 -Subject: [PATCH] WIP: media: hantro: vp8 src_fmt - -Signed-off-by: Jonas Karlman ---- - drivers/staging/media/hantro/hantro_g1_vp8_dec.c | 4 ++-- - drivers/staging/media/hantro/hantro_vp8.c | 4 ++-- - drivers/staging/media/hantro/rk3399_vpu_hw_vp8_dec.c | 4 ++-- - 3 files changed, 6 insertions(+), 6 deletions(-) - -diff --git a/drivers/staging/media/hantro/hantro_g1_vp8_dec.c b/drivers/staging/media/hantro/hantro_g1_vp8_dec.c -index a5cdf150cd16..e36538117fbf 100644 ---- a/drivers/staging/media/hantro/hantro_g1_vp8_dec.c -+++ b/drivers/staging/media/hantro/hantro_g1_vp8_dec.c -@@ -430,8 +430,8 @@ void hantro_g1_vp8_dec_run(struct hantro_ctx *ctx) - { - const struct v4l2_ctrl_vp8_frame_header *hdr; - struct hantro_dev *vpu = ctx->dev; -- size_t height = ctx->dst_fmt.height; -- size_t width = ctx->dst_fmt.width; -+ size_t height = ctx->src_fmt.height; -+ size_t width = ctx->src_fmt.width; - u32 mb_width, mb_height; - u32 reg; - -diff --git a/drivers/staging/media/hantro/hantro_vp8.c b/drivers/staging/media/hantro/hantro_vp8.c -index 0e02d147b189..e010c9088fde 100644 ---- a/drivers/staging/media/hantro/hantro_vp8.c -+++ b/drivers/staging/media/hantro/hantro_vp8.c -@@ -151,8 +151,8 @@ int hantro_vp8_dec_init(struct hantro_ctx *ctx) - int ret; - - /* segment map table size calculation */ -- mb_width = DIV_ROUND_UP(ctx->dst_fmt.width, 16); -- mb_height = DIV_ROUND_UP(ctx->dst_fmt.height, 16); -+ mb_width = MB_WIDTH(ctx->src_fmt.width); -+ mb_height = MB_HEIGHT(ctx->src_fmt.height); - segment_map_size = round_up(DIV_ROUND_UP(mb_width * mb_height, 4), 64); - - /* -diff --git a/drivers/staging/media/hantro/rk3399_vpu_hw_vp8_dec.c b/drivers/staging/media/hantro/rk3399_vpu_hw_vp8_dec.c -index a4a792f00b11..2f553e740294 100644 ---- a/drivers/staging/media/hantro/rk3399_vpu_hw_vp8_dec.c -+++ b/drivers/staging/media/hantro/rk3399_vpu_hw_vp8_dec.c -@@ -508,8 +508,8 @@ void rk3399_vpu_vp8_dec_run(struct hantro_ctx *ctx) - { - const struct v4l2_ctrl_vp8_frame_header *hdr; - struct hantro_dev *vpu = ctx->dev; -- size_t height = ctx->dst_fmt.height; -- size_t width = ctx->dst_fmt.width; -+ size_t height = ctx->src_fmt.height; -+ size_t width = ctx->src_fmt.width; - u32 mb_width, mb_height; - u32 reg; - --- -2.17.1 - - -From 4f7561c70db7347ade627ee0aacfb45c35022195 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 18 Aug 2019 10:40:31 +0000 -Subject: [PATCH] media: hantro: Refactor G1 H264 code - -Use generated code from my rockchip-vpu-regtool - -Code could possible need some cleanup - -Signed-off-by: Jonas Karlman ---- - .../staging/media/hantro/hantro_g1_h264_dec.c | 653 +++++++++++------- - drivers/staging/media/hantro/hantro_h264.c | 14 + - drivers/staging/media/hantro/hantro_hw.h | 2 + - 3 files changed, 435 insertions(+), 234 deletions(-) - -diff --git a/drivers/staging/media/hantro/hantro_g1_h264_dec.c b/drivers/staging/media/hantro/hantro_g1_h264_dec.c -index 89cf5741280e..20999b005307 100644 ---- a/drivers/staging/media/hantro/hantro_g1_h264_dec.c -+++ b/drivers/staging/media/hantro/hantro_g1_h264_dec.c -@@ -1,6 +1,6 @@ - // SPDX-License-Identifier: GPL-2.0 - /* -- * Rockchip RK3288 VPU codec driver -+ * Hantro VPU codec driver - * - * Copyright (c) 2014 Rockchip Electronics Co., Ltd. - * Hertz Wong -@@ -15,235 +15,430 @@ - - #include - --#include "hantro_g1_regs.h" - #include "hantro_hw.h" - #include "hantro_v4l2.h" - --static void set_params(struct hantro_ctx *ctx) -+#define G1_SWREG(nr) ((nr) * 4) -+ -+#define G1_REG_RLC_VLC_BASE G1_SWREG(12) -+#define G1_REG_DEC_OUT_BASE G1_SWREG(13) -+#define G1_REG_REFER0_BASE G1_SWREG(14) -+#define G1_REG_REFER1_BASE G1_SWREG(15) -+#define G1_REG_REFER2_BASE G1_SWREG(16) -+#define G1_REG_REFER3_BASE G1_SWREG(17) -+#define G1_REG_REFER4_BASE G1_SWREG(18) -+#define G1_REG_REFER5_BASE G1_SWREG(19) -+#define G1_REG_REFER6_BASE G1_SWREG(20) -+#define G1_REG_REFER7_BASE G1_SWREG(21) -+#define G1_REG_REFER8_BASE G1_SWREG(22) -+#define G1_REG_REFER9_BASE G1_SWREG(23) -+#define G1_REG_REFER10_BASE G1_SWREG(24) -+#define G1_REG_REFER11_BASE G1_SWREG(25) -+#define G1_REG_REFER12_BASE G1_SWREG(26) -+#define G1_REG_REFER13_BASE G1_SWREG(27) -+#define G1_REG_REFER14_BASE G1_SWREG(28) -+#define G1_REG_REFER15_BASE G1_SWREG(29) -+#define G1_REG_QTABLE_BASE G1_SWREG(40) -+#define G1_REG_DIR_MV_BASE G1_SWREG(41) -+#define G1_REG_DEC_E(v) ((v) ? BIT(0) : 0) -+ -+#define G1_REG_DEC_AXI_RD_ID(v) (((v) << 24) & GENMASK(31, 24)) -+#define G1_REG_DEC_TIMEOUT_E(v) ((v) ? BIT(23) : 0) -+#define G1_REG_DEC_STRSWAP32_E(v) ((v) ? BIT(22) : 0) -+#define G1_REG_DEC_STRENDIAN_E(v) ((v) ? BIT(21) : 0) -+#define G1_REG_DEC_INSWAP32_E(v) ((v) ? BIT(20) : 0) -+#define G1_REG_DEC_OUTSWAP32_E(v) ((v) ? BIT(19) : 0) -+#define G1_REG_DEC_DATA_DISC_E(v) ((v) ? BIT(18) : 0) -+#define G1_REG_DEC_LATENCY(v) (((v) << 11) & GENMASK(16, 11)) -+#define G1_REG_DEC_CLK_GATE_E(v) ((v) ? BIT(10) : 0) -+#define G1_REG_DEC_IN_ENDIAN(v) ((v) ? BIT(9) : 0) -+#define G1_REG_DEC_OUT_ENDIAN(v) ((v) ? BIT(8) : 0) -+#define G1_REG_DEC_ADV_PRE_DIS(v) ((v) ? BIT(6) : 0) -+#define G1_REG_DEC_SCMD_DIS(v) ((v) ? BIT(5) : 0) -+#define G1_REG_DEC_MAX_BURST(v) (((v) << 0) & GENMASK(4, 0)) -+ -+#define G1_REG_DEC_MODE(v) (((v) << 28) & GENMASK(31, 28)) -+#define G1_REG_RLC_MODE_E(v) ((v) ? BIT(27) : 0) -+#define G1_REG_PIC_INTERLACE_E(v) ((v) ? BIT(23) : 0) -+#define G1_REG_PIC_FIELDMODE_E(v) ((v) ? BIT(22) : 0) -+#define G1_REG_PIC_TOPFIELD_E(v) ((v) ? BIT(19) : 0) -+#define G1_REG_FILTERING_DIS(v) ((v) ? BIT(14) : 0) -+#define G1_REG_PIC_FIXED_QUANT(v) ((v) ? BIT(13) : 0) -+#define G1_REG_WRITE_MVS_E(v) ((v) ? BIT(12) : 0) -+#define G1_REG_SEQ_MBAFF_E(v) ((v) ? BIT(10) : 0) -+#define G1_REG_PICORD_COUNT_E(v) ((v) ? BIT(9) : 0) -+#define G1_REG_DEC_AXI_WR_ID(v) (((v) << 0) & GENMASK(7, 0)) -+ -+#define G1_REG_PIC_MB_WIDTH(v) (((v) << 23) & GENMASK(31, 23)) -+#define G1_REG_PIC_MB_HEIGHT_P(v) (((v) << 11) & GENMASK(18, 11)) -+#define G1_REG_REF_FRAMES(v) (((v) << 0) & GENMASK(4, 0)) -+ -+#define G1_REG_STRM_START_BIT(v) (((v) << 26) & GENMASK(31, 26)) -+#define G1_REG_TYPE1_QUANT_E(v) ((v) ? BIT(24) : 0) -+#define G1_REG_CH_QP_OFFSET(v) (((v) << 19) & GENMASK(23, 19)) -+#define G1_REG_CH_QP_OFFSET2(v) (((v) << 14) & GENMASK(18, 14)) -+#define G1_REG_FIELDPIC_FLAG_E(v) ((v) ? BIT(0) : 0) -+ -+#define G1_REG_START_CODE_E(v) ((v) ? BIT(31) : 0) -+#define G1_REG_INIT_QP(v) (((v) << 25) & GENMASK(30, 25)) -+#define G1_REG_CH_8PIX_ILEAV_E(v) ((v) ? BIT(24) : 0) -+#define G1_REG_STREAM_LEN(v) (((v) << 0) & GENMASK(23, 0)) -+ -+#define G1_REG_CABAC_E(v) ((v) ? BIT(31) : 0) -+#define G1_REG_BLACKWHITE_E(v) ((v) ? BIT(30) : 0) -+#define G1_REG_DIR_8X8_INFER_E(v) ((v) ? BIT(29) : 0) -+#define G1_REG_WEIGHT_PRED_E(v) ((v) ? BIT(28) : 0) -+#define G1_REG_WEIGHT_BIPR_IDC(v) (((v) << 26) & GENMASK(27, 26)) -+#define G1_REG_FRAMENUM_LEN(v) (((v) << 16) & GENMASK(20, 16)) -+#define G1_REG_FRAMENUM(v) (((v) << 0) & GENMASK(15, 0)) -+ -+#define G1_REG_CONST_INTRA_E(v) ((v) ? BIT(31) : 0) -+#define G1_REG_FILT_CTRL_PRES(v) ((v) ? BIT(30) : 0) -+#define G1_REG_RDPIC_CNT_PRES(v) ((v) ? BIT(29) : 0) -+#define G1_REG_8X8TRANS_FLAG_E(v) ((v) ? BIT(28) : 0) -+#define G1_REG_REFPIC_MK_LEN(v) (((v) << 17) & GENMASK(27, 17)) -+#define G1_REG_IDR_PIC_E(v) ((v) ? BIT(16) : 0) -+#define G1_REG_IDR_PIC_ID(v) (((v) << 0) & GENMASK(15, 0)) -+ -+#define G1_REG_PPS_ID(v) (((v) << 24) & GENMASK(31, 24)) -+#define G1_REG_REFIDX1_ACTIVE(v) (((v) << 19) & GENMASK(23, 19)) -+#define G1_REG_REFIDX0_ACTIVE(v) (((v) << 14) & GENMASK(18, 14)) -+#define G1_REG_POC_LENGTH(v) (((v) << 0) & GENMASK(7, 0)) -+ -+#define G1_REG_PINIT_RLIST_F9(v) (((v) << 25) & GENMASK(29, 25)) -+#define G1_REG_PINIT_RLIST_F8(v) (((v) << 20) & GENMASK(24, 20)) -+#define G1_REG_PINIT_RLIST_F7(v) (((v) << 15) & GENMASK(19, 15)) -+#define G1_REG_PINIT_RLIST_F6(v) (((v) << 10) & GENMASK(14, 10)) -+#define G1_REG_PINIT_RLIST_F5(v) (((v) << 5) & GENMASK(9, 5)) -+#define G1_REG_PINIT_RLIST_F4(v) (((v) << 0) & GENMASK(4, 0)) -+ -+#define G1_REG_PINIT_RLIST_F15(v) (((v) << 25) & GENMASK(29, 25)) -+#define G1_REG_PINIT_RLIST_F14(v) (((v) << 20) & GENMASK(24, 20)) -+#define G1_REG_PINIT_RLIST_F13(v) (((v) << 15) & GENMASK(19, 15)) -+#define G1_REG_PINIT_RLIST_F12(v) (((v) << 10) & GENMASK(14, 10)) -+#define G1_REG_PINIT_RLIST_F11(v) (((v) << 5) & GENMASK(9, 5)) -+#define G1_REG_PINIT_RLIST_F10(v) (((v) << 0) & GENMASK(4, 0)) -+ -+#define G1_REG_REFER1_NBR(v) (((v) << 16) & GENMASK(31, 16)) -+#define G1_REG_REFER0_NBR(v) (((v) << 0) & GENMASK(15, 0)) -+ -+#define G1_REG_REFER3_NBR(v) (((v) << 16) & GENMASK(31, 16)) -+#define G1_REG_REFER2_NBR(v) (((v) << 0) & GENMASK(15, 0)) -+ -+#define G1_REG_REFER5_NBR(v) (((v) << 16) & GENMASK(31, 16)) -+#define G1_REG_REFER4_NBR(v) (((v) << 0) & GENMASK(15, 0)) -+ -+#define G1_REG_REFER7_NBR(v) (((v) << 16) & GENMASK(31, 16)) -+#define G1_REG_REFER6_NBR(v) (((v) << 0) & GENMASK(15, 0)) -+ -+#define G1_REG_REFER9_NBR(v) (((v) << 16) & GENMASK(31, 16)) -+#define G1_REG_REFER8_NBR(v) (((v) << 0) & GENMASK(15, 0)) -+ -+#define G1_REG_REFER11_NBR(v) (((v) << 16) & GENMASK(31, 16)) -+#define G1_REG_REFER10_NBR(v) (((v) << 0) & GENMASK(15, 0)) -+ -+#define G1_REG_REFER13_NBR(v) (((v) << 16) & GENMASK(31, 16)) -+#define G1_REG_REFER12_NBR(v) (((v) << 0) & GENMASK(15, 0)) -+ -+#define G1_REG_REFER15_NBR(v) (((v) << 16) & GENMASK(31, 16)) -+#define G1_REG_REFER14_NBR(v) (((v) << 0) & GENMASK(15, 0)) -+ -+#define G1_REG_REFER_LTERM_E(v) (((v) << 0) & GENMASK(31, 0)) -+ -+#define G1_REG_REFER_VALID_E(v) (((v) << 0) & GENMASK(31, 0)) -+ -+#define G1_REG_BINIT_RLIST_B2(v) (((v) << 25) & GENMASK(29, 25)) -+#define G1_REG_BINIT_RLIST_F2(v) (((v) << 20) & GENMASK(24, 20)) -+#define G1_REG_BINIT_RLIST_B1(v) (((v) << 15) & GENMASK(19, 15)) -+#define G1_REG_BINIT_RLIST_F1(v) (((v) << 10) & GENMASK(14, 10)) -+#define G1_REG_BINIT_RLIST_B0(v) (((v) << 5) & GENMASK(9, 5)) -+#define G1_REG_BINIT_RLIST_F0(v) (((v) << 0) & GENMASK(4, 0)) -+ -+#define G1_REG_BINIT_RLIST_B5(v) (((v) << 25) & GENMASK(29, 25)) -+#define G1_REG_BINIT_RLIST_F5(v) (((v) << 20) & GENMASK(24, 20)) -+#define G1_REG_BINIT_RLIST_B4(v) (((v) << 15) & GENMASK(19, 15)) -+#define G1_REG_BINIT_RLIST_F4(v) (((v) << 10) & GENMASK(14, 10)) -+#define G1_REG_BINIT_RLIST_B3(v) (((v) << 5) & GENMASK(9, 5)) -+#define G1_REG_BINIT_RLIST_F3(v) (((v) << 0) & GENMASK(4, 0)) -+ -+#define G1_REG_BINIT_RLIST_B8(v) (((v) << 25) & GENMASK(29, 25)) -+#define G1_REG_BINIT_RLIST_F8(v) (((v) << 20) & GENMASK(24, 20)) -+#define G1_REG_BINIT_RLIST_B7(v) (((v) << 15) & GENMASK(19, 15)) -+#define G1_REG_BINIT_RLIST_F7(v) (((v) << 10) & GENMASK(14, 10)) -+#define G1_REG_BINIT_RLIST_B6(v) (((v) << 5) & GENMASK(9, 5)) -+#define G1_REG_BINIT_RLIST_F6(v) (((v) << 0) & GENMASK(4, 0)) -+ -+#define G1_REG_BINIT_RLIST_B11(v) (((v) << 25) & GENMASK(29, 25)) -+#define G1_REG_BINIT_RLIST_F11(v) (((v) << 20) & GENMASK(24, 20)) -+#define G1_REG_BINIT_RLIST_B10(v) (((v) << 15) & GENMASK(19, 15)) -+#define G1_REG_BINIT_RLIST_F10(v) (((v) << 10) & GENMASK(14, 10)) -+#define G1_REG_BINIT_RLIST_B9(v) (((v) << 5) & GENMASK(9, 5)) -+#define G1_REG_BINIT_RLIST_F9(v) (((v) << 0) & GENMASK(4, 0)) -+ -+#define G1_REG_BINIT_RLIST_B14(v) (((v) << 25) & GENMASK(29, 25)) -+#define G1_REG_BINIT_RLIST_F14(v) (((v) << 20) & GENMASK(24, 20)) -+#define G1_REG_BINIT_RLIST_B13(v) (((v) << 15) & GENMASK(19, 15)) -+#define G1_REG_BINIT_RLIST_F13(v) (((v) << 10) & GENMASK(14, 10)) -+#define G1_REG_BINIT_RLIST_B12(v) (((v) << 5) & GENMASK(9, 5)) -+#define G1_REG_BINIT_RLIST_F12(v) (((v) << 0) & GENMASK(4, 0)) -+ -+#define G1_REG_PINIT_RLIST_F3(v) (((v) << 25) & GENMASK(29, 25)) -+#define G1_REG_PINIT_RLIST_F2(v) (((v) << 20) & GENMASK(24, 20)) -+#define G1_REG_PINIT_RLIST_F1(v) (((v) << 15) & GENMASK(19, 15)) -+#define G1_REG_PINIT_RLIST_F0(v) (((v) << 10) & GENMASK(14, 10)) -+#define G1_REG_BINIT_RLIST_B15(v) (((v) << 5) & GENMASK(9, 5)) -+#define G1_REG_BINIT_RLIST_F15(v) (((v) << 0) & GENMASK(4, 0)) -+ -+#define G1_REG_STARTMB_X(v) (((v) << 23) & GENMASK(31, 23)) -+#define G1_REG_STARTMB_Y(v) (((v) << 15) & GENMASK(22, 15)) -+ -+#define G1_REG_PRED_BC_TAP_0_0(v) (((v) << 22) & GENMASK(31, 22)) -+#define G1_REG_PRED_BC_TAP_0_1(v) (((v) << 12) & GENMASK(21, 12)) -+#define G1_REG_PRED_BC_TAP_0_2(v) (((v) << 2) & GENMASK(11, 2)) -+ -+#define G1_REG_REFBU_E(v) ((v) ? BIT(31) : 0) -+ -+#define G1_REG_APF_THRESHOLD(v) (((v) << 0) & GENMASK(13, 0)) -+ -+void hantro_g1_h264_dec_run(struct hantro_ctx *ctx) - { -- const struct hantro_h264_dec_ctrls *ctrls = &ctx->h264_dec.ctrls; -- const struct v4l2_ctrl_h264_decode_params *dec_param = ctrls->decode; -- const struct v4l2_ctrl_h264_slice_params *slices = ctrls->slices; -- const struct v4l2_ctrl_h264_sps *sps = ctrls->sps; -- const struct v4l2_ctrl_h264_pps *pps = ctrls->pps; -- struct vb2_v4l2_buffer *src_buf = hantro_get_src_buf(ctx); - struct hantro_dev *vpu = ctx->dev; -+ struct vb2_v4l2_buffer *src_buf, *dst_buf; -+ const struct hantro_h264_dec_ctrls *ctrls; -+ const struct v4l2_ctrl_h264_decode_params *decode; -+ const struct v4l2_ctrl_h264_slice_params *slices; -+ const struct v4l2_ctrl_h264_sps *sps; -+ const struct v4l2_ctrl_h264_pps *pps; -+ const u8 *b0_reflist, *b1_reflist, *p_reflist; -+ dma_addr_t addr; -+ size_t offset = 0; - u32 reg; - -- /* Decoder control register 0. */ -- reg = G1_REG_DEC_CTRL0_DEC_AXI_WR_ID(0x0); -- if (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD) -- reg |= G1_REG_DEC_CTRL0_SEQ_MBAFF_E; -- if (sps->profile_idc > 66) { -- reg |= G1_REG_DEC_CTRL0_PICORD_COUNT_E; -- if (dec_param->nal_ref_idc) -- reg |= G1_REG_DEC_CTRL0_WRITE_MVS_E; -- } -+ /* Prepare the H264 decoder context. */ -+ if (hantro_h264_dec_prepare_run(ctx)) -+ return; - -- if (!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY) && -- (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD || -- slices[0].flags & V4L2_H264_SLICE_FLAG_FIELD_PIC)) -- reg |= G1_REG_DEC_CTRL0_PIC_INTERLACE_E; -- if (slices[0].flags & V4L2_H264_SLICE_FLAG_FIELD_PIC) -- reg |= G1_REG_DEC_CTRL0_PIC_FIELDMODE_E; -- if (!(slices[0].flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD)) -- reg |= G1_REG_DEC_CTRL0_PIC_TOPFIELD_E; -- vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL0); -- -- /* Decoder control register 1. */ -- reg = G1_REG_DEC_CTRL1_PIC_MB_WIDTH(MB_WIDTH(ctx->src_fmt.width)) | -- G1_REG_DEC_CTRL1_PIC_MB_HEIGHT_P(MB_HEIGHT(ctx->src_fmt.height)) | -- G1_REG_DEC_CTRL1_REF_FRAMES(sps->max_num_ref_frames); -- vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL1); -- -- /* Decoder control register 2. */ -- reg = G1_REG_DEC_CTRL2_CH_QP_OFFSET(pps->chroma_qp_index_offset) | -- G1_REG_DEC_CTRL2_CH_QP_OFFSET2(pps->second_chroma_qp_index_offset); -- -- /* always use the matrix sent from userspace */ -- reg |= G1_REG_DEC_CTRL2_TYPE1_QUANT_E; -- -- if (!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY)) -- reg |= G1_REG_DEC_CTRL2_FIELDPIC_FLAG_E; -- vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL2); -- -- /* Decoder control register 3. */ -- reg = G1_REG_DEC_CTRL3_START_CODE_E | -- G1_REG_DEC_CTRL3_INIT_QP(pps->pic_init_qp_minus26 + 26) | -- G1_REG_DEC_CTRL3_STREAM_LEN(vb2_get_plane_payload(&src_buf->vb2_buf, 0)); -- vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL3); -- -- /* Decoder control register 4. */ -- reg = G1_REG_DEC_CTRL4_FRAMENUM_LEN(sps->log2_max_frame_num_minus4 + 4) | -- G1_REG_DEC_CTRL4_FRAMENUM(slices[0].frame_num) | -- G1_REG_DEC_CTRL4_WEIGHT_BIPR_IDC(pps->weighted_bipred_idc); -- if (pps->flags & V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE) -- reg |= G1_REG_DEC_CTRL4_CABAC_E; -- if (sps->flags & V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE) -- reg |= G1_REG_DEC_CTRL4_DIR_8X8_INFER_E; -- if (sps->profile_idc >= 100 && sps->chroma_format_idc == 0) -- reg |= G1_REG_DEC_CTRL4_BLACKWHITE_E; -- if (pps->flags & V4L2_H264_PPS_FLAG_WEIGHTED_PRED) -- reg |= G1_REG_DEC_CTRL4_WEIGHT_PRED_E; -- vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL4); -- -- /* Decoder control register 5. */ -- reg = G1_REG_DEC_CTRL5_REFPIC_MK_LEN(slices[0].dec_ref_pic_marking_bit_size) | -- G1_REG_DEC_CTRL5_IDR_PIC_ID(slices[0].idr_pic_id); -- if (pps->flags & V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED) -- reg |= G1_REG_DEC_CTRL5_CONST_INTRA_E; -- if (pps->flags & V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT) -- reg |= G1_REG_DEC_CTRL5_FILT_CTRL_PRES; -- if (pps->flags & V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT) -- reg |= G1_REG_DEC_CTRL5_RDPIC_CNT_PRES; -- if (pps->flags & V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE) -- reg |= G1_REG_DEC_CTRL5_8X8TRANS_FLAG_E; -- if (dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC) -- reg |= G1_REG_DEC_CTRL5_IDR_PIC_E; -- vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL5); -- -- /* Decoder control register 6. */ -- reg = G1_REG_DEC_CTRL6_PPS_ID(slices[0].pic_parameter_set_id) | -- G1_REG_DEC_CTRL6_REFIDX0_ACTIVE(pps->num_ref_idx_l0_default_active_minus1 + 1) | -- G1_REG_DEC_CTRL6_REFIDX1_ACTIVE(pps->num_ref_idx_l1_default_active_minus1 + 1) | -- G1_REG_DEC_CTRL6_POC_LENGTH(slices[0].pic_order_cnt_bit_size); -- vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL6); -- -- /* Error concealment register. */ -- vdpu_write_relaxed(vpu, 0, G1_REG_ERR_CONC); -- -- /* Prediction filter tap register. */ -- vdpu_write_relaxed(vpu, -- G1_REG_PRED_FLT_PRED_BC_TAP_0_0(1) | -- G1_REG_PRED_FLT_PRED_BC_TAP_0_1(-5 & 0x3ff) | -- G1_REG_PRED_FLT_PRED_BC_TAP_0_2(20), -- G1_REG_PRED_FLT); -- -- /* Reference picture buffer control register. */ -- vdpu_write_relaxed(vpu, 0, G1_REG_REF_BUF_CTRL); -- -- /* Reference picture buffer control register 2. */ -- vdpu_write_relaxed(vpu, G1_REG_REF_BUF_CTRL2_APF_THRESHOLD(8), -- G1_REG_REF_BUF_CTRL2); --} -+ src_buf = hantro_get_src_buf(ctx); -+ dst_buf = hantro_get_dst_buf(ctx); - --static void set_ref(struct hantro_ctx *ctx) --{ -- struct v4l2_h264_dpb_entry *dpb = ctx->h264_dec.dpb; -- const u8 *b0_reflist, *b1_reflist, *p_reflist; -- struct hantro_dev *vpu = ctx->dev; -- int reg_num; -- u32 reg; -- int i; -- -- vdpu_write_relaxed(vpu, ctx->h264_dec.dpb_valid, G1_REG_VALID_REF); -- vdpu_write_relaxed(vpu, ctx->h264_dec.dpb_longterm, G1_REG_LT_REF); -- -- /* -- * Set up reference frame picture numbers. -- * -- * Each G1_REG_REF_PIC(x) register contains numbers of two -- * subsequential reference pictures. -- */ -- for (i = 0; i < HANTRO_H264_DPB_SIZE; i += 2) { -- reg = 0; -- if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM) -- reg |= G1_REG_REF_PIC_REFER0_NBR(dpb[i].pic_num); -- else -- reg |= G1_REG_REF_PIC_REFER0_NBR(dpb[i].frame_num); -- -- if (dpb[i + 1].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM) -- reg |= G1_REG_REF_PIC_REFER1_NBR(dpb[i + 1].pic_num); -- else -- reg |= G1_REG_REF_PIC_REFER1_NBR(dpb[i + 1].frame_num); -- -- vdpu_write_relaxed(vpu, reg, G1_REG_REF_PIC(i / 2)); -- } -+ ctrls = &ctx->h264_dec.ctrls; -+ decode = ctrls->decode; -+ slices = ctrls->slices; -+ sps = ctrls->sps; -+ pps = ctrls->pps; - - b0_reflist = ctx->h264_dec.reflists.b0; - b1_reflist = ctx->h264_dec.reflists.b1; - p_reflist = ctx->h264_dec.reflists.p; - -- /* -- * Each G1_REG_BD_REF_PIC(x) register contains three entries -- * of each forward and backward picture list. -- */ -- reg_num = 0; -- for (i = 0; i < 15; i += 3) { -- reg = G1_REG_BD_REF_PIC_BINIT_RLIST_F0(b0_reflist[i]) | -- G1_REG_BD_REF_PIC_BINIT_RLIST_F1(b0_reflist[i + 1]) | -- G1_REG_BD_REF_PIC_BINIT_RLIST_F2(b0_reflist[i + 2]) | -- G1_REG_BD_REF_PIC_BINIT_RLIST_B0(b1_reflist[i]) | -- G1_REG_BD_REF_PIC_BINIT_RLIST_B1(b1_reflist[i + 1]) | -- G1_REG_BD_REF_PIC_BINIT_RLIST_B2(b1_reflist[i + 2]); -- vdpu_write_relaxed(vpu, reg, G1_REG_BD_REF_PIC(reg_num++)); -- } -- -- /* -- * G1_REG_BD_P_REF_PIC register contains last entries (index 15) -- * of forward and backward reference picture lists and first 4 entries -- * of P forward picture list. -- */ -- reg = G1_REG_BD_P_REF_PIC_BINIT_RLIST_F15(b0_reflist[15]) | -- G1_REG_BD_P_REF_PIC_BINIT_RLIST_B15(b1_reflist[15]) | -- G1_REG_BD_P_REF_PIC_PINIT_RLIST_F0(p_reflist[0]) | -- G1_REG_BD_P_REF_PIC_PINIT_RLIST_F1(p_reflist[1]) | -- G1_REG_BD_P_REF_PIC_PINIT_RLIST_F2(p_reflist[2]) | -- G1_REG_BD_P_REF_PIC_PINIT_RLIST_F3(p_reflist[3]); -- vdpu_write_relaxed(vpu, reg, G1_REG_BD_P_REF_PIC); -- -- /* -- * Each G1_REG_FWD_PIC(x) register contains six consecutive -- * entries of P forward picture list, starting from index 4. -- */ -- reg_num = 0; -- for (i = 4; i < HANTRO_H264_DPB_SIZE; i += 6) { -- reg = G1_REG_FWD_PIC_PINIT_RLIST_F0(p_reflist[i]) | -- G1_REG_FWD_PIC_PINIT_RLIST_F1(p_reflist[i + 1]) | -- G1_REG_FWD_PIC_PINIT_RLIST_F2(p_reflist[i + 2]) | -- G1_REG_FWD_PIC_PINIT_RLIST_F3(p_reflist[i + 3]) | -- G1_REG_FWD_PIC_PINIT_RLIST_F4(p_reflist[i + 4]) | -- G1_REG_FWD_PIC_PINIT_RLIST_F5(p_reflist[i + 5]); -- vdpu_write_relaxed(vpu, reg, G1_REG_FWD_PIC(reg_num++)); -- } -+ reg = G1_REG_DEC_AXI_RD_ID(0xff) | -+ G1_REG_DEC_TIMEOUT_E(1) | -+ G1_REG_DEC_STRSWAP32_E(1) | -+ G1_REG_DEC_STRENDIAN_E(1) | -+ G1_REG_DEC_INSWAP32_E(1) | -+ G1_REG_DEC_OUTSWAP32_E(1) | -+ G1_REG_DEC_DATA_DISC_E(0) | -+ G1_REG_DEC_LATENCY(0) | -+ G1_REG_DEC_CLK_GATE_E(1) | -+ G1_REG_DEC_IN_ENDIAN(0) | -+ G1_REG_DEC_OUT_ENDIAN(1) | -+ G1_REG_DEC_ADV_PRE_DIS(0) | -+ G1_REG_DEC_SCMD_DIS(0) | -+ G1_REG_DEC_MAX_BURST(16); -+ vdpu_write_relaxed(vpu, reg, G1_SWREG(2)); -+ -+ reg = G1_REG_DEC_MODE(0) | -+ G1_REG_RLC_MODE_E(0) | -+ G1_REG_PIC_INTERLACE_E(!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY) && (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD || slices[0].flags & V4L2_H264_SLICE_FLAG_FIELD_PIC)) | -+ G1_REG_PIC_FIELDMODE_E(slices[0].flags & V4L2_H264_SLICE_FLAG_FIELD_PIC) | -+ G1_REG_PIC_TOPFIELD_E(!(slices[0].flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD)) | -+ G1_REG_FILTERING_DIS(0) | -+ G1_REG_PIC_FIXED_QUANT(0) | -+ G1_REG_WRITE_MVS_E(sps->profile_idc > 66 && decode->nal_ref_idc) | -+ G1_REG_SEQ_MBAFF_E(sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD) | -+ G1_REG_PICORD_COUNT_E(sps->profile_idc > 66) | -+ G1_REG_DEC_AXI_WR_ID(0); -+ vdpu_write_relaxed(vpu, reg, G1_SWREG(3)); -+ -+ reg = G1_REG_PIC_MB_WIDTH(MB_WIDTH(ctx->src_fmt.width)) | -+ G1_REG_PIC_MB_HEIGHT_P(MB_HEIGHT(ctx->src_fmt.height)) | -+ G1_REG_REF_FRAMES(sps->max_num_ref_frames); -+ vdpu_write_relaxed(vpu, reg, G1_SWREG(4)); -+ -+ reg = G1_REG_STRM_START_BIT(0) | -+ G1_REG_TYPE1_QUANT_E(1) | -+ G1_REG_CH_QP_OFFSET(pps->chroma_qp_index_offset) | -+ G1_REG_CH_QP_OFFSET2(pps->second_chroma_qp_index_offset) | -+ G1_REG_FIELDPIC_FLAG_E(!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY)); -+ vdpu_write_relaxed(vpu, reg, G1_SWREG(5)); -+ -+ reg = G1_REG_START_CODE_E(1) | -+ G1_REG_INIT_QP(pps->pic_init_qp_minus26 + 26) | -+ G1_REG_CH_8PIX_ILEAV_E(0) | -+ G1_REG_STREAM_LEN(vb2_get_plane_payload(&src_buf->vb2_buf, 0)); -+ vdpu_write_relaxed(vpu, reg, G1_SWREG(6)); -+ -+ reg = G1_REG_CABAC_E(pps->flags & V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE) | -+ G1_REG_BLACKWHITE_E(sps->profile_idc >= 100 && sps->chroma_format_idc == 0) | -+ G1_REG_DIR_8X8_INFER_E(sps->flags & V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE) | -+ G1_REG_WEIGHT_PRED_E(pps->flags & V4L2_H264_PPS_FLAG_WEIGHTED_PRED) | -+ G1_REG_WEIGHT_BIPR_IDC(pps->weighted_bipred_idc) | -+ G1_REG_FRAMENUM_LEN(sps->log2_max_frame_num_minus4 + 4) | -+ G1_REG_FRAMENUM(slices[0].frame_num); -+ vdpu_write_relaxed(vpu, reg, G1_SWREG(7)); -+ -+ reg = G1_REG_CONST_INTRA_E(pps->flags & V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED) | -+ G1_REG_FILT_CTRL_PRES(pps->flags & V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT) | -+ G1_REG_RDPIC_CNT_PRES(pps->flags & V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT) | -+ G1_REG_8X8TRANS_FLAG_E(pps->flags & V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE) | -+ G1_REG_REFPIC_MK_LEN(slices[0].dec_ref_pic_marking_bit_size) | -+ G1_REG_IDR_PIC_E(decode->flags & V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC) | -+ G1_REG_IDR_PIC_ID(slices[0].idr_pic_id); -+ vdpu_write_relaxed(vpu, reg, G1_SWREG(8)); -+ -+ reg = G1_REG_PPS_ID(slices[0].pic_parameter_set_id) | -+ G1_REG_REFIDX1_ACTIVE(pps->num_ref_idx_l1_default_active_minus1 + 1) | -+ G1_REG_REFIDX0_ACTIVE(pps->num_ref_idx_l0_default_active_minus1 + 1) | -+ G1_REG_POC_LENGTH(slices[0].pic_order_cnt_bit_size); -+ vdpu_write_relaxed(vpu, reg, G1_SWREG(9)); -+ -+ reg = G1_REG_PINIT_RLIST_F9(p_reflist[9]) | -+ G1_REG_PINIT_RLIST_F8(p_reflist[8]) | -+ G1_REG_PINIT_RLIST_F7(p_reflist[7]) | -+ G1_REG_PINIT_RLIST_F6(p_reflist[6]) | -+ G1_REG_PINIT_RLIST_F5(p_reflist[5]) | -+ G1_REG_PINIT_RLIST_F4(p_reflist[4]); -+ vdpu_write_relaxed(vpu, reg, G1_SWREG(10)); -+ -+ reg = G1_REG_PINIT_RLIST_F15(p_reflist[15]) | -+ G1_REG_PINIT_RLIST_F14(p_reflist[14]) | -+ G1_REG_PINIT_RLIST_F13(p_reflist[13]) | -+ G1_REG_PINIT_RLIST_F12(p_reflist[12]) | -+ G1_REG_PINIT_RLIST_F11(p_reflist[11]) | -+ G1_REG_PINIT_RLIST_F10(p_reflist[10]); -+ vdpu_write_relaxed(vpu, reg, G1_SWREG(11)); -+ -+ reg = G1_REG_REFER1_NBR(hantro_h264_get_ref_nbr(ctx, 1)) | -+ G1_REG_REFER0_NBR(hantro_h264_get_ref_nbr(ctx, 0)); -+ vdpu_write_relaxed(vpu, reg, G1_SWREG(30)); -+ -+ reg = G1_REG_REFER3_NBR(hantro_h264_get_ref_nbr(ctx, 3)) | -+ G1_REG_REFER2_NBR(hantro_h264_get_ref_nbr(ctx, 2)); -+ vdpu_write_relaxed(vpu, reg, G1_SWREG(31)); -+ -+ reg = G1_REG_REFER5_NBR(hantro_h264_get_ref_nbr(ctx, 5)) | -+ G1_REG_REFER4_NBR(hantro_h264_get_ref_nbr(ctx, 4)); -+ vdpu_write_relaxed(vpu, reg, G1_SWREG(32)); -+ -+ reg = G1_REG_REFER7_NBR(hantro_h264_get_ref_nbr(ctx, 7)) | -+ G1_REG_REFER6_NBR(hantro_h264_get_ref_nbr(ctx, 6)); -+ vdpu_write_relaxed(vpu, reg, G1_SWREG(33)); -+ -+ reg = G1_REG_REFER9_NBR(hantro_h264_get_ref_nbr(ctx, 9)) | -+ G1_REG_REFER8_NBR(hantro_h264_get_ref_nbr(ctx, 8)); -+ vdpu_write_relaxed(vpu, reg, G1_SWREG(34)); -+ -+ reg = G1_REG_REFER11_NBR(hantro_h264_get_ref_nbr(ctx, 11)) | -+ G1_REG_REFER10_NBR(hantro_h264_get_ref_nbr(ctx, 10)); -+ vdpu_write_relaxed(vpu, reg, G1_SWREG(35)); -+ -+ reg = G1_REG_REFER13_NBR(hantro_h264_get_ref_nbr(ctx, 13)) | -+ G1_REG_REFER12_NBR(hantro_h264_get_ref_nbr(ctx, 12)); -+ vdpu_write_relaxed(vpu, reg, G1_SWREG(36)); -+ -+ reg = G1_REG_REFER15_NBR(hantro_h264_get_ref_nbr(ctx, 15)) | -+ G1_REG_REFER14_NBR(hantro_h264_get_ref_nbr(ctx, 14)); -+ vdpu_write_relaxed(vpu, reg, G1_SWREG(37)); -+ -+ reg = G1_REG_REFER_LTERM_E(ctx->h264_dec.dpb_longterm); -+ vdpu_write_relaxed(vpu, reg, G1_SWREG(38)); -+ -+ reg = G1_REG_REFER_VALID_E(ctx->h264_dec.dpb_valid); -+ vdpu_write_relaxed(vpu, reg, G1_SWREG(39)); -+ -+ reg = G1_REG_BINIT_RLIST_B2(b1_reflist[2]) | -+ G1_REG_BINIT_RLIST_F2(b0_reflist[2]) | -+ G1_REG_BINIT_RLIST_B1(b1_reflist[1]) | -+ G1_REG_BINIT_RLIST_F1(b0_reflist[1]) | -+ G1_REG_BINIT_RLIST_B0(b1_reflist[0]) | -+ G1_REG_BINIT_RLIST_F0(b0_reflist[0]); -+ vdpu_write_relaxed(vpu, reg, G1_SWREG(42)); -+ -+ reg = G1_REG_BINIT_RLIST_B5(b1_reflist[5]) | -+ G1_REG_BINIT_RLIST_F5(b0_reflist[5]) | -+ G1_REG_BINIT_RLIST_B4(b1_reflist[4]) | -+ G1_REG_BINIT_RLIST_F4(b0_reflist[4]) | -+ G1_REG_BINIT_RLIST_B3(b1_reflist[3]) | -+ G1_REG_BINIT_RLIST_F3(b0_reflist[3]); -+ vdpu_write_relaxed(vpu, reg, G1_SWREG(43)); -+ -+ reg = G1_REG_BINIT_RLIST_B8(b1_reflist[8]) | -+ G1_REG_BINIT_RLIST_F8(b0_reflist[8]) | -+ G1_REG_BINIT_RLIST_B7(b1_reflist[7]) | -+ G1_REG_BINIT_RLIST_F7(b0_reflist[7]) | -+ G1_REG_BINIT_RLIST_B6(b1_reflist[6]) | -+ G1_REG_BINIT_RLIST_F6(b0_reflist[6]); -+ vdpu_write_relaxed(vpu, reg, G1_SWREG(44)); -+ -+ reg = G1_REG_BINIT_RLIST_B11(b1_reflist[11]) | -+ G1_REG_BINIT_RLIST_F11(b0_reflist[11]) | -+ G1_REG_BINIT_RLIST_B10(b1_reflist[10]) | -+ G1_REG_BINIT_RLIST_F10(b0_reflist[10]) | -+ G1_REG_BINIT_RLIST_B9(b1_reflist[9]) | -+ G1_REG_BINIT_RLIST_F9(b0_reflist[9]); -+ vdpu_write_relaxed(vpu, reg, G1_SWREG(45)); -+ -+ reg = G1_REG_BINIT_RLIST_B14(b1_reflist[14]) | -+ G1_REG_BINIT_RLIST_F14(b0_reflist[14]) | -+ G1_REG_BINIT_RLIST_B13(b1_reflist[13]) | -+ G1_REG_BINIT_RLIST_F13(b0_reflist[13]) | -+ G1_REG_BINIT_RLIST_B12(b1_reflist[12]) | -+ G1_REG_BINIT_RLIST_F12(b0_reflist[12]); -+ vdpu_write_relaxed(vpu, reg, G1_SWREG(46)); -+ -+ reg = G1_REG_PINIT_RLIST_F3(p_reflist[3]) | -+ G1_REG_PINIT_RLIST_F2(p_reflist[2]) | -+ G1_REG_PINIT_RLIST_F1(p_reflist[1]) | -+ G1_REG_PINIT_RLIST_F0(p_reflist[0]) | -+ G1_REG_BINIT_RLIST_B15(b1_reflist[15]) | -+ G1_REG_BINIT_RLIST_F15(b0_reflist[15]); -+ vdpu_write_relaxed(vpu, reg, G1_SWREG(47)); -+ -+ reg = G1_REG_STARTMB_X(0) | -+ G1_REG_STARTMB_Y(0); -+ vdpu_write_relaxed(vpu, reg, G1_SWREG(48)); -+ -+ reg = G1_REG_PRED_BC_TAP_0_0(1) | -+ G1_REG_PRED_BC_TAP_0_1((u32)-5) | -+ G1_REG_PRED_BC_TAP_0_2(20); -+ vdpu_write_relaxed(vpu, reg, G1_SWREG(49)); -+ -+ reg = G1_REG_REFBU_E(0); -+ vdpu_write_relaxed(vpu, reg, G1_SWREG(51)); -+ -+ reg = G1_REG_APF_THRESHOLD(8); -+ vdpu_write_relaxed(vpu, reg, G1_SWREG(55)); - -- /* Set up addresses of DPB buffers. */ -- for (i = 0; i < HANTRO_H264_DPB_SIZE; i++) { -- dma_addr_t dma_addr = hantro_h264_get_ref_buf(ctx, i); -- -- vdpu_write_relaxed(vpu, dma_addr, G1_REG_ADDR_REF(i)); -- } --} -- --static void set_buffers(struct hantro_ctx *ctx) --{ -- const struct hantro_h264_dec_ctrls *ctrls = &ctx->h264_dec.ctrls; -- struct vb2_v4l2_buffer *src_buf, *dst_buf; -- struct hantro_dev *vpu = ctx->dev; -- dma_addr_t src_dma, dst_dma; -- size_t offset = 0; -- -- src_buf = hantro_get_src_buf(ctx); -- dst_buf = hantro_get_dst_buf(ctx); -+ /* Auxiliary buffer prepared in hantro_g1_h264_dec_prepare_table(). */ -+ vdpu_write_relaxed(vpu, ctx->h264_dec.priv.dma, G1_REG_QTABLE_BASE); - - /* Source (stream) buffer. */ -- src_dma = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); -- vdpu_write_relaxed(vpu, src_dma, G1_REG_ADDR_STR); -+ addr = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); -+ vdpu_write_relaxed(vpu, addr, G1_REG_RLC_VLC_BASE); - - /* Destination (decoded frame) buffer. */ -- dst_dma = hantro_get_dec_buf_addr(ctx, &dst_buf->vb2_buf); -+ addr = hantro_get_dec_buf_addr(ctx, &dst_buf->vb2_buf); - /* Adjust dma addr to start at second line for bottom field */ -- if (ctrls->slices[0].flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD) -+ if (slices[0].flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD) - offset = ALIGN(ctx->src_fmt.width, MB_DIM); -- vdpu_write_relaxed(vpu, dst_dma + offset, G1_REG_ADDR_DST); -+ vdpu_write_relaxed(vpu, addr + offset, G1_REG_DEC_OUT_BASE); - - /* Higher profiles require DMV buffer appended to reference frames. */ -- if (ctrls->sps->profile_idc > 66 && ctrls->decode->nal_ref_idc) { -+ if (sps->profile_idc > 66 && decode->nal_ref_idc) { - unsigned int bytes_per_mb = 384; - - /* DMV buffer for monochrome start directly after Y-plane */ -- if (ctrls->sps->profile_idc >= 100 && -- ctrls->sps->chroma_format_idc == 0) -+ if (sps->profile_idc >= 100 && sps->chroma_format_idc == 0) - bytes_per_mb = 256; - offset = bytes_per_mb * MB_WIDTH(ctx->src_fmt.width) * - MB_HEIGHT(ctx->src_fmt.height); -@@ -252,42 +447,32 @@ static void set_buffers(struct hantro_ctx *ctx) - * DMV buffer is split in two for field encoded frames, - * adjust offset for bottom field - */ -- if (ctrls->slices[0].flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD) -+ if (slices[0].flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD) - offset += 32 * MB_WIDTH(ctx->src_fmt.width) * - MB_HEIGHT(ctx->src_fmt.height); -- vdpu_write_relaxed(vpu, dst_dma + offset, G1_REG_ADDR_DIR_MV); -+ vdpu_write_relaxed(vpu, addr + offset, G1_REG_DIR_MV_BASE); - } - -- /* Auxiliary buffer prepared in hantro_g1_h264_dec_prepare_table(). */ -- vdpu_write_relaxed(vpu, ctx->h264_dec.priv.dma, G1_REG_ADDR_QTABLE); --} -- --void hantro_g1_h264_dec_run(struct hantro_ctx *ctx) --{ -- struct hantro_dev *vpu = ctx->dev; -- -- /* Prepare the H264 decoder context. */ -- if (hantro_h264_dec_prepare_run(ctx)) -- return; -- -- /* Configure hardware registers. */ -- set_params(ctx); -- set_ref(ctx); -- set_buffers(ctx); -+ vdpu_write_relaxed(vpu, hantro_h264_get_ref_buf(ctx, 0), G1_REG_REFER0_BASE); -+ vdpu_write_relaxed(vpu, hantro_h264_get_ref_buf(ctx, 1), G1_REG_REFER1_BASE); -+ vdpu_write_relaxed(vpu, hantro_h264_get_ref_buf(ctx, 2), G1_REG_REFER2_BASE); -+ vdpu_write_relaxed(vpu, hantro_h264_get_ref_buf(ctx, 3), G1_REG_REFER3_BASE); -+ vdpu_write_relaxed(vpu, hantro_h264_get_ref_buf(ctx, 4), G1_REG_REFER4_BASE); -+ vdpu_write_relaxed(vpu, hantro_h264_get_ref_buf(ctx, 5), G1_REG_REFER5_BASE); -+ vdpu_write_relaxed(vpu, hantro_h264_get_ref_buf(ctx, 6), G1_REG_REFER6_BASE); -+ vdpu_write_relaxed(vpu, hantro_h264_get_ref_buf(ctx, 7), G1_REG_REFER7_BASE); -+ vdpu_write_relaxed(vpu, hantro_h264_get_ref_buf(ctx, 8), G1_REG_REFER8_BASE); -+ vdpu_write_relaxed(vpu, hantro_h264_get_ref_buf(ctx, 9), G1_REG_REFER9_BASE); -+ vdpu_write_relaxed(vpu, hantro_h264_get_ref_buf(ctx, 10), G1_REG_REFER10_BASE); -+ vdpu_write_relaxed(vpu, hantro_h264_get_ref_buf(ctx, 11), G1_REG_REFER11_BASE); -+ vdpu_write_relaxed(vpu, hantro_h264_get_ref_buf(ctx, 12), G1_REG_REFER12_BASE); -+ vdpu_write_relaxed(vpu, hantro_h264_get_ref_buf(ctx, 13), G1_REG_REFER13_BASE); -+ vdpu_write_relaxed(vpu, hantro_h264_get_ref_buf(ctx, 14), G1_REG_REFER14_BASE); -+ vdpu_write_relaxed(vpu, hantro_h264_get_ref_buf(ctx, 15), G1_REG_REFER15_BASE); - - hantro_end_prepare_run(ctx); - - /* Start decoding! */ -- vdpu_write_relaxed(vpu, -- G1_REG_CONFIG_DEC_AXI_RD_ID(0xffu) | -- G1_REG_CONFIG_DEC_TIMEOUT_E | -- G1_REG_CONFIG_DEC_OUT_ENDIAN | -- G1_REG_CONFIG_DEC_STRENDIAN_E | -- G1_REG_CONFIG_DEC_MAX_BURST(16) | -- G1_REG_CONFIG_DEC_OUTSWAP32_E | -- G1_REG_CONFIG_DEC_INSWAP32_E | -- G1_REG_CONFIG_DEC_STRSWAP32_E | -- G1_REG_CONFIG_DEC_CLK_GATE_E, -- G1_REG_CONFIG); -- vdpu_write(vpu, G1_REG_INTERRUPT_DEC_E, G1_REG_INTERRUPT); -+ reg = G1_REG_DEC_E(1); -+ vdpu_write(vpu, reg, G1_SWREG(1)); - } -diff --git a/drivers/staging/media/hantro/hantro_h264.c b/drivers/staging/media/hantro/hantro_h264.c -index 4db779354e89..2edcdda2ad63 100644 ---- a/drivers/staging/media/hantro/hantro_h264.c -+++ b/drivers/staging/media/hantro/hantro_h264.c -@@ -596,6 +596,20 @@ dma_addr_t hantro_h264_get_ref_buf(struct hantro_ctx *ctx, - return dma_addr | flags; - } - -+u16 hantro_h264_get_ref_nbr(struct hantro_ctx *ctx, -+ unsigned int dpb_idx) -+{ -+ const struct v4l2_h264_dpb_entry *dpb = &ctx->h264_dec.dpb[dpb_idx]; -+ -+ if (!(dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)) -+ return 0; -+ -+ if (dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM) -+ return dpb->pic_num; -+ -+ return dpb->frame_num; -+} -+ - int hantro_h264_dec_prepare_run(struct hantro_ctx *ctx) - { - struct hantro_h264_dec_hw_ctx *h264_ctx = &ctx->h264_dec; -diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h -index 3dc7b8f27c32..fadd3e1bf0d9 100644 ---- a/drivers/staging/media/hantro/hantro_hw.h -+++ b/drivers/staging/media/hantro/hantro_hw.h -@@ -172,6 +172,8 @@ void hantro_jpeg_enc_exit(struct hantro_ctx *ctx); - - dma_addr_t hantro_h264_get_ref_buf(struct hantro_ctx *ctx, - unsigned int dpb_idx); -+u16 hantro_h264_get_ref_nbr(struct hantro_ctx *ctx, -+ unsigned int dpb_idx); - int hantro_h264_dec_prepare_run(struct hantro_ctx *ctx); - void hantro_g1_h264_dec_run(struct hantro_ctx *ctx); - int hantro_h264_dec_init(struct hantro_ctx *ctx); --- -2.17.1 - - -From 93fc47fb35fdbcc94bf1f1008fccffe16d7465c4 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 18 Aug 2019 10:40:31 +0000 -Subject: [PATCH] media: hantro: Add support for H264 decoding on RK3399 - -Signed-off-by: Jonas Karlman ---- - drivers/staging/media/hantro/Makefile | 1 + - drivers/staging/media/hantro/hantro_hw.h | 1 + - .../media/hantro/rk3399_vpu_hw_h264_dec.c | 493 ++++++++++++++++++ - 3 files changed, 495 insertions(+) - create mode 100644 drivers/staging/media/hantro/rk3399_vpu_hw_h264_dec.c - -diff --git a/drivers/staging/media/hantro/Makefile b/drivers/staging/media/hantro/Makefile -index 496b30c3c396..9bb8a560cb0a 100644 ---- a/drivers/staging/media/hantro/Makefile -+++ b/drivers/staging/media/hantro/Makefile -@@ -9,6 +9,7 @@ hantro-vpu-y += \ - hantro_g1_mpeg2_dec.o \ - hantro_g1_vp8_dec.o \ - rk3399_vpu_hw_jpeg_enc.o \ -+ rk3399_vpu_hw_h264_dec.o \ - rk3399_vpu_hw_mpeg2_dec.o \ - rk3399_vpu_hw_vp8_dec.o \ - hantro_jpeg.o \ -diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h -index fadd3e1bf0d9..4a64873bf332 100644 ---- a/drivers/staging/media/hantro/hantro_hw.h -+++ b/drivers/staging/media/hantro/hantro_hw.h -@@ -176,6 +176,7 @@ u16 hantro_h264_get_ref_nbr(struct hantro_ctx *ctx, - unsigned int dpb_idx); - int hantro_h264_dec_prepare_run(struct hantro_ctx *ctx); - void hantro_g1_h264_dec_run(struct hantro_ctx *ctx); -+void rk3399_vpu_h264_dec_run(struct hantro_ctx *ctx); - int hantro_h264_dec_init(struct hantro_ctx *ctx); - void hantro_h264_dec_exit(struct hantro_ctx *ctx); - -diff --git a/drivers/staging/media/hantro/rk3399_vpu_hw_h264_dec.c b/drivers/staging/media/hantro/rk3399_vpu_hw_h264_dec.c -new file mode 100644 -index 000000000000..1f9de7d5a923 ---- /dev/null -+++ b/drivers/staging/media/hantro/rk3399_vpu_hw_h264_dec.c -@@ -0,0 +1,493 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Hantro VPU codec driver -+ * -+ * Copyright (c) 2014 Rockchip Electronics Co., Ltd. -+ * Hertz Wong -+ * Herman Chen -+ * -+ * Copyright (C) 2014 Google, Inc. -+ * Tomasz Figa -+ */ -+ -+#include -+#include -+ -+#include -+ -+#include "hantro_hw.h" -+#include "hantro_v4l2.h" -+ -+#define VDPU_SWREG(nr) ((nr) * 4) -+ -+#define VDPU_REG_DEC_OUT_BASE VDPU_SWREG(63) -+#define VDPU_REG_RLC_VLC_BASE VDPU_SWREG(64) -+#define VDPU_REG_QTABLE_BASE VDPU_SWREG(61) -+#define VDPU_REG_DIR_MV_BASE VDPU_SWREG(62) -+#define VDPU_REG_REFER0_BASE VDPU_SWREG(84) -+#define VDPU_REG_REFER1_BASE VDPU_SWREG(85) -+#define VDPU_REG_REFER2_BASE VDPU_SWREG(86) -+#define VDPU_REG_REFER3_BASE VDPU_SWREG(87) -+#define VDPU_REG_REFER4_BASE VDPU_SWREG(88) -+#define VDPU_REG_REFER5_BASE VDPU_SWREG(89) -+#define VDPU_REG_REFER6_BASE VDPU_SWREG(90) -+#define VDPU_REG_REFER7_BASE VDPU_SWREG(91) -+#define VDPU_REG_REFER8_BASE VDPU_SWREG(92) -+#define VDPU_REG_REFER9_BASE VDPU_SWREG(93) -+#define VDPU_REG_REFER10_BASE VDPU_SWREG(94) -+#define VDPU_REG_REFER11_BASE VDPU_SWREG(95) -+#define VDPU_REG_REFER12_BASE VDPU_SWREG(96) -+#define VDPU_REG_REFER13_BASE VDPU_SWREG(97) -+#define VDPU_REG_REFER14_BASE VDPU_SWREG(98) -+#define VDPU_REG_REFER15_BASE VDPU_SWREG(99) -+#define VDPU_REG_DEC_E(v) ((v) ? BIT(0) : 0) -+ -+#define VDPU_REG_DEC_ADV_PRE_DIS(v) ((v) ? BIT(11) : 0) -+#define VDPU_REG_DEC_SCMD_DIS(v) ((v) ? BIT(10) : 0) -+#define VDPU_REG_FILTERING_DIS(v) ((v) ? BIT(8) : 0) -+#define VDPU_REG_PIC_FIXED_QUANT(v) ((v) ? BIT(7) : 0) -+#define VDPU_REG_DEC_LATENCY(v) (((v) << 1) & GENMASK(6, 1)) -+ -+#define VDPU_REG_INIT_QP(v) (((v) << 25) & GENMASK(30, 25)) -+#define VDPU_REG_STREAM_LEN(v) (((v) << 0) & GENMASK(23, 0)) -+ -+#define VDPU_REG_APF_THRESHOLD(v) (((v) << 17) & GENMASK(30, 17)) -+#define VDPU_REG_STARTMB_X(v) (((v) << 8) & GENMASK(16, 8)) -+#define VDPU_REG_STARTMB_Y(v) (((v) << 0) & GENMASK(7, 0)) -+ -+#define VDPU_REG_DEC_MODE(v) (((v) << 0) & GENMASK(3, 0)) -+ -+#define VDPU_REG_DEC_STRENDIAN_E(v) ((v) ? BIT(5) : 0) -+#define VDPU_REG_DEC_STRSWAP32_E(v) ((v) ? BIT(4) : 0) -+#define VDPU_REG_DEC_OUTSWAP32_E(v) ((v) ? BIT(3) : 0) -+#define VDPU_REG_DEC_INSWAP32_E(v) ((v) ? BIT(2) : 0) -+#define VDPU_REG_DEC_OUT_ENDIAN(v) ((v) ? BIT(1) : 0) -+#define VDPU_REG_DEC_IN_ENDIAN(v) ((v) ? BIT(0) : 0) -+ -+#define VDPU_REG_DEC_DATA_DISC_E(v) ((v) ? BIT(22) : 0) -+#define VDPU_REG_DEC_MAX_BURST(v) (((v) << 16) & GENMASK(20, 16)) -+#define VDPU_REG_DEC_AXI_WR_ID(v) (((v) << 8) & GENMASK(15, 8)) -+#define VDPU_REG_DEC_AXI_RD_ID(v) (((v) << 0) & GENMASK(7, 0)) -+ -+#define VDPU_REG_START_CODE_E(v) ((v) ? BIT(22) : 0) -+#define VDPU_REG_CH_8PIX_ILEAV_E(v) ((v) ? BIT(21) : 0) -+#define VDPU_REG_RLC_MODE_E(v) ((v) ? BIT(20) : 0) -+#define VDPU_REG_PIC_INTERLACE_E(v) ((v) ? BIT(17) : 0) -+#define VDPU_REG_PIC_FIELDMODE_E(v) ((v) ? BIT(16) : 0) -+#define VDPU_REG_PIC_TOPFIELD_E(v) ((v) ? BIT(13) : 0) -+#define VDPU_REG_WRITE_MVS_E(v) ((v) ? BIT(10) : 0) -+#define VDPU_REG_SEQ_MBAFF_E(v) ((v) ? BIT(7) : 0) -+#define VDPU_REG_PICORD_COUNT_E(v) ((v) ? BIT(6) : 0) -+#define VDPU_REG_DEC_TIMEOUT_E(v) ((v) ? BIT(5) : 0) -+#define VDPU_REG_DEC_CLK_GATE_E(v) ((v) ? BIT(4) : 0) -+ -+#define VDPU_REG_PRED_BC_TAP_0_0(v) (((v) << 22) & GENMASK(31, 22)) -+#define VDPU_REG_PRED_BC_TAP_0_1(v) (((v) << 12) & GENMASK(21, 12)) -+#define VDPU_REG_PRED_BC_TAP_0_2(v) (((v) << 2) & GENMASK(11, 2)) -+ -+#define VDPU_REG_REFBU_E(v) ((v) ? BIT(31) : 0) -+ -+#define VDPU_REG_PINIT_RLIST_F9(v) (((v) << 25) & GENMASK(29, 25)) -+#define VDPU_REG_PINIT_RLIST_F8(v) (((v) << 20) & GENMASK(24, 20)) -+#define VDPU_REG_PINIT_RLIST_F7(v) (((v) << 15) & GENMASK(19, 15)) -+#define VDPU_REG_PINIT_RLIST_F6(v) (((v) << 10) & GENMASK(14, 10)) -+#define VDPU_REG_PINIT_RLIST_F5(v) (((v) << 5) & GENMASK(9, 5)) -+#define VDPU_REG_PINIT_RLIST_F4(v) (((v) << 0) & GENMASK(4, 0)) -+ -+#define VDPU_REG_PINIT_RLIST_F15(v) (((v) << 25) & GENMASK(29, 25)) -+#define VDPU_REG_PINIT_RLIST_F14(v) (((v) << 20) & GENMASK(24, 20)) -+#define VDPU_REG_PINIT_RLIST_F13(v) (((v) << 15) & GENMASK(19, 15)) -+#define VDPU_REG_PINIT_RLIST_F12(v) (((v) << 10) & GENMASK(14, 10)) -+#define VDPU_REG_PINIT_RLIST_F11(v) (((v) << 5) & GENMASK(9, 5)) -+#define VDPU_REG_PINIT_RLIST_F10(v) (((v) << 0) & GENMASK(4, 0)) -+ -+#define VDPU_REG_REFER1_NBR(v) (((v) << 16) & GENMASK(31, 16)) -+#define VDPU_REG_REFER0_NBR(v) (((v) << 0) & GENMASK(15, 0)) -+ -+#define VDPU_REG_REFER3_NBR(v) (((v) << 16) & GENMASK(31, 16)) -+#define VDPU_REG_REFER2_NBR(v) (((v) << 0) & GENMASK(15, 0)) -+ -+#define VDPU_REG_REFER5_NBR(v) (((v) << 16) & GENMASK(31, 16)) -+#define VDPU_REG_REFER4_NBR(v) (((v) << 0) & GENMASK(15, 0)) -+ -+#define VDPU_REG_REFER7_NBR(v) (((v) << 16) & GENMASK(31, 16)) -+#define VDPU_REG_REFER6_NBR(v) (((v) << 0) & GENMASK(15, 0)) -+ -+#define VDPU_REG_REFER9_NBR(v) (((v) << 16) & GENMASK(31, 16)) -+#define VDPU_REG_REFER8_NBR(v) (((v) << 0) & GENMASK(15, 0)) -+ -+#define VDPU_REG_REFER11_NBR(v) (((v) << 16) & GENMASK(31, 16)) -+#define VDPU_REG_REFER10_NBR(v) (((v) << 0) & GENMASK(15, 0)) -+ -+#define VDPU_REG_REFER13_NBR(v) (((v) << 16) & GENMASK(31, 16)) -+#define VDPU_REG_REFER12_NBR(v) (((v) << 0) & GENMASK(15, 0)) -+ -+#define VDPU_REG_REFER15_NBR(v) (((v) << 16) & GENMASK(31, 16)) -+#define VDPU_REG_REFER14_NBR(v) (((v) << 0) & GENMASK(15, 0)) -+ -+#define VDPU_REG_BINIT_RLIST_F5(v) (((v) << 25) & GENMASK(29, 25)) -+#define VDPU_REG_BINIT_RLIST_F4(v) (((v) << 20) & GENMASK(24, 20)) -+#define VDPU_REG_BINIT_RLIST_F3(v) (((v) << 15) & GENMASK(19, 15)) -+#define VDPU_REG_BINIT_RLIST_F2(v) (((v) << 10) & GENMASK(14, 10)) -+#define VDPU_REG_BINIT_RLIST_F1(v) (((v) << 5) & GENMASK(9, 5)) -+#define VDPU_REG_BINIT_RLIST_F0(v) (((v) << 0) & GENMASK(4, 0)) -+ -+#define VDPU_REG_BINIT_RLIST_F11(v) (((v) << 25) & GENMASK(29, 25)) -+#define VDPU_REG_BINIT_RLIST_F10(v) (((v) << 20) & GENMASK(24, 20)) -+#define VDPU_REG_BINIT_RLIST_F9(v) (((v) << 15) & GENMASK(19, 15)) -+#define VDPU_REG_BINIT_RLIST_F8(v) (((v) << 10) & GENMASK(14, 10)) -+#define VDPU_REG_BINIT_RLIST_F7(v) (((v) << 5) & GENMASK(9, 5)) -+#define VDPU_REG_BINIT_RLIST_F6(v) (((v) << 0) & GENMASK(4, 0)) -+ -+#define VDPU_REG_BINIT_RLIST_F15(v) (((v) << 15) & GENMASK(19, 15)) -+#define VDPU_REG_BINIT_RLIST_F14(v) (((v) << 10) & GENMASK(14, 10)) -+#define VDPU_REG_BINIT_RLIST_F13(v) (((v) << 5) & GENMASK(9, 5)) -+#define VDPU_REG_BINIT_RLIST_F12(v) (((v) << 0) & GENMASK(4, 0)) -+ -+#define VDPU_REG_BINIT_RLIST_B5(v) (((v) << 25) & GENMASK(29, 25)) -+#define VDPU_REG_BINIT_RLIST_B4(v) (((v) << 20) & GENMASK(24, 20)) -+#define VDPU_REG_BINIT_RLIST_B3(v) (((v) << 15) & GENMASK(19, 15)) -+#define VDPU_REG_BINIT_RLIST_B2(v) (((v) << 10) & GENMASK(14, 10)) -+#define VDPU_REG_BINIT_RLIST_B1(v) (((v) << 5) & GENMASK(9, 5)) -+#define VDPU_REG_BINIT_RLIST_B0(v) (((v) << 0) & GENMASK(4, 0)) -+ -+#define VDPU_REG_BINIT_RLIST_B11(v) (((v) << 25) & GENMASK(29, 25)) -+#define VDPU_REG_BINIT_RLIST_B10(v) (((v) << 20) & GENMASK(24, 20)) -+#define VDPU_REG_BINIT_RLIST_B9(v) (((v) << 15) & GENMASK(19, 15)) -+#define VDPU_REG_BINIT_RLIST_B8(v) (((v) << 10) & GENMASK(14, 10)) -+#define VDPU_REG_BINIT_RLIST_B7(v) (((v) << 5) & GENMASK(9, 5)) -+#define VDPU_REG_BINIT_RLIST_B6(v) (((v) << 0) & GENMASK(4, 0)) -+ -+#define VDPU_REG_BINIT_RLIST_B15(v) (((v) << 15) & GENMASK(19, 15)) -+#define VDPU_REG_BINIT_RLIST_B14(v) (((v) << 10) & GENMASK(14, 10)) -+#define VDPU_REG_BINIT_RLIST_B13(v) (((v) << 5) & GENMASK(9, 5)) -+#define VDPU_REG_BINIT_RLIST_B12(v) (((v) << 0) & GENMASK(4, 0)) -+ -+#define VDPU_REG_PINIT_RLIST_F3(v) (((v) << 15) & GENMASK(19, 15)) -+#define VDPU_REG_PINIT_RLIST_F2(v) (((v) << 10) & GENMASK(14, 10)) -+#define VDPU_REG_PINIT_RLIST_F1(v) (((v) << 5) & GENMASK(9, 5)) -+#define VDPU_REG_PINIT_RLIST_F0(v) (((v) << 0) & GENMASK(4, 0)) -+ -+#define VDPU_REG_REFER_LTERM_E(v) (((v) << 0) & GENMASK(31, 0)) -+ -+#define VDPU_REG_REFER_VALID_E(v) (((v) << 0) & GENMASK(31, 0)) -+ -+#define VDPU_REG_STRM_START_BIT(v) (((v) << 0) & GENMASK(5, 0)) -+ -+#define VDPU_REG_CH_QP_OFFSET2(v) (((v) << 22) & GENMASK(26, 22)) -+#define VDPU_REG_CH_QP_OFFSET(v) (((v) << 17) & GENMASK(21, 17)) -+#define VDPU_REG_PIC_MB_HEIGHT_P(v) (((v) << 9) & GENMASK(16, 9)) -+#define VDPU_REG_PIC_MB_WIDTH(v) (((v) << 0) & GENMASK(8, 0)) -+ -+#define VDPU_REG_WEIGHT_BIPR_IDC(v) (((v) << 16) & GENMASK(17, 16)) -+#define VDPU_REG_REF_FRAMES(v) (((v) << 0) & GENMASK(4, 0)) -+ -+#define VDPU_REG_FILT_CTRL_PRES(v) ((v) ? BIT(31) : 0) -+#define VDPU_REG_RDPIC_CNT_PRES(v) ((v) ? BIT(30) : 0) -+#define VDPU_REG_FRAMENUM_LEN(v) (((v) << 16) & GENMASK(20, 16)) -+#define VDPU_REG_FRAMENUM(v) (((v) << 0) & GENMASK(15, 0)) -+ -+#define VDPU_REG_REFPIC_MK_LEN(v) (((v) << 16) & GENMASK(26, 16)) -+#define VDPU_REG_IDR_PIC_ID(v) (((v) << 0) & GENMASK(15, 0)) -+ -+#define VDPU_REG_PPS_ID(v) (((v) << 24) & GENMASK(31, 24)) -+#define VDPU_REG_REFIDX1_ACTIVE(v) (((v) << 19) & GENMASK(23, 19)) -+#define VDPU_REG_REFIDX0_ACTIVE(v) (((v) << 14) & GENMASK(18, 14)) -+#define VDPU_REG_POC_LENGTH(v) (((v) << 0) & GENMASK(7, 0)) -+ -+#define VDPU_REG_IDR_PIC_E(v) ((v) ? BIT(8) : 0) -+#define VDPU_REG_DIR_8X8_INFER_E(v) ((v) ? BIT(7) : 0) -+#define VDPU_REG_BLACKWHITE_E(v) ((v) ? BIT(6) : 0) -+#define VDPU_REG_CABAC_E(v) ((v) ? BIT(5) : 0) -+#define VDPU_REG_WEIGHT_PRED_E(v) ((v) ? BIT(4) : 0) -+#define VDPU_REG_CONST_INTRA_E(v) ((v) ? BIT(3) : 0) -+#define VDPU_REG_8X8TRANS_FLAG_E(v) ((v) ? BIT(2) : 0) -+#define VDPU_REG_TYPE1_QUANT_E(v) ((v) ? BIT(1) : 0) -+#define VDPU_REG_FIELDPIC_FLAG_E(v) ((v) ? BIT(0) : 0) -+ -+void rk3399_vpu_h264_dec_run(struct hantro_ctx *ctx) -+{ -+ struct hantro_dev *vpu = ctx->dev; -+ struct vb2_v4l2_buffer *src_buf, *dst_buf; -+ const struct hantro_h264_dec_ctrls *ctrls; -+ const struct v4l2_ctrl_h264_decode_params *decode; -+ const struct v4l2_ctrl_h264_slice_params *slices; -+ const struct v4l2_ctrl_h264_sps *sps; -+ const struct v4l2_ctrl_h264_pps *pps; -+ const u8 *b0_reflist, *b1_reflist, *p_reflist; -+ dma_addr_t addr; -+ size_t offset = 0; -+ u32 reg; -+ -+ /* Prepare the H264 decoder context. */ -+ if (hantro_h264_dec_prepare_run(ctx)) -+ return; -+ -+ src_buf = hantro_get_src_buf(ctx); -+ dst_buf = hantro_get_dst_buf(ctx); -+ -+ ctrls = &ctx->h264_dec.ctrls; -+ decode = ctrls->decode; -+ slices = ctrls->slices; -+ sps = ctrls->sps; -+ pps = ctrls->pps; -+ -+ b0_reflist = ctx->h264_dec.reflists.b0; -+ b1_reflist = ctx->h264_dec.reflists.b1; -+ p_reflist = ctx->h264_dec.reflists.p; -+ -+ reg = VDPU_REG_DEC_ADV_PRE_DIS(0) | -+ VDPU_REG_DEC_SCMD_DIS(0) | -+ VDPU_REG_FILTERING_DIS(0) | -+ VDPU_REG_PIC_FIXED_QUANT(0) | -+ VDPU_REG_DEC_LATENCY(0); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(50)); -+ -+ reg = VDPU_REG_INIT_QP(pps->pic_init_qp_minus26 + 26) | -+ VDPU_REG_STREAM_LEN(vb2_get_plane_payload(&src_buf->vb2_buf, 0)); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(51)); -+ -+ reg = VDPU_REG_APF_THRESHOLD(8) | -+ VDPU_REG_STARTMB_X(0) | -+ VDPU_REG_STARTMB_Y(0); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(52)); -+ -+ reg = VDPU_REG_DEC_MODE(0); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(53)); -+ -+ reg = VDPU_REG_DEC_STRENDIAN_E(1) | -+ VDPU_REG_DEC_STRSWAP32_E(1) | -+ VDPU_REG_DEC_OUTSWAP32_E(1) | -+ VDPU_REG_DEC_INSWAP32_E(1) | -+ VDPU_REG_DEC_OUT_ENDIAN(1) | -+ VDPU_REG_DEC_IN_ENDIAN(0); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(54)); -+ -+ reg = VDPU_REG_DEC_DATA_DISC_E(0) | -+ VDPU_REG_DEC_MAX_BURST(16) | -+ VDPU_REG_DEC_AXI_WR_ID(0) | -+ VDPU_REG_DEC_AXI_RD_ID(0xff); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(56)); -+ -+ reg = VDPU_REG_START_CODE_E(1) | -+ VDPU_REG_CH_8PIX_ILEAV_E(0) | -+ VDPU_REG_RLC_MODE_E(0) | -+ VDPU_REG_PIC_INTERLACE_E(!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY) && (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD || slices[0].flags & V4L2_H264_SLICE_FLAG_FIELD_PIC)) | -+ VDPU_REG_PIC_FIELDMODE_E(slices[0].flags & V4L2_H264_SLICE_FLAG_FIELD_PIC) | -+ VDPU_REG_PIC_TOPFIELD_E(!(slices[0].flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD)) | -+ VDPU_REG_WRITE_MVS_E(sps->profile_idc > 66 && decode->nal_ref_idc) | -+ VDPU_REG_SEQ_MBAFF_E(sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD) | -+ VDPU_REG_PICORD_COUNT_E(sps->profile_idc > 66) | -+ VDPU_REG_DEC_TIMEOUT_E(1) | -+ VDPU_REG_DEC_CLK_GATE_E(1); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(57)); -+ -+ reg = VDPU_REG_PRED_BC_TAP_0_0(1) | -+ VDPU_REG_PRED_BC_TAP_0_1((u32)-5) | -+ VDPU_REG_PRED_BC_TAP_0_2(20); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(59)); -+ -+ reg = VDPU_REG_REFBU_E(0); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(65)); -+ -+ reg = VDPU_REG_PINIT_RLIST_F9(p_reflist[9]) | -+ VDPU_REG_PINIT_RLIST_F8(p_reflist[8]) | -+ VDPU_REG_PINIT_RLIST_F7(p_reflist[7]) | -+ VDPU_REG_PINIT_RLIST_F6(p_reflist[6]) | -+ VDPU_REG_PINIT_RLIST_F5(p_reflist[5]) | -+ VDPU_REG_PINIT_RLIST_F4(p_reflist[4]); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(74)); -+ -+ reg = VDPU_REG_PINIT_RLIST_F15(p_reflist[15]) | -+ VDPU_REG_PINIT_RLIST_F14(p_reflist[14]) | -+ VDPU_REG_PINIT_RLIST_F13(p_reflist[13]) | -+ VDPU_REG_PINIT_RLIST_F12(p_reflist[12]) | -+ VDPU_REG_PINIT_RLIST_F11(p_reflist[11]) | -+ VDPU_REG_PINIT_RLIST_F10(p_reflist[10]); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(75)); -+ -+ reg = VDPU_REG_REFER1_NBR(hantro_h264_get_ref_nbr(ctx, 1)) | -+ VDPU_REG_REFER0_NBR(hantro_h264_get_ref_nbr(ctx, 0)); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(76)); -+ -+ reg = VDPU_REG_REFER3_NBR(hantro_h264_get_ref_nbr(ctx, 3)) | -+ VDPU_REG_REFER2_NBR(hantro_h264_get_ref_nbr(ctx, 2)); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(77)); -+ -+ reg = VDPU_REG_REFER5_NBR(hantro_h264_get_ref_nbr(ctx, 5)) | -+ VDPU_REG_REFER4_NBR(hantro_h264_get_ref_nbr(ctx, 4)); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(78)); -+ -+ reg = VDPU_REG_REFER7_NBR(hantro_h264_get_ref_nbr(ctx, 7)) | -+ VDPU_REG_REFER6_NBR(hantro_h264_get_ref_nbr(ctx, 6)); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(79)); -+ -+ reg = VDPU_REG_REFER9_NBR(hantro_h264_get_ref_nbr(ctx, 9)) | -+ VDPU_REG_REFER8_NBR(hantro_h264_get_ref_nbr(ctx, 8)); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(80)); -+ -+ reg = VDPU_REG_REFER11_NBR(hantro_h264_get_ref_nbr(ctx, 11)) | -+ VDPU_REG_REFER10_NBR(hantro_h264_get_ref_nbr(ctx, 10)); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(81)); -+ -+ reg = VDPU_REG_REFER13_NBR(hantro_h264_get_ref_nbr(ctx, 13)) | -+ VDPU_REG_REFER12_NBR(hantro_h264_get_ref_nbr(ctx, 12)); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(82)); -+ -+ reg = VDPU_REG_REFER15_NBR(hantro_h264_get_ref_nbr(ctx, 15)) | -+ VDPU_REG_REFER14_NBR(hantro_h264_get_ref_nbr(ctx, 14)); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(83)); -+ -+ reg = VDPU_REG_BINIT_RLIST_F5(b0_reflist[5]) | -+ VDPU_REG_BINIT_RLIST_F4(b0_reflist[4]) | -+ VDPU_REG_BINIT_RLIST_F3(b0_reflist[3]) | -+ VDPU_REG_BINIT_RLIST_F2(b0_reflist[2]) | -+ VDPU_REG_BINIT_RLIST_F1(b0_reflist[1]) | -+ VDPU_REG_BINIT_RLIST_F0(b0_reflist[0]); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(100)); -+ -+ reg = VDPU_REG_BINIT_RLIST_F11(b0_reflist[11]) | -+ VDPU_REG_BINIT_RLIST_F10(b0_reflist[10]) | -+ VDPU_REG_BINIT_RLIST_F9(b0_reflist[9]) | -+ VDPU_REG_BINIT_RLIST_F8(b0_reflist[8]) | -+ VDPU_REG_BINIT_RLIST_F7(b0_reflist[7]) | -+ VDPU_REG_BINIT_RLIST_F6(b0_reflist[6]); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(101)); -+ -+ reg = VDPU_REG_BINIT_RLIST_F15(b0_reflist[15]) | -+ VDPU_REG_BINIT_RLIST_F14(b0_reflist[14]) | -+ VDPU_REG_BINIT_RLIST_F13(b0_reflist[13]) | -+ VDPU_REG_BINIT_RLIST_F12(b0_reflist[12]); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(102)); -+ -+ reg = VDPU_REG_BINIT_RLIST_B5(b1_reflist[5]) | -+ VDPU_REG_BINIT_RLIST_B4(b1_reflist[4]) | -+ VDPU_REG_BINIT_RLIST_B3(b1_reflist[3]) | -+ VDPU_REG_BINIT_RLIST_B2(b1_reflist[2]) | -+ VDPU_REG_BINIT_RLIST_B1(b1_reflist[1]) | -+ VDPU_REG_BINIT_RLIST_B0(b1_reflist[0]); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(103)); -+ -+ reg = VDPU_REG_BINIT_RLIST_B11(b1_reflist[11]) | -+ VDPU_REG_BINIT_RLIST_B10(b1_reflist[10]) | -+ VDPU_REG_BINIT_RLIST_B9(b1_reflist[9]) | -+ VDPU_REG_BINIT_RLIST_B8(b1_reflist[8]) | -+ VDPU_REG_BINIT_RLIST_B7(b1_reflist[7]) | -+ VDPU_REG_BINIT_RLIST_B6(b1_reflist[6]); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(104)); -+ -+ reg = VDPU_REG_BINIT_RLIST_B15(b1_reflist[15]) | -+ VDPU_REG_BINIT_RLIST_B14(b1_reflist[14]) | -+ VDPU_REG_BINIT_RLIST_B13(b1_reflist[13]) | -+ VDPU_REG_BINIT_RLIST_B12(b1_reflist[12]); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(105)); -+ -+ reg = VDPU_REG_PINIT_RLIST_F3(p_reflist[3]) | -+ VDPU_REG_PINIT_RLIST_F2(p_reflist[2]) | -+ VDPU_REG_PINIT_RLIST_F1(p_reflist[1]) | -+ VDPU_REG_PINIT_RLIST_F0(p_reflist[0]); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(106)); -+ -+ reg = VDPU_REG_REFER_LTERM_E(ctx->h264_dec.dpb_longterm); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(107)); -+ -+ reg = VDPU_REG_REFER_VALID_E(ctx->h264_dec.dpb_valid); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(108)); -+ -+ reg = VDPU_REG_STRM_START_BIT(0); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(109)); -+ -+ reg = VDPU_REG_CH_QP_OFFSET2(pps->second_chroma_qp_index_offset) | -+ VDPU_REG_CH_QP_OFFSET(pps->chroma_qp_index_offset) | -+ VDPU_REG_PIC_MB_HEIGHT_P(MB_HEIGHT(ctx->src_fmt.height)) | -+ VDPU_REG_PIC_MB_WIDTH(MB_WIDTH(ctx->src_fmt.width)); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(110)); -+ -+ reg = VDPU_REG_WEIGHT_BIPR_IDC(pps->weighted_bipred_idc) | -+ VDPU_REG_REF_FRAMES(sps->max_num_ref_frames); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(111)); -+ -+ reg = VDPU_REG_FILT_CTRL_PRES(pps->flags & V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT) | -+ VDPU_REG_RDPIC_CNT_PRES(pps->flags & V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT) | -+ VDPU_REG_FRAMENUM_LEN(sps->log2_max_frame_num_minus4 + 4) | -+ VDPU_REG_FRAMENUM(slices[0].frame_num); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(112)); -+ -+ reg = VDPU_REG_REFPIC_MK_LEN(slices[0].dec_ref_pic_marking_bit_size) | -+ VDPU_REG_IDR_PIC_ID(slices[0].idr_pic_id); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(113)); -+ -+ reg = VDPU_REG_PPS_ID(slices[0].pic_parameter_set_id) | -+ VDPU_REG_REFIDX1_ACTIVE(pps->num_ref_idx_l1_default_active_minus1 + 1) | -+ VDPU_REG_REFIDX0_ACTIVE(pps->num_ref_idx_l0_default_active_minus1 + 1) | -+ VDPU_REG_POC_LENGTH(slices[0].pic_order_cnt_bit_size); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(114)); -+ -+ reg = VDPU_REG_IDR_PIC_E(decode->flags & V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC) | -+ VDPU_REG_DIR_8X8_INFER_E(sps->flags & V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE) | -+ VDPU_REG_BLACKWHITE_E(sps->profile_idc >= 100 && sps->chroma_format_idc == 0) | -+ VDPU_REG_CABAC_E(pps->flags & V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE) | -+ VDPU_REG_WEIGHT_PRED_E(pps->flags & V4L2_H264_PPS_FLAG_WEIGHTED_PRED) | -+ VDPU_REG_CONST_INTRA_E(pps->flags & V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED) | -+ VDPU_REG_8X8TRANS_FLAG_E(pps->flags & V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE) | -+ VDPU_REG_TYPE1_QUANT_E(1) | -+ VDPU_REG_FIELDPIC_FLAG_E(!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY)); -+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(115)); -+ -+ /* Auxiliary buffer prepared in hantro_g1_h264_dec_prepare_table(). */ -+ vdpu_write_relaxed(vpu, ctx->h264_dec.priv.dma, VDPU_REG_QTABLE_BASE); -+ -+ /* Source (stream) buffer. */ -+ addr = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); -+ vdpu_write_relaxed(vpu, addr, VDPU_REG_RLC_VLC_BASE); -+ -+ /* Destination (decoded frame) buffer. */ -+ addr = hantro_get_dec_buf_addr(ctx, &dst_buf->vb2_buf); -+ /* Adjust dma addr to start at second line for bottom field */ -+ if (slices[0].flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD) -+ offset = ALIGN(ctx->src_fmt.width, MB_DIM); -+ vdpu_write_relaxed(vpu, addr + offset, VDPU_REG_DEC_OUT_BASE); -+ -+ /* Higher profiles require DMV buffer appended to reference frames. */ -+ if (sps->profile_idc > 66 && decode->nal_ref_idc) { -+ unsigned int bytes_per_mb = 384; -+ -+ /* DMV buffer for monochrome start directly after Y-plane */ -+ if (sps->profile_idc >= 100 && sps->chroma_format_idc == 0) -+ bytes_per_mb = 256; -+ offset = bytes_per_mb * MB_WIDTH(ctx->src_fmt.width) * -+ MB_HEIGHT(ctx->src_fmt.height); -+ -+ /* -+ * DMV buffer is split in two for field encoded frames, -+ * adjust offset for bottom field -+ */ -+ if (slices[0].flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD) -+ offset += 32 * MB_WIDTH(ctx->src_fmt.width) * -+ MB_HEIGHT(ctx->src_fmt.height); -+ vdpu_write_relaxed(vpu, addr + offset, VDPU_REG_DIR_MV_BASE); -+ } -+ -+ vdpu_write_relaxed(vpu, hantro_h264_get_ref_buf(ctx, 0), VDPU_REG_REFER0_BASE); -+ vdpu_write_relaxed(vpu, hantro_h264_get_ref_buf(ctx, 1), VDPU_REG_REFER1_BASE); -+ vdpu_write_relaxed(vpu, hantro_h264_get_ref_buf(ctx, 2), VDPU_REG_REFER2_BASE); -+ vdpu_write_relaxed(vpu, hantro_h264_get_ref_buf(ctx, 3), VDPU_REG_REFER3_BASE); -+ vdpu_write_relaxed(vpu, hantro_h264_get_ref_buf(ctx, 4), VDPU_REG_REFER4_BASE); -+ vdpu_write_relaxed(vpu, hantro_h264_get_ref_buf(ctx, 5), VDPU_REG_REFER5_BASE); -+ vdpu_write_relaxed(vpu, hantro_h264_get_ref_buf(ctx, 6), VDPU_REG_REFER6_BASE); -+ vdpu_write_relaxed(vpu, hantro_h264_get_ref_buf(ctx, 7), VDPU_REG_REFER7_BASE); -+ vdpu_write_relaxed(vpu, hantro_h264_get_ref_buf(ctx, 8), VDPU_REG_REFER8_BASE); -+ vdpu_write_relaxed(vpu, hantro_h264_get_ref_buf(ctx, 9), VDPU_REG_REFER9_BASE); -+ vdpu_write_relaxed(vpu, hantro_h264_get_ref_buf(ctx, 10), VDPU_REG_REFER10_BASE); -+ vdpu_write_relaxed(vpu, hantro_h264_get_ref_buf(ctx, 11), VDPU_REG_REFER11_BASE); -+ vdpu_write_relaxed(vpu, hantro_h264_get_ref_buf(ctx, 12), VDPU_REG_REFER12_BASE); -+ vdpu_write_relaxed(vpu, hantro_h264_get_ref_buf(ctx, 13), VDPU_REG_REFER13_BASE); -+ vdpu_write_relaxed(vpu, hantro_h264_get_ref_buf(ctx, 14), VDPU_REG_REFER14_BASE); -+ vdpu_write_relaxed(vpu, hantro_h264_get_ref_buf(ctx, 15), VDPU_REG_REFER15_BASE); -+ -+ hantro_end_prepare_run(ctx); -+ -+ /* Start decoding! */ -+ reg = vdpu_read(vpu, VDPU_SWREG(57)) | VDPU_REG_DEC_E(1); -+ vdpu_write(vpu, reg, VDPU_SWREG(57)); -+} --- -2.17.1 - - -From c6ad44bc8c4de5b6e468ee4449bfa181ff564f5a Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 18 Aug 2019 10:40:31 +0000 -Subject: [PATCH] media: hantro: Enable H264 decoding on RK3399 - -Signed-off-by: Jonas Karlman ---- - drivers/staging/media/hantro/rk3399_vpu_hw.c | 21 +++++++++++++++++++- - 1 file changed, 20 insertions(+), 1 deletion(-) - -diff --git a/drivers/staging/media/hantro/rk3399_vpu_hw.c b/drivers/staging/media/hantro/rk3399_vpu_hw.c -index 9ac1f2cb6a16..3e05cd2c870e 100644 ---- a/drivers/staging/media/hantro/rk3399_vpu_hw.c -+++ b/drivers/staging/media/hantro/rk3399_vpu_hw.c -@@ -60,6 +60,19 @@ static const struct hantro_fmt rk3399_vpu_dec_fmts[] = { - .fourcc = V4L2_PIX_FMT_NV12, - .codec_mode = HANTRO_MODE_NONE, - }, -+ { -+ .fourcc = V4L2_PIX_FMT_H264_SLICE, -+ .codec_mode = HANTRO_MODE_H264_DEC, -+ .max_depth = 2, -+ .frmsize = { -+ .min_width = 48, -+ .max_width = 1920, -+ .step_width = MB_DIM, -+ .min_height = 48, -+ .max_height = 1088, -+ .step_height = MB_DIM, -+ }, -+ }, - { - .fourcc = V4L2_PIX_FMT_MPEG2_SLICE, - .codec_mode = HANTRO_MODE_MPEG2_DEC, -@@ -161,6 +174,12 @@ static const struct hantro_codec_ops rk3399_vpu_codec_ops[] = { - .init = hantro_jpeg_enc_init, - .exit = hantro_jpeg_enc_exit, - }, -+ [HANTRO_MODE_H264_DEC] = { -+ .run = rk3399_vpu_h264_dec_run, -+ .reset = rk3399_vpu_dec_reset, -+ .init = hantro_h264_dec_init, -+ .exit = hantro_h264_dec_exit, -+ }, - [HANTRO_MODE_MPEG2_DEC] = { - .run = rk3399_vpu_mpeg2_dec_run, - .reset = rk3399_vpu_dec_reset, -@@ -196,7 +215,7 @@ const struct hantro_variant rk3399_vpu_variant = { - .dec_fmts = rk3399_vpu_dec_fmts, - .num_dec_fmts = ARRAY_SIZE(rk3399_vpu_dec_fmts), - .codec = HANTRO_JPEG_ENCODER | HANTRO_MPEG2_DECODER | -- HANTRO_VP8_DECODER, -+ HANTRO_VP8_DECODER | HANTRO_H264_DECODER, - .codec_ops = rk3399_vpu_codec_ops, - .irqs = rk3399_irqs, - .num_irqs = ARRAY_SIZE(rk3399_irqs), --- -2.17.1 - - -From 51ec7c26733bd0c96fc9ec7d80b18ee8110d0a7d Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 18 Aug 2019 10:40:31 +0000 -Subject: [PATCH] media: hantro: Enable H264 decoding on RK3328 - -RK3328 SoC has the same decoder IP block as RK3399, -lets enable H264 decoding on RK3328. - -Signed-off-by: Jonas Karlman ---- - drivers/staging/media/hantro/rk3399_vpu_hw.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/drivers/staging/media/hantro/rk3399_vpu_hw.c b/drivers/staging/media/hantro/rk3399_vpu_hw.c -index 3e05cd2c870e..78f878ca01ff 100644 ---- a/drivers/staging/media/hantro/rk3399_vpu_hw.c -+++ b/drivers/staging/media/hantro/rk3399_vpu_hw.c -@@ -232,7 +232,8 @@ const struct hantro_variant rk3328_vpu_variant = { - .dec_offset = 0x400, - .dec_fmts = rk3399_vpu_dec_fmts, - .num_dec_fmts = ARRAY_SIZE(rk3399_vpu_dec_fmts), -- .codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER, -+ .codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER | -+ HANTRO_H264_DECODER, - .codec_ops = rk3399_vpu_codec_ops, - .irqs = rk3328_irqs, - .num_irqs = ARRAY_SIZE(rk3328_irqs), --- -2.17.1 - diff --git a/patch/kernel/rk322x-current/01-linux-0015-fromlist-rga-for-rk322x.patch b/patch/kernel/rk322x-current/01-linux-0015-fromlist-rga-for-rk322x.patch deleted file mode 100644 index be186ba1c..000000000 --- a/patch/kernel/rk322x-current/01-linux-0015-fromlist-rga-for-rk322x.patch +++ /dev/null @@ -1,53 +0,0 @@ -Add a node to define the presence of RGA, a 2D raster -graphic acceleration unit. - -Signed-off-by: Justin Swartz ---- - arch/arm/boot/dts/rk322x.dtsi | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi -index 340ed6ccb..29d50bebc 100644 ---- a/arch/arm/boot/dts/rk322x.dtsi -+++ b/arch/arm/boot/dts/rk322x.dtsi -@@ -621,6 +621,17 @@ - status = "disabled"; - }; - -+ rga: rga@20060000 { -+ compatible = "rockchip,rk3228-rga", "rockchip,rk3288-rga"; -+ reg = <0x20060000 0x1000>; -+ interrupts = ; -+ clocks = <&cru ACLK_RGA>, <&cru HCLK_RGA>, <&cru SCLK_RGA>; -+ clock-names = "aclk", "hclk", "sclk"; -+ resets = <&cru SRST_RGA>, <&cru SRST_RGA_A>, <&cru SRST_RGA_H>; -+ reset-names = "core", "axi", "ahb"; -+ status = "disabled"; -+ }; -+ - iep_mmu: iommu@20070800 { - compatible = "rockchip,iommu"; - reg = <0x20070800 0x100>; - -Enable RGA for Mecer Xtreme Mini S6. - -Signed-off-by: Justin Swartz ---- - arch/arm/boot/dts/rk3229-xms6.dts | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/arch/arm/boot/dts/rk3229-xms6.dts b/arch/arm/boot/dts/rk3229-xms6.dts -index 679fc2b00..894f64a4a 100644 ---- a/arch/arm/boot/dts/rk3229-xms6.dts -+++ b/arch/arm/boot/dts/rk3229-xms6.dts -@@ -202,6 +202,10 @@ - status = "okay"; - }; - -+&rga { -+ status = "okay"; -+}; -+ - &sdmmc { - cap-mmc-highspeed; - disable-wp; diff --git a/patch/kernel/rk322x-current/01-linux-0015-hantro-set-of-small-cleanups-and-fixes.patch b/patch/kernel/rk322x-current/01-linux-0015-hantro-set-of-small-cleanups-and-fixes.patch deleted file mode 100644 index f83cb8f8d..000000000 --- a/patch/kernel/rk322x-current/01-linux-0015-hantro-set-of-small-cleanups-and-fixes.patch +++ /dev/null @@ -1,718 +0,0 @@ -diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c -index cc34c5ab7009..3070672e6b4f 100644 ---- a/drivers/media/v4l2-core/v4l2-mem2mem.c -+++ b/drivers/media/v4l2-core/v4l2-mem2mem.c -@@ -499,12 +499,21 @@ void v4l2_m2m_buf_done_and_job_finish(struct v4l2_m2m_dev *m2m_dev, - - if (WARN_ON(!src_buf || !dst_buf)) - goto unlock; -- v4l2_m2m_buf_done(src_buf, state); - dst_buf->is_held = src_buf->flags & V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF; - if (!dst_buf->is_held) { - v4l2_m2m_dst_buf_remove(m2m_ctx); - v4l2_m2m_buf_done(dst_buf, state); - } -+ /* -+ * If the request API is being used, returning the OUTPUT -+ * (src) buffer will wake-up any process waiting on the -+ * request file descriptor. -+ * -+ * Therefore, return the CAPTURE (dst) buffer first, -+ * to avoid signalling the request file descriptor -+ * before the CAPTURE buffer is done. -+ */ -+ v4l2_m2m_buf_done(src_buf, state); - schedule_next = _v4l2_m2m_job_finish(m2m_dev, m2m_ctx); - unlock: - spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); --- -2.17.1 - - -From 46fef6ecbc765dedaeef46339474529645f09404 Mon Sep 17 00:00:00 2001 -From: Ezequiel Garcia -Date: Wed, 18 Mar 2020 10:21:02 -0300 -Subject: [PATCH] hantro: Set buffers' zeroth plane payload in .buf_prepare - -Buffers' zeroth plane payload size is calculated at format -negotiation time, and so it can be set in .buf_prepare. - -Keep in mind that, to make this change easier, hantro_buf_prepare -is refactored, using the cedrus driver as reference. This results -in cleaner code as byproduct. - -Signed-off-by: Ezequiel Garcia ---- - drivers/staging/media/hantro/hantro_v4l2.c | 16 +++++++++++----- - 1 file changed, 11 insertions(+), 5 deletions(-) - -diff --git a/drivers/staging/media/hantro/hantro_v4l2.c b/drivers/staging/media/hantro/hantro_v4l2.c -index f4ae2cee0f18..3142ab6697d5 100644 ---- a/drivers/staging/media/hantro/hantro_v4l2.c -+++ b/drivers/staging/media/hantro/hantro_v4l2.c -@@ -608,7 +608,7 @@ hantro_queue_setup(struct vb2_queue *vq, unsigned int *num_buffers, - } - - static int --hantro_buf_plane_check(struct vb2_buffer *vb, const struct hantro_fmt *vpu_fmt, -+hantro_buf_plane_check(struct vb2_buffer *vb, - struct v4l2_pix_format_mplane *pixfmt) - { - unsigned int sz; -@@ -630,12 +630,18 @@ static int hantro_buf_prepare(struct vb2_buffer *vb) - { - struct vb2_queue *vq = vb->vb2_queue; - struct hantro_ctx *ctx = vb2_get_drv_priv(vq); -+ struct v4l2_pix_format_mplane *pix_fmt; -+ int ret; - - if (V4L2_TYPE_IS_OUTPUT(vq->type)) -- return hantro_buf_plane_check(vb, ctx->vpu_src_fmt, -- &ctx->src_fmt); -- -- return hantro_buf_plane_check(vb, ctx->vpu_dst_fmt, &ctx->dst_fmt); -+ pix_fmt = &ctx->src_fmt; -+ else -+ pix_fmt = &ctx->dst_fmt; -+ ret = hantro_buf_plane_check(vb, pix_fmt); -+ if (ret) -+ return ret; -+ vb2_set_plane_payload(vb, 0, pix_fmt->plane_fmt[0].sizeimage); -+ return 0; - } - - static void hantro_buf_queue(struct vb2_buffer *vb) --- -2.17.1 - - -From 49b98070ac9cbd4e731a84f0a3c10e6dd803d37c Mon Sep 17 00:00:00 2001 -From: Ezequiel Garcia -Date: Wed, 18 Mar 2020 10:21:03 -0300 -Subject: [PATCH] hantro: Use v4l2_m2m_buf_done_and_job_finish - -Let the core sort out the nuances of returning buffers -to userspace, by using the v4l2_m2m_buf_done_and_job_finish -helper. - -This change also removes usage of buffer sequence fields, -which shouldn't have any meaning for stateless decoders. - -Signed-off-by: Ezequiel Garcia -Nacked-by: Hans Verkuil ---- - drivers/staging/media/hantro/hantro_drv.c | 27 ++++++++--------------- - 1 file changed, 9 insertions(+), 18 deletions(-) - -diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c -index c98835326135..dd503918a017 100644 ---- a/drivers/staging/media/hantro/hantro_drv.c -+++ b/drivers/staging/media/hantro/hantro_drv.c -@@ -94,32 +94,23 @@ static void hantro_job_finish(struct hantro_dev *vpu, - unsigned int bytesused, - enum vb2_buffer_state result) - { -- struct vb2_v4l2_buffer *src, *dst; - int ret; - - pm_runtime_mark_last_busy(vpu->dev); - pm_runtime_put_autosuspend(vpu->dev); - clk_bulk_disable(vpu->variant->num_clocks, vpu->clocks); - -- src = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); -- dst = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); -- -- if (WARN_ON(!src)) -- return; -- if (WARN_ON(!dst)) -- return; -- -- src->sequence = ctx->sequence_out++; -- dst->sequence = ctx->sequence_cap++; -- -- ret = ctx->buf_finish(ctx, &dst->vb2_buf, bytesused); -- if (ret) -- result = VB2_BUF_STATE_ERROR; -+ if (ctx->buf_finish) { -+ struct vb2_v4l2_buffer *dst; - -- v4l2_m2m_buf_done(src, result); -- v4l2_m2m_buf_done(dst, result); -+ dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); -+ ret = ctx->buf_finish(ctx, &dst->vb2_buf, bytesused); -+ if (ret) -+ result = VB2_BUF_STATE_ERROR; -+ } - -- v4l2_m2m_job_finish(vpu->m2m_dev, ctx->fh.m2m_ctx); -+ v4l2_m2m_buf_done_and_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx, -+ result); - } - - void hantro_irq_done(struct hantro_dev *vpu, unsigned int bytesused, --- -2.17.1 - - -From ee3c913094e5776a0b1270b78ecce8a5e9803a42 Mon Sep 17 00:00:00 2001 -From: Ezequiel Garcia -Date: Wed, 18 Mar 2020 10:21:04 -0300 -Subject: [PATCH] hantro: Remove unneeded hantro_dec_buf_finish - -Since now .buf_prepare takes care of setting the -buffer payload size, we can get rid of this, -at least for decoders. - -Signed-off-by: Ezequiel Garcia ---- - drivers/staging/media/hantro/hantro_drv.c | 10 ---------- - 1 file changed, 10 deletions(-) - -diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c -index dd503918a017..a732beeb3bb6 100644 ---- a/drivers/staging/media/hantro/hantro_drv.c -+++ b/drivers/staging/media/hantro/hantro_drv.c -@@ -80,15 +80,6 @@ hantro_enc_buf_finish(struct hantro_ctx *ctx, struct vb2_buffer *buf, - return 0; - } - --static int --hantro_dec_buf_finish(struct hantro_ctx *ctx, struct vb2_buffer *buf, -- unsigned int bytesused) --{ -- /* For decoders set bytesused as per the output picture. */ -- buf->planes[0].bytesused = ctx->dst_fmt.plane_fmt[0].sizeimage; -- return 0; --} -- - static void hantro_job_finish(struct hantro_dev *vpu, - struct hantro_ctx *ctx, - unsigned int bytesused, -@@ -412,7 +403,6 @@ static int hantro_open(struct file *filp) - ctx->buf_finish = hantro_enc_buf_finish; - } else if (func->id == MEDIA_ENT_F_PROC_VIDEO_DECODER) { - allowed_codecs = vpu->variant->codec & HANTRO_DECODERS; -- ctx->buf_finish = hantro_dec_buf_finish; - } else { - ret = -ENODEV; - goto err_ctx_free; --- -2.17.1 - - -From 403b36c2db7e39b46f8e0f6a363af6763373933d Mon Sep 17 00:00:00 2001 -From: Ezequiel Garcia -Date: Wed, 18 Mar 2020 10:21:05 -0300 -Subject: [PATCH] hantro: Move H264 motion vector calculation to a helper - -Move the extra bytes calculation that are needed for H264 -motion vector to a helper. This is just a cosmetic cleanup. - -Signed-off-by: Ezequiel Garcia ---- - drivers/staging/media/hantro/hantro.h | 4 --- - drivers/staging/media/hantro/hantro_hw.h | 31 ++++++++++++++++++++++ - drivers/staging/media/hantro/hantro_v4l2.c | 25 ++--------------- - 3 files changed, 33 insertions(+), 27 deletions(-) - -diff --git a/drivers/staging/media/hantro/hantro.h b/drivers/staging/media/hantro/hantro.h -index b0faa43b3f79..1a010d438ac2 100644 ---- a/drivers/staging/media/hantro/hantro.h -+++ b/drivers/staging/media/hantro/hantro.h -@@ -26,10 +26,6 @@ - - #include "hantro_hw.h" - --#define MB_DIM 16 --#define MB_WIDTH(w) DIV_ROUND_UP(w, MB_DIM) --#define MB_HEIGHT(h) DIV_ROUND_UP(h, MB_DIM) -- - struct hantro_ctx; - struct hantro_codec_ops; - -diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h -index 4a64873bf332..33c1ce169203 100644 ---- a/drivers/staging/media/hantro/hantro_hw.h -+++ b/drivers/staging/media/hantro/hantro_hw.h -@@ -18,6 +18,10 @@ - - #define DEC_8190_ALIGN_MASK 0x07U - -+#define MB_DIM 16 -+#define MB_WIDTH(w) DIV_ROUND_UP(w, MB_DIM) -+#define MB_HEIGHT(h) DIV_ROUND_UP(h, MB_DIM) -+ - struct hantro_dev; - struct hantro_ctx; - struct hantro_buf; -@@ -180,6 +184,33 @@ void rk3399_vpu_h264_dec_run(struct hantro_ctx *ctx); - int hantro_h264_dec_init(struct hantro_ctx *ctx); - void hantro_h264_dec_exit(struct hantro_ctx *ctx); - -+static inline size_t -+hantro_h264_mv_size(unsigned int width, unsigned int height) -+{ -+ /* -+ * A decoded 8-bit 4:2:0 NV12 frame may need memory for up to -+ * 448 bytes per macroblock with additional 32 bytes on -+ * multi-core variants. -+ * -+ * The H264 decoder needs extra space on the output buffers -+ * to store motion vectors. This is needed for reference -+ * frames and only if the format is non-post-processed NV12. -+ * -+ * Memory layout is as follow: -+ * -+ * +---------------------------+ -+ * | Y-plane 256 bytes x MBs | -+ * +---------------------------+ -+ * | UV-plane 128 bytes x MBs | -+ * +---------------------------+ -+ * | MV buffer 64 bytes x MBs | -+ * +---------------------------+ -+ * | MC sync 32 bytes | -+ * +---------------------------+ -+ */ -+ return 64 * MB_WIDTH(width) * MB_WIDTH(height) + 32; -+} -+ - void hantro_g1_mpeg2_dec_run(struct hantro_ctx *ctx); - void rk3399_vpu_mpeg2_dec_run(struct hantro_ctx *ctx); - void hantro_mpeg2_dec_copy_qtable(u8 *qtable, -diff --git a/drivers/staging/media/hantro/hantro_v4l2.c b/drivers/staging/media/hantro/hantro_v4l2.c -index 3142ab6697d5..458b502ff01b 100644 ---- a/drivers/staging/media/hantro/hantro_v4l2.c -+++ b/drivers/staging/media/hantro/hantro_v4l2.c -@@ -273,32 +273,11 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f, - /* Fill remaining fields */ - v4l2_fill_pixfmt_mp(pix_mp, fmt->fourcc, pix_mp->width, - pix_mp->height); -- /* -- * A decoded 8-bit 4:2:0 NV12 frame may need memory for up to -- * 448 bytes per macroblock with additional 32 bytes on -- * multi-core variants. -- * -- * The H264 decoder needs extra space on the output buffers -- * to store motion vectors. This is needed for reference -- * frames and only if the format is non-post-processed NV12. -- * -- * Memory layout is as follow: -- * -- * +---------------------------+ -- * | Y-plane 256 bytes x MBs | -- * +---------------------------+ -- * | UV-plane 128 bytes x MBs | -- * +---------------------------+ -- * | MV buffer 64 bytes x MBs | -- * +---------------------------+ -- * | MC sync 32 bytes | -- * +---------------------------+ -- */ - if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_H264_SLICE && - !hantro_needs_postproc(ctx, fmt)) - pix_mp->plane_fmt[0].sizeimage += -- 64 * MB_WIDTH(pix_mp->width) * -- MB_WIDTH(pix_mp->height) + 32; -+ hantro_h264_mv_size(pix_mp->width, -+ pix_mp->height); - } else if (!pix_mp->plane_fmt[0].sizeimage) { - /* - * For coded formats the application can specify --- -2.17.1 - - -From 220559bea572812494ac528eb4bb3af770748641 Mon Sep 17 00:00:00 2001 -From: Ezequiel Garcia -Date: Wed, 18 Mar 2020 10:21:06 -0300 -Subject: [PATCH] hantro: Refactor for V4L2 API spec compliancy - -Refactor how S_FMT and TRY_FMT are handled, and also make sure -internal initial format and format reset are done properly. - -The latter is achieved by making sure the same hantro_{set,try}_fmt -helpers are called on all paths that set the format (which is -part of the driver state). - -This commit removes the following v4l2-compliance warnings: - -test VIDIOC_G_FMT: OK - fail: v4l2-test-formats.cpp(711): Video Capture Multiplanar: TRY_FMT(G_FMT) != G_FMT -test VIDIOC_TRY_FMT: FAIL - fail: v4l2-test-formats.cpp(1116): Video Capture Multiplanar: S_FMT(G_FMT) != G_FMT -test VIDIOC_S_FMT: FAIL - -Reported-by: Nicolas Dufresne -Signed-off-by: Ezequiel Garcia ---- - drivers/staging/media/hantro/hantro.h | 3 +- - drivers/staging/media/hantro/hantro_v4l2.c | 70 ++++++++++++++-------- - 2 files changed, 47 insertions(+), 26 deletions(-) - -diff --git a/drivers/staging/media/hantro/hantro.h b/drivers/staging/media/hantro/hantro.h -index 1a010d438ac2..f0aca46969f9 100644 ---- a/drivers/staging/media/hantro/hantro.h -+++ b/drivers/staging/media/hantro/hantro.h -@@ -417,7 +417,8 @@ hantro_get_dst_buf(struct hantro_ctx *ctx) - } - - static inline bool --hantro_needs_postproc(struct hantro_ctx *ctx, const struct hantro_fmt *fmt) -+hantro_needs_postproc(const struct hantro_ctx *ctx, -+ const struct hantro_fmt *fmt) - { - return fmt->fourcc != V4L2_PIX_FMT_NV12; - } -diff --git a/drivers/staging/media/hantro/hantro_v4l2.c b/drivers/staging/media/hantro/hantro_v4l2.c -index 458b502ff01b..f28a94e2fa93 100644 ---- a/drivers/staging/media/hantro/hantro_v4l2.c -+++ b/drivers/staging/media/hantro/hantro_v4l2.c -@@ -30,6 +30,11 @@ - #include "hantro_hw.h" - #include "hantro_v4l2.h" - -+static int hantro_set_fmt_out(struct hantro_ctx *ctx, -+ struct v4l2_pix_format_mplane *pix_mp); -+static int hantro_set_fmt_cap(struct hantro_ctx *ctx, -+ struct v4l2_pix_format_mplane *pix_mp); -+ - static const struct hantro_fmt * - hantro_get_formats(const struct hantro_ctx *ctx, unsigned int *num_fmts) - { -@@ -227,12 +232,12 @@ static int vidioc_g_fmt_cap_mplane(struct file *file, void *priv, - return 0; - } - --static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f, -- bool capture) -+static int hantro_try_fmt(const struct hantro_ctx *ctx, -+ struct v4l2_pix_format_mplane *pix_mp, -+ enum v4l2_buf_type type) - { -- struct hantro_ctx *ctx = fh_to_ctx(priv); -- struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; - const struct hantro_fmt *fmt, *vpu_fmt; -+ bool capture = !V4L2_TYPE_IS_OUTPUT(type); - bool coded; - - coded = capture == hantro_is_encoder_ctx(ctx); -@@ -246,7 +251,7 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f, - fmt = hantro_find_format(ctx, pix_mp->pixelformat); - if (!fmt) { - fmt = hantro_get_default_fmt(ctx, coded); -- f->fmt.pix_mp.pixelformat = fmt->fourcc; -+ pix_mp->pixelformat = fmt->fourcc; - } - - if (coded) { -@@ -294,13 +299,13 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f, - static int vidioc_try_fmt_cap_mplane(struct file *file, void *priv, - struct v4l2_format *f) - { -- return vidioc_try_fmt(file, priv, f, true); -+ return hantro_try_fmt(fh_to_ctx(priv), &f->fmt.pix_mp, f->type); - } - - static int vidioc_try_fmt_out_mplane(struct file *file, void *priv, - struct v4l2_format *f) - { -- return vidioc_try_fmt(file, priv, f, false); -+ return hantro_try_fmt(fh_to_ctx(priv), &f->fmt.pix_mp, f->type); - } - - static void -@@ -334,11 +339,12 @@ hantro_reset_encoded_fmt(struct hantro_ctx *ctx) - } - - hantro_reset_fmt(fmt, vpu_fmt); -- fmt->num_planes = 1; - fmt->width = vpu_fmt->frmsize.min_width; - fmt->height = vpu_fmt->frmsize.min_height; -- fmt->plane_fmt[0].sizeimage = vpu_fmt->header_size + -- fmt->width * fmt->height * vpu_fmt->max_depth; -+ if (hantro_is_encoder_ctx(ctx)) -+ hantro_set_fmt_cap(ctx, fmt); -+ else -+ hantro_set_fmt_out(ctx, fmt); - } - - static void -@@ -360,9 +366,12 @@ hantro_reset_raw_fmt(struct hantro_ctx *ctx) - } - - hantro_reset_fmt(raw_fmt, raw_vpu_fmt); -- v4l2_fill_pixfmt_mp(raw_fmt, raw_vpu_fmt->fourcc, -- encoded_fmt->width, -- encoded_fmt->height); -+ raw_fmt->width = encoded_fmt->width; -+ raw_fmt->width = encoded_fmt->width; -+ if (hantro_is_encoder_ctx(ctx)) -+ hantro_set_fmt_out(ctx, raw_fmt); -+ else -+ hantro_set_fmt_cap(ctx, raw_fmt); - } - - void hantro_reset_fmts(struct hantro_ctx *ctx) -@@ -388,15 +397,15 @@ hantro_update_requires_request(struct hantro_ctx *ctx, u32 fourcc) - } - } - --static int --vidioc_s_fmt_out_mplane(struct file *file, void *priv, struct v4l2_format *f) -+static int hantro_set_fmt_out(struct hantro_ctx *ctx, -+ struct v4l2_pix_format_mplane *pix_mp) - { -- struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; -- struct hantro_ctx *ctx = fh_to_ctx(priv); -- struct vb2_queue *vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); -+ struct vb2_queue *vq; - int ret; - -- ret = vidioc_try_fmt_out_mplane(file, priv, f); -+ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, -+ V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); -+ ret = hantro_try_fmt(ctx, pix_mp, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); - if (ret) - return ret; - -@@ -458,16 +467,15 @@ vidioc_s_fmt_out_mplane(struct file *file, void *priv, struct v4l2_format *f) - return 0; - } - --static int vidioc_s_fmt_cap_mplane(struct file *file, void *priv, -- struct v4l2_format *f) -+static int hantro_set_fmt_cap(struct hantro_ctx *ctx, -+ struct v4l2_pix_format_mplane *pix_mp) - { -- struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; -- struct hantro_ctx *ctx = fh_to_ctx(priv); - struct vb2_queue *vq; - int ret; - - /* Change not allowed if queue is busy. */ -- vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); -+ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, -+ V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); - if (vb2_is_busy(vq)) - return -EBUSY; - -@@ -488,7 +496,7 @@ static int vidioc_s_fmt_cap_mplane(struct file *file, void *priv, - return -EBUSY; - } - -- ret = vidioc_try_fmt_cap_mplane(file, priv, f); -+ ret = hantro_try_fmt(ctx, pix_mp, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); - if (ret) - return ret; - -@@ -522,6 +530,18 @@ static int vidioc_s_fmt_cap_mplane(struct file *file, void *priv, - return 0; - } - -+static int -+vidioc_s_fmt_out_mplane(struct file *file, void *priv, struct v4l2_format *f) -+{ -+ return hantro_set_fmt_out(fh_to_ctx(priv), &f->fmt.pix_mp); -+} -+ -+static int -+vidioc_s_fmt_cap_mplane(struct file *file, void *priv, struct v4l2_format *f) -+{ -+ return hantro_set_fmt_cap(fh_to_ctx(priv), &f->fmt.pix_mp); -+} -+ - const struct v4l2_ioctl_ops hantro_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_enum_framesizes = vidioc_enum_framesizes, --- -2.17.1 - - -From 03a4222379d16c8a5f4a9c74f78c977b6a0e16a0 Mon Sep 17 00:00:00 2001 -From: Ezequiel Garcia -Date: Wed, 18 Mar 2020 10:21:07 -0300 -Subject: [PATCH] dt-bindings: rockchip-vpu: Convert bindings to json-schema - -Convert Rockchip VPU (Hantro IP block) codec driver documentation to -json-schema. - -Cc: Rob Herring -Signed-off-by: Ezequiel Garcia ---- - .../bindings/media/rockchip-vpu.txt | 43 ---------- - .../bindings/media/rockchip-vpu.yaml | 82 +++++++++++++++++++ - MAINTAINERS | 2 +- - 3 files changed, 83 insertions(+), 44 deletions(-) - delete mode 100644 Documentation/devicetree/bindings/media/rockchip-vpu.txt - create mode 100644 Documentation/devicetree/bindings/media/rockchip-vpu.yaml - -diff --git a/Documentation/devicetree/bindings/media/rockchip-vpu.txt b/Documentation/devicetree/bindings/media/rockchip-vpu.txt -deleted file mode 100644 -index 339252d9c515..000000000000 ---- a/Documentation/devicetree/bindings/media/rockchip-vpu.txt -+++ /dev/null -@@ -1,43 +0,0 @@ --device-tree bindings for rockchip VPU codec -- --Rockchip (Video Processing Unit) present in various Rockchip platforms, --such as RK3288, RK3328 and RK3399. -- --Required properties: --- compatible: value should be one of the following -- "rockchip,rk3288-vpu"; -- "rockchip,rk3328-vpu"; -- "rockchip,rk3399-vpu"; --- interrupts: encoding and decoding interrupt specifiers --- interrupt-names: should be -- "vepu", "vdpu" on RK3288 and RK3399, -- "vdpu" on RK3328. --- clocks: phandle to VPU aclk, hclk clocks --- clock-names: should be "aclk" and "hclk" --- power-domains: phandle to power domain node --- iommus: phandle to a iommu node -- --Example: --SoC-specific DT entry: -- vpu: video-codec@ff9a0000 { -- compatible = "rockchip,rk3288-vpu"; -- reg = <0x0 0xff9a0000 0x0 0x800>; -- interrupts = , -- ; -- interrupt-names = "vepu", "vdpu"; -- clocks = <&cru ACLK_VCODEC>, <&cru HCLK_VCODEC>; -- clock-names = "aclk", "hclk"; -- power-domains = <&power RK3288_PD_VIDEO>; -- iommus = <&vpu_mmu>; -- }; -- -- vpu: video-codec@ff350000 { -- compatible = "rockchip,rk3328-vpu"; -- reg = <0x0 0xff350000 0x0 0x800>; -- interrupts = ; -- interrupt-names = "vdpu"; -- clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; -- clock-names = "aclk", "hclk"; -- power-domains = <&power RK3328_PD_VPU>; -- iommus = <&vpu_mmu>; -- }; -diff --git a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml -new file mode 100644 -index 000000000000..a0c45e05cf03 ---- /dev/null -+++ b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml -@@ -0,0 +1,82 @@ -+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) -+ -+%YAML 1.2 -+--- -+$id: "http://devicetree.org/schemas/media/rockchip-vpu.yaml#" -+$schema: "http://devicetree.org/meta-schemas/core.yaml#" -+ -+title: Hantro G1 VPU codecs implemented on Rockchip SoCs -+ -+maintainers: -+ - Ezequiel Garcia -+ -+description: -+ Hantro G1 video encode and decode accelerators present on Rockchip SoCs. -+ -+properties: -+ compatible: -+ enum: -+ - rockchip,rk3288-vpu -+ - rockchip,rk3328-vpu -+ - rockchip,rk3399-vpu -+ -+ reg: -+ maxItems: 1 -+ -+ interrupts: -+ maxItems: 2 -+ -+ interrupt-names: -+ items: -+ - const: vepu -+ - const: vdpu -+ -+ clocks: -+ maxItems: 2 -+ -+ clock-names: -+ items: -+ - const: aclk -+ - const: hclk -+ -+ power-domains: -+ maxItems: 1 -+ -+ iommus: -+ maxItems: 1 -+ -+required: -+ - compatible -+ - reg -+ - interrupts -+ - interrupt-names -+ - clocks -+ - clock-names -+ -+examples: -+ - | -+ #include -+ #include -+ -+ vpu: video-codec@ff9a0000 { -+ compatible = "rockchip,rk3288-vpu"; -+ reg = <0x0 0xff9a0000 0x0 0x800>; -+ interrupts = , -+ ; -+ interrupt-names = "vepu", "vdpu"; -+ clocks = <&cru ACLK_VCODEC>, <&cru HCLK_VCODEC>; -+ clock-names = "aclk", "hclk"; -+ power-domains = <&power RK3288_PD_VIDEO>; -+ iommus = <&vpu_mmu>; -+ }; -+ -+ vpu: video-codec@ff350000 { -+ compatible = "rockchip,rk3328-vpu"; -+ reg = <0x0 0xff350000 0x0 0x800>; -+ interrupts = ; -+ interrupt-names = "vdpu"; -+ clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; -+ clock-names = "aclk", "hclk"; -+ power-domains = <&power RK3328_PD_VPU>; -+ iommus = <&vpu_mmu>; -+ }; - - - -From 1eba04297572f566a06ab9fe50f901640c77b091 Mon Sep 17 00:00:00 2001 -From: Ezequiel Garcia -Date: Wed, 18 Mar 2020 10:21:08 -0300 -Subject: [PATCH] hantro: Add linux-rockchip mailing list to MAINTAINERS - -The linux-rockchip mailing list is relevant for the -Hantro driver, given this support the VPU present -in Rockchip SoCs. - -Signed-off-by: Ezequiel Garcia -Reviewed-by: Heiko Stuebner ---- - MAINTAINERS | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/MAINTAINERS b/MAINTAINERS -index ca95e804aae0..47876afb9e26 100644 ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -14317,6 +14317,7 @@ F: Documentation/devicetree/bindings/media/rockchip-rga.txt - HANTRO VPU CODEC DRIVER - M: Ezequiel Garcia - L: linux-media@vger.kernel.org -+L: linux-rockchip@lists.infradead.org - S: Maintained - F: drivers/staging/media/hantro/ - F: Documentation/devicetree/bindings/media/rockchip-vpu.yaml --- -2.17.1 - diff --git a/patch/kernel/rk322x-current/01-linux-0021-drm-from-5.9.patch b/patch/kernel/rk322x-current/01-linux-0021-drm-from-5.9.patch new file mode 100644 index 000000000..d97f0818a --- /dev/null +++ b/patch/kernel/rk322x-current/01-linux-0021-drm-from-5.9.patch @@ -0,0 +1,3500 @@ +From 761a6a88e4fc8d732b6d4319d0bf6f0206d280de Mon Sep 17 00:00:00 2001 +From: Emil Velikov +Date: Tue, 5 May 2020 16:16:13 +0100 +Subject: [PATCH] drm/rockchip: vop: call vop_cfg_done() under reg_lock +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The function vop_cfg_done() is a simple VOP_REG_SET(). As such it should +be done under a reg_lock. A quick look through the driver shows that all +other instances (apart from driver init) have the lock. Do the same here + +Cc: Sandy Huang +Cc: Heiko Stübner +Signed-off-by: Emil Velikov +Reviewed-by: Sandy Huang +Link: https://patchwork.freedesktop.org/patch/msgid/20200505151613.2932456-1-emil.l.velikov@gmail.com +(cherry picked from commit 5fa63f0773323b1d028f2da5c94b8f3e38619b69) +--- + drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +index 33463b79a37b..1d76455ca933 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +@@ -645,10 +645,10 @@ static int vop_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state) + s->enable_afbc = false; + } + +- spin_unlock(&vop->reg_lock); +- + vop_cfg_done(vop); + ++ spin_unlock(&vop->reg_lock); ++ + /* + * At here, vop clock & iommu is enable, R/W vop regs would be safe. + */ + +From 7e1b1997341632ffac3e1ab8fdac8923929403c9 Mon Sep 17 00:00:00 2001 +From: Bernard Zhao +Date: Mon, 27 Apr 2020 01:05:23 -0700 +Subject: [PATCH] drivers: video: hdmi: cleanup coding style in video a bit + +Eliminate the magic numbers, add vendor infoframe size macro +like other hdmi modules. + +Signed-off-by: Bernard Zhao +Cc: Uma Shankar +Cc: Ville Syrjala +Cc: Shashank Sharma +Cc: Laurent Pinchart +Cc: Daniel Vetter +Cc: opensource.kernel@vivo.com +[b.zolnierkie: add "hdmi" to the patch summary] +[b.zolnierkie: fix "vender" -> vendor" typo in the patch description] +Signed-off-by: Bartlomiej Zolnierkiewicz +Link: https://patchwork.freedesktop.org/patch/msgid/20200427080530.3234-1-bernard@vivo.com +(cherry picked from commit d43be2554b58621a21cb5f54b32db2263b3008b6) +--- + drivers/video/hdmi.c | 2 +- + include/linux/hdmi.h | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c +index e70792b3e367..b7a1d6fae90d 100644 +--- a/drivers/video/hdmi.c ++++ b/drivers/video/hdmi.c +@@ -495,7 +495,7 @@ int hdmi_vendor_infoframe_init(struct hdmi_vendor_infoframe *frame) + * value + */ + frame->s3d_struct = HDMI_3D_STRUCTURE_INVALID; +- frame->length = 4; ++ frame->length = HDMI_VENDOR_INFOFRAME_SIZE; + + return 0; + } +diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h +index 50c31f1a0a2d..9850d59d6f1c 100644 +--- a/include/linux/hdmi.h ++++ b/include/linux/hdmi.h +@@ -57,6 +57,7 @@ enum hdmi_infoframe_type { + #define HDMI_SPD_INFOFRAME_SIZE 25 + #define HDMI_AUDIO_INFOFRAME_SIZE 10 + #define HDMI_DRM_INFOFRAME_SIZE 26 ++#define HDMI_VENDOR_INFOFRAME_SIZE 4 + + #define HDMI_INFOFRAME_SIZE(type) \ + (HDMI_INFOFRAME_HEADER_SIZE + HDMI_ ## type ## _INFOFRAME_SIZE) + +From 86ce9313bd2561a632b4f3a03bdb894b92b988bb Mon Sep 17 00:00:00 2001 +From: Paul Kocialkowski +Date: Thu, 16 Apr 2020 16:05:26 +0200 +Subject: [PATCH] drm/rockchip: Add per-pixel alpha support for the PX30 VOP + +Compared to its predecessors, the PX30 VOP has a different register layout +for enabling per-pixel alpha. Instead of src_alpha_ctl and dst_alpha_ctl, +there is a single alpha control register. This register takes some fields +from src_alpha_ctl, but with a different layout. + +Add support for the required fields to the PX30 VOP window descriptions, +which makes per-pixel-alpha formats behave correctly. + +Signed-off-by: Paul Kocialkowski +Signed-off-by: Heiko Stuebner +Link: https://patchwork.freedesktop.org/patch/msgid/20200416140526.262533-1-paul.kocialkowski@bootlin.com +(cherry picked from commit 2aae8ed1f390a42ec752e4403ffca877fb3260e1) +--- + drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 4 ++++ + drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 3 +++ + drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 9 +++++++++ + 3 files changed, 16 insertions(+) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +index 1d76455ca933..c80f7d9fd13f 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +@@ -1007,6 +1007,10 @@ static void vop_plane_atomic_update(struct drm_plane *plane, + SRC_ALPHA_CAL_M0(ALPHA_NO_SATURATION) | + SRC_FACTOR_M0(ALPHA_ONE); + VOP_WIN_SET(vop, win, src_alpha_ctl, val); ++ ++ VOP_WIN_SET(vop, win, alpha_pre_mul, ALPHA_SRC_PRE_MUL); ++ VOP_WIN_SET(vop, win, alpha_mode, ALPHA_PER_PIX); ++ VOP_WIN_SET(vop, win, alpha_en, 1); + } else { + VOP_WIN_SET(vop, win, src_alpha_ctl, SRC_ALPHA_EN(0)); + } +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +index d03bdb531ef2..4a2099cb582e 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +@@ -167,6 +167,9 @@ struct vop_win_phy { + + struct vop_reg dst_alpha_ctl; + struct vop_reg src_alpha_ctl; ++ struct vop_reg alpha_pre_mul; ++ struct vop_reg alpha_mode; ++ struct vop_reg alpha_en; + struct vop_reg channel; + }; + +diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +index 2413deded22c..80053d91a301 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c ++++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +@@ -264,6 +264,9 @@ static const struct vop_win_phy px30_win0_data = { + .uv_mst = VOP_REG(PX30_WIN0_CBR_MST0, 0xffffffff, 0), + .yrgb_vir = VOP_REG(PX30_WIN0_VIR, 0x1fff, 0), + .uv_vir = VOP_REG(PX30_WIN0_VIR, 0x1fff, 16), ++ .alpha_pre_mul = VOP_REG(PX30_WIN0_ALPHA_CTRL, 0x1, 2), ++ .alpha_mode = VOP_REG(PX30_WIN0_ALPHA_CTRL, 0x1, 1), ++ .alpha_en = VOP_REG(PX30_WIN0_ALPHA_CTRL, 0x1, 0), + }; + + static const struct vop_win_phy px30_win1_data = { +@@ -277,6 +280,9 @@ static const struct vop_win_phy px30_win1_data = { + .dsp_st = VOP_REG(PX30_WIN1_DSP_ST, 0xffffffff, 0), + .yrgb_mst = VOP_REG(PX30_WIN1_MST, 0xffffffff, 0), + .yrgb_vir = VOP_REG(PX30_WIN1_VIR, 0x1fff, 0), ++ .alpha_pre_mul = VOP_REG(PX30_WIN1_ALPHA_CTRL, 0x1, 2), ++ .alpha_mode = VOP_REG(PX30_WIN1_ALPHA_CTRL, 0x1, 1), ++ .alpha_en = VOP_REG(PX30_WIN1_ALPHA_CTRL, 0x1, 0), + }; + + static const struct vop_win_phy px30_win2_data = { +@@ -291,6 +297,9 @@ static const struct vop_win_phy px30_win2_data = { + .dsp_st = VOP_REG(PX30_WIN2_DSP_ST0, 0x1fff1fff, 0), + .yrgb_mst = VOP_REG(PX30_WIN2_MST0, 0xffffffff, 0), + .yrgb_vir = VOP_REG(PX30_WIN2_VIR0_1, 0x1fff, 0), ++ .alpha_pre_mul = VOP_REG(PX30_WIN2_ALPHA_CTRL, 0x1, 2), ++ .alpha_mode = VOP_REG(PX30_WIN2_ALPHA_CTRL, 0x1, 1), ++ .alpha_en = VOP_REG(PX30_WIN2_ALPHA_CTRL, 0x1, 0), + }; + + static const struct vop_win_data px30_vop_big_win_data[] = { + +From 022f13fb762722cc81f51f2615131fd4b4cd72e6 Mon Sep 17 00:00:00 2001 +From: Krzysztof Kozlowski +Date: Wed, 27 May 2020 22:05:44 +0200 +Subject: [PATCH] drm/panfrost: Reduce the amount of logs on deferred probe + +There is no point to print deferred probe (and its failures to get +resources) as an error. Also there is no need to print regulator errors +twice. + +In case of multiple probe tries this would pollute the dmesg. + +Signed-off-by: Krzysztof Kozlowski +Reviewed-by: Steven Price +Signed-off-by: Steven Price +Link: https://patchwork.freedesktop.org/patch/msgid/20200527200544.7849-1-krzk@kernel.org +(cherry picked from commit e63adeccc0bbba34a7b988b8898bebbd5bbb6461) +--- + drivers/gpu/drm/panfrost/panfrost_device.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/panfrost/panfrost_device.c b/drivers/gpu/drm/panfrost/panfrost_device.c +index 8136babd3ba9..b172087eee6a 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_device.c ++++ b/drivers/gpu/drm/panfrost/panfrost_device.c +@@ -101,7 +101,9 @@ static int panfrost_regulator_init(struct panfrost_device *pfdev) + pfdev->comp->num_supplies, + pfdev->regulators); + if (ret < 0) { +- dev_err(pfdev->dev, "failed to get regulators: %d\n", ret); ++ if (ret != -EPROBE_DEFER) ++ dev_err(pfdev->dev, "failed to get regulators: %d\n", ++ ret); + return ret; + } + +@@ -213,10 +215,8 @@ int panfrost_device_init(struct panfrost_device *pfdev) + } + + err = panfrost_regulator_init(pfdev); +- if (err) { +- dev_err(pfdev->dev, "regulator init failed %d\n", err); ++ if (err) + goto err_out0; +- } + + err = panfrost_reset_init(pfdev); + if (err) { + +From 9bda1bca65f6067e191b056e6884ba7a9a0c4c09 Mon Sep 17 00:00:00 2001 +From: Dinghao Liu +Date: Fri, 22 May 2020 21:41:09 +0800 +Subject: [PATCH] drm/panfrost: Fix runtime PM imbalance on error + +The caller expects panfrost_job_hw_submit() to increase +runtime PM usage counter. The refcount decrement on the +error branch of WARN_ON() will break the counter balance +and needs to be removed. + +Signed-off-by: Dinghao Liu +Reviewed-by: Steven Price +Signed-off-by: Steven Price +Link: https://patchwork.freedesktop.org/patch/msgid/20200522134109.27204-1-dinghao.liu@zju.edu.cn +(cherry picked from commit 64092598c4566dc80a71ca57396dc36fdbf3da4b) +--- + drivers/gpu/drm/panfrost/panfrost_job.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c b/drivers/gpu/drm/panfrost/panfrost_job.c +index f9519afca29d..c6242fe34840 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_job.c ++++ b/drivers/gpu/drm/panfrost/panfrost_job.c +@@ -152,7 +152,6 @@ static void panfrost_job_hw_submit(struct panfrost_job *job, int js) + return; + + if (WARN_ON(job_read(pfdev, JS_COMMAND_NEXT(js)))) { +- pm_runtime_put_sync_autosuspend(pfdev->dev); + return; + } + + +From 3c403361c554bd46a9ddb2b0d794785916327a83 Mon Sep 17 00:00:00 2001 +From: Ben Davis +Date: Mon, 1 Jun 2020 17:28:17 +0100 +Subject: [PATCH] drm: drm_fourcc: add NV15, Q410, Q401 YUV formats + +DRM_FORMAT_NV15 is a 2 plane format suitable for linear and 16x16 +block-linear memory layouts (DRM_FORMAT_MOD_SAMSUNG_16_16_TILE). The +format is similar to P010 with 4:2:0 sub-sampling but has no padding +between components. Instead, luminance and chrominance samples are +grouped into 4s so that each group is packed into an integer number +of bytes: + +YYYY = UVUV = 4 * 10 bits = 40 bits = 5 bytes + +The '15' suffix refers to the optimum effective bits per pixel which is +achieved when the total number of luminance samples is a multiple of 8. + +Q410 and Q401 are both 3 plane non-subsampled formats with 16 bits per +component, but only 10 bits are used and 6 are padded. 'Q' is chosen +as the first letter to denote 3 plane YUV444, (and is the next letter +along from P which is usually 2 plane). + +V2: Updated block_w of NV15 to {4, 2, 0} +V3: Updated commit message to include specific modifier name + +NV15: +Tested-by: Jonas Karlman + +Reviewed-by: Brian Starkey +Signed-off-by: Ben Davis +Signed-off-by: Liviu Dudau +Link: https://patchwork.freedesktop.org/patch/msgid/20200601162817.18230-1-ben.davis@arm.com +(cherry picked from commit 94b292b277343190175d39172c903c0c5fb814f1) +--- + drivers/gpu/drm/drm_fourcc.c | 12 ++++++++++++ + include/uapi/drm/drm_fourcc.h | 22 ++++++++++++++++++++++ + 2 files changed, 34 insertions(+) + +diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c +index b234bfaeda06..722c7ebe4e88 100644 +--- a/drivers/gpu/drm/drm_fourcc.c ++++ b/drivers/gpu/drm/drm_fourcc.c +@@ -274,6 +274,18 @@ const struct drm_format_info *__drm_format_info(u32 format) + { .format = DRM_FORMAT_YUV420_10BIT, .depth = 0, + .num_planes = 1, .cpp = { 0, 0, 0 }, .hsub = 2, .vsub = 2, + .is_yuv = true }, ++ { .format = DRM_FORMAT_NV15, .depth = 0, ++ .num_planes = 2, .char_per_block = { 5, 5, 0 }, ++ .block_w = { 4, 2, 0 }, .block_h = { 1, 1, 0 }, .hsub = 2, ++ .vsub = 2, .is_yuv = true }, ++ { .format = DRM_FORMAT_Q410, .depth = 0, ++ .num_planes = 3, .char_per_block = { 2, 2, 2 }, ++ .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 }, .hsub = 0, ++ .vsub = 0, .is_yuv = true }, ++ { .format = DRM_FORMAT_Q401, .depth = 0, ++ .num_planes = 3, .char_per_block = { 2, 2, 2 }, ++ .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 }, .hsub = 0, ++ .vsub = 0, .is_yuv = true }, + }; + + unsigned int i; +diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h +index 490143500a50..8ba2d9153a94 100644 +--- a/include/uapi/drm/drm_fourcc.h ++++ b/include/uapi/drm/drm_fourcc.h +@@ -236,6 +236,12 @@ extern "C" { + #define DRM_FORMAT_NV61 fourcc_code('N', 'V', '6', '1') /* 2x1 subsampled Cb:Cr plane */ + #define DRM_FORMAT_NV24 fourcc_code('N', 'V', '2', '4') /* non-subsampled Cr:Cb plane */ + #define DRM_FORMAT_NV42 fourcc_code('N', 'V', '4', '2') /* non-subsampled Cb:Cr plane */ ++/* ++ * 2 plane YCbCr ++ * index 0 = Y plane, [39:0] Y3:Y2:Y1:Y0 little endian ++ * index 1 = Cr:Cb plane, [39:0] Cr1:Cb1:Cr0:Cb0 little endian ++ */ ++#define DRM_FORMAT_NV15 fourcc_code('N', 'V', '1', '5') /* 2x2 subsampled Cr:Cb plane */ + + /* + * 2 plane YCbCr MSB aligned +@@ -265,6 +271,22 @@ extern "C" { + */ + #define DRM_FORMAT_P016 fourcc_code('P', '0', '1', '6') /* 2x2 subsampled Cr:Cb plane 16 bits per channel */ + ++/* 3 plane non-subsampled (444) YCbCr ++ * 16 bits per component, but only 10 bits are used and 6 bits are padded ++ * index 0: Y plane, [15:0] Y:x [10:6] little endian ++ * index 1: Cb plane, [15:0] Cb:x [10:6] little endian ++ * index 2: Cr plane, [15:0] Cr:x [10:6] little endian ++ */ ++#define DRM_FORMAT_Q410 fourcc_code('Q', '4', '1', '0') ++ ++/* 3 plane non-subsampled (444) YCrCb ++ * 16 bits per component, but only 10 bits are used and 6 bits are padded ++ * index 0: Y plane, [15:0] Y:x [10:6] little endian ++ * index 1: Cr plane, [15:0] Cr:x [10:6] little endian ++ * index 2: Cb plane, [15:0] Cb:x [10:6] little endian ++ */ ++#define DRM_FORMAT_Q401 fourcc_code('Q', '4', '0', '1') ++ + /* + * 3 plane YCbCr + * index 0: Y plane, [7:0] Y + +From 7e57394c63258ac63d5c74cbd2a700916c31d4f6 Mon Sep 17 00:00:00 2001 +From: Ben Davis +Date: Thu, 30 Apr 2020 09:32:20 +0100 +Subject: [PATCH] drm: drm_fourcc: Add uncompressed AFBC modifier + +AFBC has a mode that guarantees use of AFBC with an uncompressed +payloads, we add a new modifier to support this mode. + +V2: updated modifier comment + +Signed-off-by: Ben Davis +Acked-by: Liviu Dudau +Signed-off-by: Liviu Dudau +Link: https://patchwork.freedesktop.org/patch/msgid/20200430083220.17347-1-ben.davis@arm.com +(cherry picked from commit 79ce058032c391b12af928b1e30abf92482a270f) +--- + include/uapi/drm/drm_fourcc.h | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h +index 8ba2d9153a94..993c1b342315 100644 +--- a/include/uapi/drm/drm_fourcc.h ++++ b/include/uapi/drm/drm_fourcc.h +@@ -914,6 +914,18 @@ drm_fourcc_canonicalize_nvidia_format_mod(__u64 modifier) + */ + #define AFBC_FORMAT_MOD_BCH (1ULL << 11) + ++/* AFBC uncompressed storage mode ++ * ++ * Indicates that the buffer is using AFBC uncompressed storage mode. ++ * In this mode all superblock payloads in the buffer use the uncompressed ++ * storage mode, which is usually only used for data which cannot be compressed. ++ * The buffer layout is the same as for AFBC buffers without USM set, this only ++ * affects the storage mode of the individual superblocks. Note that even a ++ * buffer without USM set may use uncompressed storage mode for some or all ++ * superblocks, USM just guarantees it for all. ++ */ ++#define AFBC_FORMAT_MOD_USM (1ULL << 12) ++ + /* + * Arm 16x16 Block U-Interleaved modifier + * + +From 32b33df85c3c84ce2a145f2d68305116fbec91fd Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Tue, 26 May 2020 04:14:47 +0300 +Subject: [PATCH] drm: edid: Constify connector argument to infoframe functions + +The drm_hdmi_avi_infoframe_from_display_mode(), +drm_hdmi_vendor_infoframe_from_display_mode() and +drm_hdmi_avi_infoframe_quant_range() functions take a drm_connector that +they don't modify. Mark it as const. + +Signed-off-by: Laurent Pinchart +Acked-by: Sam Ravnborg +Signed-off-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/20200526011505.31884-10-laurent.pinchart+renesas@ideasonboard.com +(cherry picked from commit 192a3aa0e4e20e1087baa29183c5d64d48716fa9) +--- + drivers/gpu/drm/drm_edid.c | 12 ++++++------ + include/drm/drm_edid.h | 6 +++--- + 2 files changed, 9 insertions(+), 9 deletions(-) + +diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c +index fed653f13c26..b3f659759adb 100644 +--- a/drivers/gpu/drm/drm_edid.c ++++ b/drivers/gpu/drm/drm_edid.c +@@ -5366,7 +5366,7 @@ void drm_set_preferred_mode(struct drm_connector *connector, + } + EXPORT_SYMBOL(drm_set_preferred_mode); + +-static bool is_hdmi2_sink(struct drm_connector *connector) ++static bool is_hdmi2_sink(const struct drm_connector *connector) + { + /* + * FIXME: sil-sii8620 doesn't have a connector around when +@@ -5451,7 +5451,7 @@ drm_hdmi_infoframe_set_hdr_metadata(struct hdmi_drm_infoframe *frame, + } + EXPORT_SYMBOL(drm_hdmi_infoframe_set_hdr_metadata); + +-static u8 drm_mode_hdmi_vic(struct drm_connector *connector, ++static u8 drm_mode_hdmi_vic(const struct drm_connector *connector, + const struct drm_display_mode *mode) + { + bool has_hdmi_infoframe = connector ? +@@ -5467,7 +5467,7 @@ static u8 drm_mode_hdmi_vic(struct drm_connector *connector, + return drm_match_hdmi_mode(mode); + } + +-static u8 drm_mode_cea_vic(struct drm_connector *connector, ++static u8 drm_mode_cea_vic(const struct drm_connector *connector, + const struct drm_display_mode *mode) + { + u8 vic; +@@ -5505,7 +5505,7 @@ static u8 drm_mode_cea_vic(struct drm_connector *connector, + */ + int + drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame, +- struct drm_connector *connector, ++ const struct drm_connector *connector, + const struct drm_display_mode *mode) + { + enum hdmi_picture_aspect picture_aspect; +@@ -5652,7 +5652,7 @@ EXPORT_SYMBOL(drm_hdmi_avi_infoframe_colorspace); + */ + void + drm_hdmi_avi_infoframe_quant_range(struct hdmi_avi_infoframe *frame, +- struct drm_connector *connector, ++ const struct drm_connector *connector, + const struct drm_display_mode *mode, + enum hdmi_quantization_range rgb_quant_range) + { +@@ -5756,7 +5756,7 @@ s3d_structure_from_display_mode(const struct drm_display_mode *mode) + */ + int + drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame, +- struct drm_connector *connector, ++ const struct drm_connector *connector, + const struct drm_display_mode *mode) + { + /* +diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h +index 34b15e3d070c..43254319ab19 100644 +--- a/include/drm/drm_edid.h ++++ b/include/drm/drm_edid.h +@@ -361,11 +361,11 @@ drm_load_edid_firmware(struct drm_connector *connector) + + int + drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame, +- struct drm_connector *connector, ++ const struct drm_connector *connector, + const struct drm_display_mode *mode); + int + drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame, +- struct drm_connector *connector, ++ const struct drm_connector *connector, + const struct drm_display_mode *mode); + + void +@@ -378,7 +378,7 @@ drm_hdmi_avi_infoframe_bars(struct hdmi_avi_infoframe *frame, + + void + drm_hdmi_avi_infoframe_quant_range(struct hdmi_avi_infoframe *frame, +- struct drm_connector *connector, ++ const struct drm_connector *connector, + const struct drm_display_mode *mode, + enum hdmi_quantization_range rgb_quant_range); + + +From 23fe85a8775eb3c926be0f3d2bc99b70a6d0bb07 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Tue, 26 May 2020 04:14:48 +0300 +Subject: [PATCH] drm: bridge: Pass drm_display_info to drm_bridge_funcs + .mode_valid() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When validating a mode, bridges may need to do so in the context of a +display, as specified by drm_display_info. An example is the meson +dw-hdmi bridge that needs to consider the YUV 4:2:0 output format to +perform clock calculations. + +Bridges that need the display info currently retrieve it from the +drm_connector created by the bridge. This gets in the way of moving +connector creation out of bridge drivers. To make this possible, pass +the drm_display_info to drm_bridge_funcs .mode_valid(). + +Changes to the bridge drivers have been performed with the following +coccinelle semantic patch and have been compile-tested. + +@ rule1 @ +identifier funcs; +identifier fn; +@@ + struct drm_bridge_funcs funcs = { + ..., + .mode_valid = fn + }; + +@ depends on rule1 @ +identifier rule1.fn; +identifier bridge; +identifier mode; +@@ + enum drm_mode_status fn( + struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode + ) + { + ... + } + +Signed-off-by: Laurent Pinchart +Reviewed-by: Neil Armstrong +Reviewed-by: Boris Brezillon +Reviewed-by: Guido Günther # for the nwl-dsi part: +Signed-off-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/20200526011505.31884-11-laurent.pinchart+renesas@ideasonboard.com +(cherry picked from commit 12c683e12cd8e2dcf7b7143bebceae484d17727a) +--- + drivers/gpu/drm/bridge/analogix/analogix-anx6345.c | 1 + + drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c | 1 + + drivers/gpu/drm/bridge/cdns-dsi.c | 1 + + drivers/gpu/drm/bridge/chrontel-ch7033.c | 1 + + drivers/gpu/drm/bridge/nwl-dsi.c | 1 + + drivers/gpu/drm/bridge/sii9234.c | 1 + + drivers/gpu/drm/bridge/sil-sii8620.c | 1 + + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 1 + + drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 1 + + drivers/gpu/drm/bridge/tc358767.c | 1 + + drivers/gpu/drm/bridge/tc358768.c | 1 + + drivers/gpu/drm/bridge/thc63lvd1024.c | 1 + + drivers/gpu/drm/bridge/ti-tfp410.c | 1 + + drivers/gpu/drm/drm_atomic_helper.c | 3 ++- + drivers/gpu/drm/drm_bridge.c | 4 +++- + drivers/gpu/drm/drm_probe_helper.c | 4 +++- + drivers/gpu/drm/i2c/tda998x_drv.c | 1 + + drivers/gpu/drm/omapdrm/dss/dpi.c | 1 + + drivers/gpu/drm/omapdrm/dss/sdi.c | 1 + + drivers/gpu/drm/omapdrm/dss/venc.c | 1 + + include/drm/drm_bridge.h | 3 +++ + 21 files changed, 28 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c b/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c +index 9af39ec958db..f082b4ed4878 100644 +--- a/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c ++++ b/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c +@@ -588,6 +588,7 @@ static int anx6345_bridge_attach(struct drm_bridge *bridge, + + static enum drm_mode_status + anx6345_bridge_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + if (mode->flags & DRM_MODE_FLAG_INTERLACE) +diff --git a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c +index 0d5a5ad0c9ee..81debd02c169 100644 +--- a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c ++++ b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c +@@ -944,6 +944,7 @@ static int anx78xx_bridge_attach(struct drm_bridge *bridge, + + static enum drm_mode_status + anx78xx_bridge_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + if (mode->flags & DRM_MODE_FLAG_INTERLACE) +diff --git a/drivers/gpu/drm/bridge/cdns-dsi.c b/drivers/gpu/drm/bridge/cdns-dsi.c +index 69c3892caee5..76373e31df92 100644 +--- a/drivers/gpu/drm/bridge/cdns-dsi.c ++++ b/drivers/gpu/drm/bridge/cdns-dsi.c +@@ -663,6 +663,7 @@ static int cdns_dsi_bridge_attach(struct drm_bridge *bridge, + + static enum drm_mode_status + cdns_dsi_bridge_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge); +diff --git a/drivers/gpu/drm/bridge/chrontel-ch7033.c b/drivers/gpu/drm/bridge/chrontel-ch7033.c +index f8675d82974b..486f405c2e16 100644 +--- a/drivers/gpu/drm/bridge/chrontel-ch7033.c ++++ b/drivers/gpu/drm/bridge/chrontel-ch7033.c +@@ -317,6 +317,7 @@ static void ch7033_bridge_detach(struct drm_bridge *bridge) + } + + static enum drm_mode_status ch7033_bridge_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + if (mode->clock > 165000) +diff --git a/drivers/gpu/drm/bridge/nwl-dsi.c b/drivers/gpu/drm/bridge/nwl-dsi.c +index c7bc194bbce3..ce94f797d090 100644 +--- a/drivers/gpu/drm/bridge/nwl-dsi.c ++++ b/drivers/gpu/drm/bridge/nwl-dsi.c +@@ -818,6 +818,7 @@ static bool nwl_dsi_bridge_mode_fixup(struct drm_bridge *bridge, + + static enum drm_mode_status + nwl_dsi_bridge_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + struct nwl_dsi *dsi = bridge_to_dsi(bridge); +diff --git a/drivers/gpu/drm/bridge/sii9234.c b/drivers/gpu/drm/bridge/sii9234.c +index b1258f0ed205..15c98a7bd81c 100644 +--- a/drivers/gpu/drm/bridge/sii9234.c ++++ b/drivers/gpu/drm/bridge/sii9234.c +@@ -873,6 +873,7 @@ static inline struct sii9234 *bridge_to_sii9234(struct drm_bridge *bridge) + } + + static enum drm_mode_status sii9234_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + if (mode->clock > MHL1_MAX_CLK) +diff --git a/drivers/gpu/drm/bridge/sil-sii8620.c b/drivers/gpu/drm/bridge/sil-sii8620.c +index ca98133411aa..95f3d8cfe9ec 100644 +--- a/drivers/gpu/drm/bridge/sil-sii8620.c ++++ b/drivers/gpu/drm/bridge/sil-sii8620.c +@@ -2244,6 +2244,7 @@ static int sii8620_is_packing_required(struct sii8620 *ctx, + } + + static enum drm_mode_status sii8620_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + struct sii8620 *ctx = bridge_to_sii8620(bridge); +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 30681398cfb0..b535354150db 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -2767,6 +2767,7 @@ static void dw_hdmi_bridge_detach(struct drm_bridge *bridge) + + static enum drm_mode_status + dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + struct dw_hdmi *hdmi = bridge->driver_private; +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c +index 5ef0f154aa7b..c223fb9a04cb 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c +@@ -924,6 +924,7 @@ static void dw_mipi_dsi_bridge_enable(struct drm_bridge *bridge) + + static enum drm_mode_status + dw_mipi_dsi_bridge_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge); +diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c +index e4c0ea03ae3a..c2777b226c75 100644 +--- a/drivers/gpu/drm/bridge/tc358767.c ++++ b/drivers/gpu/drm/bridge/tc358767.c +@@ -1306,6 +1306,7 @@ static bool tc_bridge_mode_fixup(struct drm_bridge *bridge, + } + + static enum drm_mode_status tc_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + struct tc_data *tc = bridge_to_tc(bridge); +diff --git a/drivers/gpu/drm/bridge/tc358768.c b/drivers/gpu/drm/bridge/tc358768.c +index 6650fe4cfc20..4a463fadf743 100644 +--- a/drivers/gpu/drm/bridge/tc358768.c ++++ b/drivers/gpu/drm/bridge/tc358768.c +@@ -529,6 +529,7 @@ static int tc358768_bridge_attach(struct drm_bridge *bridge, + + static enum drm_mode_status + tc358768_bridge_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + struct tc358768_priv *priv = bridge_to_tc358768(bridge); +diff --git a/drivers/gpu/drm/bridge/thc63lvd1024.c b/drivers/gpu/drm/bridge/thc63lvd1024.c +index 97d8129760e9..86b06975bfdd 100644 +--- a/drivers/gpu/drm/bridge/thc63lvd1024.c ++++ b/drivers/gpu/drm/bridge/thc63lvd1024.c +@@ -51,6 +51,7 @@ static int thc63_attach(struct drm_bridge *bridge, + } + + static enum drm_mode_status thc63_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + struct thc63_dev *thc63 = to_thc63(bridge); +diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c +index e3eb6364c0f7..30230c552aeb 100644 +--- a/drivers/gpu/drm/bridge/ti-tfp410.c ++++ b/drivers/gpu/drm/bridge/ti-tfp410.c +@@ -188,6 +188,7 @@ static void tfp410_disable(struct drm_bridge *bridge) + } + + static enum drm_mode_status tfp410_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + if (mode->clock < 25000) +diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c +index b78e142a5620..ab9078eaa912 100644 +--- a/drivers/gpu/drm/drm_atomic_helper.c ++++ b/drivers/gpu/drm/drm_atomic_helper.c +@@ -507,7 +507,8 @@ static enum drm_mode_status mode_valid_path(struct drm_connector *connector, + } + + bridge = drm_bridge_chain_get_first_bridge(encoder); +- ret = drm_bridge_chain_mode_valid(bridge, mode); ++ ret = drm_bridge_chain_mode_valid(bridge, &connector->display_info, ++ mode); + if (ret != MODE_OK) { + DRM_DEBUG_ATOMIC("[BRIDGE] mode_valid() failed\n"); + return ret; +diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c +index afdec8e5fc68..8e31af64e8fe 100644 +--- a/drivers/gpu/drm/drm_bridge.c ++++ b/drivers/gpu/drm/drm_bridge.c +@@ -377,6 +377,7 @@ EXPORT_SYMBOL(drm_bridge_chain_mode_fixup); + * drm_bridge_chain_mode_valid - validate the mode against all bridges in the + * encoder chain. + * @bridge: bridge control structure ++ * @info: display info against which the mode shall be validated + * @mode: desired mode to be validated + * + * Calls &drm_bridge_funcs.mode_valid for all the bridges in the encoder +@@ -390,6 +391,7 @@ EXPORT_SYMBOL(drm_bridge_chain_mode_fixup); + */ + enum drm_mode_status + drm_bridge_chain_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + struct drm_encoder *encoder; +@@ -404,7 +406,7 @@ drm_bridge_chain_mode_valid(struct drm_bridge *bridge, + if (!bridge->funcs->mode_valid) + continue; + +- ret = bridge->funcs->mode_valid(bridge, mode); ++ ret = bridge->funcs->mode_valid(bridge, info, mode); + if (ret != MODE_OK) + return ret; + } +diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c +index 576b4b7dcd89..f5d141e0400f 100644 +--- a/drivers/gpu/drm/drm_probe_helper.c ++++ b/drivers/gpu/drm/drm_probe_helper.c +@@ -114,7 +114,9 @@ drm_mode_validate_pipeline(struct drm_display_mode *mode, + } + + bridge = drm_bridge_chain_get_first_bridge(encoder); +- ret = drm_bridge_chain_mode_valid(bridge, mode); ++ ret = drm_bridge_chain_mode_valid(bridge, ++ &connector->display_info, ++ mode); + if (ret != MODE_OK) { + /* There is also no point in continuing for crtc check + * here. */ +diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c +index 9517f522dcb9..50fd119a5276 100644 +--- a/drivers/gpu/drm/i2c/tda998x_drv.c ++++ b/drivers/gpu/drm/i2c/tda998x_drv.c +@@ -1379,6 +1379,7 @@ static void tda998x_bridge_detach(struct drm_bridge *bridge) + } + + static enum drm_mode_status tda998x_bridge_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + /* TDA19988 dotclock can go up to 165MHz */ +diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c b/drivers/gpu/drm/omapdrm/dss/dpi.c +index 5110acb0c6c1..1d2992daef40 100644 +--- a/drivers/gpu/drm/omapdrm/dss/dpi.c ++++ b/drivers/gpu/drm/omapdrm/dss/dpi.c +@@ -434,6 +434,7 @@ static int dpi_bridge_attach(struct drm_bridge *bridge, + + static enum drm_mode_status + dpi_bridge_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + struct dpi_data *dpi = drm_bridge_to_dpi(bridge); +diff --git a/drivers/gpu/drm/omapdrm/dss/sdi.c b/drivers/gpu/drm/omapdrm/dss/sdi.c +index 417a8740ad0a..033fd30074b0 100644 +--- a/drivers/gpu/drm/omapdrm/dss/sdi.c ++++ b/drivers/gpu/drm/omapdrm/dss/sdi.c +@@ -140,6 +140,7 @@ static int sdi_bridge_attach(struct drm_bridge *bridge, + + static enum drm_mode_status + sdi_bridge_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + struct sdi_device *sdi = drm_bridge_to_sdi(bridge); +diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c +index 01ee6c50b663..e0817934ee16 100644 +--- a/drivers/gpu/drm/omapdrm/dss/venc.c ++++ b/drivers/gpu/drm/omapdrm/dss/venc.c +@@ -548,6 +548,7 @@ static int venc_bridge_attach(struct drm_bridge *bridge, + + static enum drm_mode_status + venc_bridge_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + switch (venc_get_videomode(mode)) { +diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h +index ea2aa5ebae34..e3d7f36d8c39 100644 +--- a/include/drm/drm_bridge.h ++++ b/include/drm/drm_bridge.h +@@ -35,6 +35,7 @@ + struct drm_bridge; + struct drm_bridge_timings; + struct drm_connector; ++struct drm_display_info; + struct drm_panel; + struct edid; + struct i2c_adapter; +@@ -112,6 +113,7 @@ struct drm_bridge_funcs { + * drm_mode_status Enum + */ + enum drm_mode_status (*mode_valid)(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode); + + /** +@@ -836,6 +838,7 @@ bool drm_bridge_chain_mode_fixup(struct drm_bridge *bridge, + struct drm_display_mode *adjusted_mode); + enum drm_mode_status + drm_bridge_chain_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode); + void drm_bridge_chain_disable(struct drm_bridge *bridge); + void drm_bridge_chain_post_disable(struct drm_bridge *bridge); + +From a9ae85591e16f342fc822ce27a514f2879ac4c06 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Tue, 26 May 2020 04:14:49 +0300 +Subject: [PATCH] drm: bridge: dw-hdmi: Pass private data pointer to + .mode_valid() + +Platform glue drivers for dw_hdmi may need to access device-specific +data from their .mode_valid() implementation. They currently have no +clean way to do so, and one driver hacks around it by accessing the +dev_private data of the drm_device retrieved from the connector. + +Add a priv_data void pointer to the dw_hdmi_plat_data structure, and +pass it to the .mode_valid() function. + +Signed-off-by: Laurent Pinchart +Reviewed-by: Neil Armstrong +Signed-off-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/20200526011505.31884-12-laurent.pinchart+renesas@ideasonboard.com +(cherry picked from commit 96591a4b93fb8b335941783dd6e7ded9d6d49f09) +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 6 ++++-- + drivers/gpu/drm/imx/dw_hdmi-imx.c | 6 ++++-- + drivers/gpu/drm/meson/meson_dw_hdmi.c | 3 ++- + drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c | 3 ++- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 3 ++- + drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 6 ++++-- + drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 3 ++- + include/drm/bridge/dw_hdmi.h | 14 ++++++++++++-- + 8 files changed, 32 insertions(+), 12 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index b535354150db..2b3f203cf467 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -2771,6 +2771,7 @@ dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge, + const struct drm_display_mode *mode) + { + struct dw_hdmi *hdmi = bridge->driver_private; ++ const struct dw_hdmi_plat_data *pdata = hdmi->plat_data; + struct drm_connector *connector = &hdmi->connector; + enum drm_mode_status mode_status = MODE_OK; + +@@ -2778,8 +2779,9 @@ dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge, + if (mode->flags & DRM_MODE_FLAG_DBLCLK) + return MODE_BAD; + +- if (hdmi->plat_data->mode_valid) +- mode_status = hdmi->plat_data->mode_valid(connector, mode); ++ if (pdata->mode_valid) ++ mode_status = pdata->mode_valid(hdmi, pdata->priv_data, ++ connector, mode); + + return mode_status; + } +diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c +index 87869b9997a6..ff4fde0eb5f6 100644 +--- a/drivers/gpu/drm/imx/dw_hdmi-imx.c ++++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c +@@ -145,7 +145,8 @@ static const struct drm_encoder_helper_funcs dw_hdmi_imx_encoder_helper_funcs = + }; + + static enum drm_mode_status +-imx6q_hdmi_mode_valid(struct drm_connector *con, ++imx6q_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, ++ struct drm_connector *con, + const struct drm_display_mode *mode) + { + if (mode->clock < 13500) +@@ -158,7 +159,8 @@ imx6q_hdmi_mode_valid(struct drm_connector *con, + } + + static enum drm_mode_status +-imx6dl_hdmi_mode_valid(struct drm_connector *con, ++imx6dl_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, ++ struct drm_connector *con, + const struct drm_display_mode *mode) + { + if (mode->clock < 13500) +diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c +index 24a12c453095..fc594213c0e0 100644 +--- a/drivers/gpu/drm/meson/meson_dw_hdmi.c ++++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c +@@ -630,7 +630,8 @@ static irqreturn_t dw_hdmi_top_thread_irq(int irq, void *dev_id) + } + + static enum drm_mode_status +-dw_hdmi_mode_valid(struct drm_connector *connector, ++dw_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, ++ struct drm_connector *connector, + const struct drm_display_mode *mode) + { + struct meson_drm *priv = connector->dev->dev_private; +diff --git a/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c b/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c +index 452461dc96f2..4d837a4d302d 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c ++++ b/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c +@@ -38,7 +38,8 @@ static const struct rcar_hdmi_phy_params rcar_hdmi_phy_params[] = { + }; + + static enum drm_mode_status +-rcar_hdmi_mode_valid(struct drm_connector *connector, ++rcar_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, ++ struct drm_connector *connector, + const struct drm_display_mode *mode) + { + /* +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index 121aa8a63a76..d08f86783a28 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -220,7 +220,8 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) + } + + static enum drm_mode_status +-dw_hdmi_rockchip_mode_valid(struct drm_connector *connector, ++dw_hdmi_rockchip_mode_valid(struct dw_hdmi *hdmi, void *data, ++ struct drm_connector *connector, + const struct drm_display_mode *mode) + { + const struct dw_hdmi_mpll_config *mpll_cfg = rockchip_mpll_cfg; +diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c +index 972682bb8000..0a3637442ba6 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c ++++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c +@@ -31,7 +31,8 @@ sun8i_dw_hdmi_encoder_helper_funcs = { + }; + + static enum drm_mode_status +-sun8i_dw_hdmi_mode_valid_a83t(struct drm_connector *connector, ++sun8i_dw_hdmi_mode_valid_a83t(struct dw_hdmi *hdmi, void *data, ++ struct drm_connector *connector, + const struct drm_display_mode *mode) + { + if (mode->clock > 297000) +@@ -41,7 +42,8 @@ sun8i_dw_hdmi_mode_valid_a83t(struct drm_connector *connector, + } + + static enum drm_mode_status +-sun8i_dw_hdmi_mode_valid_h6(struct drm_connector *connector, ++sun8i_dw_hdmi_mode_valid_h6(struct dw_hdmi *hdmi, void *data, ++ struct drm_connector *connector, + const struct drm_display_mode *mode) + { + /* +diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h +index 8e64945167e9..8587b8d2590e 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h ++++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h +@@ -176,7 +176,8 @@ struct sun8i_hdmi_phy { + }; + + struct sun8i_dw_hdmi_quirks { +- enum drm_mode_status (*mode_valid)(struct drm_connector *connector, ++ enum drm_mode_status (*mode_valid)(struct dw_hdmi *hdmi, void *data, ++ struct drm_connector *connector, + const struct drm_display_mode *mode); + unsigned int set_rate : 1; + unsigned int use_drm_infoframe : 1; +diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h +index 0b34a12c4a1c..66a811f75b91 100644 +--- a/include/drm/bridge/dw_hdmi.h ++++ b/include/drm/bridge/dw_hdmi.h +@@ -124,13 +124,23 @@ struct dw_hdmi_phy_ops { + + struct dw_hdmi_plat_data { + struct regmap *regm; +- enum drm_mode_status (*mode_valid)(struct drm_connector *connector, +- const struct drm_display_mode *mode); ++ + unsigned long input_bus_format; + unsigned long input_bus_encoding; + bool use_drm_infoframe; + bool ycbcr_420_allowed; + ++ /* ++ * Private data passed to all the .mode_valid() and .configure_phy() ++ * callback functions. ++ */ ++ void *priv_data; ++ ++ /* Platform-specific mode validation (optional). */ ++ enum drm_mode_status (*mode_valid)(struct dw_hdmi *hdmi, void *data, ++ struct drm_connector *connector, ++ const struct drm_display_mode *mode); ++ + /* Vendor PHY support */ + const struct dw_hdmi_phy_ops *phy_ops; + const char *phy_name; + +From 5a367989e0577a22f143fd9a0ae8bc3c5e187144 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Tue, 26 May 2020 04:14:50 +0300 +Subject: [PATCH] drm: bridge: dw-hdmi: Pass private data pointer to + .configure_phy() + +The .configure_phy() operation takes a dw_hdmi_plat_data pointer as a +context argument. This differs from .mode_valid() that takes a custom +private context pointer, causing possible confusion. Make the +dw_hdmi_plat_data operations more consistent by passing the private +context pointer to .configure_phy() as well. + +Signed-off-by: Laurent Pinchart +Reviewed-by: Neil Armstrong +Signed-off-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/20200526011505.31884-13-laurent.pinchart+renesas@ideasonboard.com +(cherry picked from commit 49da7e5d84e3b520355c0b6148d6dc9e5415a13e) +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 2 +- + drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c | 3 +-- + include/drm/bridge/dw_hdmi.h | 3 +-- + 3 files changed, 3 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 2b3f203cf467..6edb60e6c784 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -1514,7 +1514,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi) + + /* Write to the PHY as configured by the platform */ + if (pdata->configure_phy) +- ret = pdata->configure_phy(hdmi, pdata, mpixelclock); ++ ret = pdata->configure_phy(hdmi, pdata->priv_data, mpixelclock); + else + ret = phy->configure(hdmi, pdata, mpixelclock); + if (ret) { +diff --git a/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c b/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c +index 4d837a4d302d..d0dffe55a7cb 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c ++++ b/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c +@@ -52,8 +52,7 @@ rcar_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, + return MODE_OK; + } + +-static int rcar_hdmi_phy_configure(struct dw_hdmi *hdmi, +- const struct dw_hdmi_plat_data *pdata, ++static int rcar_hdmi_phy_configure(struct dw_hdmi *hdmi, void *data, + unsigned long mpixelclock) + { + const struct rcar_hdmi_phy_params *params = rcar_hdmi_phy_params; +diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h +index 66a811f75b91..09348c9cbd11 100644 +--- a/include/drm/bridge/dw_hdmi.h ++++ b/include/drm/bridge/dw_hdmi.h +@@ -151,8 +151,7 @@ struct dw_hdmi_plat_data { + const struct dw_hdmi_mpll_config *mpll_cfg; + const struct dw_hdmi_curr_ctrl *cur_ctr; + const struct dw_hdmi_phy_config *phy_config; +- int (*configure_phy)(struct dw_hdmi *hdmi, +- const struct dw_hdmi_plat_data *pdata, ++ int (*configure_phy)(struct dw_hdmi *hdmi, void *data, + unsigned long mpixelclock); + }; + + +From 93a10000d40b44c93674ca8b596019e0b3908541 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Tue, 26 May 2020 04:14:51 +0300 +Subject: [PATCH] drm: bridge: dw-hdmi: Remove unused field from + dw_hdmi_plat_data + +The input_bus_format field of struct dw_hdmi_plat_data is unused. Remove +it. + +Signed-off-by: Laurent Pinchart +Reviewed-by: Neil Armstrong +Signed-off-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/20200526011505.31884-14-laurent.pinchart+renesas@ideasonboard.com +(cherry picked from commit 29fc89719d396e81176974ce37e0cc81e23869d8) +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 5 +---- + include/drm/bridge/dw_hdmi.h | 1 - + 2 files changed, 1 insertion(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 6edb60e6c784..adc5a95a06e9 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -2137,10 +2137,7 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode) + hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 0; + hdmi->hdmi_data.video_mode.mpixelrepetitioninput = 0; + +- if (hdmi->plat_data->input_bus_format) +- hdmi->hdmi_data.enc_in_bus_format = +- hdmi->plat_data->input_bus_format; +- else if (hdmi->hdmi_data.enc_in_bus_format == MEDIA_BUS_FMT_FIXED) ++ if (hdmi->hdmi_data.enc_in_bus_format == MEDIA_BUS_FMT_FIXED) + hdmi->hdmi_data.enc_in_bus_format = MEDIA_BUS_FMT_RGB888_1X24; + + /* TOFIX: Get input encoding from plat data or fallback to none */ +diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h +index 09348c9cbd11..5dfa9d83e2d3 100644 +--- a/include/drm/bridge/dw_hdmi.h ++++ b/include/drm/bridge/dw_hdmi.h +@@ -125,7 +125,6 @@ struct dw_hdmi_phy_ops { + struct dw_hdmi_plat_data { + struct regmap *regm; + +- unsigned long input_bus_format; + unsigned long input_bus_encoding; + bool use_drm_infoframe; + bool ycbcr_420_allowed; + +From 69d79aec4b09b3dce733fedcef1c5f129220e745 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Tue, 26 May 2020 04:14:52 +0300 +Subject: [PATCH] drm: meson: dw-hdmi: Use dw_hdmi context to replace hack + +The meson-dw-hdmi driver needs to access its own context from the +.mode_valid() operation. It currently gets it from the dev_private field +of the drm_device retrieved from the connector, which is a hack. Use the +private data passed to the .mode_valid() operation instead. + +Signed-off-by: Laurent Pinchart +Reviewed-by: Neil Armstrong +Signed-off-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/20200526011505.31884-15-laurent.pinchart+renesas@ideasonboard.com +(cherry picked from commit 9bc78d6dc818701e47c5ebd0879877a512f039f0) +--- + drivers/gpu/drm/meson/meson_dw_hdmi.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c +index fc594213c0e0..607bd9f495b1 100644 +--- a/drivers/gpu/drm/meson/meson_dw_hdmi.c ++++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c +@@ -634,7 +634,8 @@ dw_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, + struct drm_connector *connector, + const struct drm_display_mode *mode) + { +- struct meson_drm *priv = connector->dev->dev_private; ++ struct meson_dw_hdmi *dw_hdmi = data; ++ struct meson_drm *priv = dw_hdmi->priv; + bool is_hdmi2_sink = connector->display_info.hdmi.scdc.supported; + unsigned int phy_freq; + unsigned int vclk_freq; +@@ -693,7 +694,7 @@ dw_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, + if (mode->flags & DRM_MODE_FLAG_DBLCLK) + venc_freq /= 2; + +- dev_dbg(connector->dev->dev, "%s: vclk:%d phy=%d venc=%d hdmi=%d\n", ++ dev_dbg(dw_hdmi->dev, "%s: vclk:%d phy=%d venc=%d hdmi=%d\n", + __func__, phy_freq, vclk_freq, venc_freq, hdmi_freq); + + return meson_vclk_vic_supported_freq(priv, phy_freq, vclk_freq); +@@ -1066,6 +1067,7 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master, + + /* Bridge / Connector */ + ++ dw_plat_data->priv_data = meson_dw_hdmi; + dw_plat_data->mode_valid = dw_hdmi_mode_valid; + dw_plat_data->phy_ops = &meson_dw_hdmi_phy_ops; + dw_plat_data->phy_name = "meson_dw_hdmi_phy"; + +From 76b17d37e5f17f622d947792abcf4477a27b609e Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Tue, 26 May 2020 04:14:53 +0300 +Subject: [PATCH] drm: bridge: dw-hdmi: Pass drm_display_info to .mode_valid() + +Replace the drm_connector pointer passed to the .mode_valid() function +with a const drm_display_info pointer, as that's all the function should +need. Use the display info passed to the bridge .mode_valid() operation +instead of retrieving it from the connector, to prepare for make +connector creation optional. + +Signed-off-by: Laurent Pinchart +Reviewed-by: Neil Armstrong +Signed-off-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/20200526011505.31884-16-laurent.pinchart+renesas@ideasonboard.com +(cherry picked from commit af05bba0fbe2c07fe500f697080d78d050be2fbf) +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 5 ++--- + drivers/gpu/drm/imx/dw_hdmi-imx.c | 4 ++-- + drivers/gpu/drm/meson/meson_dw_hdmi.c | 20 ++++++++++---------- + drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c | 2 +- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2 +- + drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 4 ++-- + drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 2 +- + include/drm/bridge/dw_hdmi.h | 4 ++-- + 8 files changed, 21 insertions(+), 22 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index adc5a95a06e9..23650e69604c 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -2769,7 +2769,6 @@ dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge, + { + struct dw_hdmi *hdmi = bridge->driver_private; + const struct dw_hdmi_plat_data *pdata = hdmi->plat_data; +- struct drm_connector *connector = &hdmi->connector; + enum drm_mode_status mode_status = MODE_OK; + + /* We don't support double-clocked modes */ +@@ -2777,8 +2776,8 @@ dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge, + return MODE_BAD; + + if (pdata->mode_valid) +- mode_status = pdata->mode_valid(hdmi, pdata->priv_data, +- connector, mode); ++ mode_status = pdata->mode_valid(hdmi, pdata->priv_data, info, ++ mode); + + return mode_status; + } +diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c +index ff4fde0eb5f6..71d84c7a5378 100644 +--- a/drivers/gpu/drm/imx/dw_hdmi-imx.c ++++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c +@@ -146,7 +146,7 @@ static const struct drm_encoder_helper_funcs dw_hdmi_imx_encoder_helper_funcs = + + static enum drm_mode_status + imx6q_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, +- struct drm_connector *con, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + if (mode->clock < 13500) +@@ -160,7 +160,7 @@ imx6q_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, + + static enum drm_mode_status + imx6dl_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, +- struct drm_connector *con, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + if (mode->clock < 13500) +diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c +index 607bd9f495b1..50b950f5ca3c 100644 +--- a/drivers/gpu/drm/meson/meson_dw_hdmi.c ++++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c +@@ -631,12 +631,12 @@ static irqreturn_t dw_hdmi_top_thread_irq(int irq, void *dev_id) + + static enum drm_mode_status + dw_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, +- struct drm_connector *connector, ++ const struct drm_display_info *display_info, + const struct drm_display_mode *mode) + { + struct meson_dw_hdmi *dw_hdmi = data; + struct meson_drm *priv = dw_hdmi->priv; +- bool is_hdmi2_sink = connector->display_info.hdmi.scdc.supported; ++ bool is_hdmi2_sink = display_info->hdmi.scdc.supported; + unsigned int phy_freq; + unsigned int vclk_freq; + unsigned int venc_freq; +@@ -647,10 +647,10 @@ dw_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, + DRM_DEBUG_DRIVER("Modeline " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode)); + + /* If sink does not support 540MHz, reject the non-420 HDMI2 modes */ +- if (connector->display_info.max_tmds_clock && +- mode->clock > connector->display_info.max_tmds_clock && +- !drm_mode_is_420_only(&connector->display_info, mode) && +- !drm_mode_is_420_also(&connector->display_info, mode)) ++ if (display_info->max_tmds_clock && ++ mode->clock > display_info->max_tmds_clock && ++ !drm_mode_is_420_only(display_info, mode) && ++ !drm_mode_is_420_also(display_info, mode)) + return MODE_BAD; + + /* Check against non-VIC supported modes */ +@@ -667,9 +667,9 @@ dw_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, + vclk_freq = mode->clock; + + /* For 420, pixel clock is half unlike venc clock */ +- if (drm_mode_is_420_only(&connector->display_info, mode) || ++ if (drm_mode_is_420_only(display_info, mode) || + (!is_hdmi2_sink && +- drm_mode_is_420_also(&connector->display_info, mode))) ++ drm_mode_is_420_also(display_info, mode))) + vclk_freq /= 2; + + /* TMDS clock is pixel_clock * 10 */ +@@ -684,9 +684,9 @@ dw_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, + + /* VENC double pixels for 1080i, 720p and YUV420 modes */ + if (meson_venc_hdmi_venc_repeat(vic) || +- drm_mode_is_420_only(&connector->display_info, mode) || ++ drm_mode_is_420_only(display_info, mode) || + (!is_hdmi2_sink && +- drm_mode_is_420_also(&connector->display_info, mode))) ++ drm_mode_is_420_also(display_info, mode))) + venc_freq *= 2; + + vclk_freq = max(venc_freq, hdmi_freq); +diff --git a/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c b/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c +index d0dffe55a7cb..7b8ec8310699 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c ++++ b/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c +@@ -39,7 +39,7 @@ static const struct rcar_hdmi_phy_params rcar_hdmi_phy_params[] = { + + static enum drm_mode_status + rcar_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, +- struct drm_connector *connector, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + /* +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index d08f86783a28..d286751bb333 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -221,7 +221,7 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) + + static enum drm_mode_status + dw_hdmi_rockchip_mode_valid(struct dw_hdmi *hdmi, void *data, +- struct drm_connector *connector, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + const struct dw_hdmi_mpll_config *mpll_cfg = rockchip_mpll_cfg; +diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c +index 0a3637442ba6..d4c08043dd81 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c ++++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c +@@ -32,7 +32,7 @@ sun8i_dw_hdmi_encoder_helper_funcs = { + + static enum drm_mode_status + sun8i_dw_hdmi_mode_valid_a83t(struct dw_hdmi *hdmi, void *data, +- struct drm_connector *connector, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + if (mode->clock > 297000) +@@ -43,7 +43,7 @@ sun8i_dw_hdmi_mode_valid_a83t(struct dw_hdmi *hdmi, void *data, + + static enum drm_mode_status + sun8i_dw_hdmi_mode_valid_h6(struct dw_hdmi *hdmi, void *data, +- struct drm_connector *connector, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + /* +diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h +index 8587b8d2590e..d983746fa194 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h ++++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h +@@ -177,7 +177,7 @@ struct sun8i_hdmi_phy { + + struct sun8i_dw_hdmi_quirks { + enum drm_mode_status (*mode_valid)(struct dw_hdmi *hdmi, void *data, +- struct drm_connector *connector, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode); + unsigned int set_rate : 1; + unsigned int use_drm_infoframe : 1; +diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h +index 5dfa9d83e2d3..fec293b21c2e 100644 +--- a/include/drm/bridge/dw_hdmi.h ++++ b/include/drm/bridge/dw_hdmi.h +@@ -8,7 +8,7 @@ + + #include + +-struct drm_connector; ++struct drm_display_info; + struct drm_display_mode; + struct drm_encoder; + struct dw_hdmi; +@@ -137,7 +137,7 @@ struct dw_hdmi_plat_data { + + /* Platform-specific mode validation (optional). */ + enum drm_mode_status (*mode_valid)(struct dw_hdmi *hdmi, void *data, +- struct drm_connector *connector, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode); + + /* Vendor PHY support */ + +From 799196d6da0801a31a7129bbdae2aa760714b187 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Tue, 26 May 2020 04:14:54 +0300 +Subject: [PATCH] drm: bridge: dw-hdmi: Constify mode argument to + dw_hdmi_phy_ops .init() + +The PHY .init() must not modify the mode it receives. Make the pointer +const to enfore that. + +Signed-off-by: Laurent Pinchart +Reviewed-by: Neil Armstrong +Signed-off-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/20200526011505.31884-17-laurent.pinchart+renesas@ideasonboard.com +(cherry picked from commit 35a395f1134bbbd2984dcca28c04f09fbbb8b0a4) +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 2 +- + drivers/gpu/drm/meson/meson_dw_hdmi.c | 4 ++-- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2 +- + drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 2 +- + include/drm/bridge/dw_hdmi.h | 2 +- + 5 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 23650e69604c..6e6a3d95e68e 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -1531,7 +1531,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi) + } + + static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data, +- struct drm_display_mode *mode) ++ const struct drm_display_mode *mode) + { + int i, ret; + +diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c +index 50b950f5ca3c..a1217df5fe5a 100644 +--- a/drivers/gpu/drm/meson/meson_dw_hdmi.c ++++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c +@@ -297,7 +297,7 @@ static inline void dw_hdmi_dwc_write_bits(struct meson_dw_hdmi *dw_hdmi, + + /* Setup PHY bandwidth modes */ + static void meson_hdmi_phy_setup_mode(struct meson_dw_hdmi *dw_hdmi, +- struct drm_display_mode *mode) ++ const struct drm_display_mode *mode) + { + struct meson_drm *priv = dw_hdmi->priv; + unsigned int pixel_clock = mode->clock; +@@ -427,7 +427,7 @@ static void dw_hdmi_set_vclk(struct meson_dw_hdmi *dw_hdmi, + } + + static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data, +- struct drm_display_mode *mode) ++ const struct drm_display_mode *mode) + { + struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data; + struct meson_drm *priv = dw_hdmi->priv; +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index d286751bb333..10e210f6455d 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -312,7 +312,7 @@ static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_fun + }; + + static int dw_hdmi_rockchip_genphy_init(struct dw_hdmi *dw_hdmi, void *data, +- struct drm_display_mode *mode) ++ const struct drm_display_mode *mode) + { + struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; + +diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c +index 43643ad31730..8e078cacf063 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c ++++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c +@@ -341,7 +341,7 @@ static int sun8i_hdmi_phy_config_h3(struct dw_hdmi *hdmi, + } + + static int sun8i_hdmi_phy_config(struct dw_hdmi *hdmi, void *data, +- struct drm_display_mode *mode) ++ const struct drm_display_mode *mode) + { + struct sun8i_hdmi_phy *phy = (struct sun8i_hdmi_phy *)data; + u32 val = 0; +diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h +index fec293b21c2e..f930d218cc6b 100644 +--- a/include/drm/bridge/dw_hdmi.h ++++ b/include/drm/bridge/dw_hdmi.h +@@ -114,7 +114,7 @@ struct dw_hdmi_phy_config { + + struct dw_hdmi_phy_ops { + int (*init)(struct dw_hdmi *hdmi, void *data, +- struct drm_display_mode *mode); ++ const struct drm_display_mode *mode); + void (*disable)(struct dw_hdmi *hdmi, void *data); + enum drm_connector_status (*read_hpd)(struct dw_hdmi *hdmi, void *data); + void (*update_hpd)(struct dw_hdmi *hdmi, void *data, + +From 39e51f084a6c1b5a94151803063f5d2ec44c2389 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Tue, 26 May 2020 04:14:55 +0300 +Subject: [PATCH] drm: bridge: dw-hdmi: Constify mode argument to internal + functions + +Several internal functions take a drm_display_mode argument to configure +the HDMI encoder or the HDMI PHY. They must not modify the mode, make +the pointer const to enforce that. + +Signed-off-by: Laurent Pinchart +Reviewed-by: Neil Armstrong +Signed-off-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/20200526011505.31884-18-laurent.pinchart+renesas@ideasonboard.com +(cherry picked from commit 9fbfa320b435e6f25499a63f7bb74b4fc5341b30) +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 6e6a3d95e68e..5b5f07a23400 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -1628,7 +1628,8 @@ static void hdmi_tx_hdcp_config(struct dw_hdmi *hdmi) + HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK, HDMI_A_HDCPCFG1); + } + +-static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode) ++static void hdmi_config_AVI(struct dw_hdmi *hdmi, ++ const struct drm_display_mode *mode) + { + struct hdmi_avi_infoframe frame; + u8 val; +@@ -1756,7 +1757,7 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode) + } + + static void hdmi_config_vendor_specific_infoframe(struct dw_hdmi *hdmi, +- struct drm_display_mode *mode) ++ const struct drm_display_mode *mode) + { + struct hdmi_vendor_infoframe frame; + u8 buffer[10]; +@@ -2112,7 +2113,8 @@ static void hdmi_disable_overflow_interrupts(struct dw_hdmi *hdmi) + HDMI_IH_MUTE_FC_STAT2); + } + +-static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode) ++static int dw_hdmi_setup(struct dw_hdmi *hdmi, ++ const struct drm_display_mode *mode) + { + int ret; + + +From 9dd65c0f564ebe5257c3d5322e40200ac254570b Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Tue, 26 May 2020 04:14:56 +0300 +Subject: [PATCH] drm: bridge: dw-hdmi: Pass drm_display_info to + dw_hdmi_support_scdc() + +To prepare for making connector creation optional in the driver, pass +the drm_display_info explicitly to dw_hdmi_support_scdc(). The pointer +is passed to the callers where required, particularly to the +dw_hdmi_phy_ops .init() function. + +Signed-off-by: Laurent Pinchart +Reviewed-by: Neil Armstrong +Signed-off-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/20200526011505.31884-19-laurent.pinchart+renesas@ideasonboard.com +(cherry picked from commit 7be390d4c0a125266c558c30a3687d931c3b6101) +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 32 ++++++++++++--------- + drivers/gpu/drm/meson/meson_dw_hdmi.c | 3 +- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 1 + + drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 1 + + include/drm/bridge/dw_hdmi.h | 4 ++- + 5 files changed, 26 insertions(+), 15 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 5b5f07a23400..a18794cce0d8 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -1241,10 +1241,9 @@ void dw_hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data, + EXPORT_SYMBOL_GPL(dw_hdmi_phy_i2c_write); + + /* Filter out invalid setups to avoid configuring SCDC and scrambling */ +-static bool dw_hdmi_support_scdc(struct dw_hdmi *hdmi) ++static bool dw_hdmi_support_scdc(struct dw_hdmi *hdmi, ++ const struct drm_display_info *display) + { +- struct drm_display_info *display = &hdmi->connector.display_info; +- + /* Completely disable SCDC support for older controllers */ + if (hdmi->version < 0x200a) + return false; +@@ -1282,12 +1281,13 @@ static bool dw_hdmi_support_scdc(struct dw_hdmi *hdmi) + * helper should called right before enabling the TMDS Clock and Data in + * the PHY configuration callback. + */ +-void dw_hdmi_set_high_tmds_clock_ratio(struct dw_hdmi *hdmi) ++void dw_hdmi_set_high_tmds_clock_ratio(struct dw_hdmi *hdmi, ++ const struct drm_display_info *display) + { + unsigned long mtmdsclock = hdmi->hdmi_data.video_mode.mtmdsclock; + + /* Control for TMDS Bit Period/TMDS Clock-Period Ratio */ +- if (dw_hdmi_support_scdc(hdmi)) { ++ if (dw_hdmi_support_scdc(hdmi, display)) { + if (mtmdsclock > HDMI14_MAX_TMDSCLK) + drm_scdc_set_high_tmds_clock_ratio(hdmi->ddc, 1); + else +@@ -1490,7 +1490,8 @@ static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi, + return 0; + } + +-static int hdmi_phy_configure(struct dw_hdmi *hdmi) ++static int hdmi_phy_configure(struct dw_hdmi *hdmi, ++ const struct drm_display_info *display) + { + const struct dw_hdmi_phy_data *phy = hdmi->phy.data; + const struct dw_hdmi_plat_data *pdata = hdmi->plat_data; +@@ -1500,7 +1501,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi) + + dw_hdmi_phy_power_off(hdmi); + +- dw_hdmi_set_high_tmds_clock_ratio(hdmi); ++ dw_hdmi_set_high_tmds_clock_ratio(hdmi, display); + + /* Leave low power consumption mode by asserting SVSRET. */ + if (phy->has_svsret) +@@ -1531,6 +1532,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi) + } + + static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data, ++ const struct drm_display_info *display, + const struct drm_display_mode *mode) + { + int i, ret; +@@ -1540,7 +1542,7 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data, + dw_hdmi_phy_sel_data_en_pol(hdmi, 1); + dw_hdmi_phy_sel_interface_control(hdmi, 0); + +- ret = hdmi_phy_configure(hdmi); ++ ret = hdmi_phy_configure(hdmi, display); + if (ret) + return ret; + } +@@ -1846,10 +1848,11 @@ static void hdmi_config_drm_infoframe(struct dw_hdmi *hdmi) + } + + static void hdmi_av_composer(struct dw_hdmi *hdmi, ++ const struct drm_display_info *display, + const struct drm_display_mode *mode) + { + u8 inv_val, bytes; +- struct drm_hdmi_info *hdmi_info = &hdmi->connector.display_info.hdmi; ++ const struct drm_hdmi_info *hdmi_info = &display->hdmi; + struct hdmi_vmode *vmode = &hdmi->hdmi_data.video_mode; + int hblank, vblank, h_de_hs, v_de_vs, hsync_len, vsync_len; + unsigned int vdisplay, hdisplay; +@@ -1882,7 +1885,7 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi, + + /* Set up HDMI_FC_INVIDCONF */ + inv_val = (hdmi->hdmi_data.hdcp_enable || +- (dw_hdmi_support_scdc(hdmi) && ++ (dw_hdmi_support_scdc(hdmi, display) && + (vmode->mtmdsclock > HDMI14_MAX_TMDSCLK || + hdmi_info->scdc.scrambling.low_rates)) ? + HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE : +@@ -1950,7 +1953,7 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi, + } + + /* Scrambling Control */ +- if (dw_hdmi_support_scdc(hdmi)) { ++ if (dw_hdmi_support_scdc(hdmi, display)) { + if (vmode->mtmdsclock > HDMI14_MAX_TMDSCLK || + hdmi_info->scdc.scrambling.low_rates) { + /* +@@ -2116,6 +2119,7 @@ static void hdmi_disable_overflow_interrupts(struct dw_hdmi *hdmi) + static int dw_hdmi_setup(struct dw_hdmi *hdmi, + const struct drm_display_mode *mode) + { ++ struct drm_connector *connector = &hdmi->connector; + int ret; + + hdmi_disable_overflow_interrupts(hdmi); +@@ -2161,10 +2165,12 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, + hdmi->hdmi_data.video_mode.mdataenablepolarity = true; + + /* HDMI Initialization Step B.1 */ +- hdmi_av_composer(hdmi, mode); ++ hdmi_av_composer(hdmi, &connector->display_info, mode); + + /* HDMI Initializateion Step B.2 */ +- ret = hdmi->phy.ops->init(hdmi, hdmi->phy.data, &hdmi->previous_mode); ++ ret = hdmi->phy.ops->init(hdmi, hdmi->phy.data, ++ &connector->display_info, ++ &hdmi->previous_mode); + if (ret) + return ret; + hdmi->phy.enabled = true; +diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c +index a1217df5fe5a..29a8ff41595d 100644 +--- a/drivers/gpu/drm/meson/meson_dw_hdmi.c ++++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c +@@ -427,6 +427,7 @@ static void dw_hdmi_set_vclk(struct meson_dw_hdmi *dw_hdmi, + } + + static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data, ++ const struct drm_display_info *display, + const struct drm_display_mode *mode) + { + struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data; +@@ -496,7 +497,7 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data, + /* Disable clock, fifo, fifo_wr */ + regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 0xf, 0); + +- dw_hdmi_set_high_tmds_clock_ratio(hdmi); ++ dw_hdmi_set_high_tmds_clock_ratio(hdmi, display); + + msleep(100); + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index 10e210f6455d..23de359a1dec 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -312,6 +312,7 @@ static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_fun + }; + + static int dw_hdmi_rockchip_genphy_init(struct dw_hdmi *dw_hdmi, void *data, ++ const struct drm_display_info *display, + const struct drm_display_mode *mode) + { + struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; +diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c +index 8e078cacf063..156d00e5165b 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c ++++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c +@@ -341,6 +341,7 @@ static int sun8i_hdmi_phy_config_h3(struct dw_hdmi *hdmi, + } + + static int sun8i_hdmi_phy_config(struct dw_hdmi *hdmi, void *data, ++ const struct drm_display_info *display, + const struct drm_display_mode *mode) + { + struct sun8i_hdmi_phy *phy = (struct sun8i_hdmi_phy *)data; +diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h +index f930d218cc6b..ea34ca146b82 100644 +--- a/include/drm/bridge/dw_hdmi.h ++++ b/include/drm/bridge/dw_hdmi.h +@@ -114,6 +114,7 @@ struct dw_hdmi_phy_config { + + struct dw_hdmi_phy_ops { + int (*init)(struct dw_hdmi *hdmi, void *data, ++ const struct drm_display_info *display, + const struct drm_display_mode *mode); + void (*disable)(struct dw_hdmi *hdmi, void *data); + enum drm_connector_status (*read_hpd)(struct dw_hdmi *hdmi, void *data); +@@ -174,7 +175,8 @@ void dw_hdmi_set_channel_status(struct dw_hdmi *hdmi, u8 *channel_status); + void dw_hdmi_set_channel_allocation(struct dw_hdmi *hdmi, unsigned int ca); + void dw_hdmi_audio_enable(struct dw_hdmi *hdmi); + void dw_hdmi_audio_disable(struct dw_hdmi *hdmi); +-void dw_hdmi_set_high_tmds_clock_ratio(struct dw_hdmi *hdmi); ++void dw_hdmi_set_high_tmds_clock_ratio(struct dw_hdmi *hdmi, ++ const struct drm_display_info *display); + + /* PHY configuration */ + void dw_hdmi_phy_i2c_set_addr(struct dw_hdmi *hdmi, u8 address); + +From 57c01c57d5aff20753b3c418abb52b3b317c0166 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Tue, 26 May 2020 04:14:57 +0300 +Subject: [PATCH] drm: bridge: dw-hdmi: Split connector creation to a separate + function + +Isolate all the code related to connector creation to a new +dw_hdmi_connector_create() function, to prepare for making connector +creation optional. + +Signed-off-by: Laurent Pinchart +Reviewed-by: Neil Armstrong +Signed-off-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/20200526011505.31884-20-laurent.pinchart+renesas@ideasonboard.com +(cherry picked from commit 3f588fda4b80dbd7dafa08b0e16fd72a42676e3c) +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 107 +++++++++++++--------- + 1 file changed, 62 insertions(+), 45 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index a18794cce0d8..35d38b644912 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -2317,6 +2317,10 @@ static void dw_hdmi_update_phy_mask(struct dw_hdmi *hdmi) + hdmi->rxsense); + } + ++/* ----------------------------------------------------------------------------- ++ * DRM Connector Operations ++ */ ++ + static enum drm_connector_status + dw_hdmi_connector_detect(struct drm_connector *connector, bool force) + { +@@ -2438,6 +2442,59 @@ static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = + .atomic_check = dw_hdmi_connector_atomic_check, + }; + ++static int dw_hdmi_connector_create(struct dw_hdmi *hdmi) ++{ ++ struct drm_connector *connector = &hdmi->connector; ++ struct cec_connector_info conn_info; ++ struct cec_notifier *notifier; ++ ++ if (hdmi->version >= 0x200a) ++ connector->ycbcr_420_allowed = ++ hdmi->plat_data->ycbcr_420_allowed; ++ else ++ connector->ycbcr_420_allowed = false; ++ ++ connector->interlace_allowed = 1; ++ connector->polled = DRM_CONNECTOR_POLL_HPD; ++ ++ drm_connector_helper_add(connector, &dw_hdmi_connector_helper_funcs); ++ ++ drm_connector_init_with_ddc(hdmi->bridge.dev, connector, ++ &dw_hdmi_connector_funcs, ++ DRM_MODE_CONNECTOR_HDMIA, ++ hdmi->ddc); ++ ++ /* ++ * drm_connector_attach_max_bpc_property() requires the ++ * connector to have a state. ++ */ ++ drm_atomic_helper_connector_reset(connector); ++ ++ drm_connector_attach_max_bpc_property(connector, 8, 16); ++ ++ if (hdmi->version >= 0x200a && hdmi->plat_data->use_drm_infoframe) ++ drm_object_attach_property(&connector->base, ++ connector->dev->mode_config.hdr_output_metadata_property, 0); ++ ++ drm_connector_attach_encoder(connector, hdmi->bridge.encoder); ++ ++ cec_fill_conn_info_from_drm(&conn_info, connector); ++ ++ notifier = cec_notifier_conn_register(hdmi->dev, NULL, &conn_info); ++ if (!notifier) ++ return -ENOMEM; ++ ++ mutex_lock(&hdmi->cec_notifier_mutex); ++ hdmi->cec_notifier = notifier; ++ mutex_unlock(&hdmi->cec_notifier_mutex); ++ ++ return 0; ++} ++ ++/* ----------------------------------------------------------------------------- ++ * DRM Bridge Operations ++ */ ++ + /* + * Possible output formats : + * - MEDIA_BUS_FMT_UYYVYY16_0_5X48, +@@ -2713,51 +2770,13 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge, + enum drm_bridge_attach_flags flags) + { + struct dw_hdmi *hdmi = bridge->driver_private; +- struct drm_encoder *encoder = bridge->encoder; +- struct drm_connector *connector = &hdmi->connector; +- struct cec_connector_info conn_info; +- struct cec_notifier *notifier; + + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { + DRM_ERROR("Fix bridge driver to make connector optional!"); + return -EINVAL; + } + +- connector->interlace_allowed = 1; +- connector->polled = DRM_CONNECTOR_POLL_HPD; +- +- drm_connector_helper_add(connector, &dw_hdmi_connector_helper_funcs); +- +- drm_connector_init_with_ddc(bridge->dev, connector, +- &dw_hdmi_connector_funcs, +- DRM_MODE_CONNECTOR_HDMIA, +- hdmi->ddc); +- +- /* +- * drm_connector_attach_max_bpc_property() requires the +- * connector to have a state. +- */ +- drm_atomic_helper_connector_reset(connector); +- +- drm_connector_attach_max_bpc_property(connector, 8, 16); +- +- if (hdmi->version >= 0x200a && hdmi->plat_data->use_drm_infoframe) +- drm_object_attach_property(&connector->base, +- connector->dev->mode_config.hdr_output_metadata_property, 0); +- +- drm_connector_attach_encoder(connector, encoder); +- +- cec_fill_conn_info_from_drm(&conn_info, connector); +- +- notifier = cec_notifier_conn_register(hdmi->dev, NULL, &conn_info); +- if (!notifier) +- return -ENOMEM; +- +- mutex_lock(&hdmi->cec_notifier_mutex); +- hdmi->cec_notifier = notifier; +- mutex_unlock(&hdmi->cec_notifier_mutex); +- +- return 0; ++ return dw_hdmi_connector_create(hdmi); + } + + static void dw_hdmi_bridge_detach(struct drm_bridge *bridge) +@@ -2841,6 +2860,10 @@ static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = { + .mode_valid = dw_hdmi_bridge_mode_valid, + }; + ++/* ----------------------------------------------------------------------------- ++ * IRQ Handling ++ */ ++ + static irqreturn_t dw_hdmi_i2c_irq(struct dw_hdmi *hdmi) + { + struct dw_hdmi_i2c *i2c = hdmi->i2c; +@@ -3303,12 +3326,6 @@ __dw_hdmi_probe(struct platform_device *pdev, + hdmi->bridge.of_node = pdev->dev.of_node; + #endif + +- if (hdmi->version >= 0x200a) +- hdmi->connector.ycbcr_420_allowed = +- hdmi->plat_data->ycbcr_420_allowed; +- else +- hdmi->connector.ycbcr_420_allowed = false; +- + memset(&pdevinfo, 0, sizeof(pdevinfo)); + pdevinfo.parent = dev; + pdevinfo.id = PLATFORM_DEVID_AUTO; + +From a3b8c4bc7907f025862b25aca04c9edc999a44e5 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Tue, 26 May 2020 04:14:58 +0300 +Subject: [PATCH] drm: bridge: dw-hdmi: Store current connector in struct + dw_hdmi + +Store the connector that the bridge is currently wired to in the dw_hdmi +structure. This is currently identical to the connector field, but will +differ once the driver supports disabling connector creation. + +Signed-off-by: Laurent Pinchart +Reviewed-by: Neil Armstrong +Signed-off-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/20200526011505.31884-21-laurent.pinchart+renesas@ideasonboard.com +(cherry picked from commit ca7b6b7176ffea4d07afbd98ede7a94fb0f68fa1) +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 35d38b644912..16bffedb4715 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -181,6 +181,7 @@ struct dw_hdmi { + + struct mutex mutex; /* for state below and previous_mode */ + enum drm_connector_force force; /* mutex-protected force state */ ++ struct drm_connector *curr_conn;/* current connector (only valid when !disabled) */ + bool disabled; /* DRM has disabled our bridge */ + bool bridge_is_on; /* indicates the bridge is on */ + bool rxsense; /* rxsense state */ +@@ -2823,23 +2824,32 @@ static void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge, + mutex_unlock(&hdmi->mutex); + } + +-static void dw_hdmi_bridge_disable(struct drm_bridge *bridge) ++static void dw_hdmi_bridge_atomic_disable(struct drm_bridge *bridge, ++ struct drm_bridge_state *old_state) + { + struct dw_hdmi *hdmi = bridge->driver_private; + + mutex_lock(&hdmi->mutex); + hdmi->disabled = true; ++ hdmi->curr_conn = NULL; + dw_hdmi_update_power(hdmi); + dw_hdmi_update_phy_mask(hdmi); + mutex_unlock(&hdmi->mutex); + } + +-static void dw_hdmi_bridge_enable(struct drm_bridge *bridge) ++static void dw_hdmi_bridge_atomic_enable(struct drm_bridge *bridge, ++ struct drm_bridge_state *old_state) + { + struct dw_hdmi *hdmi = bridge->driver_private; ++ struct drm_atomic_state *state = old_state->base.state; ++ struct drm_connector *connector; ++ ++ connector = drm_atomic_get_new_connector_for_encoder(state, ++ bridge->encoder); + + mutex_lock(&hdmi->mutex); + hdmi->disabled = false; ++ hdmi->curr_conn = connector; + dw_hdmi_update_power(hdmi); + dw_hdmi_update_phy_mask(hdmi); + mutex_unlock(&hdmi->mutex); +@@ -2854,8 +2864,8 @@ static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = { + .atomic_check = dw_hdmi_bridge_atomic_check, + .atomic_get_output_bus_fmts = dw_hdmi_bridge_atomic_get_output_bus_fmts, + .atomic_get_input_bus_fmts = dw_hdmi_bridge_atomic_get_input_bus_fmts, +- .enable = dw_hdmi_bridge_enable, +- .disable = dw_hdmi_bridge_disable, ++ .atomic_enable = dw_hdmi_bridge_atomic_enable, ++ .atomic_disable = dw_hdmi_bridge_atomic_disable, + .mode_set = dw_hdmi_bridge_mode_set, + .mode_valid = dw_hdmi_bridge_mode_valid, + }; + +From 30b1907401f2475b4b7e8341269a36ef3a45a6bb Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Tue, 26 May 2020 04:14:59 +0300 +Subject: [PATCH] drm: bridge: dw-hdmi: Pass drm_connector to internal + functions as needed + +To prepare for making connector creation optional in the driver, pass +the drm_connector explicitly to the internal functions that require it. +The functions that still access the connector from the dw_hdmi structure +are dw_hdmi_connector_create() and __dw_hdmi_probe(). The former access +is expected, as that's where the internal connector is created. The +latter will be addressed separately. + +Signed-off-by: Laurent Pinchart +Reviewed-by: Neil Armstrong +Signed-off-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/20200526011505.31884-22-laurent.pinchart+renesas@ideasonboard.com +(cherry picked from commit 81980037fb275d9db1bbb0239682d707e8dd62a0) +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 31 +++++++++++++---------- + 1 file changed, 18 insertions(+), 13 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 16bffedb4715..b69c14b9de62 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -1632,18 +1632,17 @@ static void hdmi_tx_hdcp_config(struct dw_hdmi *hdmi) + } + + static void hdmi_config_AVI(struct dw_hdmi *hdmi, ++ const struct drm_connector *connector, + const struct drm_display_mode *mode) + { + struct hdmi_avi_infoframe frame; + u8 val; + + /* Initialise info frame from DRM mode */ +- drm_hdmi_avi_infoframe_from_display_mode(&frame, +- &hdmi->connector, mode); ++ drm_hdmi_avi_infoframe_from_display_mode(&frame, connector, mode); + + if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) { +- drm_hdmi_avi_infoframe_quant_range(&frame, &hdmi->connector, +- mode, ++ drm_hdmi_avi_infoframe_quant_range(&frame, connector, mode, + hdmi->hdmi_data.rgb_limited_range ? + HDMI_QUANTIZATION_RANGE_LIMITED : + HDMI_QUANTIZATION_RANGE_FULL); +@@ -1760,14 +1759,14 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, + } + + static void hdmi_config_vendor_specific_infoframe(struct dw_hdmi *hdmi, ++ const struct drm_connector *connector, + const struct drm_display_mode *mode) + { + struct hdmi_vendor_infoframe frame; + u8 buffer[10]; + ssize_t err; + +- err = drm_hdmi_vendor_infoframe_from_display_mode(&frame, +- &hdmi->connector, ++ err = drm_hdmi_vendor_infoframe_from_display_mode(&frame, connector, + mode); + if (err < 0) + /* +@@ -1813,9 +1812,10 @@ static void hdmi_config_vendor_specific_infoframe(struct dw_hdmi *hdmi, + HDMI_FC_DATAUTO0_VSD_MASK); + } + +-static void hdmi_config_drm_infoframe(struct dw_hdmi *hdmi) ++static void hdmi_config_drm_infoframe(struct dw_hdmi *hdmi, ++ const struct drm_connector *connector) + { +- const struct drm_connector_state *conn_state = hdmi->connector.state; ++ const struct drm_connector_state *conn_state = connector->state; + struct hdmi_drm_infoframe frame; + u8 buffer[30]; + ssize_t err; +@@ -2118,9 +2118,9 @@ static void hdmi_disable_overflow_interrupts(struct dw_hdmi *hdmi) + } + + static int dw_hdmi_setup(struct dw_hdmi *hdmi, ++ const struct drm_connector *connector, + const struct drm_display_mode *mode) + { +- struct drm_connector *connector = &hdmi->connector; + int ret; + + hdmi_disable_overflow_interrupts(hdmi); +@@ -2192,9 +2192,9 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, + dev_dbg(hdmi->dev, "%s HDMI mode\n", __func__); + + /* HDMI Initialization Step F - Configure AVI InfoFrame */ +- hdmi_config_AVI(hdmi, mode); +- hdmi_config_vendor_specific_infoframe(hdmi, mode); +- hdmi_config_drm_infoframe(hdmi); ++ hdmi_config_AVI(hdmi, connector, mode); ++ hdmi_config_vendor_specific_infoframe(hdmi, connector, mode); ++ hdmi_config_drm_infoframe(hdmi, connector); + } else { + dev_dbg(hdmi->dev, "%s DVI mode\n", __func__); + } +@@ -2263,7 +2263,12 @@ static void initialize_hdmi_ih_mutes(struct dw_hdmi *hdmi) + static void dw_hdmi_poweron(struct dw_hdmi *hdmi) + { + hdmi->bridge_is_on = true; +- dw_hdmi_setup(hdmi, &hdmi->previous_mode); ++ ++ /* ++ * The curr_conn field is guaranteed to be valid here, as this function ++ * is only be called when !hdmi->disabled. ++ */ ++ dw_hdmi_setup(hdmi, hdmi->curr_conn, &hdmi->previous_mode); + } + + static void dw_hdmi_poweroff(struct dw_hdmi *hdmi) + +From 26ccb66a87e10784ccfc8366494769888f21ebf2 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Tue, 26 May 2020 04:15:00 +0300 +Subject: [PATCH] drm: bridge: dw-hdmi: Make connector creation optional + +Implement the drm_bridge_funcs .detect() and .get_edid() operations, and +call drm_bridge_hpd_notify() notify to report HPD. This provides the +necessary API to support disabling connector creation, do so by +accepting DRM_BRIDGE_ATTACH_NO_CONNECTOR in dw_hdmi_bridge_attach(). + +Signed-off-by: Laurent Pinchart +Reviewed-by: Neil Armstrong +Signed-off-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/20200526011505.31884-23-laurent.pinchart+renesas@ideasonboard.com +(cherry picked from commit ec971aaa6775cff555b4f58777ceab1d9a8370e0) +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 104 +++++++++++++++------- + 1 file changed, 74 insertions(+), 30 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index b69c14b9de62..6148a022569a 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -2323,15 +2323,8 @@ static void dw_hdmi_update_phy_mask(struct dw_hdmi *hdmi) + hdmi->rxsense); + } + +-/* ----------------------------------------------------------------------------- +- * DRM Connector Operations +- */ +- +-static enum drm_connector_status +-dw_hdmi_connector_detect(struct drm_connector *connector, bool force) ++static enum drm_connector_status dw_hdmi_detect(struct dw_hdmi *hdmi) + { +- struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, +- connector); + enum drm_connector_status result; + + mutex_lock(&hdmi->mutex); +@@ -2354,31 +2347,57 @@ dw_hdmi_connector_detect(struct drm_connector *connector, bool force) + return result; + } + +-static int dw_hdmi_connector_get_modes(struct drm_connector *connector) ++static struct edid *dw_hdmi_get_edid(struct dw_hdmi *hdmi, ++ struct drm_connector *connector) + { +- struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, +- connector); + struct edid *edid; +- int ret = 0; + + if (!hdmi->ddc) +- return 0; ++ return NULL; + + edid = drm_get_edid(connector, hdmi->ddc); +- if (edid) { +- dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]\n", +- edid->width_cm, edid->height_cm); +- +- hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid); +- hdmi->sink_has_audio = drm_detect_monitor_audio(edid); +- drm_connector_update_edid_property(connector, edid); +- cec_notifier_set_phys_addr_from_edid(hdmi->cec_notifier, edid); +- ret = drm_add_edid_modes(connector, edid); +- kfree(edid); +- } else { ++ if (!edid) { + dev_dbg(hdmi->dev, "failed to get edid\n"); ++ return NULL; + } + ++ dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]\n", ++ edid->width_cm, edid->height_cm); ++ ++ hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid); ++ hdmi->sink_has_audio = drm_detect_monitor_audio(edid); ++ ++ return edid; ++} ++ ++/* ----------------------------------------------------------------------------- ++ * DRM Connector Operations ++ */ ++ ++static enum drm_connector_status ++dw_hdmi_connector_detect(struct drm_connector *connector, bool force) ++{ ++ struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, ++ connector); ++ return dw_hdmi_detect(hdmi); ++} ++ ++static int dw_hdmi_connector_get_modes(struct drm_connector *connector) ++{ ++ struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, ++ connector); ++ struct edid *edid; ++ int ret; ++ ++ edid = dw_hdmi_get_edid(hdmi, connector); ++ if (!edid) ++ return 0; ++ ++ drm_connector_update_edid_property(connector, edid); ++ cec_notifier_set_phys_addr_from_edid(hdmi->cec_notifier, edid); ++ ret = drm_add_edid_modes(connector, edid); ++ kfree(edid); ++ + return ret; + } + +@@ -2777,10 +2796,8 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge, + { + struct dw_hdmi *hdmi = bridge->driver_private; + +- if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { +- DRM_ERROR("Fix bridge driver to make connector optional!"); +- return -EINVAL; +- } ++ if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) ++ return 0; + + return dw_hdmi_connector_create(hdmi); + } +@@ -2860,6 +2877,21 @@ static void dw_hdmi_bridge_atomic_enable(struct drm_bridge *bridge, + mutex_unlock(&hdmi->mutex); + } + ++static enum drm_connector_status dw_hdmi_bridge_detect(struct drm_bridge *bridge) ++{ ++ struct dw_hdmi *hdmi = bridge->driver_private; ++ ++ return dw_hdmi_detect(hdmi); ++} ++ ++static struct edid *dw_hdmi_bridge_get_edid(struct drm_bridge *bridge, ++ struct drm_connector *connector) ++{ ++ struct dw_hdmi *hdmi = bridge->driver_private; ++ ++ return dw_hdmi_get_edid(hdmi, connector); ++} ++ + static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = { + .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, +@@ -2873,6 +2905,8 @@ static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = { + .atomic_disable = dw_hdmi_bridge_atomic_disable, + .mode_set = dw_hdmi_bridge_mode_set, + .mode_valid = dw_hdmi_bridge_mode_valid, ++ .detect = dw_hdmi_bridge_detect, ++ .get_edid = dw_hdmi_bridge_get_edid, + }; + + /* ----------------------------------------------------------------------------- +@@ -2988,10 +3022,18 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) + } + + if (intr_stat & HDMI_IH_PHY_STAT0_HPD) { ++ enum drm_connector_status status = phy_int_pol & HDMI_PHY_HPD ++ ? connector_status_connected ++ : connector_status_disconnected; ++ + dev_dbg(hdmi->dev, "EVENT=%s\n", +- phy_int_pol & HDMI_PHY_HPD ? "plugin" : "plugout"); +- if (hdmi->bridge.dev) ++ status == connector_status_connected ? ++ "plugin" : "plugout"); ++ ++ if (hdmi->bridge.dev) { + drm_helper_hpd_irq_event(hdmi->bridge.dev); ++ drm_bridge_hpd_notify(&hdmi->bridge, status); ++ } + } + + hdmi_writeb(hdmi, intr_stat, HDMI_IH_PHY_STAT0); +@@ -3337,6 +3379,8 @@ __dw_hdmi_probe(struct platform_device *pdev, + + hdmi->bridge.driver_private = hdmi; + hdmi->bridge.funcs = &dw_hdmi_bridge_funcs; ++ hdmi->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID ++ | DRM_BRIDGE_OP_HPD; + #ifdef CONFIG_OF + hdmi->bridge.of_node = pdev->dev.of_node; + #endif + +From 5631b3347b2c688d45a5804cc706702553873c3f Mon Sep 17 00:00:00 2001 +From: Stanislav Lisovskiy +Date: Tue, 30 Jun 2020 05:56:58 +0530 +Subject: [PATCH] drm: Add helper to compare edids. + +Many drivers would benefit from using +drm helper to compare edid, rather +than bothering with own implementation. + +v2: Added documentation for this function. + +Signed-off-by: Stanislav Lisovskiy +Signed-off-by: Maarten Lankhorst +Link: https://patchwork.freedesktop.org/patch/msgid/20200630002700.5451-2-kunal1.joshi@intel.com +(cherry picked from commit 536faa450e17f32fddb1a2124e3df71a966122cd) +--- + drivers/gpu/drm/drm_edid.c | 33 +++++++++++++++++++++++++++++++++ + include/drm/drm_edid.h | 9 +++++++++ + 2 files changed, 42 insertions(+) + +diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c +index b3f659759adb..aa0644d8272a 100644 +--- a/drivers/gpu/drm/drm_edid.c ++++ b/drivers/gpu/drm/drm_edid.c +@@ -1615,6 +1615,39 @@ static bool drm_edid_is_zero(const u8 *in_edid, int length) + return true; + } + ++/** ++ * drm_edid_are_equal - compare two edid blobs. ++ * @edid1: pointer to first blob ++ * @edid2: pointer to second blob ++ * This helper can be used during probing to determine if ++ * edid had changed. ++ */ ++bool drm_edid_are_equal(const struct edid *edid1, const struct edid *edid2) ++{ ++ int edid1_len, edid2_len; ++ bool edid1_present = edid1 != NULL; ++ bool edid2_present = edid2 != NULL; ++ ++ if (edid1_present != edid2_present) ++ return false; ++ ++ if (edid1) { ++ ++ edid1_len = EDID_LENGTH * (1 + edid1->extensions); ++ edid2_len = EDID_LENGTH * (1 + edid2->extensions); ++ ++ if (edid1_len != edid2_len) ++ return false; ++ ++ if (memcmp(edid1, edid2, edid1_len)) ++ return false; ++ } ++ ++ return true; ++} ++EXPORT_SYMBOL(drm_edid_are_equal); ++ ++ + /** + * drm_edid_block_valid - Sanity check the EDID block (base or extension) + * @raw_edid: pointer to raw EDID block +diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h +index 43254319ab19..cfa4f5af49af 100644 +--- a/include/drm/drm_edid.h ++++ b/include/drm/drm_edid.h +@@ -359,6 +359,15 @@ drm_load_edid_firmware(struct drm_connector *connector) + } + #endif + ++/** ++ * drm_edid_are_equal - compare two edid blobs. ++ * @edid1: pointer to first blob ++ * @edid2: pointer to second blob ++ * This helper can be used during probing to determine if ++ * edid had changed. ++ */ ++bool drm_edid_are_equal(const struct edid *edid1, const struct edid *edid2); ++ + int + drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame, + const struct drm_connector *connector, + +From 00fb1055155719f429be43ff1864959cea9a56e2 Mon Sep 17 00:00:00 2001 +From: Stanislav Lisovskiy +Date: Tue, 30 Jun 2020 05:56:59 +0530 +Subject: [PATCH] drm: Introduce epoch counter to drm_connector + +This counter will be used by drm_helper_probe_detect caller to determine +if anything had changed(including edid, connection status and etc). +Hardware specific driver detect hooks are responsible for updating this +counter when some change is detected to notify the drm part, +which can trigger for example hotplug event. + +Also now call drm_connector_update_edid_property +right after we get edid always to make sure there is a +unified way to handle edid change, without having to +change tons of source code as currently +drm_connector_update_edid_property is called only in +certain cases like reprobing and not right after edid is +actually updated. + +v2: Added documentation for the new counter. Rename change_counter to + epoch_counter. + +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=105540 + +Signed-off-by: Stanislav Lisovskiy +Signed-off-by: Maarten Lankhorst +Link: https://patchwork.freedesktop.org/patch/msgid/20200630002700.5451-3-kunal1.joshi@intel.com +(cherry picked from commit 5186421cbfe250002308d4d759674214b385752f) +--- + drivers/gpu/drm/drm_connector.c | 16 +++++++++++++ + drivers/gpu/drm/drm_edid.c | 8 ++++--- + drivers/gpu/drm/drm_probe_helper.c | 38 ++++++++++++++++++++++++++---- + include/drm/drm_connector.h | 2 ++ + 4 files changed, 56 insertions(+), 8 deletions(-) + +diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c +index d877ddc6dc57..c6d7fc45aeac 100644 +--- a/drivers/gpu/drm/drm_connector.c ++++ b/drivers/gpu/drm/drm_connector.c +@@ -269,6 +269,7 @@ int drm_connector_init(struct drm_device *dev, + INIT_LIST_HEAD(&connector->modes); + mutex_init(&connector->mutex); + connector->edid_blob_ptr = NULL; ++ connector->epoch_counter = 0; + connector->tile_blob_ptr = NULL; + connector->status = connector_status_unknown; + connector->display_info.panel_orientation = +@@ -1954,6 +1955,7 @@ int drm_connector_update_edid_property(struct drm_connector *connector, + struct drm_device *dev = connector->dev; + size_t size = 0; + int ret; ++ const struct edid *old_edid; + + /* ignore requests to set edid when overridden */ + if (connector->override_edid) +@@ -1977,6 +1979,20 @@ int drm_connector_update_edid_property(struct drm_connector *connector, + + drm_update_tile_info(connector, edid); + ++ if (connector->edid_blob_ptr) { ++ old_edid = (const struct edid *)connector->edid_blob_ptr->data; ++ if (old_edid) { ++ if (!drm_edid_are_equal(edid, old_edid)) { ++ DRM_DEBUG_KMS("[CONNECTOR:%d:%s] Edid was changed.\n", ++ connector->base.id, connector->name); ++ ++ connector->epoch_counter += 1; ++ DRM_DEBUG_KMS("Updating change counter to %llu\n", ++ connector->epoch_counter); ++ } ++ } ++ } ++ + drm_object_property_set_value(&connector->base, + dev->mode_config.non_desktop_property, + connector->display_info.non_desktop); +diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c +index aa0644d8272a..ddb9a093ad0d 100644 +--- a/drivers/gpu/drm/drm_edid.c ++++ b/drivers/gpu/drm/drm_edid.c +@@ -1632,7 +1632,6 @@ bool drm_edid_are_equal(const struct edid *edid1, const struct edid *edid2) + return false; + + if (edid1) { +- + edid1_len = EDID_LENGTH * (1 + edid1->extensions); + edid2_len = EDID_LENGTH * (1 + edid2->extensions); + +@@ -1647,7 +1646,6 @@ bool drm_edid_are_equal(const struct edid *edid1, const struct edid *edid2) + } + EXPORT_SYMBOL(drm_edid_are_equal); + +- + /** + * drm_edid_block_valid - Sanity check the EDID block (base or extension) + * @raw_edid: pointer to raw EDID block +@@ -2050,13 +2048,17 @@ EXPORT_SYMBOL(drm_probe_ddc); + struct edid *drm_get_edid(struct drm_connector *connector, + struct i2c_adapter *adapter) + { ++ struct edid *edid; ++ + if (connector->force == DRM_FORCE_OFF) + return NULL; + + if (connector->force == DRM_FORCE_UNSPECIFIED && !drm_probe_ddc(adapter)) + return NULL; + +- return drm_do_get_edid(connector, drm_do_probe_ddc_edid, adapter); ++ edid = drm_do_get_edid(connector, drm_do_probe_ddc_edid, adapter); ++ drm_connector_update_edid_property(connector, edid); ++ return edid; + } + EXPORT_SYMBOL(drm_get_edid); + +diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c +index f5d141e0400f..6d3a1dbfcba5 100644 +--- a/drivers/gpu/drm/drm_probe_helper.c ++++ b/drivers/gpu/drm/drm_probe_helper.c +@@ -290,6 +290,9 @@ drm_helper_probe_detect_ctx(struct drm_connector *connector, bool force) + if (WARN_ON(ret < 0)) + ret = connector_status_unknown; + ++ if (ret != connector->status) ++ connector->epoch_counter += 1; ++ + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); + +@@ -323,11 +326,16 @@ drm_helper_probe_detect(struct drm_connector *connector, + return ret; + + if (funcs->detect_ctx) +- return funcs->detect_ctx(connector, ctx, force); ++ ret = funcs->detect_ctx(connector, ctx, force); + else if (connector->funcs->detect) +- return connector->funcs->detect(connector, force); ++ ret = connector->funcs->detect(connector, force); + else +- return connector_status_connected; ++ ret = connector_status_connected; ++ ++ if (ret != connector->status) ++ connector->epoch_counter += 1; ++ ++ return ret; + } + EXPORT_SYMBOL(drm_helper_probe_detect); + +@@ -780,6 +788,7 @@ bool drm_helper_hpd_irq_event(struct drm_device *dev) + struct drm_connector_list_iter conn_iter; + enum drm_connector_status old_status; + bool changed = false; ++ u64 old_epoch_counter; + + if (!dev->mode_config.poll_enabled) + return false; +@@ -793,20 +802,39 @@ bool drm_helper_hpd_irq_event(struct drm_device *dev) + + old_status = connector->status; + ++ old_epoch_counter = connector->epoch_counter; ++ ++ DRM_DEBUG_KMS("[CONNECTOR:%d:%s] Old epoch counter %llu\n", connector->base.id, ++ connector->name, ++ old_epoch_counter); ++ + connector->status = drm_helper_probe_detect(connector, NULL, false); + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n", + connector->base.id, + connector->name, + drm_get_connector_status_name(old_status), + drm_get_connector_status_name(connector->status)); +- if (old_status != connector->status) ++ ++ DRM_DEBUG_KMS("[CONNECTOR:%d:%s] New epoch counter %llu\n", ++ connector->base.id, ++ connector->name, ++ connector->epoch_counter); ++ ++ /* ++ * Check if epoch counter had changed, meaning that we need ++ * to send a uevent. ++ */ ++ if (old_epoch_counter != connector->epoch_counter) + changed = true; ++ + } + drm_connector_list_iter_end(&conn_iter); + mutex_unlock(&dev->mode_config.mutex); + +- if (changed) ++ if (changed) { + drm_kms_helper_hotplug_event(dev); ++ DRM_DEBUG_KMS("Sent hotplug event\n"); ++ } + + return changed; + } +diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h +index fd543d1db9b2..6a451b86c454 100644 +--- a/include/drm/drm_connector.h ++++ b/include/drm/drm_connector.h +@@ -1329,6 +1329,8 @@ struct drm_connector { + enum drm_connector_force force; + /** @override_edid: has the EDID been overwritten through debugfs for testing? */ + bool override_edid; ++ /** @epoch_counter: used to detect any other changes in connector, besides status */ ++ u64 epoch_counter; + + /** + * @possible_encoders: Bit mask of encoders that can drive this + +From 0402c6b6ec3351cdf475a0a7b4196cea5e213bd0 Mon Sep 17 00:00:00 2001 +From: Neil Armstrong +Date: Fri, 3 Jul 2020 10:07:23 +0200 +Subject: [PATCH] drm/fourcc: Add modifier definitions for describing Amlogic + Video Framebuffer Compression + +Amlogic uses a proprietary lossless image compression protocol and format +for their hardware video codec accelerators, either video decoders or +video input encoders. + +It considerably reduces memory bandwidth while writing and reading +frames in memory. + +The underlying storage is considered to be 3 components, 8bit or 10-bit +per component, YCbCr 420, single plane : +- DRM_FORMAT_YUV420_8BIT +- DRM_FORMAT_YUV420_10BIT + +This modifier will be notably added to DMA-BUF frames imported from the V4L2 +Amlogic VDEC decoder. + +This introduces the basic layout composed of: +- a body content organized in 64x32 superblocks with 4096 bytes per + superblock in default mode. +- a 32 bytes per 128x64 header block + +This layout is tranferrable between Amlogic SoCs supporting this modifier. + +The Memory Saving option exist changing the layout superblock size to save memory when +using 8bit components pixels size. + +Finally is also adds the Scatter Memory layout, meaning the header contains IOMMU +references to the compressed frames content to optimize memory access +and layout. + +In this mode, only the header memory address is needed, thus the content +memory organization is tied to the current producer execution and cannot +be saved/dumped neither transferrable between Amlogic SoCs supporting this +modifier. + +Signed-off-by: Neil Armstrong +Tested-by: Kevin Hilman +Reviewed-by: Kevin Hilman +Acked-by: Daniel Vetter +Link: https://patchwork.freedesktop.org/patch/msgid/20200703080728.25207-2-narmstrong@baylibre.com +(cherry picked from commit d6528ec883096e7ccdb08257bcc45670bc878519) +--- + include/uapi/drm/drm_fourcc.h | 81 +++++++++++++++++++++++++++++++++++ + 1 file changed, 81 insertions(+) + +diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h +index 993c1b342315..cbf92fdf2712 100644 +--- a/include/uapi/drm/drm_fourcc.h ++++ b/include/uapi/drm/drm_fourcc.h +@@ -331,6 +331,7 @@ extern "C" { + #define DRM_FORMAT_MOD_VENDOR_BROADCOM 0x07 + #define DRM_FORMAT_MOD_VENDOR_ARM 0x08 + #define DRM_FORMAT_MOD_VENDOR_ALLWINNER 0x09 ++#define DRM_FORMAT_MOD_VENDOR_AMLOGIC 0x0a + + /* add more to the end as needed */ + +@@ -950,6 +951,86 @@ drm_fourcc_canonicalize_nvidia_format_mod(__u64 modifier) + */ + #define DRM_FORMAT_MOD_ALLWINNER_TILED fourcc_mod_code(ALLWINNER, 1) + ++/* ++ * Amlogic Video Framebuffer Compression modifiers ++ * ++ * Amlogic uses a proprietary lossless image compression protocol and format ++ * for their hardware video codec accelerators, either video decoders or ++ * video input encoders. ++ * ++ * It considerably reduces memory bandwidth while writing and reading ++ * frames in memory. ++ * ++ * The underlying storage is considered to be 3 components, 8bit or 10-bit ++ * per component YCbCr 420, single plane : ++ * - DRM_FORMAT_YUV420_8BIT ++ * - DRM_FORMAT_YUV420_10BIT ++ * ++ * The first 8 bits of the mode defines the layout, then the following 8 bits ++ * defines the options changing the layout. ++ * ++ * Not all combinations are valid, and different SoCs may support different ++ * combinations of layout and options. ++ */ ++#define __fourcc_mod_amlogic_layout_mask 0xf ++#define __fourcc_mod_amlogic_options_shift 8 ++#define __fourcc_mod_amlogic_options_mask 0xf ++ ++#define DRM_FORMAT_MOD_AMLOGIC_FBC(__layout, __options) \ ++ fourcc_mod_code(AMLOGIC, \ ++ ((__layout) & __fourcc_mod_amlogic_layout_mask) | \ ++ ((__options) & __fourcc_mod_amlogic_options_mask \ ++ << __fourcc_mod_amlogic_options_shift)) ++ ++/* Amlogic FBC Layouts */ ++ ++/* ++ * Amlogic FBC Basic Layout ++ * ++ * The basic layout is composed of: ++ * - a body content organized in 64x32 superblocks with 4096 bytes per ++ * superblock in default mode. ++ * - a 32 bytes per 128x64 header block ++ * ++ * This layout is transferrable between Amlogic SoCs supporting this modifier. ++ */ ++#define AMLOGIC_FBC_LAYOUT_BASIC (1ULL) ++ ++/* ++ * Amlogic FBC Scatter Memory layout ++ * ++ * Indicates the header contains IOMMU references to the compressed ++ * frames content to optimize memory access and layout. ++ * ++ * In this mode, only the header memory address is needed, thus the ++ * content memory organization is tied to the current producer ++ * execution and cannot be saved/dumped neither transferrable between ++ * Amlogic SoCs supporting this modifier. ++ * ++ * Due to the nature of the layout, these buffers are not expected to ++ * be accessible by the user-space clients, but only accessible by the ++ * hardware producers and consumers. ++ * ++ * The user-space clients should expect a failure while trying to mmap ++ * the DMA-BUF handle returned by the producer. ++ */ ++#define AMLOGIC_FBC_LAYOUT_SCATTER (2ULL) ++ ++/* Amlogic FBC Layout Options Bit Mask */ ++ ++/* ++ * Amlogic FBC Memory Saving mode ++ * ++ * Indicates the storage is packed when pixel size is multiple of word ++ * boudaries, i.e. 8bit should be stored in this mode to save allocation ++ * memory. ++ * ++ * This mode reduces body layout to 3072 bytes per 64x32 superblock with ++ * the basic layout and 3200 bytes per 64x32 superblock combined with ++ * the scatter layout. ++ */ ++#define AMLOGIC_FBC_OPTION_MEM_SAVING (1ULL << 0) ++ + #if defined(__cplusplus) + } + #endif + +From bca1f53e15b80ac4fa24a073f96e8f99d994ca8a Mon Sep 17 00:00:00 2001 +From: Brian Starkey +Date: Fri, 26 Jun 2020 17:48:00 +0100 +Subject: [PATCH] drm: drm_fourcc: Add generic alias for 16_16_TILE modifier + +In cases such as DRM_FORMAT_MOD_SAMSUNG_16_16_TILE, the modifier +describes a generic pixel re-ordering which can be applicable to +multiple vendors. + +Define an alias: DRM_FORMAT_MOD_GENERIC_16_16_TILE, which can be +used to describe this layout in a vendor-neutral way, and add a +comment about the expected usage of such "generic" modifiers. + +Changes in v2: + - Move note about future cases to comment (Daniel) + +Signed-off-by: Brian Starkey +Reviewed-by: Daniel Vetter +Signed-off-by: Liviu Dudau +Link: https://patchwork.freedesktop.org/patch/msgid/20200626164800.11595-1-brian.starkey@arm.com +(cherry picked from commit 9ac2b63791ef63935c71e2a7f5444a1118c4d084) +--- + include/uapi/drm/drm_fourcc.h | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h +index cbf92fdf2712..4bee7de5f306 100644 +--- a/include/uapi/drm/drm_fourcc.h ++++ b/include/uapi/drm/drm_fourcc.h +@@ -346,8 +346,33 @@ extern "C" { + * When adding a new token please document the layout with a code comment, + * similar to the fourcc codes above. drm_fourcc.h is considered the + * authoritative source for all of these. ++ * ++ * Generic modifier names: ++ * ++ * DRM_FORMAT_MOD_GENERIC_* definitions are used to provide vendor-neutral names ++ * for layouts which are common across multiple vendors. To preserve ++ * compatibility, in cases where a vendor-specific definition already exists and ++ * a generic name for it is desired, the common name is a purely symbolic alias ++ * and must use the same numerical value as the original definition. ++ * ++ * Note that generic names should only be used for modifiers which describe ++ * generic layouts (such as pixel re-ordering), which may have ++ * independently-developed support across multiple vendors. ++ * ++ * In future cases where a generic layout is identified before merging with a ++ * vendor-specific modifier, a new 'GENERIC' vendor or modifier using vendor ++ * 'NONE' could be considered. This should only be for obvious, exceptional ++ * cases to avoid polluting the 'GENERIC' namespace with modifiers which only ++ * apply to a single vendor. ++ * ++ * Generic names should not be used for cases where multiple hardware vendors ++ * have implementations of the same standardised compression scheme (such as ++ * AFBC). In those cases, all implementations should use the same format ++ * modifier(s), reflecting the vendor of the standard. + */ + ++#define DRM_FORMAT_MOD_GENERIC_16_16_TILE DRM_FORMAT_MOD_SAMSUNG_16_16_TILE ++ + /* + * Invalid Modifier + * + +From 01f7cea4ef8c373df777713ceef5599a3efa88cb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= +Date: Wed, 27 May 2020 16:03:08 +0300 +Subject: [PATCH] drm/edid: Allow looking for ext blocks starting from a + specified index +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Apparently EDIDs with multiple DispID ext blocks is a thing, so prepare +for iterating through multiple ext blocks of the same type by +passing the starting ext block index to drm_find_edid_extension(). Well +also have drm_find_edid_extension() update the index to point to the +next ext block on success. Thus we should be able to call +drm_find_edid_extension() in loop. + +Signed-off-by: Ville Syrjälä +Link: https://patchwork.freedesktop.org/patch/msgid/20200527130310.27099-1-ville.syrjala@linux.intel.com +Reviewed-by: José Roberto de Souza +(cherry picked from commit 8873cfa384055d0348c03161420b1e9b6c1dc5d0) +--- + drivers/gpu/drm/drm_edid.c | 30 +++++++++++++++++++++--------- + 1 file changed, 21 insertions(+), 9 deletions(-) + +diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c +index ddb9a093ad0d..06cb75b9fc44 100644 +--- a/drivers/gpu/drm/drm_edid.c ++++ b/drivers/gpu/drm/drm_edid.c +@@ -3226,7 +3226,8 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid, + /* + * Search EDID for CEA extension block. + */ +-static u8 *drm_find_edid_extension(const struct edid *edid, int ext_id) ++static u8 *drm_find_edid_extension(const struct edid *edid, ++ int ext_id, int *ext_index) + { + u8 *edid_ext = NULL; + int i; +@@ -3236,23 +3237,26 @@ static u8 *drm_find_edid_extension(const struct edid *edid, int ext_id) + return NULL; + + /* Find CEA extension */ +- for (i = 0; i < edid->extensions; i++) { ++ for (i = *ext_index; i < edid->extensions; i++) { + edid_ext = (u8 *)edid + EDID_LENGTH * (i + 1); + if (edid_ext[0] == ext_id) + break; + } + +- if (i == edid->extensions) ++ if (i >= edid->extensions) + return NULL; + ++ *ext_index = i + 1; ++ + return edid_ext; + } + + + static u8 *drm_find_displayid_extension(const struct edid *edid, +- int *length, int *idx) ++ int *length, int *idx, ++ int *ext_index) + { +- u8 *displayid = drm_find_edid_extension(edid, DISPLAYID_EXT); ++ u8 *displayid = drm_find_edid_extension(edid, DISPLAYID_EXT, ext_index); + struct displayid_hdr *base; + int ret; + +@@ -3279,14 +3283,18 @@ static u8 *drm_find_cea_extension(const struct edid *edid) + struct displayid_block *block; + u8 *cea; + u8 *displayid; ++ int ext_index; + + /* Look for a top level CEA extension block */ +- cea = drm_find_edid_extension(edid, CEA_EXT); ++ ext_index = 0; ++ cea = drm_find_edid_extension(edid, CEA_EXT, &ext_index); + if (cea) + return cea; + + /* CEA blocks can also be found embedded in a DisplayID block */ +- displayid = drm_find_displayid_extension(edid, &length, &idx); ++ ext_index = 0; ++ displayid = drm_find_displayid_extension(edid, &length, &idx, ++ &ext_index); + if (!displayid) + return NULL; + +@@ -5236,8 +5244,10 @@ static int add_displayid_detailed_modes(struct drm_connector *connector, + int length, idx; + struct displayid_block *block; + int num_modes = 0; ++ int ext_index = 0; + +- displayid = drm_find_displayid_extension(edid, &length, &idx); ++ displayid = drm_find_displayid_extension(edid, &length, &idx, ++ &ext_index); + if (!displayid) + return 0; + +@@ -5911,11 +5921,13 @@ void drm_update_tile_info(struct drm_connector *connector, + const struct edid *edid) + { + const void *displayid = NULL; ++ int ext_index = 0; + int length, idx; + int ret; + + connector->has_tile = false; +- displayid = drm_find_displayid_extension(edid, &length, &idx); ++ displayid = drm_find_displayid_extension(edid, &length, &idx, ++ &ext_index); + if (!displayid) { + /* drop reference to any tile group we had */ + goto out_drop_ref; + +From 181edc12e551c8194591969ee528ed6041e4ada4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= +Date: Wed, 27 May 2020 16:03:09 +0300 +Subject: [PATCH] drm/edid: Iterate through all DispID ext blocks +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Apparently there are EDIDs in the wild with multiple DispID extension +blocks. Iterate through them all. + +In one particular case the tile information is specicied in the +second DispID ext block, and since the current parser only looks +at the first DispID ext block we don't notice that we're dealing +with a tiled display. + +While at it change a few functions to return void since we have +no use for the errno. + +References: https://gitlab.freedesktop.org/drm/intel/-/issues/27 +Signed-off-by: Ville Syrjälä +Link: https://patchwork.freedesktop.org/patch/msgid/20200527130310.27099-2-ville.syrjala@linux.intel.com +Reviewed-by: José Roberto de Souza +(cherry picked from commit 7f261afdcfae363192e3eef52dd34855cc149c15) +--- + drivers/gpu/drm/drm_edid.c | 84 +++++++++++++++++--------------------- + 1 file changed, 38 insertions(+), 46 deletions(-) + +diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c +index 06cb75b9fc44..fcd739af570f 100644 +--- a/drivers/gpu/drm/drm_edid.c ++++ b/drivers/gpu/drm/drm_edid.c +@@ -3286,6 +3286,7 @@ static u8 *drm_find_cea_extension(const struct edid *edid) + int ext_index; + + /* Look for a top level CEA extension block */ ++ /* FIXME: make callers iterate through multiple CEA ext blocks? */ + ext_index = 0; + cea = drm_find_edid_extension(edid, CEA_EXT, &ext_index); + if (cea) +@@ -3293,20 +3294,20 @@ static u8 *drm_find_cea_extension(const struct edid *edid) + + /* CEA blocks can also be found embedded in a DisplayID block */ + ext_index = 0; +- displayid = drm_find_displayid_extension(edid, &length, &idx, +- &ext_index); +- if (!displayid) +- return NULL; ++ for (;;) { ++ displayid = drm_find_displayid_extension(edid, &length, &idx, ++ &ext_index); ++ if (!displayid) ++ return NULL; + +- idx += sizeof(struct displayid_hdr); +- for_each_displayid_db(displayid, block, idx, length) { +- if (block->tag == DATA_BLOCK_CTA) { +- cea = (u8 *)block; +- break; ++ idx += sizeof(struct displayid_hdr); ++ for_each_displayid_db(displayid, block, idx, length) { ++ if (block->tag == DATA_BLOCK_CTA) ++ return (u8 *)block; + } + } + +- return cea; ++ return NULL; + } + + static __always_inline const struct drm_display_mode *cea_mode_for_vic(u8 vic) +@@ -5246,19 +5247,22 @@ static int add_displayid_detailed_modes(struct drm_connector *connector, + int num_modes = 0; + int ext_index = 0; + +- displayid = drm_find_displayid_extension(edid, &length, &idx, +- &ext_index); +- if (!displayid) +- return 0; +- +- idx += sizeof(struct displayid_hdr); +- for_each_displayid_db(displayid, block, idx, length) { +- switch (block->tag) { +- case DATA_BLOCK_TYPE_1_DETAILED_TIMING: +- num_modes += add_displayid_detailed_1_modes(connector, block); ++ for (;;) { ++ displayid = drm_find_displayid_extension(edid, &length, &idx, ++ &ext_index); ++ if (!displayid) + break; ++ ++ idx += sizeof(struct displayid_hdr); ++ for_each_displayid_db(displayid, block, idx, length) { ++ switch (block->tag) { ++ case DATA_BLOCK_TYPE_1_DETAILED_TIMING: ++ num_modes += add_displayid_detailed_1_modes(connector, block); ++ break; ++ } + } + } ++ + return num_modes; + } + +@@ -5838,8 +5842,8 @@ drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame, + } + EXPORT_SYMBOL(drm_hdmi_vendor_infoframe_from_display_mode); + +-static int drm_parse_tiled_block(struct drm_connector *connector, +- const struct displayid_block *block) ++static void drm_parse_tiled_block(struct drm_connector *connector, ++ const struct displayid_block *block) + { + const struct displayid_tiled_block *tile = (struct displayid_tiled_block *)block; + u16 w, h; +@@ -5877,7 +5881,7 @@ static int drm_parse_tiled_block(struct drm_connector *connector, + tg = drm_mode_create_tile_group(connector->dev, tile->topology_id); + } + if (!tg) +- return -ENOMEM; ++ return; + + if (connector->tile_group != tg) { + /* if we haven't got a pointer, +@@ -5889,14 +5893,12 @@ static int drm_parse_tiled_block(struct drm_connector *connector, + } else + /* if same tile group, then release the ref we just took. */ + drm_mode_put_tile_group(connector->dev, tg); +- return 0; + } + +-static int drm_displayid_parse_tiled(struct drm_connector *connector, +- const u8 *displayid, int length, int idx) ++static void drm_displayid_parse_tiled(struct drm_connector *connector, ++ const u8 *displayid, int length, int idx) + { + const struct displayid_block *block; +- int ret; + + idx += sizeof(struct displayid_hdr); + for_each_displayid_db(displayid, block, idx, length) { +@@ -5905,16 +5907,13 @@ static int drm_displayid_parse_tiled(struct drm_connector *connector, + + switch (block->tag) { + case DATA_BLOCK_TILED_DISPLAY: +- ret = drm_parse_tiled_block(connector, block); +- if (ret) +- return ret; ++ drm_parse_tiled_block(connector, block); + break; + default: + DRM_DEBUG_KMS("found DisplayID tag 0x%x, unhandled\n", block->tag); + break; + } + } +- return 0; + } + + void drm_update_tile_info(struct drm_connector *connector, +@@ -5923,26 +5922,19 @@ void drm_update_tile_info(struct drm_connector *connector, + const void *displayid = NULL; + int ext_index = 0; + int length, idx; +- int ret; + + connector->has_tile = false; +- displayid = drm_find_displayid_extension(edid, &length, &idx, +- &ext_index); +- if (!displayid) { +- /* drop reference to any tile group we had */ +- goto out_drop_ref; ++ for (;;) { ++ displayid = drm_find_displayid_extension(edid, &length, &idx, ++ &ext_index); ++ if (!displayid) ++ break; ++ ++ drm_displayid_parse_tiled(connector, displayid, length, idx); + } + +- ret = drm_displayid_parse_tiled(connector, displayid, length, idx); +- if (ret < 0) +- goto out_drop_ref; +- if (!connector->has_tile) +- goto out_drop_ref; +- return; +-out_drop_ref: +- if (connector->tile_group) { ++ if (!connector->has_tile && connector->tile_group) { + drm_mode_put_tile_group(connector->dev, connector->tile_group); + connector->tile_group = NULL; + } +- return; + } + +From c4a01f31ea528f8a1057b720eed47d502b19a3fb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= +Date: Wed, 27 May 2020 16:03:10 +0300 +Subject: [PATCH] drm/edid: Clean up some curly braces +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Drop some pointless curly braces, and add some across the +else when the if has them too. + +Signed-off-by: Ville Syrjälä +Link: https://patchwork.freedesktop.org/patch/msgid/20200527130310.27099-3-ville.syrjala@linux.intel.com +Reviewed-by: José Roberto de Souza +(cherry picked from commit 392f9fcb159bf95ec3c7de340a880f4778167275) +--- + drivers/gpu/drm/drm_edid.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c +index fcd739af570f..c28e7678014d 100644 +--- a/drivers/gpu/drm/drm_edid.c ++++ b/drivers/gpu/drm/drm_edid.c +@@ -5877,22 +5877,21 @@ static void drm_parse_tiled_block(struct drm_connector *connector, + DRM_DEBUG_KMS("vend %c%c%c\n", tile->topology_id[0], tile->topology_id[1], tile->topology_id[2]); + + tg = drm_mode_get_tile_group(connector->dev, tile->topology_id); +- if (!tg) { ++ if (!tg) + tg = drm_mode_create_tile_group(connector->dev, tile->topology_id); +- } + if (!tg) + return; + + if (connector->tile_group != tg) { + /* if we haven't got a pointer, + take the reference, drop ref to old tile group */ +- if (connector->tile_group) { ++ if (connector->tile_group) + drm_mode_put_tile_group(connector->dev, connector->tile_group); +- } + connector->tile_group = tg; +- } else ++ } else { + /* if same tile group, then release the ref we just took. */ + drm_mode_put_tile_group(connector->dev, tg); ++ } + } + + static void drm_displayid_parse_tiled(struct drm_connector *connector, + +From 7a5d301a5077083f45d826c49248882eacec778d Mon Sep 17 00:00:00 2001 +From: Liu Ying +Date: Thu, 9 Jul 2020 10:02:35 +0800 +Subject: [PATCH] drm/bridge: dw-hdmi: Don't cleanup i2c adapter and ddc ptr in + __dw_hdmi_probe() bailout path + +It's unnecessary to cleanup the i2c adapter and the ddc pointer in +the bailout path of __dw_hdmi_probe(), since the adapter is not +added and the ddc pointer is not set. + +Fixes: a23d6265f033 ("drm: bridge: dw-hdmi: Extract PHY interrupt setup to a function") +Cc: Andrzej Hajda +Cc: Neil Armstrong +Cc: Laurent Pinchart +Cc: Jonas Karlman +Cc: Jernej Skrabec +Cc: David Airlie +Cc: Daniel Vetter +Cc: Boris Brezillon +Cc: Jerome Brunet +Cc: Cheng-Yi Chiang +Cc: Dariusz Marcinkiewicz +Cc: Archit Taneja +Cc: Jose Abreu +Cc: dri-devel@lists.freedesktop.org +Cc: NXP Linux Team +Signed-off-by: Liu Ying +Reviewed-by: Laurent Pinchart +Signed-off-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/1594260156-8316-1-git-send-email-victor.liu@nxp.com +(cherry picked from commit 2ae53e79f2dec41949d7b089c0b6d7edce292d10) +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 5 ----- + 1 file changed, 5 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 6148a022569a..137b6ebfed19 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -3441,11 +3441,6 @@ __dw_hdmi_probe(struct platform_device *pdev, + return hdmi; + + err_iahb: +- if (hdmi->i2c) { +- i2c_del_adapter(&hdmi->i2c->adap); +- hdmi->ddc = NULL; +- } +- + clk_disable_unprepare(hdmi->iahb_clk); + if (hdmi->cec_clk) + clk_disable_unprepare(hdmi->cec_clk); + +From fe98962cfe32f385bed8c1fea444aeb887b472e6 Mon Sep 17 00:00:00 2001 +From: Liu Ying +Date: Thu, 9 Jul 2020 10:02:36 +0800 +Subject: [PATCH] drm/bridge: dw-hdmi: Always add the bridge in the global + bridge list + +It doesn't hurt to add the bridge in the global bridge list also for +platform specific dw-hdmi drivers which are based on the component +framework. This can be achieved by moving the drm_bridge_add() function +call from dw_hdmi_probe() to __dw_hdmi_probe(). A counterpart movement +for drm_bridge_remove() is also needed then. Moreover, since drm_bridge_add() +initializes &bridge->hpd_mutex, this may help those platform specific +dw-hdmi drivers(based on the component framework) avoid accessing the +uninitialized mutex in drm_bridge_hpd_notify() which is called in +dw_hdmi_irq(). Putting drm_bridge_add() in __dw_hdmi_probe() just before +it returns successfully should bring no logic change for platforms based +on the DRM bridge API, which is a good choice from safety point of view. +Also, __dw_hdmi_probe() is renamed to dw_hdmi_probe() since dw_hdmi_probe() +does nothing else but calling __dw_hdmi_probe(). Similar renaming applies +to the __dw_hdmi_remove()/dw_hdmi_remove() pair. + +Fixes: ec971aaa6775 ("drm: bridge: dw-hdmi: Make connector creation optional") +Cc: Andrzej Hajda +Cc: Neil Armstrong +Cc: Laurent Pinchart +Cc: Jonas Karlman +Cc: Jernej Skrabec +Cc: David Airlie +Cc: Daniel Vetter +Cc: Boris Brezillon +Cc: Jerome Brunet +Cc: Cheng-Yi Chiang +Cc: Dariusz Marcinkiewicz +Cc: Archit Taneja +Cc: Jose Abreu +Cc: Sam Ravnborg +Cc: dri-devel@lists.freedesktop.org +Cc: NXP Linux Team +Signed-off-by: Liu Ying +Signed-off-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/1594260156-8316-2-git-send-email-victor.liu@nxp.com +(cherry picked from commit 0bf4f5b5d3972df7014df302b95b58b8de1a1e94) +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 44 +++++++---------------- + 1 file changed, 13 insertions(+), 31 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 137b6ebfed19..748df1cacd2b 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -3179,9 +3179,11 @@ static void dw_hdmi_init_hw(struct dw_hdmi *hdmi) + hdmi->phy.ops->setup_hpd(hdmi, hdmi->phy.data); + } + +-static struct dw_hdmi * +-__dw_hdmi_probe(struct platform_device *pdev, +- const struct dw_hdmi_plat_data *plat_data) ++/* ----------------------------------------------------------------------------- ++ * Probe/remove API, used from platforms based on the DRM bridge API. ++ */ ++struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev, ++ const struct dw_hdmi_plat_data *plat_data) + { + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; +@@ -3438,6 +3440,8 @@ __dw_hdmi_probe(struct platform_device *pdev, + hdmi->cec = platform_device_register_full(&pdevinfo); + } + ++ drm_bridge_add(&hdmi->bridge); ++ + return hdmi; + + err_iahb: +@@ -3451,9 +3455,12 @@ __dw_hdmi_probe(struct platform_device *pdev, + + return ERR_PTR(ret); + } ++EXPORT_SYMBOL_GPL(dw_hdmi_probe); + +-static void __dw_hdmi_remove(struct dw_hdmi *hdmi) ++void dw_hdmi_remove(struct dw_hdmi *hdmi) + { ++ drm_bridge_remove(&hdmi->bridge); ++ + if (hdmi->audio && !IS_ERR(hdmi->audio)) + platform_device_unregister(hdmi->audio); + if (!IS_ERR(hdmi->cec)) +@@ -3472,31 +3479,6 @@ static void __dw_hdmi_remove(struct dw_hdmi *hdmi) + else + i2c_put_adapter(hdmi->ddc); + } +- +-/* ----------------------------------------------------------------------------- +- * Probe/remove API, used from platforms based on the DRM bridge API. +- */ +-struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev, +- const struct dw_hdmi_plat_data *plat_data) +-{ +- struct dw_hdmi *hdmi; +- +- hdmi = __dw_hdmi_probe(pdev, plat_data); +- if (IS_ERR(hdmi)) +- return hdmi; +- +- drm_bridge_add(&hdmi->bridge); +- +- return hdmi; +-} +-EXPORT_SYMBOL_GPL(dw_hdmi_probe); +- +-void dw_hdmi_remove(struct dw_hdmi *hdmi) +-{ +- drm_bridge_remove(&hdmi->bridge); +- +- __dw_hdmi_remove(hdmi); +-} + EXPORT_SYMBOL_GPL(dw_hdmi_remove); + + /* ----------------------------------------------------------------------------- +@@ -3509,7 +3491,7 @@ struct dw_hdmi *dw_hdmi_bind(struct platform_device *pdev, + struct dw_hdmi *hdmi; + int ret; + +- hdmi = __dw_hdmi_probe(pdev, plat_data); ++ hdmi = dw_hdmi_probe(pdev, plat_data); + if (IS_ERR(hdmi)) + return hdmi; + +@@ -3526,7 +3508,7 @@ EXPORT_SYMBOL_GPL(dw_hdmi_bind); + + void dw_hdmi_unbind(struct dw_hdmi *hdmi) + { +- __dw_hdmi_remove(hdmi); ++ dw_hdmi_remove(hdmi); + } + EXPORT_SYMBOL_GPL(dw_hdmi_unbind); + + +From d046fd09e47e5ea681fa9a0ba441eb493a8b5b14 Mon Sep 17 00:00:00 2001 +From: Andrey Lebedev +Date: Fri, 19 Jun 2020 10:58:59 +0300 +Subject: [PATCH] drm/lima: Expose job_hang_limit module parameter + +Some pp or gp jobs can be successfully repeated even after they time outs. +Introduce lima module parameter to specify number of times a job can hang +before being dropped. + +Signed-off-by: Andrey Lebedev +Signed-off-by: Qiang Yu +Link: https://patchwork.freedesktop.org/patch/msgid/20200619075900.3030696-1-andrey.lebedev@gmail.com +(cherry picked from commit de48984486d942d4f23e2b29374639f21042bdaa) +--- + drivers/gpu/drm/lima/lima_drv.c | 4 ++++ + drivers/gpu/drm/lima/lima_drv.h | 1 + + drivers/gpu/drm/lima/lima_sched.c | 5 +++-- + 3 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/lima/lima_drv.c b/drivers/gpu/drm/lima/lima_drv.c +index a831565af813..ab460121fd52 100644 +--- a/drivers/gpu/drm/lima/lima_drv.c ++++ b/drivers/gpu/drm/lima/lima_drv.c +@@ -19,6 +19,7 @@ + int lima_sched_timeout_ms; + uint lima_heap_init_nr_pages = 8; + uint lima_max_error_tasks; ++uint lima_job_hang_limit; + + MODULE_PARM_DESC(sched_timeout_ms, "task run timeout in ms"); + module_param_named(sched_timeout_ms, lima_sched_timeout_ms, int, 0444); +@@ -29,6 +30,9 @@ module_param_named(heap_init_nr_pages, lima_heap_init_nr_pages, uint, 0444); + MODULE_PARM_DESC(max_error_tasks, "max number of error tasks to save"); + module_param_named(max_error_tasks, lima_max_error_tasks, uint, 0644); + ++MODULE_PARM_DESC(job_hang_limit, "number of times to allow a job to hang before dropping it (default 0)"); ++module_param_named(job_hang_limit, lima_job_hang_limit, uint, 0444); ++ + static int lima_ioctl_get_param(struct drm_device *dev, void *data, struct drm_file *file) + { + struct drm_lima_get_param *args = data; +diff --git a/drivers/gpu/drm/lima/lima_drv.h b/drivers/gpu/drm/lima/lima_drv.h +index fdbd4077c768..c738d288547b 100644 +--- a/drivers/gpu/drm/lima/lima_drv.h ++++ b/drivers/gpu/drm/lima/lima_drv.h +@@ -11,6 +11,7 @@ + extern int lima_sched_timeout_ms; + extern uint lima_heap_init_nr_pages; + extern uint lima_max_error_tasks; ++extern uint lima_job_hang_limit; + + struct lima_vm; + struct lima_bo; +diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c +index e6cefda00279..1602985dfa04 100644 +--- a/drivers/gpu/drm/lima/lima_sched.c ++++ b/drivers/gpu/drm/lima/lima_sched.c +@@ -503,8 +503,9 @@ int lima_sched_pipe_init(struct lima_sched_pipe *pipe, const char *name) + + INIT_WORK(&pipe->recover_work, lima_sched_recover_work); + +- return drm_sched_init(&pipe->base, &lima_sched_ops, 1, 0, +- msecs_to_jiffies(timeout), name); ++ return drm_sched_init(&pipe->base, &lima_sched_ops, 1, ++ lima_job_hang_limit, msecs_to_jiffies(timeout), ++ name); + } + + void lima_sched_pipe_fini(struct lima_sched_pipe *pipe) diff --git a/patch/kernel/rk322x-current/01-linux-0022-drm-from-next.patch b/patch/kernel/rk322x-current/01-linux-0022-drm-from-next.patch new file mode 100644 index 000000000..4cf8cdbe7 --- /dev/null +++ b/patch/kernel/rk322x-current/01-linux-0022-drm-from-next.patch @@ -0,0 +1,1276 @@ +From 055013808487a12514bd6a10d5f1be4267d3cf4a Mon Sep 17 00:00:00 2001 +From: Neil Armstrong +Date: Thu, 23 Jul 2020 11:05:50 +0200 +Subject: [PATCH] drm/fourcc: fix Amlogic Video Framebuffer Compression macro + +Fix the Amlogic Video Framebuffer Compression modifier macro to +correctly add the layout options, a pair of parenthesis was missing. + +Fixes: d6528ec88309 ("drm/fourcc: Add modifier definitions for describing Amlogic Video Framebuffer Compression") +Signed-off-by: Neil Armstrong +Acked-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/20200723090551.27529-1-narmstrong@baylibre.com +(cherry picked from commit da3a9e9a6aa96ef589c153078f66e0646bf06b55) +--- + include/uapi/drm/drm_fourcc.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h +index 4bee7de5f306..82f327801267 100644 +--- a/include/uapi/drm/drm_fourcc.h ++++ b/include/uapi/drm/drm_fourcc.h +@@ -1004,7 +1004,7 @@ drm_fourcc_canonicalize_nvidia_format_mod(__u64 modifier) + #define DRM_FORMAT_MOD_AMLOGIC_FBC(__layout, __options) \ + fourcc_mod_code(AMLOGIC, \ + ((__layout) & __fourcc_mod_amlogic_layout_mask) | \ +- ((__options) & __fourcc_mod_amlogic_options_mask \ ++ (((__options) & __fourcc_mod_amlogic_options_mask) \ + << __fourcc_mod_amlogic_options_shift)) + + /* Amlogic FBC Layouts */ + +From 9df4c74d07ec7d3141b2a243b49de48f3e36932b Mon Sep 17 00:00:00 2001 +From: Tomeu Vizoso +Date: Thu, 11 Jun 2020 10:58:43 +0200 +Subject: [PATCH] drm/panfrost: Make sure GPU is powered on when reading + GPU_LATEST_FLUSH_ID + +Bifrost devices do support the flush reduction feature, so on first job +submit we were trying to read the register while still powered off. + +If the GPU is powered off, the feature doesn't bring any benefit, so +don't try to read. + +Tested-by: Heiko Stuebner +Reviewed-by: Steven Price +Signed-off-by: Tomeu Vizoso +Signed-off-by: Rob Herring +Link: https://patchwork.freedesktop.org/patch/msgid/20200611085900.49740-1-tomeu.vizoso@collabora.com +(cherry picked from commit 3a74265c54f883c847ed8554129baefb3e04f135) +--- + drivers/gpu/drm/panfrost/panfrost_gpu.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/panfrost/panfrost_gpu.c b/drivers/gpu/drm/panfrost/panfrost_gpu.c +index f2c1ddc41a9b..e0f190e43813 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_gpu.c ++++ b/drivers/gpu/drm/panfrost/panfrost_gpu.c +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + + #include "panfrost_device.h" + #include "panfrost_features.h" +@@ -368,7 +369,16 @@ void panfrost_gpu_fini(struct panfrost_device *pfdev) + + u32 panfrost_gpu_get_latest_flush_id(struct panfrost_device *pfdev) + { +- if (panfrost_has_hw_feature(pfdev, HW_FEATURE_FLUSH_REDUCTION)) +- return gpu_read(pfdev, GPU_LATEST_FLUSH_ID); ++ u32 flush_id; ++ ++ if (panfrost_has_hw_feature(pfdev, HW_FEATURE_FLUSH_REDUCTION)) { ++ /* Flush reduction only makes sense when the GPU is kept powered on between jobs */ ++ if (pm_runtime_get_if_in_use(pfdev->dev)) { ++ flush_id = gpu_read(pfdev, GPU_LATEST_FLUSH_ID); ++ pm_runtime_put(pfdev->dev); ++ return flush_id; ++ } ++ } ++ + return 0; + } + +From 956be03f3fc751937bbb07a4e4201a2a73aa87f1 Mon Sep 17 00:00:00 2001 +From: Tomeu Vizoso +Date: Thu, 11 Jun 2020 10:58:44 +0200 +Subject: [PATCH] drm/panfrost: Add compatible string for bifrost + +Mesa now supports some Bifrost devices, so enable it. + +Tested-by: Heiko Stuebner +Reviewed-by: Steven Price +Reviewed-by: Heiko Stuebner +Signed-off-by: Tomeu Vizoso +Signed-off-by: Rob Herring +Link: https://patchwork.freedesktop.org/patch/msgid/20200611085900.49740-2-tomeu.vizoso@collabora.com +(cherry picked from commit 72ef7fe96fd20d3d0e538e165b393819f99870ad) +--- + drivers/gpu/drm/panfrost/panfrost_drv.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c +index 882fecc33fdb..8ff8e140f91e 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_drv.c ++++ b/drivers/gpu/drm/panfrost/panfrost_drv.c +@@ -677,6 +677,7 @@ static const struct of_device_id dt_match[] = { + { .compatible = "arm,mali-t830", .data = &default_data, }, + { .compatible = "arm,mali-t860", .data = &default_data, }, + { .compatible = "arm,mali-t880", .data = &default_data, }, ++ { .compatible = "arm,mali-bifrost", .data = &default_data, }, + {} + }; + MODULE_DEVICE_TABLE(of, dt_match); + +From 1404f107a58a28fb71227550469c4785fa58081c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= +Date: Fri, 10 Jul 2020 11:53:56 +0200 +Subject: [PATCH] drm/panfrost: avoid static declaration +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This declaration can be avoided so change it. + +Reviewed-by: Steven Price +Reviewed-by: Alyssa Rosenzweig +Signed-off-by: Clément Péron +Signed-off-by: Rob Herring +Link: https://patchwork.freedesktop.org/patch/msgid/20200710095409.407087-2-peron.clem@gmail.com +(cherry picked from commit 862cc626210e34501b4d7a7795c41a67785987e5) +--- + drivers/gpu/drm/panfrost/panfrost_devfreq.c | 38 ++++++++++----------- + 1 file changed, 18 insertions(+), 20 deletions(-) + +diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.c b/drivers/gpu/drm/panfrost/panfrost_devfreq.c +index 413987038fbf..1b560b903ea6 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_devfreq.c ++++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.c +@@ -14,7 +14,24 @@ + #include "panfrost_gpu.h" + #include "panfrost_regs.h" + +-static void panfrost_devfreq_update_utilization(struct panfrost_device *pfdev); ++static void panfrost_devfreq_update_utilization(struct panfrost_device *pfdev) ++{ ++ ktime_t now; ++ ktime_t last; ++ ++ if (!pfdev->devfreq.devfreq) ++ return; ++ ++ now = ktime_get(); ++ last = pfdev->devfreq.time_last_update; ++ ++ if (atomic_read(&pfdev->devfreq.busy_count) > 0) ++ pfdev->devfreq.busy_time += ktime_sub(now, last); ++ else ++ pfdev->devfreq.idle_time += ktime_sub(now, last); ++ ++ pfdev->devfreq.time_last_update = now; ++} + + static int panfrost_devfreq_target(struct device *dev, unsigned long *freq, + u32 flags) +@@ -139,25 +156,6 @@ void panfrost_devfreq_suspend(struct panfrost_device *pfdev) + devfreq_suspend_device(pfdev->devfreq.devfreq); + } + +-static void panfrost_devfreq_update_utilization(struct panfrost_device *pfdev) +-{ +- ktime_t now; +- ktime_t last; +- +- if (!pfdev->devfreq.devfreq) +- return; +- +- now = ktime_get(); +- last = pfdev->devfreq.time_last_update; +- +- if (atomic_read(&pfdev->devfreq.busy_count) > 0) +- pfdev->devfreq.busy_time += ktime_sub(now, last); +- else +- pfdev->devfreq.idle_time += ktime_sub(now, last); +- +- pfdev->devfreq.time_last_update = now; +-} +- + void panfrost_devfreq_record_busy(struct panfrost_device *pfdev) + { + panfrost_devfreq_update_utilization(pfdev); + +From 42e45c3c4195d8e7ebe5bf970c7da55fc9c0d157 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= +Date: Fri, 10 Jul 2020 11:53:57 +0200 +Subject: [PATCH] drm/panfrost: clean headers in devfreq +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Don't include not required headers and sort them. + +Reviewed-by: Steven Price +Reviewed-by: Alyssa Rosenzweig +Signed-off-by: Clément Péron +Signed-off-by: Rob Herring +Link: https://patchwork.freedesktop.org/patch/msgid/20200710095409.407087-3-peron.clem@gmail.com +(cherry picked from commit 9713e942a539c55b5e0bc64ba83b736bda1087fe) +--- + drivers/gpu/drm/panfrost/panfrost_devfreq.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.c b/drivers/gpu/drm/panfrost/panfrost_devfreq.c +index 1b560b903ea6..df7b71da9a84 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_devfreq.c ++++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.c +@@ -1,18 +1,14 @@ + // SPDX-License-Identifier: GPL-2.0 + /* Copyright 2019 Collabora ltd. */ ++ ++#include + #include + #include + #include + #include +-#include +-#include + + #include "panfrost_device.h" + #include "panfrost_devfreq.h" +-#include "panfrost_features.h" +-#include "panfrost_issues.h" +-#include "panfrost_gpu.h" +-#include "panfrost_regs.h" + + static void panfrost_devfreq_update_utilization(struct panfrost_device *pfdev) + { + +From 99fda3d26b30e5f30d45fc6197da6335a2806e73 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= +Date: Fri, 10 Jul 2020 11:53:58 +0200 +Subject: [PATCH] drm/panfrost: don't use pfdevfreq.busy_count to know if hw is + idle +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This use devfreq variable that will be lock with spinlock in future +patches. We should either introduce a function to access this one +but as devfreq is optional let's just remove it. + +Reviewed-by: Steven Price +Reviewed-by: Alyssa Rosenzweig +Signed-off-by: Clément Péron +Signed-off-by: Rob Herring +Link: https://patchwork.freedesktop.org/patch/msgid/20200710095409.407087-4-peron.clem@gmail.com +(cherry picked from commit eb9dd67249b55fd1fa3d7359be387ea2079247a6) +--- + drivers/gpu/drm/panfrost/panfrost_job.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c b/drivers/gpu/drm/panfrost/panfrost_job.c +index c6242fe34840..aec05be1ba7a 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_job.c ++++ b/drivers/gpu/drm/panfrost/panfrost_job.c +@@ -581,10 +581,6 @@ int panfrost_job_is_idle(struct panfrost_device *pfdev) + struct panfrost_job_slot *js = pfdev->js; + int i; + +- /* Check whether the hardware is idle */ +- if (atomic_read(&pfdev->devfreq.busy_count)) +- return false; +- + for (i = 0; i < NUM_JOB_SLOTS; i++) { + /* If there are any jobs in the HW queue, we're not idle */ + if (atomic_read(&js->queue[i].sched.hw_rq_count)) + +From ca3fb7080e5fbaf5894bed7e119e8f4e49545449 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= +Date: Fri, 10 Jul 2020 11:53:59 +0200 +Subject: [PATCH] drm/panfrost: introduce panfrost_devfreq struct +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Introduce a proper panfrost_devfreq to deal with devfreq variables. + +Reviewed-by: Steven Price +Reviewed-by: Alyssa Rosenzweig +Signed-off-by: Clément Péron +Signed-off-by: Rob Herring +Link: https://patchwork.freedesktop.org/patch/msgid/20200710095409.407087-5-peron.clem@gmail.com +(cherry picked from commit 9bfacfc82f903b066b0b63460d5b7943705048a4) +--- + drivers/gpu/drm/panfrost/panfrost_devfreq.c | 76 ++++++++++++--------- + drivers/gpu/drm/panfrost/panfrost_devfreq.h | 20 +++++- + drivers/gpu/drm/panfrost/panfrost_device.h | 11 +-- + drivers/gpu/drm/panfrost/panfrost_job.c | 6 +- + 4 files changed, 66 insertions(+), 47 deletions(-) + +diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.c b/drivers/gpu/drm/panfrost/panfrost_devfreq.c +index df7b71da9a84..962550363391 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_devfreq.c ++++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.c +@@ -10,23 +10,23 @@ + #include "panfrost_device.h" + #include "panfrost_devfreq.h" + +-static void panfrost_devfreq_update_utilization(struct panfrost_device *pfdev) ++static void panfrost_devfreq_update_utilization(struct panfrost_devfreq *pfdevfreq) + { + ktime_t now; + ktime_t last; + +- if (!pfdev->devfreq.devfreq) ++ if (!pfdevfreq->devfreq) + return; + + now = ktime_get(); +- last = pfdev->devfreq.time_last_update; ++ last = pfdevfreq->time_last_update; + +- if (atomic_read(&pfdev->devfreq.busy_count) > 0) +- pfdev->devfreq.busy_time += ktime_sub(now, last); ++ if (atomic_read(&pfdevfreq->busy_count) > 0) ++ pfdevfreq->busy_time += ktime_sub(now, last); + else +- pfdev->devfreq.idle_time += ktime_sub(now, last); ++ pfdevfreq->idle_time += ktime_sub(now, last); + +- pfdev->devfreq.time_last_update = now; ++ pfdevfreq->time_last_update = now; + } + + static int panfrost_devfreq_target(struct device *dev, unsigned long *freq, +@@ -47,30 +47,31 @@ static int panfrost_devfreq_target(struct device *dev, unsigned long *freq, + return 0; + } + +-static void panfrost_devfreq_reset(struct panfrost_device *pfdev) ++static void panfrost_devfreq_reset(struct panfrost_devfreq *pfdevfreq) + { +- pfdev->devfreq.busy_time = 0; +- pfdev->devfreq.idle_time = 0; +- pfdev->devfreq.time_last_update = ktime_get(); ++ pfdevfreq->busy_time = 0; ++ pfdevfreq->idle_time = 0; ++ pfdevfreq->time_last_update = ktime_get(); + } + + static int panfrost_devfreq_get_dev_status(struct device *dev, + struct devfreq_dev_status *status) + { + struct panfrost_device *pfdev = dev_get_drvdata(dev); ++ struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq; + +- panfrost_devfreq_update_utilization(pfdev); ++ panfrost_devfreq_update_utilization(pfdevfreq); + + status->current_frequency = clk_get_rate(pfdev->clock); +- status->total_time = ktime_to_ns(ktime_add(pfdev->devfreq.busy_time, +- pfdev->devfreq.idle_time)); ++ status->total_time = ktime_to_ns(ktime_add(pfdevfreq->busy_time, ++ pfdevfreq->idle_time)); + +- status->busy_time = ktime_to_ns(pfdev->devfreq.busy_time); ++ status->busy_time = ktime_to_ns(pfdevfreq->busy_time); + +- panfrost_devfreq_reset(pfdev); ++ panfrost_devfreq_reset(pfdevfreq); + +- dev_dbg(pfdev->dev, "busy %lu total %lu %lu %% freq %lu MHz\n", status->busy_time, +- status->total_time, ++ dev_dbg(pfdev->dev, "busy %lu total %lu %lu %% freq %lu MHz\n", ++ status->busy_time, status->total_time, + status->busy_time / (status->total_time / 100), + status->current_frequency / 1000 / 1000); + +@@ -91,6 +92,7 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) + struct device *dev = &pfdev->pdev->dev; + struct devfreq *devfreq; + struct thermal_cooling_device *cooling; ++ struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq; + + ret = dev_pm_opp_of_add_table(dev); + if (ret == -ENODEV) /* Optional, continue without devfreq */ +@@ -98,7 +100,7 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) + else if (ret) + return ret; + +- panfrost_devfreq_reset(pfdev); ++ panfrost_devfreq_reset(pfdevfreq); + + cur_freq = clk_get_rate(pfdev->clock); + +@@ -116,53 +118,59 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) + dev_pm_opp_of_remove_table(dev); + return PTR_ERR(devfreq); + } +- pfdev->devfreq.devfreq = devfreq; ++ pfdevfreq->devfreq = devfreq; + + cooling = of_devfreq_cooling_register(dev->of_node, devfreq); + if (IS_ERR(cooling)) + DRM_DEV_INFO(dev, "Failed to register cooling device\n"); + else +- pfdev->devfreq.cooling = cooling; ++ pfdevfreq->cooling = cooling; + + return 0; + } + + void panfrost_devfreq_fini(struct panfrost_device *pfdev) + { +- if (pfdev->devfreq.cooling) +- devfreq_cooling_unregister(pfdev->devfreq.cooling); ++ struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq; ++ ++ if (pfdevfreq->cooling) ++ devfreq_cooling_unregister(pfdevfreq->cooling); + dev_pm_opp_of_remove_table(&pfdev->pdev->dev); + } + + void panfrost_devfreq_resume(struct panfrost_device *pfdev) + { +- if (!pfdev->devfreq.devfreq) ++ struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq; ++ ++ if (!pfdevfreq->devfreq) + return; + +- panfrost_devfreq_reset(pfdev); ++ panfrost_devfreq_reset(pfdevfreq); + +- devfreq_resume_device(pfdev->devfreq.devfreq); ++ devfreq_resume_device(pfdevfreq->devfreq); + } + + void panfrost_devfreq_suspend(struct panfrost_device *pfdev) + { +- if (!pfdev->devfreq.devfreq) ++ struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq; ++ ++ if (!pfdevfreq->devfreq) + return; + +- devfreq_suspend_device(pfdev->devfreq.devfreq); ++ devfreq_suspend_device(pfdevfreq->devfreq); + } + +-void panfrost_devfreq_record_busy(struct panfrost_device *pfdev) ++void panfrost_devfreq_record_busy(struct panfrost_devfreq *pfdevfreq) + { +- panfrost_devfreq_update_utilization(pfdev); +- atomic_inc(&pfdev->devfreq.busy_count); ++ panfrost_devfreq_update_utilization(pfdevfreq); ++ atomic_inc(&pfdevfreq->busy_count); + } + +-void panfrost_devfreq_record_idle(struct panfrost_device *pfdev) ++void panfrost_devfreq_record_idle(struct panfrost_devfreq *pfdevfreq) + { + int count; + +- panfrost_devfreq_update_utilization(pfdev); +- count = atomic_dec_if_positive(&pfdev->devfreq.busy_count); ++ panfrost_devfreq_update_utilization(pfdevfreq); ++ count = atomic_dec_if_positive(&pfdevfreq->busy_count); + WARN_ON(count < 0); + } +diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.h b/drivers/gpu/drm/panfrost/panfrost_devfreq.h +index 0611beffc8d0..0697f8d5aa34 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_devfreq.h ++++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.h +@@ -4,13 +4,29 @@ + #ifndef __PANFROST_DEVFREQ_H__ + #define __PANFROST_DEVFREQ_H__ + ++#include ++ ++struct devfreq; ++struct thermal_cooling_device; ++ ++struct panfrost_device; ++ ++struct panfrost_devfreq { ++ struct devfreq *devfreq; ++ struct thermal_cooling_device *cooling; ++ ktime_t busy_time; ++ ktime_t idle_time; ++ ktime_t time_last_update; ++ atomic_t busy_count; ++}; ++ + int panfrost_devfreq_init(struct panfrost_device *pfdev); + void panfrost_devfreq_fini(struct panfrost_device *pfdev); + + void panfrost_devfreq_resume(struct panfrost_device *pfdev); + void panfrost_devfreq_suspend(struct panfrost_device *pfdev); + +-void panfrost_devfreq_record_busy(struct panfrost_device *pfdev); +-void panfrost_devfreq_record_idle(struct panfrost_device *pfdev); ++void panfrost_devfreq_record_busy(struct panfrost_devfreq *devfreq); ++void panfrost_devfreq_record_idle(struct panfrost_devfreq *devfreq); + + #endif /* __PANFROST_DEVFREQ_H__ */ +diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h +index c30c719a8059..2efa59c9d1c5 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_device.h ++++ b/drivers/gpu/drm/panfrost/panfrost_device.h +@@ -13,6 +13,8 @@ + #include + #include + ++#include "panfrost_devfreq.h" ++ + struct panfrost_device; + struct panfrost_mmu; + struct panfrost_job_slot; +@@ -107,14 +109,7 @@ struct panfrost_device { + struct list_head shrinker_list; + struct shrinker shrinker; + +- struct { +- struct devfreq *devfreq; +- struct thermal_cooling_device *cooling; +- ktime_t busy_time; +- ktime_t idle_time; +- ktime_t time_last_update; +- atomic_t busy_count; +- } devfreq; ++ struct panfrost_devfreq pfdevfreq; + }; + + struct panfrost_mmu { +diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c b/drivers/gpu/drm/panfrost/panfrost_job.c +index aec05be1ba7a..2f297d962e64 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_job.c ++++ b/drivers/gpu/drm/panfrost/panfrost_job.c +@@ -145,7 +145,7 @@ static void panfrost_job_hw_submit(struct panfrost_job *job, int js) + u64 jc_head = job->jc; + int ret; + +- panfrost_devfreq_record_busy(pfdev); ++ panfrost_devfreq_record_busy(&pfdev->pfdevfreq); + + ret = pm_runtime_get_sync(pfdev->dev); + if (ret < 0) +@@ -410,7 +410,7 @@ static void panfrost_job_timedout(struct drm_sched_job *sched_job) + for (i = 0; i < NUM_JOB_SLOTS; i++) { + if (pfdev->jobs[i]) { + pm_runtime_put_noidle(pfdev->dev); +- panfrost_devfreq_record_idle(pfdev); ++ panfrost_devfreq_record_idle(&pfdev->pfdevfreq); + pfdev->jobs[i] = NULL; + } + } +@@ -478,7 +478,7 @@ static irqreturn_t panfrost_job_irq_handler(int irq, void *data) + pfdev->jobs[j] = NULL; + + panfrost_mmu_as_put(pfdev, &job->file_priv->mmu); +- panfrost_devfreq_record_idle(pfdev); ++ panfrost_devfreq_record_idle(&pfdev->pfdevfreq); + + dma_fence_signal_locked(job->done_fence); + pm_runtime_put_autosuspend(pfdev->dev); + +From 950ed8f4f8c6ab02e5f1c7b107e5af9a896c90dc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= +Date: Fri, 10 Jul 2020 11:54:00 +0200 +Subject: [PATCH] drm/panfrost: use spinlock instead of atomic +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Convert busy_count to a simple int protected by spinlock. + +Reviewed-by: Steven Price +Reviewed-by: Alyssa Rosenzweig +Signed-off-by: Clément Péron +Signed-off-by: Rob Herring +Link: https://patchwork.freedesktop.org/patch/msgid/20200710095409.407087-6-peron.clem@gmail.com +(cherry picked from commit ed85df3f60740bb4be23fbc2db283d59b361a834) +--- + drivers/gpu/drm/panfrost/panfrost_devfreq.c | 43 +++++++++++++++------ + drivers/gpu/drm/panfrost/panfrost_devfreq.h | 9 ++++- + 2 files changed, 40 insertions(+), 12 deletions(-) + +diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.c b/drivers/gpu/drm/panfrost/panfrost_devfreq.c +index 962550363391..78753cfb59fb 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_devfreq.c ++++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.c +@@ -12,16 +12,12 @@ + + static void panfrost_devfreq_update_utilization(struct panfrost_devfreq *pfdevfreq) + { +- ktime_t now; +- ktime_t last; +- +- if (!pfdevfreq->devfreq) +- return; ++ ktime_t now, last; + + now = ktime_get(); + last = pfdevfreq->time_last_update; + +- if (atomic_read(&pfdevfreq->busy_count) > 0) ++ if (pfdevfreq->busy_count > 0) + pfdevfreq->busy_time += ktime_sub(now, last); + else + pfdevfreq->idle_time += ktime_sub(now, last); +@@ -59,10 +55,14 @@ static int panfrost_devfreq_get_dev_status(struct device *dev, + { + struct panfrost_device *pfdev = dev_get_drvdata(dev); + struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq; ++ unsigned long irqflags; ++ ++ status->current_frequency = clk_get_rate(pfdev->clock); ++ ++ spin_lock_irqsave(&pfdevfreq->lock, irqflags); + + panfrost_devfreq_update_utilization(pfdevfreq); + +- status->current_frequency = clk_get_rate(pfdev->clock); + status->total_time = ktime_to_ns(ktime_add(pfdevfreq->busy_time, + pfdevfreq->idle_time)); + +@@ -70,6 +70,8 @@ static int panfrost_devfreq_get_dev_status(struct device *dev, + + panfrost_devfreq_reset(pfdevfreq); + ++ spin_unlock_irqrestore(&pfdevfreq->lock, irqflags); ++ + dev_dbg(pfdev->dev, "busy %lu total %lu %lu %% freq %lu MHz\n", + status->busy_time, status->total_time, + status->busy_time / (status->total_time / 100), +@@ -100,6 +102,8 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) + else if (ret) + return ret; + ++ spin_lock_init(&pfdevfreq->lock); ++ + panfrost_devfreq_reset(pfdevfreq); + + cur_freq = clk_get_rate(pfdev->clock); +@@ -162,15 +166,32 @@ void panfrost_devfreq_suspend(struct panfrost_device *pfdev) + + void panfrost_devfreq_record_busy(struct panfrost_devfreq *pfdevfreq) + { ++ unsigned long irqflags; ++ ++ if (!pfdevfreq->devfreq) ++ return; ++ ++ spin_lock_irqsave(&pfdevfreq->lock, irqflags); ++ + panfrost_devfreq_update_utilization(pfdevfreq); +- atomic_inc(&pfdevfreq->busy_count); ++ ++ pfdevfreq->busy_count++; ++ ++ spin_unlock_irqrestore(&pfdevfreq->lock, irqflags); + } + + void panfrost_devfreq_record_idle(struct panfrost_devfreq *pfdevfreq) + { +- int count; ++ unsigned long irqflags; ++ ++ if (!pfdevfreq->devfreq) ++ return; ++ ++ spin_lock_irqsave(&pfdevfreq->lock, irqflags); + + panfrost_devfreq_update_utilization(pfdevfreq); +- count = atomic_dec_if_positive(&pfdevfreq->busy_count); +- WARN_ON(count < 0); ++ ++ WARN_ON(--pfdevfreq->busy_count < 0); ++ ++ spin_unlock_irqrestore(&pfdevfreq->lock, irqflags); + } +diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.h b/drivers/gpu/drm/panfrost/panfrost_devfreq.h +index 0697f8d5aa34..3392df1020be 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_devfreq.h ++++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.h +@@ -4,6 +4,7 @@ + #ifndef __PANFROST_DEVFREQ_H__ + #define __PANFROST_DEVFREQ_H__ + ++#include + #include + + struct devfreq; +@@ -14,10 +15,16 @@ struct panfrost_device; + struct panfrost_devfreq { + struct devfreq *devfreq; + struct thermal_cooling_device *cooling; ++ + ktime_t busy_time; + ktime_t idle_time; + ktime_t time_last_update; +- atomic_t busy_count; ++ int busy_count; ++ /* ++ * Protect busy_time, idle_time, time_last_update and busy_count ++ * because these can be updated concurrently between multiple jobs. ++ */ ++ spinlock_t lock; + }; + + int panfrost_devfreq_init(struct panfrost_device *pfdev); + +From ac548872c7b7887d34b549efa3b8334b2cc862ed Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= +Date: Fri, 10 Jul 2020 11:54:01 +0200 +Subject: [PATCH] drm/panfrost: properly handle error in probe +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Introduce a boolean to know if opp table has been added. + +With this, we can call panfrost_devfreq_fini() in case of error +and release what has been initialised. + +Reviewed-by: Steven Price +Reviewed-by: Alyssa Rosenzweig +Signed-off-by: Clément Péron +Signed-off-by: Rob Herring +Link: https://patchwork.freedesktop.org/patch/msgid/20200710095409.407087-7-peron.clem@gmail.com +(cherry picked from commit 81f2fbe62cb54b6cf3d91078c4d49451ba7b9877) +--- + drivers/gpu/drm/panfrost/panfrost_devfreq.c | 25 ++++++++++++++++----- + drivers/gpu/drm/panfrost/panfrost_devfreq.h | 1 + + 2 files changed, 20 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.c b/drivers/gpu/drm/panfrost/panfrost_devfreq.c +index 78753cfb59fb..d9007f44b772 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_devfreq.c ++++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.c +@@ -101,6 +101,7 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) + return 0; + else if (ret) + return ret; ++ pfdevfreq->opp_of_table_added = true; + + spin_lock_init(&pfdevfreq->lock); + +@@ -109,8 +110,10 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) + cur_freq = clk_get_rate(pfdev->clock); + + opp = devfreq_recommended_opp(dev, &cur_freq, 0); +- if (IS_ERR(opp)) +- return PTR_ERR(opp); ++ if (IS_ERR(opp)) { ++ ret = PTR_ERR(opp); ++ goto err_fini; ++ } + + panfrost_devfreq_profile.initial_freq = cur_freq; + dev_pm_opp_put(opp); +@@ -119,8 +122,8 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) + DEVFREQ_GOV_SIMPLE_ONDEMAND, NULL); + if (IS_ERR(devfreq)) { + DRM_DEV_ERROR(dev, "Couldn't initialize GPU devfreq\n"); +- dev_pm_opp_of_remove_table(dev); +- return PTR_ERR(devfreq); ++ ret = PTR_ERR(devfreq); ++ goto err_fini; + } + pfdevfreq->devfreq = devfreq; + +@@ -131,15 +134,25 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) + pfdevfreq->cooling = cooling; + + return 0; ++ ++err_fini: ++ panfrost_devfreq_fini(pfdev); ++ return ret; + } + + void panfrost_devfreq_fini(struct panfrost_device *pfdev) + { + struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq; + +- if (pfdevfreq->cooling) ++ if (pfdevfreq->cooling) { + devfreq_cooling_unregister(pfdevfreq->cooling); +- dev_pm_opp_of_remove_table(&pfdev->pdev->dev); ++ pfdevfreq->cooling = NULL; ++ } ++ ++ if (pfdevfreq->opp_of_table_added) { ++ dev_pm_opp_of_remove_table(&pfdev->pdev->dev); ++ pfdevfreq->opp_of_table_added = false; ++ } + } + + void panfrost_devfreq_resume(struct panfrost_device *pfdev) +diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.h b/drivers/gpu/drm/panfrost/panfrost_devfreq.h +index 3392df1020be..210269944687 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_devfreq.h ++++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.h +@@ -15,6 +15,7 @@ struct panfrost_device; + struct panfrost_devfreq { + struct devfreq *devfreq; + struct thermal_cooling_device *cooling; ++ bool opp_of_table_added; + + ktime_t busy_time; + ktime_t idle_time; + +From 96a752deaead8b45cd188cde09cb873fd8dfd4b6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= +Date: Fri, 10 Jul 2020 11:54:02 +0200 +Subject: [PATCH] drm/panfrost: rename error labels in device_init +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Rename goto labels in device_init it will be easier to maintain. + +Reviewed-by: Alyssa Rosenzweig +Reviewed-by: Steven Price +Signed-off-by: Clément Péron +Signed-off-by: Rob Herring +Link: https://patchwork.freedesktop.org/patch/msgid/20200710095409.407087-8-peron.clem@gmail.com +(cherry picked from commit d3c335da0200be9287cdf5755d19f62ce1670a8d) +--- + drivers/gpu/drm/panfrost/panfrost_device.c | 30 +++++++++++----------- + 1 file changed, 15 insertions(+), 15 deletions(-) + +diff --git a/drivers/gpu/drm/panfrost/panfrost_device.c b/drivers/gpu/drm/panfrost/panfrost_device.c +index b172087eee6a..9f89984f652a 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_device.c ++++ b/drivers/gpu/drm/panfrost/panfrost_device.c +@@ -216,56 +216,56 @@ int panfrost_device_init(struct panfrost_device *pfdev) + + err = panfrost_regulator_init(pfdev); + if (err) +- goto err_out0; ++ goto out_clk; + + err = panfrost_reset_init(pfdev); + if (err) { + dev_err(pfdev->dev, "reset init failed %d\n", err); +- goto err_out1; ++ goto out_regulator; + } + + err = panfrost_pm_domain_init(pfdev); + if (err) +- goto err_out2; ++ goto out_reset; + + res = platform_get_resource(pfdev->pdev, IORESOURCE_MEM, 0); + pfdev->iomem = devm_ioremap_resource(pfdev->dev, res); + if (IS_ERR(pfdev->iomem)) { + dev_err(pfdev->dev, "failed to ioremap iomem\n"); + err = PTR_ERR(pfdev->iomem); +- goto err_out3; ++ goto out_pm_domain; + } + + err = panfrost_gpu_init(pfdev); + if (err) +- goto err_out3; ++ goto out_pm_domain; + + err = panfrost_mmu_init(pfdev); + if (err) +- goto err_out4; ++ goto out_gpu; + + err = panfrost_job_init(pfdev); + if (err) +- goto err_out5; ++ goto out_mmu; + + err = panfrost_perfcnt_init(pfdev); + if (err) +- goto err_out6; ++ goto out_job; + + return 0; +-err_out6: ++out_job: + panfrost_job_fini(pfdev); +-err_out5: ++out_mmu: + panfrost_mmu_fini(pfdev); +-err_out4: ++out_gpu: + panfrost_gpu_fini(pfdev); +-err_out3: ++out_pm_domain: + panfrost_pm_domain_fini(pfdev); +-err_out2: ++out_reset: + panfrost_reset_fini(pfdev); +-err_out1: ++out_regulator: + panfrost_regulator_fini(pfdev); +-err_out0: ++out_clk: + panfrost_clk_fini(pfdev); + return err; + } + +From 9c803e01258f241d49e1162ca6db5b29a98ba57d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= +Date: Fri, 10 Jul 2020 11:54:03 +0200 +Subject: [PATCH] drm/panfrost: move devfreq_init()/fini() in device +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Later we will introduce devfreq probing regulator if they +are present. As regulator should be probe only one time we +need to get this logic in the device_init(). + +panfrost_device is already taking care of devfreq_resume() +and devfreq_suspend(), so it's not totally illogic to move +the devfreq_init() and devfreq_fini() here. + +Reviewed-by: Alyssa Rosenzweig +Reviewed-by: Steven Price +Signed-off-by: Clément Péron +Signed-off-by: Rob Herring +Link: https://patchwork.freedesktop.org/patch/msgid/20200710095409.407087-9-peron.clem@gmail.com +(cherry picked from commit 25e247bbf85af3ad721dfeb2e2caf405f43b7e66) +--- + drivers/gpu/drm/panfrost/panfrost_device.c | 12 +++++++++++- + drivers/gpu/drm/panfrost/panfrost_drv.c | 15 ++------------- + 2 files changed, 13 insertions(+), 14 deletions(-) + +diff --git a/drivers/gpu/drm/panfrost/panfrost_device.c b/drivers/gpu/drm/panfrost/panfrost_device.c +index 9f89984f652a..36b5c8fea3eb 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_device.c ++++ b/drivers/gpu/drm/panfrost/panfrost_device.c +@@ -214,9 +214,16 @@ int panfrost_device_init(struct panfrost_device *pfdev) + return err; + } + ++ err = panfrost_devfreq_init(pfdev); ++ if (err) { ++ if (err != -EPROBE_DEFER) ++ dev_err(pfdev->dev, "devfreq init failed %d\n", err); ++ goto out_clk; ++ } ++ + err = panfrost_regulator_init(pfdev); + if (err) +- goto out_clk; ++ goto out_devfreq; + + err = panfrost_reset_init(pfdev); + if (err) { +@@ -265,6 +272,8 @@ int panfrost_device_init(struct panfrost_device *pfdev) + panfrost_reset_fini(pfdev); + out_regulator: + panfrost_regulator_fini(pfdev); ++out_devfreq: ++ panfrost_devfreq_fini(pfdev); + out_clk: + panfrost_clk_fini(pfdev); + return err; +@@ -278,6 +287,7 @@ void panfrost_device_fini(struct panfrost_device *pfdev) + panfrost_gpu_fini(pfdev); + panfrost_pm_domain_fini(pfdev); + panfrost_reset_fini(pfdev); ++ panfrost_devfreq_fini(pfdev); + panfrost_regulator_fini(pfdev); + panfrost_clk_fini(pfdev); + } +diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c +index 8ff8e140f91e..ed8bcdd6b211 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_drv.c ++++ b/drivers/gpu/drm/panfrost/panfrost_drv.c +@@ -14,7 +14,6 @@ + #include + + #include "panfrost_device.h" +-#include "panfrost_devfreq.h" + #include "panfrost_gem.h" + #include "panfrost_mmu.h" + #include "panfrost_job.h" +@@ -606,13 +605,6 @@ static int panfrost_probe(struct platform_device *pdev) + goto err_out0; + } + +- err = panfrost_devfreq_init(pfdev); +- if (err) { +- if (err != -EPROBE_DEFER) +- dev_err(&pdev->dev, "Fatal error during devfreq init\n"); +- goto err_out1; +- } +- + pm_runtime_set_active(pfdev->dev); + pm_runtime_mark_last_busy(pfdev->dev); + pm_runtime_enable(pfdev->dev); +@@ -625,16 +617,14 @@ static int panfrost_probe(struct platform_device *pdev) + */ + err = drm_dev_register(ddev, 0); + if (err < 0) +- goto err_out2; ++ goto err_out1; + + panfrost_gem_shrinker_init(ddev); + + return 0; + +-err_out2: +- pm_runtime_disable(pfdev->dev); +- panfrost_devfreq_fini(pfdev); + err_out1: ++ pm_runtime_disable(pfdev->dev); + panfrost_device_fini(pfdev); + err_out0: + drm_dev_put(ddev); +@@ -650,7 +640,6 @@ static int panfrost_remove(struct platform_device *pdev) + panfrost_gem_shrinker_cleanup(ddev); + + pm_runtime_get_sync(pfdev->dev); +- panfrost_devfreq_fini(pfdev); + panfrost_device_fini(pfdev); + pm_runtime_put_sync_suspend(pfdev->dev); + pm_runtime_disable(pfdev->dev); + +From d858649520907e147d85147efb8cfdb280ee5852 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= +Date: Fri, 10 Jul 2020 11:54:04 +0200 +Subject: [PATCH] drm/panfrost: dynamically alloc regulators +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We will later introduce regulators managed by OPP. + +Only alloc regulators when it's needed. This also help use +to release the regulators only when they are allocated. + +Reviewed-by: Steven Price +Reviewed-by: Alyssa Rosenzweig +Signed-off-by: Clément Péron +Signed-off-by: Rob Herring +Link: https://patchwork.freedesktop.org/patch/msgid/20200710095409.407087-10-peron.clem@gmail.com +(cherry picked from commit 512f21227fd3d2dbe7aad57a995b9732229c9b56) +--- + drivers/gpu/drm/panfrost/panfrost_device.c | 14 +++++++++----- + drivers/gpu/drm/panfrost/panfrost_device.h | 3 +-- + 2 files changed, 10 insertions(+), 7 deletions(-) + +diff --git a/drivers/gpu/drm/panfrost/panfrost_device.c b/drivers/gpu/drm/panfrost/panfrost_device.c +index 36b5c8fea3eb..f1474b961def 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_device.c ++++ b/drivers/gpu/drm/panfrost/panfrost_device.c +@@ -90,9 +90,11 @@ static int panfrost_regulator_init(struct panfrost_device *pfdev) + { + int ret, i; + +- if (WARN(pfdev->comp->num_supplies > ARRAY_SIZE(pfdev->regulators), +- "Too many supplies in compatible structure.\n")) +- return -EINVAL; ++ pfdev->regulators = devm_kcalloc(pfdev->dev, pfdev->comp->num_supplies, ++ sizeof(*pfdev->regulators), ++ GFP_KERNEL); ++ if (!pfdev->regulators) ++ return -ENOMEM; + + for (i = 0; i < pfdev->comp->num_supplies; i++) + pfdev->regulators[i].supply = pfdev->comp->supply_names[i]; +@@ -119,8 +121,10 @@ static int panfrost_regulator_init(struct panfrost_device *pfdev) + + static void panfrost_regulator_fini(struct panfrost_device *pfdev) + { +- regulator_bulk_disable(pfdev->comp->num_supplies, +- pfdev->regulators); ++ if (!pfdev->regulators) ++ return; ++ ++ regulator_bulk_disable(pfdev->comp->num_supplies, pfdev->regulators); + } + + static void panfrost_pm_domain_fini(struct panfrost_device *pfdev) +diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h +index 2efa59c9d1c5..953f7536a773 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_device.h ++++ b/drivers/gpu/drm/panfrost/panfrost_device.h +@@ -22,7 +22,6 @@ struct panfrost_job; + struct panfrost_perfcnt; + + #define NUM_JOB_SLOTS 3 +-#define MAX_REGULATORS 2 + #define MAX_PM_DOMAINS 3 + + struct panfrost_features { +@@ -81,7 +80,7 @@ struct panfrost_device { + void __iomem *iomem; + struct clk *clock; + struct clk *bus_clock; +- struct regulator_bulk_data regulators[MAX_REGULATORS]; ++ struct regulator_bulk_data *regulators; + struct reset_control *rstc; + /* pm_domains for devices with more than one. */ + struct device *pm_domain_devs[MAX_PM_DOMAINS]; + +From 1ee7aed7c3c6736b33828d488a6d29bd8f0e0e84 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= +Date: Fri, 10 Jul 2020 11:54:05 +0200 +Subject: [PATCH] drm/panfrost: add regulators to devfreq +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Some OPP tables specify voltage for each frequency. Devfreq can +handle these regulators but they should be get only 1 time to avoid +issue and know who is in charge. + +If OPP table is probe don't init regulator. + +Reviewed-by: Steven Price +Reviewed-by: Alyssa Rosenzweig +Signed-off-by: Clément Péron +Signed-off-by: Rob Herring +Link: https://patchwork.freedesktop.org/patch/msgid/20200710095409.407087-11-peron.clem@gmail.com +(cherry picked from commit fd587ff01d59554144e2fd20f4113638a45c7c4e) +--- + drivers/gpu/drm/panfrost/panfrost_devfreq.c | 29 ++++++++++++++++++--- + drivers/gpu/drm/panfrost/panfrost_devfreq.h | 2 ++ + drivers/gpu/drm/panfrost/panfrost_device.c | 9 ++++--- + 3 files changed, 33 insertions(+), 7 deletions(-) + +diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.c b/drivers/gpu/drm/panfrost/panfrost_devfreq.c +index d9007f44b772..8ab025d0035f 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_devfreq.c ++++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.c +@@ -93,14 +93,30 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) + unsigned long cur_freq; + struct device *dev = &pfdev->pdev->dev; + struct devfreq *devfreq; ++ struct opp_table *opp_table; + struct thermal_cooling_device *cooling; + struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq; + ++ opp_table = dev_pm_opp_set_regulators(dev, pfdev->comp->supply_names, ++ pfdev->comp->num_supplies); ++ if (IS_ERR(opp_table)) { ++ ret = PTR_ERR(opp_table); ++ /* Continue if the optional regulator is missing */ ++ if (ret != -ENODEV) { ++ DRM_DEV_ERROR(dev, "Couldn't set OPP regulators\n"); ++ goto err_fini; ++ } ++ } else { ++ pfdevfreq->regulators_opp_table = opp_table; ++ } ++ + ret = dev_pm_opp_of_add_table(dev); +- if (ret == -ENODEV) /* Optional, continue without devfreq */ +- return 0; +- else if (ret) +- return ret; ++ if (ret) { ++ /* Optional, continue without devfreq */ ++ if (ret == -ENODEV) ++ ret = 0; ++ goto err_fini; ++ } + pfdevfreq->opp_of_table_added = true; + + spin_lock_init(&pfdevfreq->lock); +@@ -153,6 +169,11 @@ void panfrost_devfreq_fini(struct panfrost_device *pfdev) + dev_pm_opp_of_remove_table(&pfdev->pdev->dev); + pfdevfreq->opp_of_table_added = false; + } ++ ++ if (pfdevfreq->regulators_opp_table) { ++ dev_pm_opp_put_regulators(pfdevfreq->regulators_opp_table); ++ pfdevfreq->regulators_opp_table = NULL; ++ } + } + + void panfrost_devfreq_resume(struct panfrost_device *pfdev) +diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.h b/drivers/gpu/drm/panfrost/panfrost_devfreq.h +index 210269944687..db6ea48e21f9 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_devfreq.h ++++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.h +@@ -8,12 +8,14 @@ + #include + + struct devfreq; ++struct opp_table; + struct thermal_cooling_device; + + struct panfrost_device; + + struct panfrost_devfreq { + struct devfreq *devfreq; ++ struct opp_table *regulators_opp_table; + struct thermal_cooling_device *cooling; + bool opp_of_table_added; + +diff --git a/drivers/gpu/drm/panfrost/panfrost_device.c b/drivers/gpu/drm/panfrost/panfrost_device.c +index f1474b961def..e6896733838a 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_device.c ++++ b/drivers/gpu/drm/panfrost/panfrost_device.c +@@ -225,9 +225,12 @@ int panfrost_device_init(struct panfrost_device *pfdev) + goto out_clk; + } + +- err = panfrost_regulator_init(pfdev); +- if (err) +- goto out_devfreq; ++ /* OPP will handle regulators */ ++ if (!pfdev->pfdevfreq.opp_of_table_added) { ++ err = panfrost_regulator_init(pfdev); ++ if (err) ++ goto out_devfreq; ++ } + + err = panfrost_reset_init(pfdev); + if (err) { + +From 94b3398f3b4d5e963f284bd39515bfdf84530c6c Mon Sep 17 00:00:00 2001 +From: Navid Emamdoost +Date: Sun, 14 Jun 2020 01:36:19 -0500 +Subject: [PATCH] drm/panfrost: perfcnt: fix ref count leak in + panfrost_perfcnt_enable_locked + +in panfrost_perfcnt_enable_locked, pm_runtime_get_sync is called which +increments the counter even in case of failure, leading to incorrect +ref count. In case of failure, decrement the ref count before returning. + +Acked-by: Alyssa Rosenzweig +Signed-off-by: Navid Emamdoost +Signed-off-by: Rob Herring +Link: https://patchwork.freedesktop.org/patch/msgid/20200614063619.44944-1-navid.emamdoost@gmail.com +(cherry picked from commit 9df0e0c1889677175037445d5ad1654d54176369) +--- + drivers/gpu/drm/panfrost/panfrost_perfcnt.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/panfrost/panfrost_perfcnt.c b/drivers/gpu/drm/panfrost/panfrost_perfcnt.c +index 6913578d5aa7..6169644d4469 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_perfcnt.c ++++ b/drivers/gpu/drm/panfrost/panfrost_perfcnt.c +@@ -83,11 +83,13 @@ static int panfrost_perfcnt_enable_locked(struct panfrost_device *pfdev, + + ret = pm_runtime_get_sync(pfdev->dev); + if (ret < 0) +- return ret; ++ goto err_put_pm; + + bo = drm_gem_shmem_create(pfdev->ddev, perfcnt->bosize); +- if (IS_ERR(bo)) +- return PTR_ERR(bo); ++ if (IS_ERR(bo)) { ++ ret = PTR_ERR(bo); ++ goto err_put_pm; ++ } + + /* Map the perfcnt buf in the address space attached to file_priv. */ + ret = panfrost_gem_open(&bo->base, file_priv); +@@ -168,6 +170,8 @@ static int panfrost_perfcnt_enable_locked(struct panfrost_device *pfdev, + panfrost_gem_close(&bo->base, file_priv); + err_put_bo: + drm_gem_object_put_unlocked(&bo->base); ++err_put_pm: ++ pm_runtime_put(pfdev->dev); + return ret; + } + diff --git a/patch/kernel/rk322x-current/01-linux-1000-clk-rockchip-rk3228-fixup.patch b/patch/kernel/rk322x-current/01-linux-1000-clk-rockchip-rk3228-fixup.patch deleted file mode 100644 index 21826f856..000000000 --- a/patch/kernel/rk322x-current/01-linux-1000-clk-rockchip-rk3228-fixup.patch +++ /dev/null @@ -1,98 +0,0 @@ -diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c -index 0127d702720c..6ef71ec239ae 100644 ---- a/drivers/clk/rockchip/clk-rk3228.c -+++ b/drivers/clk/rockchip/clk-rk3228.c -@@ -353,7 +353,7 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { - RK2928_CLKGATE_CON(10), 12, GFLAGS), - - COMPOSITE(SCLK_WIFI, "sclk_wifi", mux_pll_src_cpll_gpll_usb480m_p, 0, -- RK2928_CLKSEL_CON(23), 5, 2, MFLAGS, 0, 6, DFLAGS, -+ RK2928_CLKSEL_CON(23), 5, 2, MFLAGS, 0, 5, DFLAGS, - RK2928_CLKGATE_CON(2), 15, GFLAGS), - - COMPOSITE(SCLK_SDMMC, "sclk_sdmmc", mux_mmc_src_p, 0, --- -2.17.1 - - -From 3acbbe5eb438e8b1061a803881579030d3c2b424 Mon Sep 17 00:00:00 2001 -From: Chen Lei -Date: Tue, 25 Dec 2018 18:29:04 +0800 -Subject: [PATCH] clk: rockchip: rk322x: fix wrong mmc phase shift for rk3228 - -mmc sample shift should be 1 for rk3228, or it will fail -if we enable mmc tuning for rk3228. - -Change-Id: I301c2a7d33de8d519d7c288aef03a82531016373 -Signed-off-by: Chen Lei ---- - drivers/clk/rockchip/clk-rk3228.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c -index 6ef71ec239ae..27adfca1a095 100644 ---- a/drivers/clk/rockchip/clk-rk3228.c -+++ b/drivers/clk/rockchip/clk-rk3228.c -@@ -610,13 +610,13 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { - - /* PD_MMC */ - MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "sclk_sdmmc", RK3228_SDMMC_CON0, 1), -- MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK3228_SDMMC_CON1, 0), -+ MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK3228_SDMMC_CON1, 1), - - MMC(SCLK_SDIO_DRV, "sdio_drv", "sclk_sdio", RK3228_SDIO_CON0, 1), -- MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "sclk_sdio", RK3228_SDIO_CON1, 0), -+ MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "sclk_sdio", RK3228_SDIO_CON1, 1), - - MMC(SCLK_EMMC_DRV, "emmc_drv", "sclk_emmc", RK3228_EMMC_CON0, 1), -- MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RK3228_EMMC_CON1, 0), -+ MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RK3228_EMMC_CON1, 1), - }; - - static const char *const rk3228_critical_clocks[] __initconst = { --- -2.17.1 - - -From a692001c1249473bdfe975ef53d2bdb8a4df736d Mon Sep 17 00:00:00 2001 -From: Finley Xiao -Date: Mon, 5 Feb 2018 10:04:15 +0800 -Subject: [PATCH] clk: rockchip: rk3228: Fix armclk parent - -Change-Id: I09830d96b37cca600f1782b9013b25e043467f97 -Signed-off-by: Finley Xiao ---- - drivers/clk/rockchip/clk-rk3228.c | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c -index 58292f80ad66..fba513de94eb 100644 ---- a/drivers/clk/rockchip/clk-rk3228.c -+++ b/drivers/clk/rockchip/clk-rk3228.c -@@ -170,7 +170,7 @@ static struct rockchip_pll_clock rk3228_pll_clks[] __initdata = { - [cpll] = PLL(pll_rk3036, PLL_CPLL, "cpll", mux_pll_p, 0, RK2928_PLL_CON(6), - RK2928_MODE_CON, 8, 8, 0, NULL), - [gpll] = PLL(pll_rk3036, PLL_GPLL, "gpll", mux_pll_p, 0, RK2928_PLL_CON(9), -- RK2928_MODE_CON, 12, 9, ROCKCHIP_PLL_SYNC_RATE, rk3228_pll_rates), -+ RK2928_MODE_CON, 12, 9, 0, rk3228_pll_rates), - }; - - #define MFLAGS CLK_MUX_HIWORD_MASK --- -2.17.1 - - -From f57d5061e7357a8f7a181517530658a223ba415b Mon Sep 17 00:00:00 2001 -From: Finley Xiao -Date: Thu, 22 Jun 2017 19:53:46 +0800 -Subject: [PATCH] clk: rockchip: rk3228: fix gpu gate-register - -Fix a typo making the aclk_gpu and aclk_gpu_noc access a wrong register to -handle its gate. - -Change-Id: Ie0bac8014363af7c0409b8a56eacf2e858818843 -Signed-off-by: Finley Xiao ---- - drivers/clk/rockchip/clk-rk3228.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - diff --git a/patch/kernel/rk322x-current/01-linux-1000-export-mm_trace_rss_stat.patch b/patch/kernel/rk322x-current/01-linux-1000-export-mm_trace_rss_stat.patch new file mode 100644 index 000000000..03be01030 --- /dev/null +++ b/patch/kernel/rk322x-current/01-linux-1000-export-mm_trace_rss_stat.patch @@ -0,0 +1,12 @@ +diff --git a/mm/memory.c b/mm/memory.c +index 606da18..8429abc 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -158,6 +158,7 @@ + { + trace_rss_stat(mm, member, count); + } ++EXPORT_SYMBOL(mm_trace_rss_stat); + + #if defined(SPLIT_RSS_COUNTING) + diff --git a/patch/kernel/rk322x-current/01-linux-1001-clk-rockchip-rk3228-more-fixes.patch b/patch/kernel/rk322x-current/01-linux-1001-clk-rockchip-rk3228-more-fixes.patch deleted file mode 100644 index 024940cd3..000000000 --- a/patch/kernel/rk322x-current/01-linux-1001-clk-rockchip-rk3228-more-fixes.patch +++ /dev/null @@ -1,219 +0,0 @@ -diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c -index 448b202bf4f3..828d0003a18e 100644 ---- a/drivers/clk/rockchip/clk-rk3228.c -+++ b/drivers/clk/rockchip/clk-rk3228.c -@@ -510,12 +510,12 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { - - /* PD_VOP */ - GATE(ACLK_RGA, "aclk_rga", "aclk_rga_pre", 0, RK2928_CLKGATE_CON(13), 0, GFLAGS), -- GATE(0, "aclk_rga_noc", "aclk_rga_pre", 0, RK2928_CLKGATE_CON(13), 11, GFLAGS), -+ GATE(0, "aclk_rga_noc", "aclk_rga_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(13), 11, GFLAGS), - GATE(ACLK_IEP, "aclk_iep", "aclk_iep_pre", 0, RK2928_CLKGATE_CON(13), 2, GFLAGS), -- GATE(0, "aclk_iep_noc", "aclk_iep_pre", 0, RK2928_CLKGATE_CON(13), 9, GFLAGS), -+ GATE(0, "aclk_iep_noc", "aclk_iep_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(13), 9, GFLAGS), - - GATE(ACLK_VOP, "aclk_vop", "aclk_vop_pre", 0, RK2928_CLKGATE_CON(13), 5, GFLAGS), -- GATE(0, "aclk_vop_noc", "aclk_vop_pre", 0, RK2928_CLKGATE_CON(13), 12, GFLAGS), -+ GATE(0, "aclk_vop_noc", "aclk_vop_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(13), 12, GFLAGS), - - GATE(ACLK_HDCP, "aclk_hdcp", "aclk_hdcp_pre", 0, RK2928_CLKGATE_CON(14), 10, GFLAGS), - GATE(0, "aclk_hdcp_noc", "aclk_hdcp_pre", 0, RK2928_CLKGATE_CON(13), 10, GFLAGS), -@@ -523,13 +523,13 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { - GATE(HCLK_RGA, "hclk_rga", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 1, GFLAGS), - GATE(HCLK_IEP, "hclk_iep", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 3, GFLAGS), - GATE(HCLK_VOP, "hclk_vop", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 6, GFLAGS), -- GATE(0, "hclk_vio_ahb_arbi", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 7, GFLAGS), -- GATE(0, "hclk_vio_noc", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 8, GFLAGS), -- GATE(0, "hclk_vop_noc", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 13, GFLAGS), -- GATE(HCLK_VIO_H2P, "hclk_vio_h2p", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 7, GFLAGS), -+ GATE(0, "hclk_vio_ahb_arbi", "hclk_vio_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(13), 7, GFLAGS), -+ GATE(0, "hclk_vio_noc", "hclk_vio_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(13), 8, GFLAGS), -+ GATE(0, "hclk_vop_noc", "hclk_vio_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(13), 13, GFLAGS), -+ GATE(HCLK_VIO_H2P, "hclk_vio_h2p", "hclk_vio_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(14), 7, GFLAGS), - GATE(HCLK_HDCP_MMU, "hclk_hdcp_mmu", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 12, GFLAGS), - GATE(PCLK_HDMI_CTRL, "pclk_hdmi_ctrl", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 6, GFLAGS), -- GATE(PCLK_VIO_H2P, "pclk_vio_h2p", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 8, GFLAGS), -+ GATE(PCLK_VIO_H2P, "pclk_vio_h2p", "hclk_vio_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(14), 8, GFLAGS), - GATE(PCLK_HDCP, "pclk_hdcp", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 11, GFLAGS), - - /* PD_PERI */ -@@ -541,13 +541,13 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { - GATE(HCLK_EMMC, "hclk_emmc", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 2, GFLAGS), - GATE(HCLK_NANDC, "hclk_nandc", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 3, GFLAGS), - GATE(HCLK_HOST0, "hclk_host0", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 6, GFLAGS), -- GATE(0, "hclk_host0_arb", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 7, GFLAGS), -+ GATE(0, "hclk_host0_arb", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(11), 7, GFLAGS), - GATE(HCLK_HOST1, "hclk_host1", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 8, GFLAGS), -- GATE(0, "hclk_host1_arb", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 9, GFLAGS), -+ GATE(0, "hclk_host1_arb", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(11), 9, GFLAGS), - GATE(HCLK_HOST2, "hclk_host2", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 10, GFLAGS), - GATE(HCLK_OTG, "hclk_otg", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 12, GFLAGS), -- GATE(0, "hclk_otg_pmu", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 13, GFLAGS), -- GATE(0, "hclk_host2_arb", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 14, GFLAGS), -+ GATE(0, "hclk_otg_pmu", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(11), 13, GFLAGS), -+ GATE(0, "hclk_host2_arb", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(11), 14, GFLAGS), - GATE(0, "hclk_peri_noc", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(12), 1, GFLAGS), - - GATE(PCLK_GMAC, "pclk_gmac", "pclk_peri", 0, RK2928_CLKGATE_CON(11), 5, GFLAGS), -@@ -555,15 +555,15 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { - - /* PD_GPU */ - GATE(ACLK_GPU, "aclk_gpu", "aclk_gpu_pre", 0, RK2928_CLKGATE_CON(7), 14, GFLAGS), -- GATE(0, "aclk_gpu_noc", "aclk_gpu_pre", 0, RK2928_CLKGATE_CON(7), 15, GFLAGS), -+ GATE(0, "aclk_gpu_noc", "aclk_gpu_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(7), 15, GFLAGS), - - /* PD_BUS */ -- GATE(0, "sclk_initmem_mbist", "aclk_cpu", 0, RK2928_CLKGATE_CON(8), 1, GFLAGS), -- GATE(0, "aclk_initmem", "aclk_cpu", 0, RK2928_CLKGATE_CON(8), 0, GFLAGS), -+ GATE(0, "sclk_initmem_mbist", "aclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(8), 1, GFLAGS), -+ GATE(0, "aclk_initmem", "aclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(8), 0, GFLAGS), - GATE(ACLK_DMAC, "aclk_dmac_bus", "aclk_cpu", 0, RK2928_CLKGATE_CON(8), 2, GFLAGS), - GATE(0, "aclk_bus_noc", "aclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 1, GFLAGS), - -- GATE(0, "hclk_rom", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 3, GFLAGS), -+ GATE(0, "hclk_rom", "hclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(8), 3, GFLAGS), - GATE(HCLK_I2S0_8CH, "hclk_i2s0_8ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 7, GFLAGS), - GATE(HCLK_I2S1_8CH, "hclk_i2s1_8ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 8, GFLAGS), - GATE(HCLK_I2S2_2CH, "hclk_i2s2_2ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 9, GFLAGS), -@@ -572,9 +572,9 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { - GATE(HCLK_M_CRYPTO, "hclk_crypto_mst", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 11, GFLAGS), - GATE(HCLK_S_CRYPTO, "hclk_crypto_slv", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 12, GFLAGS), - -- GATE(0, "pclk_ddrupctl", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(8), 4, GFLAGS), -- GATE(0, "pclk_ddrmon", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(8), 6, GFLAGS), -- GATE(0, "pclk_msch_noc", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(10), 2, GFLAGS), -+ GATE(0, "pclk_ddrupctl", "pclk_ddr_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(8), 4, GFLAGS), -+ GATE(0, "pclk_ddrmon", "pclk_ddr_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(8), 6, GFLAGS), -+ GATE(0, "pclk_msch_noc", "pclk_ddr_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 2, GFLAGS), - - GATE(PCLK_EFUSE_1024, "pclk_efuse_1024", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 13, GFLAGS), - GATE(PCLK_EFUSE_256, "pclk_efuse_256", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 14, GFLAGS), -@@ -583,7 +583,7 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { - GATE(PCLK_I2C2, "pclk_i2c2", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 1, GFLAGS), - GATE(PCLK_I2C3, "pclk_i2c3", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 2, GFLAGS), - GATE(PCLK_TIMER, "pclk_timer0", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 4, GFLAGS), -- GATE(0, "pclk_stimer", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 5, GFLAGS), -+ GATE(0, "pclk_stimer", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 5, GFLAGS), - GATE(PCLK_SPI0, "pclk_spi0", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 6, GFLAGS), - GATE(PCLK_PWM, "pclk_rk_pwm", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 7, GFLAGS), - GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 8, GFLAGS), -@@ -597,22 +597,22 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { - GATE(PCLK_GRF, "pclk_grf", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 0, GFLAGS), - GATE(0, "pclk_cru", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 1, GFLAGS), - GATE(0, "pclk_sgrf", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 2, GFLAGS), -- GATE(0, "pclk_sim", "pclk_cpu", 0, RK2928_CLKGATE_CON(10), 3, GFLAGS), -+ GATE(0, "pclk_sim", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 3, GFLAGS), - -- GATE(0, "pclk_ddrphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 3, GFLAGS), -- GATE(0, "pclk_acodecphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 5, GFLAGS), -+ GATE(0, "pclk_ddrphy", "pclk_phy_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 3, GFLAGS), -+ GATE(PCLK_ACODECPHY, "pclk_acodecphy", "pclk_phy_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 5, GFLAGS), - GATE(PCLK_HDMI_PHY, "pclk_hdmiphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 7, GFLAGS), -- GATE(0, "pclk_vdacphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 8, GFLAGS), -- GATE(0, "pclk_phy_noc", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 9, GFLAGS), -+ GATE(0, "pclk_vdacphy", "pclk_phy_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 8, GFLAGS), -+ GATE(0, "pclk_phy_noc", "pclk_phy_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 9, GFLAGS), - - GATE(ACLK_VPU, "aclk_vpu", "aclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 0, GFLAGS), -- GATE(0, "aclk_vpu_noc", "aclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 4, GFLAGS), -+ GATE(0, "aclk_vpu_noc", "aclk_vpu_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(15), 4, GFLAGS), - GATE(ACLK_RKVDEC, "aclk_rkvdec", "aclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 2, GFLAGS), -- GATE(0, "aclk_rkvdec_noc", "aclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 6, GFLAGS), -+ GATE(0, "aclk_rkvdec_noc", "aclk_rkvdec_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(15), 6, GFLAGS), - GATE(HCLK_VPU, "hclk_vpu", "hclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 1, GFLAGS), -- GATE(0, "hclk_vpu_noc", "hclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 5, GFLAGS), -+ GATE(0, "hclk_vpu_noc", "hclk_vpu_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(15), 5, GFLAGS), - GATE(HCLK_RKVDEC, "hclk_rkvdec", "hclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 3, GFLAGS), -- GATE(0, "hclk_rkvdec_noc", "hclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 7, GFLAGS), -+ GATE(0, "hclk_rkvdec_noc", "hclk_rkvdec_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(15), 7, GFLAGS), - - /* PD_MMC */ - MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "sclk_sdmmc", RK3228_SDMMC_CON0, 1), -@@ -656,25 +656,34 @@ static const char *const rk3228_critical_clocks[] __initconst = { - "pclk_phy_noc", - "aclk_vpu_noc", - "aclk_rkvdec_noc", -+ "aclk_rkvdec", - "hclk_vpu_noc", - "hclk_rkvdec_noc", -+ "hclk_rkvdec", - }; - -+static void __iomem *rk3228_cru_base; -+ -+static void rk3228_clk_shutdown(void) -+{ -+ writel_relaxed(0x11010000, rk3228_cru_base + RK3228_MODE_CON); -+} -+ - static void __init rk3228_clk_init(struct device_node *np) - { - struct rockchip_clk_provider *ctx; -- void __iomem *reg_base; - -- reg_base = of_iomap(np, 0); -- if (!reg_base) { -+ rk3228_cru_base = of_iomap(np, 0); -+ -+ if (!rk3228_cru_base) { - pr_err("%s: could not map cru region\n", __func__); - return; - } - -- ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS); -+ ctx = rockchip_clk_init(np, rk3228_cru_base, CLK_NR_CLKS); - if (IS_ERR(ctx)) { - pr_err("%s: rockchip clk init failed\n", __func__); -- iounmap(reg_base); -+ iounmap(rk3228_cru_base); - return; - } - -@@ -691,10 +700,10 @@ static void __init rk3228_clk_init(struct device_node *np) - &rk3228_cpuclk_data, rk3228_cpuclk_rates, - ARRAY_SIZE(rk3228_cpuclk_rates)); - -- rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0), -+ rockchip_register_softrst(np, 9, rk3228_cru_base + RK2928_SOFTRST_CON(0), - ROCKCHIP_SOFTRST_HIWORD_MASK); - -- rockchip_register_restart_notifier(ctx, RK3228_GLB_SRST_FST, NULL); -+ rockchip_register_restart_notifier(ctx, RK3228_GLB_SRST_FST, rk3228_clk_shutdown); - - rockchip_clk_of_add_provider(np, ctx); - } -diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h -index 2271a84124b0..f2f80f224f30 100644 ---- a/drivers/clk/rockchip/clk.h -+++ b/drivers/clk/rockchip/clk.h -@@ -134,6 +134,7 @@ struct clk; - #define RK3308_EMMC_CON0 0x490 - #define RK3308_EMMC_CON1 0x494 - -+#define RK3228_MODE_CON 0x40 - #define RK3328_PLL_CON(x) RK2928_PLL_CON(x) - #define RK3328_CLKSEL_CON(x) ((x) * 0x4 + 0x100) - #define RK3328_CLKGATE_CON(x) ((x) * 0x4 + 0x200) -diff --git a/include/dt-bindings/clock/rk3228-cru.h b/include/dt-bindings/clock/rk3228-cru.h -index de550ea56eeb..16e1feae5ce4 100644 ---- a/include/dt-bindings/clock/rk3228-cru.h -+++ b/include/dt-bindings/clock/rk3228-cru.h -@@ -65,6 +65,7 @@ - #define SCLK_OTGPHY0 142 - #define SCLK_OTGPHY1 143 - #define SCLK_HDMI_PHY 144 -+#define SCLK_DDRC 145 - - /* dclk gates */ - #define DCLK_VOP 190 -@@ -115,6 +116,7 @@ - #define PCLK_HDMI_CTRL 364 - #define PCLK_HDMI_PHY 365 - #define PCLK_GMAC 367 -+#define PCLK_ACODECPHY 368 - - /* hclk gates */ - #define HCLK_I2S0_8CH 442 --- -2.17.1 - diff --git a/patch/kernel/rk322x-current/01-linux-1002-arm-dts-rk322x-dts.patch b/patch/kernel/rk322x-current/01-linux-1002-arm-dts-rk322x-dts.patch deleted file mode 100644 index 45cb9be72..000000000 --- a/patch/kernel/rk322x-current/01-linux-1002-arm-dts-rk322x-dts.patch +++ /dev/null @@ -1,1586 +0,0 @@ -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index e8dd99201..02d9d3ae7 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -952,6 +952,12 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \ - rk3188-px3-evb.dtb \ - rk3188-radxarock.dtb \ - rk3228-evb.dtb \ -+ rk3228a-box.dtb \ -+ rk3228a-box-h96mini.dtb \ -+ rk3228a-box-nand.dtb \ -+ rk3229-box.dtb \ -+ rk3229-box-a95xr1.dtb \ -+ rk3229-box-nand.dtb \ - rk3229-evb.dtb \ - rk3229-xms6.dtb \ - rk3288-evb-act8846.dtb \ -diff --git a/arch/arm/boot/dts/rk3228a-box-h96mini.dts b/arch/arm/boot/dts/rk3228a-box-h96mini.dts -new file mode 100644 -index 000000000..c624500d1 ---- /dev/null -+++ b/arch/arm/boot/dts/rk3228a-box-h96mini.dts -@@ -0,0 +1,106 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+ -+/dts-v1/; -+#include -+#include -+#include "rk3228a-box.dtsi" -+ -+/ { -+ compatible = "eledvb,h96mini", "rockchip,rk3228a-box", "rockchip,rk3229"; -+ model = "Rockchip RK3228A Box H96 mini"; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ led_green { -+ gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>; -+ default-state = "on"; -+ }; -+ -+ led_red { -+ gpios = <&gpio0 RK_PB0 GPIO_ACTIVE_HIGH>; -+ default-state = "off"; -+ }; -+ }; -+ -+}; -+ -+&emmc { -+ mmc-hs200-1_8v; -+ status = "okay"; -+}; -+ -+&gmac { -+ tx_delay = <0x26>; -+ rx_delay = <0x11>; -+}; -+ -+&ir_receiver { -+ status = "okay"; -+}; -+ -+&pinctrl { -+ wifi { -+ wifi_host_wake_l: wifi-host-wake-l { -+ rockchip,pins = <0 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+ -+ bt { -+ bt_host_wake_l: bt-host-wake-l { -+ rockchip,pins = <3 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ -+ bt_reg_on_h: bt-reg-on-h { -+ rockchip,pins = <2 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ -+ bt_wake_l: bt-wake-l { -+ rockchip,pins = <3 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+}; -+ -+&power_key { -+ status = "okay"; -+}; -+ -+&sdio { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ brcmf: wifi@1 { -+ compatible = "brcm,bcm4329-fmac"; -+ reg = <1>; -+ interrupt-parent = <&gpio0>; -+ interrupts = ; -+ interrupt-names = "host-wake"; -+ brcm,drive-strength = <5>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&wifi_host_wake_l>; -+ }; -+}; -+ -+&sdmmc { -+ disable-wp; -+ status = "okay"; -+}; -+ -+&uart1 { -+ status = "okay"; -+ -+ bluetooth { -+ compatible = "brcm,bcm4330-bt"; -+ host-wakeup-gpios = <&gpio3 RK_PD2 GPIO_ACTIVE_HIGH>; -+ device-wakeup-gpios = <&gpio3 RK_PD3 GPIO_ACTIVE_HIGH>; -+ shutdown-gpios = <&gpio2 RK_PD5 GPIO_ACTIVE_HIGH>; -+ max-speed = <4000000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&bt_reg_on_h &bt_host_wake_l &bt_wake_l>; -+ }; -+}; -+ -+&usb_otg { -+ dr_mode = "host"; -+}; -diff --git a/arch/arm/boot/dts/rk3228a-box-nand.dts b/arch/arm/boot/dts/rk3228a-box-nand.dts -new file mode 100644 -index 000000000..f3e5ab894 ---- /dev/null -+++ b/arch/arm/boot/dts/rk3228a-box-nand.dts -@@ -0,0 +1,57 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+ -+/dts-v1/; -+#include "rk3228a-box.dtsi" -+ -+/ { -+ model = "Rockchip RK3228A Box"; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ led_blue { -+ gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>; -+ default-state = "on"; -+ }; -+ -+ led_red { -+ gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_HIGH>; -+ default-state = "off"; -+ }; -+ }; -+ -+}; -+ -+&ir_receiver { -+ status = "okay"; -+}; -+ -+&nfc { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ nand@0 { -+ reg = <0>; -+ nand-ecc-mode = "hw"; -+ nand-ecc-strength = <60>; -+ nand-ecc-step-size = <1024>; -+ nand-bus-width = <8>; -+ }; -+}; -+ -+&sdio { -+ status = "okay"; -+}; -+ -+&sdmmc { -+ status = "okay"; -+}; -+ -+&uart1 { -+ status = "okay"; -+}; -+ -+&usb_otg { -+ dr_mode = "host"; -+}; -diff --git a/arch/arm/boot/dts/rk3228a-box.dts b/arch/arm/boot/dts/rk3228a-box.dts -new file mode 100644 -index 000000000..e68ef44b9 ---- /dev/null -+++ b/arch/arm/boot/dts/rk3228a-box.dts -@@ -0,0 +1,47 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+ -+/dts-v1/; -+#include "rk3228a-box.dtsi" -+ -+/ { -+ model = "Rockchip RK3228A Box"; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ led_blue { -+ gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>; -+ default-state = "on"; -+ }; -+ -+ led_red { -+ gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_HIGH>; -+ default-state = "off"; -+ }; -+ }; -+ -+}; -+ -+&emmc { -+ status = "okay"; -+}; -+ -+&ir_receiver { -+ status = "okay"; -+}; -+ -+&sdio { -+ status = "okay"; -+}; -+ -+&sdmmc { -+ status = "okay"; -+}; -+ -+&uart1 { -+ status = "okay"; -+}; -+ -+&usb_otg { -+ dr_mode = "host"; -+}; -diff --git a/arch/arm/boot/dts/rk3228a-box.dtsi b/arch/arm/boot/dts/rk3228a-box.dtsi -new file mode 100644 -index 000000000..dbd5c5dc4 ---- /dev/null -+++ b/arch/arm/boot/dts/rk3228a-box.dtsi -@@ -0,0 +1,12 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+ -+/dts-v1/; -+ -+#include "rk322x-box.dtsi" -+ -+/ { -+ -+ model = "Rockchip RK3228A Box"; -+ compatible = "rockchip,rk3228a-box", "rockchip,rk3229"; -+ -+}; -diff --git a/arch/arm/boot/dts/rk3229-box-a95xr1.dts b/arch/arm/boot/dts/rk3229-box-a95xr1.dts -new file mode 100644 -index 000000000..b3695fb0b ---- /dev/null -+++ b/arch/arm/boot/dts/rk3229-box-a95xr1.dts -@@ -0,0 +1,57 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+ -+/dts-v1/; -+#include -+#include -+#include "rk3229-box.dtsi" -+ -+/ { -+ model = "Rockchip RK3229 Box A95X-R1"; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ led_blue { -+ gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>; -+ default-state = "on"; -+ }; -+ -+ led_red { -+ gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_HIGH>; -+ default-state = "off"; -+ linux,default-trigger = "rc-feedback"; -+ }; -+ }; -+ -+}; -+ -+&emmc { -+ mmc-hs200-1_8v; -+ status = "okay"; -+}; -+ -+&gmac { -+ tx_delay = <0x26>; -+ rx_delay = <0x11>; -+}; -+ -+&ir_receiver { -+ status = "okay"; -+}; -+ -+&power_key { -+ status = "okay"; -+}; -+ -+&sdio { -+ status = "okay"; -+}; -+ -+&sdmmc { -+ disable-wp; -+ status = "okay"; -+}; -+ -+&usb_otg { -+ dr_mode = "host"; -+}; -diff --git a/arch/arm/boot/dts/rk3229-box-nand.dts b/arch/arm/boot/dts/rk3229-box-nand.dts -new file mode 100644 -index 000000000..5eca0f335 ---- /dev/null -+++ b/arch/arm/boot/dts/rk3229-box-nand.dts -@@ -0,0 +1,60 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+ -+/dts-v1/; -+#include "rk3229-box.dtsi" -+ -+/ { -+ model = "Rockchip RK3229 Box"; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ led_green { -+ gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>; -+ default-state = "on"; -+ }; -+ -+ led_red { -+ gpios = <&gpio0 RK_PB0 GPIO_ACTIVE_HIGH>; -+ default-state = "off"; -+ }; -+ }; -+}; -+ -+&ir_receiver { -+ status = "okay"; -+}; -+ -+&nfc { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ nand@0 { -+ reg = <0>; -+ nand-ecc-mode = "hw"; -+ nand-ecc-strength = <60>; -+ nand-ecc-step-size = <1024>; -+ nand-bus-width = <8>; -+ }; -+}; -+ -+&power_key { -+ status = "okay"; -+}; -+ -+&sdio { -+ status = "okay"; -+}; -+ -+&sdmmc { -+ status = "okay"; -+}; -+ -+&uart1 { -+ status = "okay"; -+}; -+ -+&usb_otg { -+ dr_mode = "host"; -+}; -diff --git a/arch/arm/boot/dts/rk3229-box.dts b/arch/arm/boot/dts/rk3229-box.dts -new file mode 100644 -index 000000000..b63e61cda ---- /dev/null -+++ b/arch/arm/boot/dts/rk3229-box.dts -@@ -0,0 +1,50 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+ -+/dts-v1/; -+#include "rk3229-box.dtsi" -+ -+/ { -+ model = "Rockchip RK3229 Box"; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ led_green { -+ gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>; -+ default-state = "on"; -+ }; -+ -+ led_red { -+ gpios = <&gpio0 RK_PB0 GPIO_ACTIVE_HIGH>; -+ default-state = "off"; -+ }; -+ }; -+}; -+ -+&emmc { -+ status = "okay"; -+}; -+ -+&ir_receiver { -+ status = "okay"; -+}; -+ -+&power_key { -+ status = "okay"; -+}; -+ -+&sdio { -+ status = "okay"; -+}; -+ -+&sdmmc { -+ status = "okay"; -+}; -+ -+&uart1 { -+ status = "okay"; -+}; -+ -+&usb_otg { -+ dr_mode = "host"; -+}; -diff --git a/arch/arm/boot/dts/rk3229-box.dtsi b/arch/arm/boot/dts/rk3229-box.dtsi -new file mode 100644 -index 000000000..79e2524e0 ---- /dev/null -+++ b/arch/arm/boot/dts/rk3229-box.dtsi -@@ -0,0 +1,21 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+ -+/dts-v1/; -+ -+#include "rk322x-box.dtsi" -+#include "rk3229-cpu-opp.dtsi" -+ -+/ { -+ -+ model = "Rockchip RK3229 Box"; -+ compatible = "rockchip,rk3229-box", "rockchip,rk3229"; -+ -+}; -+ -+&cpu0_opp_table { -+ -+ opp-1464000000 { -+ status = "disabled"; -+ }; -+ -+}; -diff --git a/arch/arm/boot/dts/rk3229-cpu-opp.dtsi b/arch/arm/boot/dts/rk3229-cpu-opp.dtsi -new file mode 100644 -index 000000000..c1c7613ba ---- /dev/null -+++ b/arch/arm/boot/dts/rk3229-cpu-opp.dtsi -@@ -0,0 +1,50 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd -+ */ -+ -+/ { -+ compatible = "rockchip,rk3229"; -+ -+ /delete-node/ opp-table0; -+ -+ cpu0_opp_table: opp_table0 { -+ compatible = "operating-points-v2"; -+ opp-shared; -+ -+ opp-408000000 { -+ opp-hz = /bits/ 64 <408000000>; -+ opp-microvolt = <950000 950000 1400000>; -+ clock-latency-ns = <40000>; -+ opp-suspend; -+ }; -+ opp-600000000 { -+ opp-hz = /bits/ 64 <600000000>; -+ opp-microvolt = <975000 975000 1400000>; -+ }; -+ opp-816000000 { -+ opp-hz = /bits/ 64 <816000000>; -+ opp-microvolt = <1000000 1000000 1400000>; -+ }; -+ opp-1008000000 { -+ opp-hz = /bits/ 64 <1008000000>; -+ opp-microvolt = <1175000 1175000 1400000>; -+ }; -+ opp-1200000000 { -+ opp-hz = /bits/ 64 <1200000000>; -+ opp-microvolt = <1275000 1275000 1400000>; -+ }; -+ opp-1296000000 { -+ opp-hz = /bits/ 64 <1296000000>; -+ opp-microvolt = <1325000 1325000 1400000>; -+ }; -+ opp-1392000000 { -+ opp-hz = /bits/ 64 <1392000000>; -+ opp-microvolt = <1350000 1350000 1400000>; -+ }; -+ opp-1464000000 { -+ opp-hz = /bits/ 64 <1464000000>; -+ opp-microvolt = <1400000 1400000 1400000>; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/rk322x-box.dtsi b/arch/arm/boot/dts/rk322x-box.dtsi -new file mode 100644 -index 000000000..44fb2f4ea ---- /dev/null -+++ b/arch/arm/boot/dts/rk322x-box.dtsi -@@ -0,0 +1,250 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+ -+/dts-v1/; -+ -+#include -+#include -+#include -+#include -+#include "rk322x-dcdc.dtsi" -+ -+/ { -+ model = "Rockchip RK322x Box"; -+ compatible = "rockchip,rk3229"; -+ -+ chosen { -+ bootargs = "earlyprintk=uart8250,mmio32,0x11030000"; -+ }; -+ -+ gpio_keys { -+ compatible = "gpio-keys"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ autorepeat; -+ -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pwr_key>; -+ -+ power_key: power-key { -+ label = "GPIO Key Power"; -+ gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_LOW>; -+ linux,code = ; -+ debounce-interval = <100>; -+ wakeup-source; -+ status = "disabled"; -+ }; -+ }; -+ -+ ir_receiver: ir-receiver { -+ compatible = "gpio-ir-receiver"; -+ gpios = <&gpio1 RK_PB3 GPIO_ACTIVE_LOW>; -+ pinctrl-0 = <&ir_int>; -+ pinctrl-names = "default"; -+ status = "disabled"; -+ }; -+ -+ memory@60000000 { -+ device_type = "memory"; -+ reg = <0x60000000 0x40000000>; -+ }; -+ -+ reserved-memory { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ -+ trust_reserved: trust@68400000 { -+ reg = <0x68400000 0xe00000>; -+ no-map; -+ }; -+ }; -+ -+ sdio_pwrseq: sdio-pwrseq { -+ compatible = "mmc-pwrseq-simple"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&wifi_enable_h>; -+ reset-gpios = <&gpio2 RK_PD2 GPIO_ACTIVE_LOW>; -+ }; -+ -+ timer { -+ arm,cpu-registers-not-fw-configured; -+ }; -+}; -+ -+&cpu_alert1 { -+ temperature = <105000>; -+}; -+ -+&cpu_crit { -+ temperature = <115000>; -+}; -+ -+&cpu_thermal { -+ cooling-maps { -+ /delete-node/ map0; -+ }; -+}; -+ -+&emmc { -+ cap-mmc-highspeed; -+ keep-power-in-suspend; -+ non-removable; -+}; -+ -+&gmac { -+ assigned-clocks = <&cru SCLK_MAC_SRC>; -+ assigned-clock-rates = <50000000>; -+ clock_in_out = "output"; -+ phy-handle = <&phy>; -+ phy-mode = "rmii"; -+ status = "okay"; -+ -+ mdio { -+ compatible = "snps,dwmac-mdio"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ phy: phy@0 { -+ compatible = "ethernet-phy-id1234.d400", -+ "ethernet-phy-ieee802.3-c22"; -+ reg = <0>; -+ clocks = <&cru SCLK_MAC_PHY>; -+ phy-is-integrated; -+ resets = <&cru SRST_MACPHY>; -+ }; -+ }; -+}; -+ -+&hdmi { -+ status = "okay"; -+}; -+ -+&hdmi_sound { -+ status = "okay"; -+}; -+ -+&hdmi_phy { -+ status = "okay"; -+}; -+ -+&i2s0 { -+ status = "okay"; -+}; -+ -+&pinctrl { -+ -+ ir { -+ ir_int: ir-int { -+ rockchip,pins = <1 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+ -+ keys { -+ pwr_key: pwr-key { -+ rockchip,pins = <3 RK_PC7 RK_FUNC_GPIO &pcfg_pull_up>; -+ }; -+ }; -+ -+ sdio-pwrseq { -+ wifi_enable_h: wifi-enable-h { -+ rockchip,pins = <2 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+ -+}; -+ -+&rga { -+ status = "okay"; -+}; -+ -+&sdio { -+ mmc-pwrseq = <&sdio_pwrseq>; -+ cap-sd-highspeed; -+ cap-sdio-irq; -+ keep-power-in-suspend; -+ non-removable; -+ no-sd; -+}; -+ -+&sdmmc { -+ cap-sd-highspeed; -+ keep-power-in-suspend; -+ no-sdio; -+}; -+ -+&spdif { -+ status = "okay"; -+}; -+ -+&spdif_out { -+ status = "okay"; -+}; -+ -+&spdif_sound { -+ status = "okay"; -+}; -+ -+&tsadc { -+ rockchip,hw-tshut-mode = <0>; -+ rockchip,hw-tshut-polarity = <1>; -+ status = "okay"; -+}; -+ -+&u2phy0 { -+ status = "okay"; -+}; -+ -+&u2phy1 { -+ status = "okay"; -+}; -+ -+&uart1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&uart11_xfer &uart11_rts &uart11_cts>; -+}; -+ -+&uart2 { -+ status = "okay"; -+}; -+ -+&usb_host0_ehci { -+ status = "okay"; -+}; -+ -+&usb_host0_ohci { -+ status = "okay"; -+}; -+ -+&usb_host1_ehci { -+ status = "okay"; -+}; -+ -+&usb_host1_ohci { -+ status = "okay"; -+}; -+ -+&usb_host2_ehci { -+ status = "okay"; -+}; -+ -+&usb_host2_ohci { -+ status = "okay"; -+}; -+ -+&usb_otg { -+ status = "okay"; -+}; -+ -+&vop { -+ assigned-clocks = <&cru DCLK_VOP>; -+ assigned-clock-parents = <&cru SCLK_HDMI_PHY>; -+ status = "okay"; -+}; -+ -+&vop_mmu { -+ status = "okay"; -+}; -+ -+&wdt { -+ status = "okay"; -+}; -diff --git a/arch/arm/boot/dts/rk322x-dcdc.dtsi b/arch/arm/boot/dts/rk322x-dcdc.dtsi -new file mode 100644 -index 000000000..6076cb1d0 ---- /dev/null -+++ b/arch/arm/boot/dts/rk322x-dcdc.dtsi -@@ -0,0 +1,164 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+ -+/dts-v1/; -+ -+#include -+#include -+#include "rk322x.dtsi" -+ -+/ { -+ -+ vcc_host: vcc-host-regulator { -+ compatible = "regulator-fixed"; -+ enable-active-high; -+ gpio = <&gpio3 RK_PC4 GPIO_ACTIVE_HIGH>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&host_vbus_drv>; -+ regulator-name = "vcc_host"; -+ regulator-always-on; -+ regulator-boot-on; -+ vin-supply = <&vcc_sys>; -+ }; -+ -+ vccio_1v8: vccio-1v8-regulator { -+ compatible = "regulator-fixed"; -+ regulator-name = "vccio_1v8"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-always-on; -+ vin-supply = <&vcc_sys>; -+ }; -+ -+ vccio_3v3: vccio-3v3-regulator { -+ compatible = "regulator-fixed"; -+ regulator-name = "vccio_3v3"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ vin-supply = <&vcc_sys>; -+ }; -+ -+ -+ vcc_otg: vcc-otg-regulator { -+ compatible = "regulator-fixed"; -+ enable-active-high; -+ gpio = <&gpio3 RK_PC6 GPIO_ACTIVE_HIGH>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&otg_vbus_drv>; -+ regulator-name = "vcc_otg_vbus"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ regulator-always-on; -+ regulator-boot-on; -+ vin-supply = <&vcc_sys>; -+ }; -+ -+ vcc_phy: vcc-phy-regulator { -+ compatible = "regulator-fixed"; -+ enable-active-high; -+ regulator-name = "vcc_phy"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-always-on; -+ regulator-boot-on; -+ vin-supply = <&vccio_1v8>; -+ }; -+ -+ vcc_sys: vcc-sys-regulator { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc_sys"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ }; -+ -+ vdd_arm: vdd-arm-regulator { -+ compatible = "pwm-regulator"; -+ pwms = <&pwm1 0 5000 1>; -+ pwm-supply = <&vcc_sys>; -+ regulator-name = "vdd_arm"; -+ regulator-min-microvolt = <950000>; -+ regulator-max-microvolt = <1400000>; -+ regulator-ramp-delay = <12500>; -+ regulator-settling-time-up-us = <250>; -+ regulator-always-on; -+ regulator-boot-on; -+ }; -+ -+ vdd_log: vdd-log-regulator { -+ compatible = "pwm-regulator"; -+ pwms = <&pwm2 0 5000 1>; -+ pwm-supply = <&vcc_sys>; -+ regulator-name = "vdd_log"; -+ regulator-min-microvolt = <1000000>; -+ regulator-max-microvolt = <1300000>; -+ regulator-ramp-delay = <12500>; -+ regulator-settling-time-up-us = <250>; -+ regulator-always-on; -+ regulator-boot-on; -+ }; -+ -+}; -+ -+ -+&cpu0 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&cpu1 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&cpu2 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&cpu3 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&io_domains { -+ vccio1-supply = <&vccio_3v3>; -+ vccio2-supply = <&vccio_1v8>; -+ vccio4-supply = <&vccio_3v3>; -+ status = "okay"; -+}; -+ -+&gmac { -+ phy-supply = <&vcc_phy>; -+}; -+ -+&gpu { -+ mali-supply = <&vdd_log>; -+}; -+ -+&pwm1 { -+ pinctrl-0 = <&pwm1_pin_pull_down>; -+ status = "okay"; -+}; -+ -+&pwm2 { -+ pinctrl-0 = <&pwm2_pin_pull_up>; -+ status = "okay"; -+}; -+ -+&u2phy0 { -+ u2phy0_host: host-port { -+ phy-supply = <&vcc_host>; -+ }; -+ -+ u2phy0_otg: otg-port { -+ phy-supply = <&vcc_otg>; -+ }; -+}; -+ -+&u2phy1 { -+ u2phy1_host: host-port { -+ phy-supply = <&vcc_host>; -+ }; -+ -+ u2phy1_otg: otg-port { -+ phy-supply = <&vcc_otg>; -+ }; -+}; -diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi -index 5485a9918..c3ca67301 100644 ---- a/arch/arm/boot/dts/rk322x.dtsi -+++ b/arch/arm/boot/dts/rk322x.dtsi -@@ -5,6 +5,8 @@ - #include - #include - #include -+#include -+#include - #include - - / { -@@ -14,6 +16,7 @@ / { - interrupt-parent = <&gic>; - - aliases { -+ ethernet0 = &gmac; - serial0 = &uart0; - serial1 = &uart1; - serial2 = &uart2; -@@ -73,25 +76,25 @@ cpu0_opp_table: opp_table0 { - - opp-408000000 { - opp-hz = /bits/ 64 <408000000>; -- opp-microvolt = <950000>; -+ opp-microvolt = <950000 950000 1275000>; - clock-latency-ns = <40000>; - opp-suspend; - }; - opp-600000000 { - opp-hz = /bits/ 64 <600000000>; -- opp-microvolt = <975000>; -+ opp-microvolt = <975000 975000 1275000>; - }; - opp-816000000 { - opp-hz = /bits/ 64 <816000000>; -- opp-microvolt = <1000000>; -+ opp-microvolt = <1000000 1000000 1275000>; - }; - opp-1008000000 { - opp-hz = /bits/ 64 <1008000000>; -- opp-microvolt = <1175000>; -+ opp-microvolt = <1175000 1175000 1275000>; - }; - opp-1200000000 { - opp-hz = /bits/ 64 <1200000000>; -- opp-microvolt = <1275000>; -+ opp-microvolt = <1275000 1275000 1275000>; - }; - }; - -@@ -121,11 +124,52 @@ arm-pmu { - interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>; - }; - -+ display_subsystem: display-subsystem { -+ compatible = "rockchip,display-subsystem"; -+ ports = <&vop_out>; -+ }; -+ -+ hdmi_sound: hdmi-sound { -+ compatible = "simple-audio-card"; -+ simple-audio-card,name = "HDMI"; -+ simple-audio-card,format = "i2s"; -+ simple-audio-card,mclk-fs = <128>; -+ status = "disabled"; -+ -+ simple-audio-card,cpu { -+ sound-dai = <&i2s0>; -+ }; -+ -+ simple-audio-card,codec { -+ sound-dai = <&hdmi>; -+ }; -+ }; -+ - psci { - compatible = "arm,psci-1.0", "arm,psci-0.2"; - method = "smc"; - }; - -+ spdif_out: spdif-out { -+ compatible = "linux,spdif-dit"; -+ #sound-dai-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ spdif_sound: spdif-sound { -+ compatible = "simple-audio-card"; -+ simple-audio-card,name = "SPDIF"; -+ status = "disabled"; -+ -+ simple-audio-card,cpu { -+ sound-dai = <&spdif>; -+ }; -+ -+ simple-audio-card,codec { -+ sound-dai = <&spdif_out>; -+ }; -+ }; -+ - timer { - compatible = "arm,armv7-timer"; - arm,cpu-registers-not-fw-configured; -@@ -143,15 +187,13 @@ xin24m: oscillator { - #clock-cells = <0>; - }; - -- display_subsystem: display-subsystem { -- compatible = "rockchip,display-subsystem"; -- ports = <&vop_out>; -- }; -- - i2s1: i2s1@100b0000 { - compatible = "rockchip,rk3228-i2s", "rockchip,rk3066-i2s"; - reg = <0x100b0000 0x4000>; - interrupts = ; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ #sound-dai-cells = <0>; - clock-names = "i2s_clk", "i2s_hclk"; - clocks = <&cru SCLK_I2S1>, <&cru HCLK_I2S1_8CH>; - dmas = <&pdma 14>, <&pdma 15>; -@@ -165,6 +207,9 @@ i2s0: i2s0@100c0000 { - compatible = "rockchip,rk3228-i2s", "rockchip,rk3066-i2s"; - reg = <0x100c0000 0x4000>; - interrupts = ; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ #sound-dai-cells = <0>; - clock-names = "i2s_clk", "i2s_hclk"; - clocks = <&cru SCLK_I2S0>, <&cru HCLK_I2S0_8CH>; - dmas = <&pdma 11>, <&pdma 12>; -@@ -182,6 +227,7 @@ spdif: spdif@100d0000 { - dma-names = "tx"; - pinctrl-names = "default"; - pinctrl-0 = <&spdif_tx>; -+ #sound-dai-cells = <0>; - status = "disabled"; - }; - -@@ -189,6 +235,9 @@ i2s2: i2s2@100e0000 { - compatible = "rockchip,rk3228-i2s", "rockchip,rk3066-i2s"; - reg = <0x100e0000 0x4000>; - interrupts = ; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ #sound-dai-cells = <0>; - clock-names = "i2s_clk", "i2s_hclk"; - clocks = <&cru SCLK_I2S2>, <&cru HCLK_I2S2_2CH>; - dmas = <&pdma 0>, <&pdma 1>; -@@ -207,6 +256,43 @@ io_domains: io-domains { - status = "disabled"; - }; - -+ power: power-controller { -+ compatible = "rockchip,rk3228-power-controller"; -+ #power-domain-cells = <1>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ pd_gpu@RK3228_PD_GPU { -+ reg = ; -+ clocks = <&cru ACLK_GPU>; -+ pm_qos = <&qos_gpu>; -+ }; -+ -+ pd_vpu@RK3228_PD_VPU { -+ reg = ; -+ clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; -+ pm_qos = <&qos_vpu>; -+ }; -+ -+ pd_rkvdec@RK3228_PD_RKVDEC { -+ reg = ; -+ clocks = <&cru ACLK_RKVDEC>, -+ <&cru HCLK_RKVDEC>, -+ <&cru SCLK_VDEC_CABAC>, -+ <&cru SCLK_VDEC_CORE>; -+ pm_qos = <&qos_rkvdec_r>, <&qos_rkvdec_w>; -+ }; -+ }; -+ -+ reboot_mode: reboot-mode { -+ compatible = "syscon-reboot-mode"; -+ offset = <0x5c8>; -+ mode-normal = ; -+ mode-recovery = ; -+ mode-bootloader = ; -+ mode-loader = ; -+ }; -+ - u2phy0: usb2-phy@760 { - compatible = "rockchip,rk3228-usb2phy"; - reg = <0x0760 0x0c>; -@@ -257,6 +343,7 @@ u2phy1_host: host-port { - status = "disabled"; - }; - }; -+ - }; - - uart0: serial@11010000 { -@@ -295,7 +382,7 @@ uart2: serial@11030000 { - clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>; - clock-names = "baudclk", "apb_pclk"; - pinctrl-names = "default"; -- pinctrl-0 = <&uart2_xfer>; -+ pinctrl-0 = <&uart21_xfer>; - reg-shift = <2>; - reg-io-width = <4>; - status = "disabled"; -@@ -454,13 +541,13 @@ cru: clock-controller@110e0000 { - <&cru PLL_CPLL>, <&cru ACLK_PERI>, - <&cru HCLK_PERI>, <&cru PCLK_PERI>, - <&cru ACLK_CPU>, <&cru HCLK_CPU>, -- <&cru PCLK_CPU>; -+ <&cru PCLK_CPU>, <&cru ACLK_VOP>; - assigned-clock-rates = -- <594000000>, <816000000>, -+ <1200000000>, <816000000>, - <500000000>, <150000000>, - <150000000>, <75000000>, - <150000000>, <150000000>, -- <75000000>; -+ <75000000>, <400000000>; - }; - - thermal-zones { -@@ -505,6 +592,12 @@ map1 { - <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; -+ -+ map2 { -+ trip = <&cpu_alert1>; -+ cooling-device = -+ <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; -+ }; - }; - }; - }; -@@ -523,8 +616,9 @@ tsadc: tsadc@11150000 { - pinctrl-0 = <&otp_gpio>; - pinctrl-1 = <&otp_out>; - pinctrl-2 = <&otp_gpio>; -+ rockchip,grf = <&grf>; -+ rockchip,hw-tshut-temp = <120000>; - #thermal-sensor-cells = <0>; -- rockchip,hw-tshut-temp = <95000>; - status = "disabled"; - }; - -@@ -554,10 +648,33 @@ gpu: gpu@20000000 { - "ppmmu0", - "pp1", - "ppmmu1"; -+ assigned-clocks = <&cru ACLK_GPU>; -+ assigned-clock-rates = <300000000>; - clocks = <&cru ACLK_GPU>, <&cru ACLK_GPU>; - clock-names = "bus", "core"; -+ operating-points-v2 = <&gpu_opp_table>; -+ #cooling-cells = <2>; /* min followed by max */ -+ power-domains = <&power RK3228_PD_GPU>; - resets = <&cru SRST_GPU_A>; -- status = "disabled"; -+ }; -+ -+ gpu_opp_table: opp-table2 { -+ compatible = "operating-points-v2"; -+ -+ opp-200000000 { -+ opp-hz = /bits/ 64 <200000000>; -+ opp-microvolt = <1050000>; -+ }; -+ -+ opp-300000000 { -+ opp-hz = /bits/ 64 <300000000>; -+ opp-microvolt = <1050000>; -+ }; -+ -+ opp-500000000 { -+ opp-hz = /bits/ 64 <500000000>; -+ opp-microvolt = <1150000>; -+ }; - }; - - vpu_mmu: iommu@20020800 { -@@ -567,8 +684,8 @@ vpu_mmu: iommu@20020800 { - interrupt-names = "vpu_mmu"; - clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; - clock-names = "aclk", "iface"; -- iommu-cells = <0>; -- status = "disabled"; -+ power-domains = <&power RK3228_PD_VPU>; -+ #iommu-cells = <0>; - }; - - vdec_mmu: iommu@20030480 { -@@ -578,8 +695,8 @@ vdec_mmu: iommu@20030480 { - interrupt-names = "vdec_mmu"; - clocks = <&cru ACLK_RKVDEC>, <&cru HCLK_RKVDEC>; - clock-names = "aclk", "iface"; -- iommu-cells = <0>; -- status = "disabled"; -+ power-domains = <&power RK3228_PD_RKVDEC>; -+ #iommu-cells = <0>; - }; - - vop: vop@20050000 { -@@ -622,7 +739,7 @@ iep_mmu: iommu@20070800 { - interrupt-names = "iep_mmu"; - clocks = <&cru ACLK_IEP>, <&cru HCLK_IEP>; - clock-names = "aclk", "iface"; -- iommu-cells = <0>; -+ #iommu-cells = <0>; - status = "disabled"; - }; - -@@ -642,6 +759,7 @@ hdmi: hdmi@200a0000 { - phys = <&hdmi_phy>; - phy-names = "hdmi"; - rockchip,grf = <&grf>; -+ #sound-dai-cells = <0>; - status = "disabled"; - - ports { -@@ -663,9 +781,13 @@ sdmmc: mmc@30000000 { - clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>, - <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>; - clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; -+ bus-width = <4>; - fifo-depth = <0x100>; -+ max-frequency = <150000000>; - pinctrl-names = "default"; -- pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_bus4>; -+ pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_bus4 &sdmmc_pwr>; -+ resets = <&cru SRST_SDMMC>; -+ reset-names = "reset"; - status = "disabled"; - }; - -@@ -675,10 +797,14 @@ sdio: mmc@30010000 { - interrupts = ; - clocks = <&cru HCLK_SDIO>, <&cru SCLK_SDIO>, - <&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>; -+ bus-width = <4>; - clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; - fifo-depth = <0x100>; -+ max-frequency = <150000000>; - pinctrl-names = "default"; - pinctrl-0 = <&sdio_clk &sdio_cmd &sdio_bus4>; -+ resets = <&cru SRST_SDIO>; -+ reset-names = "reset"; - status = "disabled"; - }; - -@@ -686,8 +812,7 @@ emmc: mmc@30020000 { - compatible = "rockchip,rk3228-dw-mshc", "rockchip,rk3288-dw-mshc"; - reg = <0x30020000 0x4000>; - interrupts = ; -- clock-frequency = <37500000>; -- max-frequency = <37500000>; -+ max-frequency = <150000000>; - clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>, - <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>; - clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; -@@ -701,6 +826,22 @@ emmc: mmc@30020000 { - status = "disabled"; - }; - -+ nfc: nand-controller@ff4b0000 { -+ compatible = "rockchip,rk3228_nfc"; -+ reg = <0x30030000 0x4000>; -+ interrupts = ; -+ clocks = <&cru SCLK_NANDC>, <&cru HCLK_NANDC>; -+ clock-names = "nfc", "ahb"; -+ assigned-clocks = <&cru SCLK_NANDC>; -+ assigned-clock-rates = <150000000>; -+ -+ pinctrl-names = "default"; -+ pinctrl-0 = <&flash_cs0 &flash_rdy &flash_ale &flash_cle -+ &flash_wrn &flash_rdn &flash_bus8>; -+ status = "disabled"; -+ -+ }; -+ - usb_otg: usb@30040000 { - compatible = "rockchip,rk3228-usb", "rockchip,rk3066-usb", - "snps,dwc2"; -@@ -796,6 +937,26 @@ gmac: ethernet@30200000 { - status = "disabled"; - }; - -+ qos_vpu: qos@31040000 { -+ compatible = "syscon"; -+ reg = <0x31040000 0x20>; -+ }; -+ -+ qos_gpu: qos@31050000 { -+ compatible = "syscon"; -+ reg = <0x31050000 0x20>; -+ }; -+ -+ qos_rkvdec_r: qos@31070000 { -+ compatible = "syscon"; -+ reg = <0x31070000 0x20>; -+ }; -+ -+ qos_rkvdec_w: qos@31070080 { -+ compatible = "syscon"; -+ reg = <0x31070080 0x20>; -+ }; -+ - gic: interrupt-controller@32010000 { - compatible = "arm,gic-400"; - interrupt-controller; -@@ -884,6 +1045,11 @@ pcfg_pull_none_drv_12ma: pcfg-pull-none-drv-12ma { - drive-strength = <12>; - }; - -+ pcfg_pull_up_12ma: pcfg-pull-up-12ma { -+ bias-pull-up; -+ drive-strength = <12>; -+ }; -+ - sdmmc { - sdmmc_clk: sdmmc-clk { - rockchip,pins = <1 RK_PC0 1 &pcfg_pull_none_drv_12ma>; -@@ -899,6 +1065,10 @@ sdmmc_bus4: sdmmc-bus4 { - <1 RK_PC4 1 &pcfg_pull_none_drv_12ma>, - <1 RK_PC5 1 &pcfg_pull_none_drv_12ma>; - }; -+ -+ sdmmc_pwr: sdmmc-pwr { -+ rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; - }; - - sdio { -@@ -939,6 +1109,55 @@ emmc_bus8: emmc-bus8 { - }; - }; - -+ flash { -+ -+ flash_cs0: flash-cs0 { -+ rockchip,pins = -+ <2 RK_PA6 1 &pcfg_pull_none>; -+ }; -+ -+ flash_cs1: flash-cs1 { -+ rockchip,pins = -+ <0 RK_PC7 1 &pcfg_pull_none>; -+ }; -+ -+ flash_rdy: flash-rdy { -+ rockchip,pins = -+ <2 RK_PA4 1 &pcfg_pull_none>; -+ }; -+ -+ flash_ale: flash-ale { -+ rockchip,pins = -+ <2 RK_PA0 1 &pcfg_pull_none>; -+ }; -+ -+ flash_cle: flash-cle { -+ rockchip,pins = -+ <2 RK_PA1 1 &pcfg_pull_none>; -+ }; -+ -+ flash_wrn: flash-wrn { -+ rockchip,pins = -+ <2 RK_PA2 1 &pcfg_pull_none>; -+ }; -+ -+ flash_rdn: flash-rdn { -+ rockchip,pins = -+ <2 RK_PA3 1 &pcfg_pull_none>; -+ }; -+ -+ flash_bus8: flash-bus8 { -+ rockchip,pins = <1 RK_PD0 1 &pcfg_pull_none>, -+ <1 RK_PD1 1 &pcfg_pull_none>, -+ <1 RK_PD2 1 &pcfg_pull_none>, -+ <1 RK_PD3 1 &pcfg_pull_none>, -+ <1 RK_PD4 1 &pcfg_pull_none>, -+ <1 RK_PD5 1 &pcfg_pull_none>, -+ <1 RK_PD6 1 &pcfg_pull_none>, -+ <1 RK_PD7 1 &pcfg_pull_none>; -+ }; -+ }; -+ - gmac { - rgmii_pins: rgmii-pins { - rockchip,pins = <2 RK_PB6 1 &pcfg_pull_none>, -@@ -1080,12 +1299,20 @@ pwm1 { - pwm1_pin: pwm1-pin { - rockchip,pins = <0 RK_PD6 2 &pcfg_pull_none>; - }; -+ -+ pwm1_pin_pull_down: pwm1-pin-pull-down { -+ rockchip,pins = <0 RK_PD6 RK_FUNC_2 &pcfg_pull_down>; -+ }; - }; - - pwm2 { - pwm2_pin: pwm2-pin { - rockchip,pins = <1 RK_PB4 2 &pcfg_pull_none>; - }; -+ -+ pwm2_pin_pull_up: pwm2-pin-pull-up { -+ rockchip,pins = <1 RK_PB4 RK_FUNC_2 &pcfg_pull_up>; -+ }; - }; - - pwm3 { -@@ -1140,16 +1367,31 @@ uart1_rts: uart1-rts { - }; - }; - -+ uart1-1 { -+ uart11_xfer: uart11-xfer { -+ rockchip,pins = <3 RK_PB6 RK_FUNC_1 &pcfg_pull_up>, -+ <3 RK_PB5 RK_FUNC_1 &pcfg_pull_none>; -+ }; -+ -+ uart11_cts: uart11-cts { -+ rockchip,pins = <3 RK_PA7 RK_FUNC_1 &pcfg_pull_none>; -+ }; -+ -+ uart11_rts: uart11-rts { -+ rockchip,pins = <3 RK_PA6 RK_FUNC_1 &pcfg_pull_none>; -+ }; -+ -+ uart11_rts_gpio: uart11-rts-gpio { -+ rockchip,pins = <3 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+ - uart2 { - uart2_xfer: uart2-xfer { - rockchip,pins = <1 RK_PC2 2 &pcfg_pull_up>, - <1 RK_PC3 2 &pcfg_pull_none>; - }; - -- uart21_xfer: uart21-xfer { -- rockchip,pins = <1 RK_PB2 2 &pcfg_pull_up>, -- <1 RK_PB1 2 &pcfg_pull_none>; -- }; - - uart2_cts: uart2-cts { - rockchip,pins = <0 RK_PD1 1 &pcfg_pull_none>; -@@ -1159,5 +1401,23 @@ uart2_rts: uart2-rts { - rockchip,pins = <0 RK_PD0 1 &pcfg_pull_none>; - }; - }; -+ -+ uart2-1 { -+ uart21_xfer: uart21-xfer { -+ rockchip,pins = <1 RK_PB2 RK_FUNC_2 &pcfg_pull_up>, -+ <1 RK_PB1 RK_FUNC_2 &pcfg_pull_none>; -+ }; -+ }; -+ -+ usb { -+ host_vbus_drv: host-vbus-drv { -+ rockchip,pins = <3 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ -+ otg_vbus_drv: otg-vbus-drv { -+ rockchip,pins = <3 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+ - }; - }; -diff --git a/arch/arm/boot/dts/rk322x.dtsi.rej b/arch/arm/boot/dts/rk322x.dtsi.rej -new file mode 100644 -index 000000000..cc36be3e9 ---- /dev/null -+++ b/arch/arm/boot/dts/rk322x.dtsi.rej -@@ -0,0 +1,45 @@ -+--- arch/arm/boot/dts/rk322x.dtsi -++++ arch/arm/boot/dts/rk322x.dtsi -+@@ -187,17 +231,13 @@ -+ #clock-cells = <0>; -+ }; -+ -+- display_subsystem: display-subsystem { -+- compatible = "rockchip,display-subsystem"; -+- ports = <&vop_out>; -+- }; -+- -+ i2s1: i2s1@100b0000 { -+ compatible = "rockchip,rk3228-i2s", "rockchip,rk3066-i2s"; -+ reg = <0x100b0000 0x4000>; -+ interrupts = ; -+ #address-cells = <1>; -+ #size-cells = <0>; -++ #sound-dai-cells = <0>; -+ clock-names = "i2s_clk", "i2s_hclk"; -+ clocks = <&cru SCLK_I2S1>, <&cru HCLK_I2S1_8CH>; -+ dmas = <&pdma 14>, <&pdma 15>; -+@@ -213,6 +253,7 @@ -+ interrupts = ; -+ #address-cells = <1>; -+ #size-cells = <0>; -++ #sound-dai-cells = <0>; -+ clock-names = "i2s_clk", "i2s_hclk"; -+ clocks = <&cru SCLK_I2S0>, <&cru HCLK_I2S0_8CH>; -+ dmas = <&pdma 11>, <&pdma 12>; -+@@ -825,14 +944,13 @@ -+ compatible = "rockchip,rk3228-dw-mshc", "rockchip,rk3288-dw-mshc"; -+ reg = <0x30020000 0x4000>; -+ interrupts = ; -+- clock-frequency = <37500000>; -+- max-frequency = <37500000>; -+ clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>, -+ <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>; -+ clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; -+ bus-width = <8>; -+ default-sample-phase = <158>; -+ fifo-depth = <0x100>; -++ max-frequency = <150000000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; -+ resets = <&cru SRST_EMMC>; diff --git a/patch/kernel/rk322x-current/01-linux-1003-rk322x-hantro.patch b/patch/kernel/rk322x-current/01-linux-1003-rk322x-hantro.patch deleted file mode 100644 index e63bce853..000000000 --- a/patch/kernel/rk322x-current/01-linux-1003-rk322x-hantro.patch +++ /dev/null @@ -1,98 +0,0 @@ -diff --git a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml -index a0c45e05cf03..a20cfaa8973e 100644 ---- a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml -+++ b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml -@@ -16,6 +16,7 @@ description: - properties: - compatible: - enum: -+ - rockchip,rk322x-vpu - - rockchip,rk3288-vpu - - rockchip,rk3328-vpu - - rockchip,rk3399-vpu -diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi -index f7a50b903a7d..2ed8aa7ae520 100644 ---- a/arch/arm/boot/dts/rk322x.dtsi -+++ b/arch/arm/boot/dts/rk322x.dtsi -@@ -676,6 +676,18 @@ - }; - }; - -+ vpu: video-codec@20020000 { -+ compatible = "rockchip,rk322x-vpu"; -+ reg = <0x20020000 0x800>; -+ interrupts = , -+ ; -+ interrupt-names = "vepu", "vdpu"; -+ clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; -+ clock-names = "aclk", "hclk"; -+ iommus = <&vpu_mmu>; -+ power-domains = <&power RK3228_PD_VPU>; -+ }; -+ - vpu_mmu: iommu@20020800 { - compatible = "rockchip,iommu"; - reg = <0x20020800 0x100>; -diff --git a/drivers/staging/media/hantro/Kconfig b/drivers/staging/media/hantro/Kconfig -index de77fe6554e7..9f99d1c9f453 100644 ---- a/drivers/staging/media/hantro/Kconfig -+++ b/drivers/staging/media/hantro/Kconfig -@@ -20,4 +20,4 @@ config VIDEO_HANTRO_ROCKCHIP - depends on ARCH_ROCKCHIP || COMPILE_TEST - default y - help -- Enable support for RK3288, RK3328, and RK3399 SoCs. -+ Enable support for RK322x, RK3288, RK3328, and RK3399 SoCs. -diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c -index a732beeb3bb6..fae9555a349b 100644 ---- a/drivers/staging/media/hantro/hantro_drv.c -+++ b/drivers/staging/media/hantro/hantro_drv.c -@@ -469,6 +469,7 @@ static const struct of_device_id of_hantro_match[] = { - { .compatible = "rockchip,rk3399-vpu", .data = &rk3399_vpu_variant, }, - { .compatible = "rockchip,rk3328-vpu", .data = &rk3328_vpu_variant, }, - { .compatible = "rockchip,rk3288-vpu", .data = &rk3288_vpu_variant, }, -+ { .compatible = "rockchip,rk322x-vpu", .data = &rk322x_vpu_variant, }, - #endif - { /* sentinel */ } - }; -diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h -index 33c1ce169203..e64369e01a21 100644 ---- a/drivers/staging/media/hantro/hantro_hw.h -+++ b/drivers/staging/media/hantro/hantro_hw.h -@@ -157,6 +157,7 @@ enum hantro_enc_fmt { - extern const struct hantro_variant rk3399_vpu_variant; - extern const struct hantro_variant rk3328_vpu_variant; - extern const struct hantro_variant rk3288_vpu_variant; -+extern const struct hantro_variant rk322x_vpu_variant; - extern const struct hantro_variant imx8mq_vpu_variant; - - extern const struct hantro_postproc_regs hantro_g1_postproc_regs; - -diff --git a/drivers/staging/media/hantro/rk3399_vpu_hw.c b/drivers/staging/media/hantro/rk3399_vpu_hw.c -index 78f878ca01ff..0a6c021c2332 100644 ---- a/drivers/staging/media/hantro/rk3399_vpu_hw.c -+++ b/drivers/staging/media/hantro/rk3399_vpu_hw.c -@@ -241,3 +241,20 @@ const struct hantro_variant rk3328_vpu_variant = { - .clk_names = rk3399_clk_names, - .num_clocks = ARRAY_SIZE(rk3399_clk_names), - }; -+ -+const struct hantro_variant rk322x_vpu_variant = { -+ .enc_offset = 0x0, -+ .enc_fmts = rk3399_vpu_enc_fmts, -+ .num_enc_fmts = ARRAY_SIZE(rk3399_vpu_enc_fmts), -+ .dec_offset = 0x400, -+ .dec_fmts = rk3399_vpu_dec_fmts, -+ .num_dec_fmts = ARRAY_SIZE(rk3399_vpu_dec_fmts), -+ .codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER | -+ HANTRO_H264_DECODER, -+ .codec_ops = rk3399_vpu_codec_ops, -+ .irqs = rk3399_irqs, -+ .num_irqs = ARRAY_SIZE(rk3399_irqs), -+ .init = rk3399_vpu_hw_init, -+ .clk_names = rk3399_clk_names, -+ .num_clocks = ARRAY_SIZE(rk3399_clk_names) -+}; --- -2.17.1 - diff --git a/patch/kernel/rk322x-current/01-linux-1004-rockchip-rk322x-enhancements-and-fixes.patch b/patch/kernel/rk322x-current/01-linux-1004-rockchip-rk322x-enhancements-and-fixes.patch deleted file mode 100644 index aa5a48973..000000000 --- a/patch/kernel/rk322x-current/01-linux-1004-rockchip-rk322x-enhancements-and-fixes.patch +++ /dev/null @@ -1,383 +0,0 @@ -diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c -index 54eb6cfc5d5b..c6b33f7c43df 100644 ---- a/drivers/soc/rockchip/pm_domains.c -+++ b/drivers/soc/rockchip/pm_domains.c -@@ -71,6 +71,7 @@ struct rockchip_pm_domain { - struct regmap **qos_regmap; - u32 *qos_save_regs[MAX_QOS_REGS_NUM]; - int num_clks; -+ bool is_ignore_pwr; - struct clk_bulk_data *clks; - }; - -@@ -330,6 +331,9 @@ static int rockchip_pd_power_on(struct generic_pm_domain *domain) - { - struct rockchip_pm_domain *pd = to_rockchip_pd(domain); - -+ if (pd->is_ignore_pwr) -+ return 0; -+ - return rockchip_pd_power(pd, true); - } - -@@ -337,6 +341,9 @@ static int rockchip_pd_power_off(struct generic_pm_domain *domain) - { - struct rockchip_pm_domain *pd = to_rockchip_pd(domain); - -+ if (pd->is_ignore_pwr) -+ return 0; -+ - return rockchip_pd_power(pd, false); - } - -@@ -416,6 +423,9 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, - pd->info = pd_info; - pd->pmu = pmu; - -+ if (!pd_info->pwr_mask) -+ pd->is_ignore_pwr = true; -+ - pd->num_clks = of_clk_get_parent_count(node); - if (pd->num_clks > 0) { - pd->clks = devm_kcalloc(pmu->dev, pd->num_clks, -@@ -566,6 +576,7 @@ static int rockchip_pm_add_subdomain(struct rockchip_pmu *pmu, - { - struct device_node *np; - struct generic_pm_domain *child_domain, *parent_domain; -+ struct rockchip_pm_domain *child_pd, *parent_pd; - int error; - - for_each_child_of_node(parent, np) { -@@ -606,6 +617,18 @@ static int rockchip_pm_add_subdomain(struct rockchip_pmu *pmu, - parent_domain->name, child_domain->name); - } - -+ /* -+ * If child_pd doesn't do idle request or power on/off, -+ * parent_pd may fail to do power on/off, so if parent_pd -+ * need to power on/off, child_pd can't ignore to do idle -+ * request and power on/off. -+ */ -+ child_pd = to_rockchip_pd(child_domain); -+ parent_pd = to_rockchip_pd(parent_domain); -+ if (!parent_pd->is_ignore_pwr) -+ child_pd->is_ignore_pwr = false; -+ -+ - rockchip_pm_add_subdomain(pmu, np); - } - --- -2.17.1 - -From c94b1272290bafced10d79b7da1525466e8c843b Mon Sep 17 00:00:00 2001 -From: "Huang, Tao" -Date: Thu, 28 Jul 2016 10:59:22 +0800 -Subject: [PATCH] power: reset: reboot-mode: fix normal mode setup - -If cmd is empty in get_reboot_mode_magic, we should return normal magic. - -Change-Id: I10931adc49e33f72ae73d9471159f82cc02ff0c0 -Signed-off-by: Huang, Tao ---- - drivers/power/reset/reboot-mode.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/power/reset/reboot-mode.c b/drivers/power/reset/reboot-mode.c -index b4076b10b893..47f9a162807d 100644 ---- a/drivers/power/reset/reboot-mode.c -+++ b/drivers/power/reset/reboot-mode.c -@@ -26,7 +26,7 @@ static unsigned int get_reboot_mode_magic(struct reboot_mode_driver *reboot, - int magic = 0; - struct mode_info *info; - -- if (!cmd) -+ if (!cmd || !cmd[0]) - cmd = normal; - - list_for_each_entry(info, &reboot->head, list) { --- -2.17.1 - - -From be9674f270c97399f9f6b1facb11e93eced6ec34 Mon Sep 17 00:00:00 2001 -From: Andy Yan -Date: Thu, 8 Dec 2016 16:58:07 +0800 -Subject: [PATCH] power: reset: reboot-mode: treat unrecognized reboot mode as - normal mode - -Some bootloader will check the reboot mode to take different action, so -we treat unrecognized reboot mode as normal mode to prevent the system -run into abnormal case. - -Change-Id: I88063a5b41e4e645443229fa490b2b55db5ccf27 -Signed-off-by: Andy Yan ---- - drivers/power/reset/reboot-mode.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/drivers/power/reset/reboot-mode.c b/drivers/power/reset/reboot-mode.c -index 47f9a162807d..99bf938404e3 100644 ---- a/drivers/power/reset/reboot-mode.c -+++ b/drivers/power/reset/reboot-mode.c -@@ -47,6 +47,8 @@ static int reboot_mode_notify(struct notifier_block *this, - - reboot = container_of(this, struct reboot_mode_driver, reboot_notifier); - magic = get_reboot_mode_magic(reboot, cmd); -+ if (!magic) -+ magic = get_reboot_mode_magic(reboot, NULL); - if (magic) - reboot->write(reboot, magic); - --- -2.17.1 - -From 7c097120eb21a9bd15ab63c0ac60ffd5cba902b2 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Fri, 24 Apr 2020 13:01:07 +0200 -Subject: [PATCH] sound: soc: rockchip: use rouned rate for i2s - ---- - sound/soc/rockchip/rockchip_i2s.c | 9 +++++++-- - 1 file changed, 7 insertions(+), 2 deletions(-) - -diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c -index 61c984f10d8e..efca853eba6b 100644 ---- a/sound/soc/rockchip/rockchip_i2s.c -+++ b/sound/soc/rockchip/rockchip_i2s.c -@@ -279,10 +279,13 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, - if (i2s->is_master_mode) { - mclk_rate = clk_get_rate(i2s->mclk); - bclk_rate = 2 * 32 * params_rate(params); -- if (bclk_rate && mclk_rate % bclk_rate) -+ if (!bclk_rate) { -+ dev_err(i2s->dev, "invalid bclk_rate: %d\n", -+ bclk_rate); - return -EINVAL; -+ } - -- div_bclk = mclk_rate / bclk_rate; -+ div_bclk = DIV_ROUND_CLOSEST(mclk_rate, bclk_rate); - div_lrck = bclk_rate / params_rate(params); - regmap_update_bits(i2s->regmap, I2S_CKR, - I2S_CKR_MDIV_MASK, -@@ -312,6 +315,8 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, - val |= I2S_TXCR_VDW(32); - break; - default: -+ dev_err(i2s->dev, "invalid format: %d\n", -+ params_format(params)); - return -EINVAL; - } - --- -2.17.1 - - -From 4102c5b07d8610c729d577612c1df52737fb9a0f Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Fri, 24 Apr 2020 09:08:44 +0200 -Subject: [PATCH] phy: rockchip: hdmi: readout hdmi phy flag for RK3228 HDMI - phys - -Some RK3228 HDMI phys only get a stable pll on frequencies higher 337,5 MHz. -This is defined in a flag in efuse of those devices. ---- - arch/arm/boot/dts/rk322x.dtsi | 7 ++++ - drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 38 ++++++++++++++++++- - 2 files changed, 43 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi -index 2ed8aa7ae520..8c50dcb0e9f1 100644 ---- a/arch/arm/boot/dts/rk322x.dtsi -+++ b/arch/arm/boot/dts/rk322x.dtsi -@@ -402,6 +402,11 @@ - cpu_leakage: cpu_leakage@17 { - reg = <0x17 0x1>; - }; -+ -+ hdmi_phy_flag: hdmi-phy-flag@1d { -+ reg = <0x1d 0x1>; -+ bits = <1 1>; -+ }; - }; - - i2c0: i2c@11050000 { -@@ -628,6 +633,8 @@ - clock-names = "sysclk", "refoclk", "refpclk"; - #clock-cells = <0>; - clock-output-names = "hdmiphy_phy"; -+ nvmem-cells = <&hdmi_phy_flag>; -+ nvmem-cell-names = "hdmi-phy-flag"; - #phy-cells = <0>; - status = "disabled"; - }; -diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c -index bb8bdf5e3301..0c7a97352714 100644 ---- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c -+++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c -@@ -237,6 +237,9 @@ struct inno_hdmi_phy { - struct clk *refoclk; - struct clk *refpclk; - -+ /* phy_flag flag */ -+ bool phy_flag; -+ - /* platform data */ - const struct inno_hdmi_phy_drv_data *plat_data; - int chip_version; -@@ -347,6 +350,7 @@ static const struct pre_pll_config pre_pll_cfg_table[] = { - static const struct post_pll_config post_pll_cfg_table[] = { - {33750000, 1, 40, 8, 1}, - {33750000, 1, 80, 8, 2}, -+ {33750000, 1, 10, 2, 4}, - {74250000, 1, 40, 8, 1}, - {74250000, 18, 80, 8, 2}, - {148500000, 2, 40, 4, 3}, -@@ -497,8 +501,11 @@ static int inno_hdmi_phy_power_on(struct phy *phy) - return -EINVAL; - - for (; cfg->tmdsclock != 0; cfg++) -- if (tmdsclock <= cfg->tmdsclock && -- cfg->version & inno->chip_version) -+ if (((!inno->phy_flag || tmdsclock > 33750000) -+ && tmdsclock <= cfg->tmdsclock -+ && cfg->version & inno->chip_version) || -+ (inno->phy_flag && tmdsclock <= 33750000 -+ && cfg->version & 4)) - break; - - for (; phy_cfg->tmdsclock != 0; phy_cfg++) -@@ -909,6 +916,10 @@ static int inno_hdmi_phy_clk_register(struct inno_hdmi_phy *inno) - - static int inno_hdmi_phy_rk3228_init(struct inno_hdmi_phy *inno) - { -+ struct nvmem_cell *cell; -+ unsigned char *efuse_buf; -+ size_t len; -+ - /* - * Use phy internal register control - * rxsense/poweron/pllpd/pdataen signal. -@@ -923,7 +934,28 @@ static int inno_hdmi_phy_rk3228_init(struct inno_hdmi_phy *inno) - inno_update_bits(inno, 0xaa, RK3228_POST_PLL_CTRL_MANUAL, - RK3228_POST_PLL_CTRL_MANUAL); - -+ - inno->chip_version = 1; -+ inno->phy_flag = false; -+ -+ cell = nvmem_cell_get(inno->dev, "hdmi-phy-flag"); -+ if (IS_ERR(cell)) { -+ if (PTR_ERR(cell) == -EPROBE_DEFER) -+ return -EPROBE_DEFER; -+ -+ return 0; -+ } -+ -+ efuse_buf = nvmem_cell_read(cell, &len); -+ nvmem_cell_put(cell); -+ -+ if (IS_ERR(efuse_buf)) -+ return 0; -+ if (len == 1) -+ inno->phy_flag = (efuse_buf[0] & BIT(1)) ? true : false; -+ kfree(efuse_buf); -+ -+ dev_info(inno->dev, "phy_flag is: %d\n", inno->phy_flag); - - return 0; - } -@@ -1023,6 +1055,8 @@ static int inno_hdmi_phy_rk3328_init(struct inno_hdmi_phy *inno) - - /* try to read the chip-version */ - inno->chip_version = 1; -+ inno->phy_flag = false; -+ - cell = nvmem_cell_get(inno->dev, "cpu-version"); - if (IS_ERR(cell)) { - if (PTR_ERR(cell) == -EPROBE_DEFER) --- -2.17.1 - - -From fe30b024a7a7d6261dff0b87c2aec270ad530c39 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Fri, 24 Apr 2020 14:23:38 +0200 -Subject: [PATCH] drm: rockchip: Use 2nd RK3228 plane as an overlay - -As per datasheet the second plane of RK3228 vop is an overlay window. For -the missing implementation of hardware cursor it is missued as such (as -already pointed in comment for RK3288). Furthermore the overlay window -does not support YUV modes with the current implementation - so it -supports only RGB modes for now. ---- - drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 44 +++++++++++++++++++-- - 1 file changed, 41 insertions(+), 3 deletions(-) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -index 73d24c6bbf05..d4ac6e161ef2 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -@@ -614,6 +614,44 @@ static const struct vop_common rk3288_common = { - .dsp_background = VOP_REG(RK3288_DSP_BG, 0xffffffff, 0), - }; - -+static const struct vop_win_phy rk3228_win0_data = { -+ .scl = &rk3288_win_full_scl, -+ .data_formats = formats_win_full, -+ .nformats = ARRAY_SIZE(formats_win_full), -+ .enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0), -+ .format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1), -+ .rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12), -+ .act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0), -+ .dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0), -+ .dsp_st = VOP_REG(RK3288_WIN0_DSP_ST, 0x1fff1fff, 0), -+ .yrgb_mst = VOP_REG(RK3288_WIN0_YRGB_MST, 0xffffffff, 0), -+ .uv_mst = VOP_REG(RK3288_WIN0_CBR_MST, 0xffffffff, 0), -+ .yrgb_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 0), -+ .uv_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 16), -+ .src_alpha_ctl = VOP_REG(RK3288_WIN0_SRC_ALPHA_CTRL, 0xff, 0), -+ .dst_alpha_ctl = VOP_REG(RK3288_WIN0_DST_ALPHA_CTRL, 0xff, 0), -+ .channel = VOP_REG(RK3288_WIN0_CTRL2, 0xff, 0), -+}; -+ -+static const struct vop_win_phy rk3228_win1_data = { -+ .scl = &rk3288_win_full_scl, -+ .data_formats = formats_win_lite, -+ .nformats = ARRAY_SIZE(formats_win_lite), -+ .enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0), -+ .format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1), -+ .rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12), -+ .act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0), -+ .dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0), -+ .dsp_st = VOP_REG(RK3288_WIN0_DSP_ST, 0x1fff1fff, 0), -+ .yrgb_mst = VOP_REG(RK3288_WIN0_YRGB_MST, 0xffffffff, 0), -+ .uv_mst = VOP_REG(RK3288_WIN0_CBR_MST, 0xffffffff, 0), -+ .yrgb_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 0), -+ .uv_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 16), -+ .src_alpha_ctl = VOP_REG(RK3288_WIN0_SRC_ALPHA_CTRL, 0xff, 0), -+ .dst_alpha_ctl = VOP_REG(RK3288_WIN0_DST_ALPHA_CTRL, 0xff, 0), -+ .channel = VOP_REG(RK3288_WIN0_CTRL2, 0xff, 0), -+}; -+ - /* - * Note: rk3288 has a dedicated 'cursor' window, however, that window requires - * special support to get alpha blending working. For now, just use overlay -@@ -864,10 +902,10 @@ static const struct vop_data rk3399_vop_lit = { - }; - - static const struct vop_win_data rk3228_vop_win_data[] = { -- { .base = 0x00, .phy = &rk3288_win01_data, -+ { .base = 0x00, .phy = &rk3228_win0_data, - .type = DRM_PLANE_TYPE_PRIMARY }, -- { .base = 0x40, .phy = &rk3288_win01_data, -- .type = DRM_PLANE_TYPE_CURSOR }, -+ { .base = 0x40, .phy = &rk3228_win1_data, -+ .type = DRM_PLANE_TYPE_OVERLAY }, - }; - - static const struct vop_data rk3228_vop = { --- -2.17.1 - diff --git a/patch/kernel/rk322x-current/01-linux-2000-rockchip-drm-wip.patch b/patch/kernel/rk322x-current/01-linux-2000-rockchip-drm-wip.patch new file mode 100644 index 000000000..454c77a33 --- /dev/null +++ b/patch/kernel/rk322x-current/01-linux-2000-rockchip-drm-wip.patch @@ -0,0 +1,5333 @@ +From 4fe70563eb6f08f737ecc7091b8c4806e18a2479 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 8 Jan 2020 21:07:47 +0000 +Subject: [PATCH] phy/rockchip: inno-hdmi: use correct vco_div_5 macro on + rk3328 + +inno_hdmi_phy_rk3328_clk_set_rate() is using the RK3228 macro +when configuring vco_div_5 on RK3328. + +Fix this by using correct vco_div_5 macro for RK3328. + +Fixes: 53706a116863 ("phy: add Rockchip Innosilicon hdmi phy") +Signed-off-by: Jonas Karlman +--- + drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c +index 9ca20c947283..b0ac1d3ee390 100644 +--- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c +@@ -790,8 +790,8 @@ static int inno_hdmi_phy_rk3328_clk_set_rate(struct clk_hw *hw, + RK3328_PRE_PLL_POWER_DOWN); + + /* Configure pre-pll */ +- inno_update_bits(inno, 0xa0, RK3228_PCLK_VCO_DIV_5_MASK, +- RK3228_PCLK_VCO_DIV_5(cfg->vco_div_5_en)); ++ inno_update_bits(inno, 0xa0, RK3328_PCLK_VCO_DIV_5_MASK, ++ RK3328_PCLK_VCO_DIV_5(cfg->vco_div_5_en)); + inno_write(inno, 0xa1, RK3328_PRE_PLL_PRE_DIV(cfg->prediv)); + + val = RK3328_SPREAD_SPECTRUM_MOD_DISABLE; + +From 619967c6bc6f6c81a3dabf8b2d4c0f5f3b3afc78 Mon Sep 17 00:00:00 2001 +From: Zheng Yang +Date: Wed, 8 Jan 2020 21:07:48 +0000 +Subject: [PATCH] phy/rockchip: inno-hdmi: round fractal pixclock in rk3328 + recalc_rate + +inno_hdmi_phy_rk3328_clk_recalc_rate() is returning a rate not found +in the pre pll config table when the fractal divider is used. +This can prevent proper power_on because a tmdsclock for the new rate +is not found in the pre pll config table. + +Fix this by saving and returning a rounded pixel rate that exist +in the pre pll config table. + +Fixes: 53706a116863 ("phy: add Rockchip Innosilicon hdmi phy") +Signed-off-by: Zheng Yang +Signed-off-by: Jonas Karlman +--- + drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c +index b0ac1d3ee390..093d2334e8cd 100644 +--- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c +@@ -745,10 +745,12 @@ unsigned long inno_hdmi_phy_rk3328_clk_recalc_rate(struct clk_hw *hw, + do_div(vco, (nd * (no_a == 1 ? no_b : no_a) * no_d * 2)); + } + +- inno->pixclock = vco; +- dev_dbg(inno->dev, "%s rate %lu\n", __func__, inno->pixclock); ++ inno->pixclock = DIV_ROUND_CLOSEST((unsigned long)vco, 1000) * 1000; + +- return vco; ++ dev_dbg(inno->dev, "%s rate %lu vco %llu\n", ++ __func__, inno->pixclock, vco); ++ ++ return inno->pixclock; + } + + static long inno_hdmi_phy_rk3328_clk_round_rate(struct clk_hw *hw, + +From 8fe477a61c44d9df65a1f3a7bd9a0d7b4be7760b Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 8 Jan 2020 21:07:48 +0000 +Subject: [PATCH] phy/rockchip: inno-hdmi: remove unused no_c from rk3328 + recalc_rate + +no_c is not used in any calculation, lets remove it. + +Signed-off-by: Jonas Karlman +--- + drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c +index 093d2334e8cd..06db69c8373e 100644 +--- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c +@@ -714,7 +714,7 @@ unsigned long inno_hdmi_phy_rk3328_clk_recalc_rate(struct clk_hw *hw, + { + struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw); + unsigned long frac; +- u8 nd, no_a, no_b, no_c, no_d; ++ u8 nd, no_a, no_b, no_d; + u64 vco; + u16 nf; + +@@ -737,9 +737,6 @@ unsigned long inno_hdmi_phy_rk3328_clk_recalc_rate(struct clk_hw *hw, + no_b = inno_read(inno, 0xa5) & RK3328_PRE_PLL_PCLK_DIV_B_MASK; + no_b >>= RK3328_PRE_PLL_PCLK_DIV_B_SHIFT; + no_b += 2; +- no_c = inno_read(inno, 0xa6) & RK3328_PRE_PLL_PCLK_DIV_C_MASK; +- no_c >>= RK3328_PRE_PLL_PCLK_DIV_C_SHIFT; +- no_c = 1 << no_c; + no_d = inno_read(inno, 0xa6) & RK3328_PRE_PLL_PCLK_DIV_D_MASK; + + do_div(vco, (nd * (no_a == 1 ? no_b : no_a) * no_d * 2)); + +From 428d1129cfacf119ed86954e6b21c938510ef2b2 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 8 Jan 2020 21:07:48 +0000 +Subject: [PATCH] phy/rockchip: inno-hdmi: do not power on rk3328 post pll on + reg write + +inno_write is used to configure 0xaa reg, that also hold the +POST_PLL_POWER_DOWN bit. +When POST_PLL_REFCLK_SEL_TMDS is configured the power down bit is not +taken into consideration. + +Fix this by keeping the power down bit until configuration is complete. +Also reorder the reg write order for consistency. + +Fixes: 53706a116863 ("phy: add Rockchip Innosilicon hdmi phy") +Signed-off-by: Jonas Karlman +--- + drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c +index 06db69c8373e..3a59a6da0440 100644 +--- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c +@@ -1020,9 +1020,10 @@ inno_hdmi_phy_rk3328_power_on(struct inno_hdmi_phy *inno, + + inno_write(inno, 0xac, RK3328_POST_PLL_FB_DIV_7_0(cfg->fbdiv)); + if (cfg->postdiv == 1) { +- inno_write(inno, 0xaa, RK3328_POST_PLL_REFCLK_SEL_TMDS); + inno_write(inno, 0xab, RK3328_POST_PLL_FB_DIV_8(cfg->fbdiv) | + RK3328_POST_PLL_PRE_DIV(cfg->prediv)); ++ inno_write(inno, 0xaa, RK3328_POST_PLL_REFCLK_SEL_TMDS | ++ RK3328_POST_PLL_POWER_DOWN); + } else { + v = (cfg->postdiv / 2) - 1; + v &= RK3328_POST_PLL_POST_DIV_MASK; +@@ -1030,7 +1031,8 @@ inno_hdmi_phy_rk3328_power_on(struct inno_hdmi_phy *inno, + inno_write(inno, 0xab, RK3328_POST_PLL_FB_DIV_8(cfg->fbdiv) | + RK3328_POST_PLL_PRE_DIV(cfg->prediv)); + inno_write(inno, 0xaa, RK3328_POST_PLL_POST_DIV_ENABLE | +- RK3328_POST_PLL_REFCLK_SEL_TMDS); ++ RK3328_POST_PLL_REFCLK_SEL_TMDS | ++ RK3328_POST_PLL_POWER_DOWN); + } + + for (v = 0; v < 14; v++) + +From 335bf9964e953ca56351df1c35ed4249740f548d Mon Sep 17 00:00:00 2001 +From: Huicong Xu +Date: Wed, 8 Jan 2020 21:07:49 +0000 +Subject: [PATCH] phy/rockchip: inno-hdmi: force set_rate on power_on + +Regular 8-bit and Deep Color video formats mainly differ in TMDS rate and +not in pixel clock rate. +When the hdmiphy clock is configured with the same pixel clock rate using +clk_set_rate() the clock framework do not signal the hdmi phy driver +to set_rate when switching between 8-bit and Deep Color. +This result in pre/post pll not being re-configured when switching between +regular 8-bit and Deep Color video formats. + +Fix this by calling set_rate in power_on to force pre pll re-configuration. + +Signed-off-by: Huicong Xu +Signed-off-by: Jonas Karlman +--- + drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c +index 3a59a6da0440..3719309ad0d0 100644 +--- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c +@@ -245,6 +245,7 @@ struct inno_hdmi_phy { + struct clk_hw hw; + struct clk *phyclk; + unsigned long pixclock; ++ unsigned long tmdsclock; + }; + + struct pre_pll_config { +@@ -485,6 +486,8 @@ static int inno_hdmi_phy_power_on(struct phy *phy) + + dev_dbg(inno->dev, "Inno HDMI PHY Power On\n"); + ++ inno->plat_data->clk_ops->set_rate(&inno->hw, inno->pixclock, 24000000); ++ + ret = clk_prepare_enable(inno->phyclk); + if (ret) + return ret; +@@ -509,6 +512,8 @@ static int inno_hdmi_phy_power_off(struct phy *phy) + + clk_disable_unprepare(inno->phyclk); + ++ inno->tmdsclock = 0; ++ + dev_dbg(inno->dev, "Inno HDMI PHY Power Off\n"); + + return 0; +@@ -628,6 +633,9 @@ static int inno_hdmi_phy_rk3228_clk_set_rate(struct clk_hw *hw, + dev_dbg(inno->dev, "%s rate %lu tmdsclk %lu\n", + __func__, rate, tmdsclock); + ++ if (inno->pixclock == rate && inno->tmdsclock == tmdsclock) ++ return 0; ++ + cfg = inno_hdmi_phy_get_pre_pll_cfg(inno, rate); + if (IS_ERR(cfg)) + return PTR_ERR(cfg); +@@ -670,6 +678,7 @@ static int inno_hdmi_phy_rk3228_clk_set_rate(struct clk_hw *hw, + } + + inno->pixclock = rate; ++ inno->tmdsclock = tmdsclock; + + return 0; + } +@@ -781,6 +790,9 @@ static int inno_hdmi_phy_rk3328_clk_set_rate(struct clk_hw *hw, + dev_dbg(inno->dev, "%s rate %lu tmdsclk %lu\n", + __func__, rate, tmdsclock); + ++ if (inno->pixclock == rate && inno->tmdsclock == tmdsclock) ++ return 0; ++ + cfg = inno_hdmi_phy_get_pre_pll_cfg(inno, rate); + if (IS_ERR(cfg)) + return PTR_ERR(cfg); +@@ -820,6 +832,7 @@ static int inno_hdmi_phy_rk3328_clk_set_rate(struct clk_hw *hw, + } + + inno->pixclock = rate; ++ inno->tmdsclock = tmdsclock; + + return 0; + } + +From b4a0c66750a98eea4b1ab65026cd46a4364512cb Mon Sep 17 00:00:00 2001 +From: Algea Cao +Date: Wed, 8 Jan 2020 21:07:53 +0000 +Subject: [PATCH] phy/rockchip: inno-hdmi: Support more pre-pll configuration + +Adding the following freq cfg in 8-bit and 10-bit color depth: + +{ + 40000000, 65000000, 71000000, 83500000, 85750000, + 88750000, 108000000, 119000000, 162000000 +} + +New freq has been validated by quantumdata 980. + +For some freq which can't be got by only using integer freq div, +frac freq div is needed, Such as 88.75Mhz 10-bit. But The actual +freq is different from the target freq, We must try to narrow +the gap between them. RK322X only support integer freq div. + +The VCO of pre-PLL must be more than 2Ghz, otherwise PLL may be +unlocked. + +Signed-off-by: Algea Cao +Signed-off-by: Jonas Karlman +Acked-by: Heiko Stuebner +--- + drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 74 ++++++++++++------- + 1 file changed, 49 insertions(+), 25 deletions(-) + +diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c +index 3719309ad0d0..bb8bdf5e3301 100644 +--- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c +@@ -291,32 +291,56 @@ struct inno_hdmi_phy_drv_data { + const struct phy_config *phy_cfg_table; + }; + ++/* ++ * If only using integer freq div can't get frequency we want, frac ++ * freq div is needed. For example, pclk 88.75 Mhz and tmdsclk ++ * 110.9375 Mhz must use frac div 0xF00000. The actual frequency is different ++ * from the target frequency. Such as the tmds clock 110.9375 Mhz, ++ * the actual tmds clock we get is 110.93719 Mhz. It is important ++ * to note that RK322X platforms do not support frac div. ++ */ + static const struct pre_pll_config pre_pll_cfg_table[] = { +- { 27000000, 27000000, 1, 90, 3, 2, 2, 10, 3, 3, 4, 0, 0}, +- { 27000000, 33750000, 1, 90, 1, 3, 3, 10, 3, 3, 4, 0, 0}, +- { 40000000, 40000000, 1, 80, 2, 2, 2, 12, 2, 2, 2, 0, 0}, +- { 59341000, 59341000, 1, 98, 3, 1, 2, 1, 3, 3, 4, 0, 0xE6AE6B}, +- { 59400000, 59400000, 1, 99, 3, 1, 1, 1, 3, 3, 4, 0, 0}, +- { 59341000, 74176250, 1, 98, 0, 3, 3, 1, 3, 3, 4, 0, 0xE6AE6B}, +- { 59400000, 74250000, 1, 99, 1, 2, 2, 1, 3, 3, 4, 0, 0}, +- { 74176000, 74176000, 1, 98, 1, 2, 2, 1, 2, 3, 4, 0, 0xE6AE6B}, +- { 74250000, 74250000, 1, 99, 1, 2, 2, 1, 2, 3, 4, 0, 0}, +- { 74176000, 92720000, 4, 494, 1, 2, 2, 1, 3, 3, 4, 0, 0x816817}, +- { 74250000, 92812500, 4, 495, 1, 2, 2, 1, 3, 3, 4, 0, 0}, +- {148352000, 148352000, 1, 98, 1, 1, 1, 1, 2, 2, 2, 0, 0xE6AE6B}, +- {148500000, 148500000, 1, 99, 1, 1, 1, 1, 2, 2, 2, 0, 0}, +- {148352000, 185440000, 4, 494, 0, 2, 2, 1, 3, 2, 2, 0, 0x816817}, +- {148500000, 185625000, 4, 495, 0, 2, 2, 1, 3, 2, 2, 0, 0}, +- {296703000, 296703000, 1, 98, 0, 1, 1, 1, 0, 2, 2, 0, 0xE6AE6B}, +- {297000000, 297000000, 1, 99, 0, 1, 1, 1, 0, 2, 2, 0, 0}, +- {296703000, 370878750, 4, 494, 1, 2, 0, 1, 3, 1, 1, 0, 0x816817}, +- {297000000, 371250000, 4, 495, 1, 2, 0, 1, 3, 1, 1, 0, 0}, +- {593407000, 296703500, 1, 98, 0, 1, 1, 1, 0, 2, 1, 0, 0xE6AE6B}, +- {594000000, 297000000, 1, 99, 0, 1, 1, 1, 0, 2, 1, 0, 0}, +- {593407000, 370879375, 4, 494, 1, 2, 0, 1, 3, 1, 1, 1, 0x816817}, +- {594000000, 371250000, 4, 495, 1, 2, 0, 1, 3, 1, 1, 1, 0}, +- {593407000, 593407000, 1, 98, 0, 2, 0, 1, 0, 1, 1, 0, 0xE6AE6B}, +- {594000000, 594000000, 1, 99, 0, 2, 0, 1, 0, 1, 1, 0, 0}, ++ { 27000000, 27000000, 1, 90, 3, 2, 2, 10, 3, 3, 4, 0, 0}, ++ { 27000000, 33750000, 1, 90, 1, 3, 3, 10, 3, 3, 4, 0, 0}, ++ { 40000000, 40000000, 1, 80, 2, 2, 2, 12, 2, 2, 2, 0, 0}, ++ { 40000000, 50000000, 1, 100, 2, 2, 2, 1, 0, 0, 15, 0, 0}, ++ { 59341000, 59341000, 1, 98, 3, 1, 2, 1, 3, 3, 4, 0, 0xE6AE6B}, ++ { 59400000, 59400000, 1, 99, 3, 1, 1, 1, 3, 3, 4, 0, 0}, ++ { 59341000, 74176250, 1, 98, 0, 3, 3, 1, 3, 3, 4, 0, 0xE6AE6B}, ++ { 59400000, 74250000, 1, 99, 1, 2, 2, 1, 3, 3, 4, 0, 0}, ++ { 65000000, 65000000, 1, 130, 2, 2, 2, 1, 0, 0, 12, 0, 0}, ++ { 65000000, 81250000, 3, 325, 0, 3, 3, 1, 0, 0, 10, 0, 0}, ++ { 71000000, 71000000, 3, 284, 0, 3, 3, 1, 0, 0, 8, 0, 0}, ++ { 71000000, 88750000, 3, 355, 0, 3, 3, 1, 0, 0, 10, 0, 0}, ++ { 74176000, 74176000, 1, 98, 1, 2, 2, 1, 2, 3, 4, 0, 0xE6AE6B}, ++ { 74250000, 74250000, 1, 99, 1, 2, 2, 1, 2, 3, 4, 0, 0}, ++ { 74176000, 92720000, 4, 494, 1, 2, 2, 1, 3, 3, 4, 0, 0x816817}, ++ { 74250000, 92812500, 4, 495, 1, 2, 2, 1, 3, 3, 4, 0, 0}, ++ { 83500000, 83500000, 2, 167, 2, 1, 1, 1, 0, 0, 6, 0, 0}, ++ { 83500000, 104375000, 1, 104, 2, 1, 1, 1, 1, 0, 5, 0, 0x600000}, ++ { 85750000, 85750000, 3, 343, 0, 3, 3, 1, 0, 0, 8, 0, 0}, ++ { 88750000, 88750000, 3, 355, 0, 3, 3, 1, 0, 0, 8, 0, 0}, ++ { 88750000, 110937500, 1, 110, 2, 1, 1, 1, 1, 0, 5, 0, 0xF00000}, ++ {108000000, 108000000, 1, 90, 3, 0, 0, 1, 0, 0, 5, 0, 0}, ++ {108000000, 135000000, 1, 90, 0, 2, 2, 1, 0, 0, 5, 0, 0}, ++ {119000000, 119000000, 1, 119, 2, 1, 1, 1, 0, 0, 6, 0, 0}, ++ {119000000, 148750000, 1, 99, 0, 2, 2, 1, 0, 0, 5, 0, 0x2AAAAA}, ++ {148352000, 148352000, 1, 98, 1, 1, 1, 1, 2, 2, 2, 0, 0xE6AE6B}, ++ {148500000, 148500000, 1, 99, 1, 1, 1, 1, 2, 2, 2, 0, 0}, ++ {148352000, 185440000, 4, 494, 0, 2, 2, 1, 3, 2, 2, 0, 0x816817}, ++ {148500000, 185625000, 4, 495, 0, 2, 2, 1, 3, 2, 2, 0, 0}, ++ {162000000, 162000000, 1, 108, 0, 2, 2, 1, 0, 0, 4, 0, 0}, ++ {162000000, 202500000, 1, 135, 0, 2, 2, 1, 0, 0, 5, 0, 0}, ++ {296703000, 296703000, 1, 98, 0, 1, 1, 1, 0, 2, 2, 0, 0xE6AE6B}, ++ {297000000, 297000000, 1, 99, 0, 1, 1, 1, 0, 2, 2, 0, 0}, ++ {296703000, 370878750, 4, 494, 1, 2, 0, 1, 3, 1, 1, 0, 0x816817}, ++ {297000000, 371250000, 4, 495, 1, 2, 0, 1, 3, 1, 1, 0, 0}, ++ {593407000, 296703500, 1, 98, 0, 1, 1, 1, 0, 2, 1, 0, 0xE6AE6B}, ++ {594000000, 297000000, 1, 99, 0, 1, 1, 1, 0, 2, 1, 0, 0}, ++ {593407000, 370879375, 4, 494, 1, 2, 0, 1, 3, 1, 1, 1, 0x816817}, ++ {594000000, 371250000, 4, 495, 1, 2, 0, 1, 3, 1, 1, 1, 0}, ++ {593407000, 593407000, 1, 98, 0, 2, 0, 1, 0, 1, 1, 0, 0xE6AE6B}, ++ {594000000, 594000000, 1, 99, 0, 2, 0, 1, 0, 1, 1, 0, 0}, + { /* sentinel */ } + }; + + +From ddc63db13e520a56bf1afbe6c5ebd3d9935f282f Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 3 May 2020 16:51:31 +0000 +Subject: [PATCH] drm/rockchip: vop: filter modes outside 0.5% pixel clock + tolerance + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 33 +++++++++++++++++++++ + 1 file changed, 33 insertions(+) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +index c80f7d9fd13f..6cbdb4672a4b 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +@@ -1142,6 +1142,38 @@ static void vop_crtc_disable_vblank(struct drm_crtc *crtc) + spin_unlock_irqrestore(&vop->irq_lock, flags); + } + ++/* ++ * The VESA DMT standard specifies a 0.5% pixel clock frequency tolerance. ++ * The CVT spec reuses that tolerance in its examples. ++ */ ++#define CLOCK_TOLERANCE_PER_MILLE 5 ++ ++static enum drm_mode_status vop_crtc_mode_valid(struct drm_crtc *crtc, ++ const struct drm_display_mode *mode) ++{ ++ struct vop *vop = to_vop(crtc); ++ struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state); ++ long rounded_rate; ++ long lowest, highest; ++ ++ if (s->output_type != DRM_MODE_CONNECTOR_HDMIA) ++ return MODE_OK; ++ ++ rounded_rate = clk_round_rate(vop->dclk, mode->clock * 1000 + 999); ++ if (rounded_rate < 0) ++ return MODE_NOCLOCK; ++ ++ lowest = mode->clock * (1000 - CLOCK_TOLERANCE_PER_MILLE); ++ if (rounded_rate < lowest) ++ return MODE_CLOCK_LOW; ++ ++ highest = mode->clock * (1000 + CLOCK_TOLERANCE_PER_MILLE); ++ if (rounded_rate > highest) ++ return MODE_CLOCK_HIGH; ++ ++ return MODE_OK; ++} ++ + static bool vop_crtc_mode_fixup(struct drm_crtc *crtc, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +@@ -1512,6 +1544,7 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc, + } + + static const struct drm_crtc_helper_funcs vop_crtc_helper_funcs = { ++ .mode_valid = vop_crtc_mode_valid, + .mode_fixup = vop_crtc_mode_fixup, + .atomic_check = vop_crtc_atomic_check, + .atomic_begin = vop_crtc_atomic_begin, + +From 204bb448d3adbe5597d94ddf15ab7fa927931685 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 20 Jul 2020 11:46:16 +0000 +Subject: [PATCH] WIP: drm/rockchip: vop: max_output + +--- + drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 5 +++++ + drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 6 ++++++ + drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 7 +++++++ + 3 files changed, 18 insertions(+) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +index 6cbdb4672a4b..106b38ea12df 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +@@ -1152,6 +1152,7 @@ static enum drm_mode_status vop_crtc_mode_valid(struct drm_crtc *crtc, + const struct drm_display_mode *mode) + { + struct vop *vop = to_vop(crtc); ++ const struct vop_rect *max_output = &vop->data->max_output; + struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state); + long rounded_rate; + long lowest, highest; +@@ -1171,6 +1172,10 @@ static enum drm_mode_status vop_crtc_mode_valid(struct drm_crtc *crtc, + if (rounded_rate > highest) + return MODE_CLOCK_HIGH; + ++ if (max_output->width && max_output->height) ++ return drm_mode_validate_size(mode, max_output->width, ++ max_output->height); ++ + return MODE_OK; + } + +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +index 4a2099cb582e..1516231bbf93 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +@@ -185,6 +185,11 @@ struct vop_win_data { + enum drm_plane_type type; + }; + ++struct vop_rect { ++ int width; ++ int height; ++}; ++ + struct vop_data { + uint32_t version; + const struct vop_intr *intr; +@@ -197,6 +202,7 @@ struct vop_data { + const struct vop_win_data *win; + unsigned int win_size; + unsigned int lut_size; ++ struct vop_rect max_output; + + #define VOP_FEATURE_OUTPUT_RGB10 BIT(0) + #define VOP_FEATURE_INTERNAL_RGB BIT(1) +diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +index 80053d91a301..57c36e9207c1 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c ++++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +@@ -682,6 +682,7 @@ static const struct vop_intr rk3288_vop_intr = { + static const struct vop_data rk3288_vop = { + .version = VOP_VERSION(3, 1), + .feature = VOP_FEATURE_OUTPUT_RGB10, ++ .max_output = { 3840, 2160 }, + .intr = &rk3288_vop_intr, + .common = &rk3288_common, + .modeset = &rk3288_modeset, +@@ -782,6 +783,7 @@ static const struct vop_misc rk3368_misc = { + + static const struct vop_data rk3368_vop = { + .version = VOP_VERSION(3, 2), ++ .max_output = { 4096, 2160 }, + .intr = &rk3368_vop_intr, + .common = &rk3288_common, + .modeset = &rk3288_modeset, +@@ -803,6 +805,7 @@ static const struct vop_intr rk3366_vop_intr = { + + static const struct vop_data rk3366_vop = { + .version = VOP_VERSION(3, 4), ++ .max_output = { 4096, 2160 }, + .intr = &rk3366_vop_intr, + .common = &rk3288_common, + .modeset = &rk3288_modeset, +@@ -909,6 +912,7 @@ static const struct vop_afbc rk3399_vop_afbc = { + static const struct vop_data rk3399_vop_big = { + .version = VOP_VERSION(3, 5), + .feature = VOP_FEATURE_OUTPUT_RGB10, ++ .max_output = { 4096, 2160 }, + .intr = &rk3366_vop_intr, + .common = &rk3288_common, + .modeset = &rk3288_modeset, +@@ -935,6 +939,7 @@ static const struct vop_win_yuv2yuv_data rk3399_vop_lit_win_yuv2yuv_data[] = { + + static const struct vop_data rk3399_vop_lit = { + .version = VOP_VERSION(3, 6), ++ .max_output = { 2560, 1600 }, + .intr = &rk3366_vop_intr, + .common = &rk3288_common, + .modeset = &rk3288_modeset, +@@ -955,6 +960,7 @@ static const struct vop_win_data rk3228_vop_win_data[] = { + static const struct vop_data rk3228_vop = { + .version = VOP_VERSION(3, 7), + .feature = VOP_FEATURE_OUTPUT_RGB10, ++ .max_output = { 4096, 2160 }, + .intr = &rk3366_vop_intr, + .common = &rk3288_common, + .modeset = &rk3288_modeset, +@@ -1026,6 +1032,7 @@ static const struct vop_win_data rk3328_vop_win_data[] = { + static const struct vop_data rk3328_vop = { + .version = VOP_VERSION(3, 8), + .feature = VOP_FEATURE_OUTPUT_RGB10, ++ .max_output = { 4096, 2160 }, + .intr = &rk3328_vop_intr, + .common = &rk3328_common, + .modeset = &rk3328_modeset, + +From 77dae737d6b7ab099707e746311bf683729b662b Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 8 Jan 2020 21:07:51 +0000 +Subject: [PATCH] arm64: dts: rockchip: increase vop clock rate on rk3328 + +The VOP on RK3328 needs to run at higher rate in order to +produce a proper 3840x2160 signal. + +Signed-off-by: Jonas Karlman +--- + arch/arm64/boot/dts/rockchip/rk3328.dtsi | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +index bbdb19a3e85d..6547e2b4b617 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +@@ -802,8 +802,8 @@ cru: clock-controller@ff440000 { + <0>, <24000000>, + <24000000>, <24000000>, + <15000000>, <15000000>, +- <100000000>, <100000000>, +- <100000000>, <100000000>, ++ <300000000>, <100000000>, ++ <400000000>, <100000000>, + <50000000>, <100000000>, + <100000000>, <100000000>, + <50000000>, <50000000>, + +From 8312c58922e497f6d26c0845597bd23dbeba95d7 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 8 Jan 2020 21:07:49 +0000 +Subject: [PATCH] drm/rockchip: dw-hdmi: allow high tmds bit rates + +Prepare support for High TMDS Bit Rates used by HDMI2.0 display modes. + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index 23de359a1dec..cdf953850873 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -317,6 +317,8 @@ static int dw_hdmi_rockchip_genphy_init(struct dw_hdmi *dw_hdmi, void *data, + { + struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; + ++ dw_hdmi_set_high_tmds_clock_ratio(dw_hdmi, display); ++ + return phy_power_on(hdmi->phy); + } + + +From 1638ed24fb959926267f59a590e61b04c1050b96 Mon Sep 17 00:00:00 2001 +From: Yakir Yang +Date: Mon, 11 Jul 2016 19:05:39 +0800 +Subject: [PATCH] drm/rockchip: dw_hdmi: adjust cklvl & txlvl for RF/EMI + +Dut to the high HDMI signal voltage driver, Mickey have meet +a serious RF/EMI problem, so we decided to reduce HDMI signal +voltage to a proper value. + +The default params for phy is cklvl = 20 & txlvl = 13 (RF/EMI failed) + ck: lvl = 13, term=100, vlo = 2.71, vhi=3.14, vswing = 0.43 + tx: lvl = 20, term=100, vlo = 2.81, vhi=3.16, vswing = 0.35 + +1. We decided to reduce voltage value to lower, but VSwing still +keep high, RF/EMI have been improved but still failed. + ck: lvl = 6, term=100, vlo = 2.61, vhi=3.11, vswing = 0.50 + tx: lvl = 6, term=100, vlo = 2.61, vhi=3.11, vswing = 0.50 + +2. We try to keep voltage value and vswing both lower, then RF/EMI +test all passed ;) + ck: lvl = 11, term= 66, vlo = 2.68, vhi=3.09, vswing = 0.40 + tx: lvl = 11, term= 66, vlo = 2.68, vhi=3.09, vswing = 0.40 +When we back to run HDMI different test and single-end test, we see +different test passed, but signle-end test failed. The oscilloscope +show that simgle-end clock's VL value is 1.78v (which remind LowLimit +should not lower then 2.6v). + +3. That's to say there are some different between PHY document and +measure value. And according to experiment 2 results, we need to +higher clock voltage and lower data voltage, then we can keep RF/EMI +satisfied and single-end & differen test passed. + ck: lvl = 9, term=100, vlo = 2.65, vhi=3.12, vswing = 0.47 + tx: lvl = 16, term=100, vlo = 2.75, vhi=3.15, vswing = 0.39 + +Signed-off-by: Yakir Yang +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index cdf953850873..4652c0e0dcd6 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -181,7 +181,7 @@ static const struct dw_hdmi_curr_ctrl rockchip_cur_ctr[] = { + static const struct dw_hdmi_phy_config rockchip_phy_config[] = { + /*pixelclk symbol term vlev*/ + { 74250000, 0x8009, 0x0004, 0x0272}, +- { 148500000, 0x802b, 0x0004, 0x028d}, ++ { 165000000, 0x802b, 0x0004, 0x0209}, + { 297000000, 0x8039, 0x0005, 0x028d}, + { ~0UL, 0x0000, 0x0000, 0x0000} + }; + +From f60a4b188ee2e3bfcc44dd8d1fa3b5fa19f90720 Mon Sep 17 00:00:00 2001 +From: Nickey Yang +Date: Mon, 13 Feb 2017 15:40:29 +0800 +Subject: [PATCH] drm/rockchip: dw_hdmi: add phy_config for 594Mhz pixel clock + +Add phy_config for 594Mhz pixel clock used for 4K@60hz + +Signed-off-by: Nickey Yang +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index 4652c0e0dcd6..10c3dc521cbd 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -183,6 +183,7 @@ static const struct dw_hdmi_phy_config rockchip_phy_config[] = { + { 74250000, 0x8009, 0x0004, 0x0272}, + { 165000000, 0x802b, 0x0004, 0x0209}, + { 297000000, 0x8039, 0x0005, 0x028d}, ++ { 594000000, 0x8039, 0x0000, 0x019d}, + { ~0UL, 0x0000, 0x0000, 0x0000} + }; + + +From 6835093bddcc3634ba0ebd98deb72ab59d916f9c Mon Sep 17 00:00:00 2001 +From: Douglas Anderson +Date: Mon, 11 Jul 2016 19:05:36 +0800 +Subject: [PATCH] drm/rockchip: dw_hdmi: Set cur_ctr to 0 always + +Jitter was improved by lowering the MPLL bandwidth to account for high +frequency noise in the rk3288 PLL. In each case MPLL bandwidth was +lowered only enough to get us a comfortable margin. We believe that +lowering the bandwidth like this is safe given sufficient testing. + +Signed-off-by: Douglas Anderson +Signed-off-by: Yakir Yang +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 16 ++-------------- + 1 file changed, 2 insertions(+), 14 deletions(-) + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index 10c3dc521cbd..cc7675638e4f 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -160,20 +160,8 @@ static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = { + static const struct dw_hdmi_curr_ctrl rockchip_cur_ctr[] = { + /* pixelclk bpp8 bpp10 bpp12 */ + { +- 40000000, { 0x0018, 0x0018, 0x0018 }, +- }, { +- 65000000, { 0x0028, 0x0028, 0x0028 }, +- }, { +- 66000000, { 0x0038, 0x0038, 0x0038 }, +- }, { +- 74250000, { 0x0028, 0x0038, 0x0038 }, +- }, { +- 83500000, { 0x0028, 0x0038, 0x0038 }, +- }, { +- 146250000, { 0x0038, 0x0038, 0x0038 }, +- }, { +- 148500000, { 0x0000, 0x0038, 0x0038 }, +- }, { ++ 600000000, { 0x0000, 0x0000, 0x0000 }, ++ }, { + ~0UL, { 0x0000, 0x0000, 0x0000}, + } + }; + +From da024b1ee785c2443d32a955321dbae7e5b280d3 Mon Sep 17 00:00:00 2001 +From: Douglas Anderson +Date: Mon, 11 Jul 2016 19:05:42 +0800 +Subject: [PATCH] drm/rockchip: dw_hdmi: Use auto-generated tables + +The previous tables for mpll_cfg and curr_ctrl were created using the +20-pages of example settings provided by the PHY vendor. Those +example settings weren't particularly dense, so there were places +where we were guessing what the settings would be for 10-bit and +12-bit (not that we use those anyway). It was also always a lot of +extra work every time we wanted to add a new clock rate since we had +to cross-reference several tables. + +In I've gone through the work to figure +out how to generate this table automatically. Let's now use the +automatically generated table and then we'll never need to look at it +again. + +We only support 8-bit mode right now and only support a small number +of clock rates and and I've verified that the only 8-bit rate that was +affected was 148.5. That mode appears to have been wrong in the old +table. + +Signed-off-by: Douglas Anderson +Signed-off-by: Yakir Yang +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 130 +++++++++++--------- + 1 file changed, 69 insertions(+), 61 deletions(-) + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index cc7675638e4f..c4c158106ca4 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -79,80 +79,88 @@ struct rockchip_hdmi { + + static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = { + { +- 27000000, { +- { 0x00b3, 0x0000}, +- { 0x2153, 0x0000}, +- { 0x40f3, 0x0000} ++ 30666000, { ++ { 0x00b3, 0x0000 }, ++ { 0x2153, 0x0000 }, ++ { 0x40f3, 0x0000 }, + }, +- }, { +- 36000000, { +- { 0x00b3, 0x0000}, +- { 0x2153, 0x0000}, +- { 0x40f3, 0x0000} ++ }, { ++ 36800000, { ++ { 0x00b3, 0x0000 }, ++ { 0x2153, 0x0000 }, ++ { 0x40a2, 0x0001 }, + }, +- }, { +- 40000000, { +- { 0x00b3, 0x0000}, +- { 0x2153, 0x0000}, +- { 0x40f3, 0x0000} ++ }, { ++ 46000000, { ++ { 0x00b3, 0x0000 }, ++ { 0x2142, 0x0001 }, ++ { 0x40a2, 0x0001 }, + }, +- }, { +- 54000000, { +- { 0x0072, 0x0001}, +- { 0x2142, 0x0001}, +- { 0x40a2, 0x0001}, ++ }, { ++ 61333000, { ++ { 0x0072, 0x0001 }, ++ { 0x2142, 0x0001 }, ++ { 0x40a2, 0x0001 }, + }, +- }, { +- 65000000, { +- { 0x0072, 0x0001}, +- { 0x2142, 0x0001}, +- { 0x40a2, 0x0001}, ++ }, { ++ 73600000, { ++ { 0x0072, 0x0001 }, ++ { 0x2142, 0x0001 }, ++ { 0x4061, 0x0002 }, + }, +- }, { +- 66000000, { +- { 0x013e, 0x0003}, +- { 0x217e, 0x0002}, +- { 0x4061, 0x0002} ++ }, { ++ 92000000, { ++ { 0x0072, 0x0001 }, ++ { 0x2145, 0x0002 }, ++ { 0x4061, 0x0002 }, ++ }, ++ }, { ++ 122666000, { ++ { 0x0051, 0x0002 }, ++ { 0x2145, 0x0002 }, ++ { 0x4061, 0x0002 }, + }, +- }, { +- 74250000, { +- { 0x0072, 0x0001}, +- { 0x2145, 0x0002}, +- { 0x4061, 0x0002} ++ }, { ++ 147200000, { ++ { 0x0051, 0x0002 }, ++ { 0x2145, 0x0002 }, ++ { 0x4064, 0x0003 }, + }, +- }, { +- 83500000, { +- { 0x0072, 0x0001}, ++ }, { ++ 184000000, { ++ { 0x0051, 0x0002 }, ++ { 0x214c, 0x0003 }, ++ { 0x4064, 0x0003 }, + }, +- }, { +- 108000000, { +- { 0x0051, 0x0002}, +- { 0x2145, 0x0002}, +- { 0x4061, 0x0002} ++ }, { ++ 226666000, { ++ { 0x0040, 0x0003 }, ++ { 0x214c, 0x0003 }, ++ { 0x4064, 0x0003 }, + }, +- }, { +- 106500000, { +- { 0x0051, 0x0002}, +- { 0x2145, 0x0002}, +- { 0x4061, 0x0002} ++ }, { ++ 272000000, { ++ { 0x0040, 0x0003 }, ++ { 0x214c, 0x0003 }, ++ { 0x5a64, 0x0003 }, + }, +- }, { +- 146250000, { +- { 0x0051, 0x0002}, +- { 0x2145, 0x0002}, +- { 0x4061, 0x0002} ++ }, { ++ 340000000, { ++ { 0x0040, 0x0003 }, ++ { 0x3b4c, 0x0003 }, ++ { 0x5a64, 0x0003 }, + }, +- }, { +- 148500000, { +- { 0x0051, 0x0003}, +- { 0x214c, 0x0003}, +- { 0x4064, 0x0003} ++ }, { ++ 600000000, { ++ { 0x1a40, 0x0003 }, ++ { 0x3b4c, 0x0003 }, ++ { 0x5a64, 0x0003 }, + }, +- }, { ++ }, { + ~0UL, { +- { 0x00a0, 0x000a }, +- { 0x2001, 0x000f }, +- { 0x4002, 0x000f }, ++ { 0x0000, 0x0000 }, ++ { 0x0000, 0x0000 }, ++ { 0x0000, 0x0000 }, + }, + } + }; + +From 45e1a78887ebd640f8518afc1cfd5b2f2beb3ba4 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 8 Jan 2020 21:07:52 +0000 +Subject: [PATCH] drm/rockchip: dw-hdmi: limit tmds to 340mhz + +RK3228/RK3328 does not provide a stable hdmi signal at TMDS rates +above 371.25MHz (340MHz pixel clock). + +Limit the pixel clock rate to 340MHz to provide a stable signal. +Also limit the pixel clock to the display reported max tmds clock. + +This also enables use of pixel clocks up to 340MHz on RK3288/RK3399. + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 16 ++++------------ + 1 file changed, 4 insertions(+), 12 deletions(-) + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index c4c158106ca4..b62d8f4fc9a8 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -221,19 +221,11 @@ dw_hdmi_rockchip_mode_valid(struct dw_hdmi *hdmi, void *data, + const struct drm_display_info *info, + const struct drm_display_mode *mode) + { +- const struct dw_hdmi_mpll_config *mpll_cfg = rockchip_mpll_cfg; +- int pclk = mode->clock * 1000; +- bool valid = false; +- int i; +- +- for (i = 0; mpll_cfg[i].mpixelclock != (~0UL); i++) { +- if (pclk == mpll_cfg[i].mpixelclock) { +- valid = true; +- break; +- } +- } ++ if (mode->clock > 340000 || ++ (info->max_tmds_clock && mode->clock > info->max_tmds_clock)) ++ return MODE_CLOCK_HIGH; + +- return (valid) ? MODE_OK : MODE_BAD; ++ return MODE_OK; + } + + static void dw_hdmi_rockchip_encoder_disable(struct drm_encoder *encoder) + +From 13fdba7d97013c909f5574dea1d006ae8380de82 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 3 May 2020 22:36:23 +0000 +Subject: [PATCH] drm/rockchip: dw-hdmi: limit resolution to 3840x2160 + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index b62d8f4fc9a8..6f7641fbe6cc 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -225,7 +225,7 @@ dw_hdmi_rockchip_mode_valid(struct dw_hdmi *hdmi, void *data, + (info->max_tmds_clock && mode->clock > info->max_tmds_clock)) + return MODE_CLOCK_HIGH; + +- return MODE_OK; ++ return drm_mode_validate_size(mode, 3840, 2160); + } + + static void dw_hdmi_rockchip_encoder_disable(struct drm_encoder *encoder) + +From af4d3cc6fbed0adca1b20bf25929b37c980c8b96 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 8 Jan 2020 21:07:52 +0000 +Subject: [PATCH] drm/rockchip: dw-hdmi: remove unused plat_data on + rk3228/rk3328 + +mpll_cfg/cur_ctr/phy_config is not used when phy_force_vendor is true, +lets remove them. + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index 6f7641fbe6cc..cc20a83fa9b8 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -396,9 +396,6 @@ static struct rockchip_hdmi_chip_data rk3228_chip_data = { + + static const struct dw_hdmi_plat_data rk3228_hdmi_drv_data = { + .mode_valid = dw_hdmi_rockchip_mode_valid, +- .mpll_cfg = rockchip_mpll_cfg, +- .cur_ctr = rockchip_cur_ctr, +- .phy_config = rockchip_phy_config, + .phy_data = &rk3228_chip_data, + .phy_ops = &rk3228_hdmi_phy_ops, + .phy_name = "inno_dw_hdmi_phy2", +@@ -433,9 +430,6 @@ static struct rockchip_hdmi_chip_data rk3328_chip_data = { + + static const struct dw_hdmi_plat_data rk3328_hdmi_drv_data = { + .mode_valid = dw_hdmi_rockchip_mode_valid, +- .mpll_cfg = rockchip_mpll_cfg, +- .cur_ctr = rockchip_cur_ctr, +- .phy_config = rockchip_phy_config, + .phy_data = &rk3328_chip_data, + .phy_ops = &rk3328_hdmi_phy_ops, + .phy_name = "inno_dw_hdmi_phy2", + +From 8b696168a0ff4acd7b1add7ea689a51f9259f294 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 8 Jan 2020 21:07:50 +0000 +Subject: [PATCH] clk: rockchip: set parent rate for DCLK_VOP clock on rk3228 + +Signed-off-by: Jonas Karlman +--- + drivers/clk/rockchip/clk-rk3228.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c +index d7243c09cc84..dd414c8255e3 100644 +--- a/drivers/clk/rockchip/clk-rk3228.c ++++ b/drivers/clk/rockchip/clk-rk3228.c +@@ -408,7 +408,7 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + RK2928_CLKSEL_CON(29), 0, 3, DFLAGS), + DIV(0, "sclk_vop_pre", "sclk_vop_src", 0, + RK2928_CLKSEL_CON(27), 8, 8, DFLAGS), +- MUX(DCLK_VOP, "dclk_vop", mux_dclk_vop_p, 0, ++ MUX(DCLK_VOP, "dclk_vop", mux_dclk_vop_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + RK2928_CLKSEL_CON(27), 1, 1, MFLAGS), + + FACTOR(0, "xin12m", "xin24m", 0, 1, 2), + +From 41fdeaa849dcebfd9a9c9e5d3d48fc146dc1e789 Mon Sep 17 00:00:00 2001 +From: Nickey Yang +Date: Mon, 17 Jul 2017 16:35:34 +0800 +Subject: [PATCH] HACK: clk: rockchip: rk3288: dedicate npll for vopb and hdmi + use + +MINIARM: set npll be used for hdmi only + +Signed-off-by: Nickey Yang +Signed-off-by: Jonas Karlman +--- + arch/arm/boot/dts/rk3288.dtsi | 2 ++ + drivers/clk/rockchip/clk-rk3288.c | 4 ++-- + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi +index 68d5a58cfe88..a376dea3bb1b 100644 +--- a/arch/arm/boot/dts/rk3288.dtsi ++++ b/arch/arm/boot/dts/rk3288.dtsi +@@ -1046,6 +1046,8 @@ vopb: vop@ff930000 { + resets = <&cru SRST_LCDC0_AXI>, <&cru SRST_LCDC0_AHB>, <&cru SRST_LCDC0_DCLK>; + reset-names = "axi", "ahb", "dclk"; + iommus = <&vopb_mmu>; ++ assigned-clocks = <&cru DCLK_VOP0>; ++ assigned-clock-parents = <&cru PLL_NPLL>; + status = "disabled"; + + vopb_out: port { +diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c +index 93c794695c46..db6c8bbb35f4 100644 +--- a/drivers/clk/rockchip/clk-rk3288.c ++++ b/drivers/clk/rockchip/clk-rk3288.c +@@ -231,7 +231,7 @@ static struct rockchip_pll_clock rk3288_pll_clks[] __initdata = { + [gpll] = PLL(pll_rk3066, PLL_GPLL, "gpll", mux_pll_p, 0, RK3288_PLL_CON(12), + RK3288_MODE_CON, 12, 8, ROCKCHIP_PLL_SYNC_RATE, rk3288_pll_rates), + [npll] = PLL(pll_rk3066, PLL_NPLL, "npll", mux_pll_p, 0, RK3288_PLL_CON(16), +- RK3288_MODE_CON, 14, 9, ROCKCHIP_PLL_SYNC_RATE, rk3288_pll_rates), ++ RK3288_MODE_CON, 14, 9, 0, rk3288_pll_rates), + }; + + static struct clk_div_table div_hclk_cpu_t[] = { +@@ -441,7 +441,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { + RK3288_CLKSEL_CON(30), 14, 2, MFLAGS, 8, 5, DFLAGS, + RK3288_CLKGATE_CON(3), 4, GFLAGS), + +- COMPOSITE(DCLK_VOP0, "dclk_vop0", mux_pll_src_cpll_gpll_npll_p, 0, ++ COMPOSITE(DCLK_VOP0, "dclk_vop0", mux_pll_src_cpll_gpll_npll_p, CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT, + RK3288_CLKSEL_CON(27), 0, 2, MFLAGS, 8, 8, DFLAGS, + RK3288_CLKGATE_CON(3), 1, GFLAGS), + COMPOSITE(DCLK_VOP1, "dclk_vop1", mux_pll_src_cpll_gpll_npll_p, 0, + +From 0a33b20a1a890158d704b8a2cc759036952a09e2 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 4 Aug 2018 14:51:14 +0200 +Subject: [PATCH] HACK: clk: rockchip: rk3288: use npll table to to improve + HDMI compatibility + +Based on https://github.com/TinkerBoard/debian_kernel/commit/3d90870530b8a2901681f7b7fa598ee7381e49f3 + +Signed-off-by: Jonas Karlman +--- + drivers/clk/rockchip/clk-rk3288.c | 23 ++++++++++++++++++++++- + 1 file changed, 22 insertions(+), 1 deletion(-) + +diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c +index db6c8bbb35f4..426309f5dd44 100644 +--- a/drivers/clk/rockchip/clk-rk3288.c ++++ b/drivers/clk/rockchip/clk-rk3288.c +@@ -121,6 +121,27 @@ static struct rockchip_pll_rate_table rk3288_pll_rates[] = { + { /* sentinel */ }, + }; + ++static struct rockchip_pll_rate_table rk3288_npll_rates[] = { ++ RK3066_PLL_RATE_NB(594000000, 1, 99, 4, 32), ++ RK3066_PLL_RATE_NB(585000000, 6, 585, 4, 32), ++ RK3066_PLL_RATE_NB(432000000, 3, 216, 4, 32), ++ RK3066_PLL_RATE_NB(426000000, 3, 213, 4, 32), ++ RK3066_PLL_RATE_NB(400000000, 1, 100, 6, 32), ++ RK3066_PLL_RATE_NB(342000000, 3, 171, 4, 32), ++ RK3066_PLL_RATE_NB(297000000, 2, 198, 8, 16), ++ RK3066_PLL_RATE_NB(270000000, 1, 135, 12, 32), ++ RK3066_PLL_RATE_NB(260000000, 1, 130, 12, 32), ++ RK3066_PLL_RATE_NB(148500000, 1, 99, 16, 32), ++ RK3066_PLL_RATE(148352000, 13, 1125, 14), ++ RK3066_PLL_RATE_NB(146250000, 6, 585, 16, 32), ++ RK3066_PLL_RATE_NB(108000000, 1, 54, 12, 32), ++ RK3066_PLL_RATE_NB(106500000, 4, 213, 12, 32), ++ RK3066_PLL_RATE_NB(85500000, 4, 171, 12, 32), ++ RK3066_PLL_RATE_NB(74250000, 4, 198, 16, 32), ++ RK3066_PLL_RATE(74176000, 26, 1125, 14), ++ { /* sentinel */ }, ++}; ++ + #define RK3288_DIV_ACLK_CORE_M0_MASK 0xf + #define RK3288_DIV_ACLK_CORE_M0_SHIFT 0 + #define RK3288_DIV_ACLK_CORE_MP_MASK 0xf +@@ -231,7 +252,7 @@ static struct rockchip_pll_clock rk3288_pll_clks[] __initdata = { + [gpll] = PLL(pll_rk3066, PLL_GPLL, "gpll", mux_pll_p, 0, RK3288_PLL_CON(12), + RK3288_MODE_CON, 12, 8, ROCKCHIP_PLL_SYNC_RATE, rk3288_pll_rates), + [npll] = PLL(pll_rk3066, PLL_NPLL, "npll", mux_pll_p, 0, RK3288_PLL_CON(16), +- RK3288_MODE_CON, 14, 9, 0, rk3288_pll_rates), ++ RK3288_MODE_CON, 14, 9, 0, rk3288_npll_rates), + }; + + static struct clk_div_table div_hclk_cpu_t[] = { + +From 5c8dac1f946b2a4f2ec3e605a221d5cba56ee59f Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 28 Oct 2018 21:43:01 +0100 +Subject: [PATCH] HACK: clk: rockchip: rk3288: add more npll clocks + +Fixes 2560x1440@60Hz, 1600x1200@60Hz, 1920x1200@60Hz, 1680x1050@60Hz and 1440x900@60Hz modes on my monitor + +Signed-off-by: Jonas Karlman +--- + drivers/clk/rockchip/clk-rk3288.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c +index 426309f5dd44..b3247a3a7290 100644 +--- a/drivers/clk/rockchip/clk-rk3288.c ++++ b/drivers/clk/rockchip/clk-rk3288.c +@@ -127,18 +127,34 @@ static struct rockchip_pll_rate_table rk3288_npll_rates[] = { + RK3066_PLL_RATE_NB(432000000, 3, 216, 4, 32), + RK3066_PLL_RATE_NB(426000000, 3, 213, 4, 32), + RK3066_PLL_RATE_NB(400000000, 1, 100, 6, 32), ++ RK3066_PLL_RATE(348500000, 8, 697, 6), + RK3066_PLL_RATE_NB(342000000, 3, 171, 4, 32), + RK3066_PLL_RATE_NB(297000000, 2, 198, 8, 16), + RK3066_PLL_RATE_NB(270000000, 1, 135, 12, 32), + RK3066_PLL_RATE_NB(260000000, 1, 130, 12, 32), ++ RK3066_PLL_RATE(241500000, 2, 161, 8), ++ RK3066_PLL_RATE(162000000, 1, 81, 12), ++ RK3066_PLL_RATE(154000000, 6, 539, 14), + RK3066_PLL_RATE_NB(148500000, 1, 99, 16, 32), + RK3066_PLL_RATE(148352000, 13, 1125, 14), + RK3066_PLL_RATE_NB(146250000, 6, 585, 16, 32), ++ RK3066_PLL_RATE(121750000, 6, 487, 16), ++ RK3066_PLL_RATE(119000000, 3, 238, 16), + RK3066_PLL_RATE_NB(108000000, 1, 54, 12, 32), + RK3066_PLL_RATE_NB(106500000, 4, 213, 12, 32), ++ RK3066_PLL_RATE(101000000, 3, 202, 16), ++ RK3066_PLL_RATE(88750000, 6, 355, 16), + RK3066_PLL_RATE_NB(85500000, 4, 171, 12, 32), ++ RK3066_PLL_RATE(83500000, 3, 167, 16), ++ RK3066_PLL_RATE(79500000, 1, 53, 16), + RK3066_PLL_RATE_NB(74250000, 4, 198, 16, 32), + RK3066_PLL_RATE(74176000, 26, 1125, 14), ++ RK3066_PLL_RATE(72000000, 1, 48, 16), ++ RK3066_PLL_RATE(71000000, 3, 142, 16), ++ RK3066_PLL_RATE(68250000, 2, 91, 16), ++ RK3066_PLL_RATE(65000000, 3, 130, 16), ++ RK3066_PLL_RATE(40000000, 3, 80, 16), ++ RK3066_PLL_RATE(33750000, 2, 45, 16), + { /* sentinel */ }, + }; + + +From bcdd0b34aa22e3bf3d5750d003267cc072fed5db Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 25 May 2020 20:36:45 +0000 +Subject: [PATCH] HACK: clk: rockchip: rk3399: dedicate vpll for vopb and hdmi + use + +Signed-off-by: Jonas Karlman +--- + drivers/clk/rockchip/clk-rk3399.c | 32 +++++++++++++++++++++++++------ + 1 file changed, 26 insertions(+), 6 deletions(-) + +diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c +index ce1d2446f142..f75df0afa2bd 100644 +--- a/drivers/clk/rockchip/clk-rk3399.c ++++ b/drivers/clk/rockchip/clk-rk3399.c +@@ -103,6 +103,25 @@ static struct rockchip_pll_rate_table rk3399_pll_rates[] = { + { /* sentinel */ }, + }; + ++static struct rockchip_pll_rate_table rk3399_vpll_rates[] = { ++ /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */ ++ RK3036_PLL_RATE( 594000000, 1, 123, 5, 1, 0, 12582912), /* vco = 2970000000 */ ++ RK3036_PLL_RATE( 593406592, 1, 123, 5, 1, 0, 10508804), /* vco = 2967032965 */ ++ RK3036_PLL_RATE( 297000000, 1, 123, 5, 2, 0, 12582912), /* vco = 2970000000 */ ++ RK3036_PLL_RATE( 296703296, 1, 123, 5, 2, 0, 10508807), /* vco = 2967032970 */ ++ RK3036_PLL_RATE( 148500000, 1, 129, 7, 3, 0, 15728640), /* vco = 3118500000 */ ++ RK3036_PLL_RATE( 148351648, 1, 123, 5, 4, 0, 10508800), /* vco = 2967032960 */ ++ RK3036_PLL_RATE( 106500000, 1, 124, 7, 4, 0, 4194304), /* vco = 2982000000 */ ++ RK3036_PLL_RATE( 74250000, 1, 129, 7, 6, 0, 15728640), /* vco = 3118500000 */ ++ RK3036_PLL_RATE( 74175824, 1, 129, 7, 6, 0, 13550823), /* vco = 3115384608 */ ++ RK3036_PLL_RATE( 65000000, 1, 113, 7, 6, 0, 12582912), /* vco = 2730000000 */ ++ RK3036_PLL_RATE( 59340659, 1, 121, 7, 7, 0, 2581098), /* vco = 2907692291 */ ++ RK3036_PLL_RATE( 54000000, 1, 110, 7, 7, 0, 4194304), /* vco = 2646000000 */ ++ RK3036_PLL_RATE( 27000000, 1, 55, 7, 7, 0, 2097152), /* vco = 1323000000 */ ++ RK3036_PLL_RATE( 26973026, 1, 55, 7, 7, 0, 1173232), /* vco = 1321678323 */ ++ { /* sentinel */ }, ++}; ++ + /* CRU parents */ + PNAME(mux_pll_p) = { "xin24m", "xin32k" }; + +@@ -121,7 +140,7 @@ PNAME(mux_ddrclk_p) = { "clk_ddrc_lpll_src", + PNAME(mux_aclk_cci_p) = { "cpll_aclk_cci_src", + "gpll_aclk_cci_src", + "npll_aclk_cci_src", +- "vpll_aclk_cci_src" }; ++ "prevent:vpll" }; + PNAME(mux_cci_trace_p) = { "cpll_cci_trace", + "gpll_cci_trace" }; + PNAME(mux_cs_p) = { "cpll_cs", "gpll_cs", +@@ -148,9 +167,10 @@ PNAME(mux_pll_src_cpll_gpll_npll_ppll_upll_24m_p) = { "cpll", "gpll", "npll", + "ppll", "upll", "xin24m" }; + + PNAME(mux_pll_src_vpll_cpll_gpll_p) = { "vpll", "cpll", "gpll" }; +-PNAME(mux_pll_src_vpll_cpll_gpll_npll_p) = { "vpll", "cpll", "gpll", ++ ++PNAME(mux_pll_src_vpll_cpll_gpll_npll_p) = { "prevent:vpll", "cpll", "gpll", + "npll" }; +-PNAME(mux_pll_src_vpll_cpll_gpll_24m_p) = { "vpll", "cpll", "gpll", ++PNAME(mux_pll_src_vpll_cpll_gpll_24m_p) = { "prevent:vpll", "cpll", "gpll", + "xin24m" }; + + PNAME(mux_dclk_vop0_p) = { "dclk_vop0_div", +@@ -227,7 +247,7 @@ static struct rockchip_pll_clock rk3399_pll_clks[] __initdata = { + [npll] = PLL(pll_rk3399, PLL_NPLL, "npll", mux_pll_p, 0, RK3399_PLL_CON(40), + RK3399_PLL_CON(43), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk3399_pll_rates), + [vpll] = PLL(pll_rk3399, PLL_VPLL, "vpll", mux_pll_p, 0, RK3399_PLL_CON(48), +- RK3399_PLL_CON(51), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk3399_pll_rates), ++ RK3399_PLL_CON(51), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk3399_vpll_rates), + }; + + static struct rockchip_pll_clock rk3399_pmu_pll_clks[] __initdata = { +@@ -277,7 +297,7 @@ static struct rockchip_clk_branch rk3399_uart4_pmu_fracmux __initdata = + RK3399_PMU_CLKSEL_CON(5), 8, 2, MFLAGS); + + static struct rockchip_clk_branch rk3399_dclk_vop0_fracmux __initdata = +- MUX(DCLK_VOP0, "dclk_vop0", mux_dclk_vop0_p, CLK_SET_RATE_PARENT, ++ MUX(DCLK_VOP0, "dclk_vop0", mux_dclk_vop0_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + RK3399_CLKSEL_CON(49), 11, 1, MFLAGS); + + static struct rockchip_clk_branch rk3399_dclk_vop1_fracmux __initdata = +@@ -1158,7 +1178,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { + GATE(HCLK_VOP0_NOC, "hclk_vop0_noc", "hclk_vop0_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(28), 0, GFLAGS), + +- COMPOSITE(DCLK_VOP0_DIV, "dclk_vop0_div", mux_pll_src_vpll_cpll_gpll_p, 0, ++ COMPOSITE(DCLK_VOP0_DIV, "dclk_vop0_div", mux_pll_src_vpll_cpll_gpll_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + RK3399_CLKSEL_CON(49), 8, 2, MFLAGS, 0, 8, DFLAGS, + RK3399_CLKGATE_CON(10), 12, GFLAGS), + + +From 1178026ac93b4a05b643d9e68b7c98d0434b8b0e Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 19 Jul 2020 16:35:11 +0000 +Subject: [PATCH] HACK: dts: rockchip: do not use vopl for hdmi + +--- + arch/arm/boot/dts/rk3288.dtsi | 9 --------- + arch/arm64/boot/dts/rockchip/rk3399.dtsi | 9 --------- + 2 files changed, 18 deletions(-) + +diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi +index a376dea3bb1b..9757976d6e8a 100644 +--- a/arch/arm/boot/dts/rk3288.dtsi ++++ b/arch/arm/boot/dts/rk3288.dtsi +@@ -1104,11 +1104,6 @@ vopl_out: port { + #address-cells = <1>; + #size-cells = <0>; + +- vopl_out_hdmi: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&hdmi_in_vopl>; +- }; +- + vopl_out_edp: endpoint@1 { + reg = <1>; + remote-endpoint = <&edp_in_vopl>; +@@ -1249,10 +1244,6 @@ hdmi_in_vopb: endpoint@0 { + reg = <0>; + remote-endpoint = <&vopb_out_hdmi>; + }; +- hdmi_in_vopl: endpoint@1 { +- reg = <1>; +- remote-endpoint = <&vopl_out_hdmi>; +- }; + }; + }; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi +index ada724b12f01..8973bf68d652 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi +@@ -1637,11 +1637,6 @@ vopl_out_edp: endpoint@1 { + remote-endpoint = <&edp_in_vopl>; + }; + +- vopl_out_hdmi: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&hdmi_in_vopl>; +- }; +- + vopl_out_mipi1: endpoint@3 { + reg = <3>; + remote-endpoint = <&mipi1_in_vopl>; +@@ -1787,10 +1782,6 @@ hdmi_in_vopb: endpoint@0 { + reg = <0>; + remote-endpoint = <&vopb_out_hdmi>; + }; +- hdmi_in_vopl: endpoint@1 { +- reg = <1>; +- remote-endpoint = <&vopl_out_hdmi>; +- }; + }; + }; + }; + +From df6bdd1b82221a3d03736963bdc1845222ff3b5c Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Tue, 26 Feb 2019 20:45:14 +0000 +Subject: [PATCH] WIP: dw-hdmi-cec: sleep 100ms on error + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c | 19 +++++++++++++++++-- + 1 file changed, 17 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c +index 70ab4fbdc23e..f6a85f73b90d 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c +@@ -4,6 +4,7 @@ + * + * Copyright (C) 2015-2017 Russell King. + */ ++#include + #include + #include + #include +@@ -129,8 +130,16 @@ static irqreturn_t dw_hdmi_cec_hardirq(int irq, void *data) + + dw_hdmi_write(cec, stat, HDMI_IH_CEC_STAT0); + +- if (stat & CEC_STAT_ERROR_INIT) { +- cec->tx_status = CEC_TX_STATUS_ERROR; ++ /* ++ * Status with both done and error_initiator bits have been seen ++ * on Rockchip RK3328 devices, transmit attempt seems to have failed ++ * when this happens, report as low drive and block cec-framework ++ * 100ms before core retransmits the failed message, this seems to ++ * mitigate the issue with failed transmit attempts. ++ */ ++ if ((stat & (CEC_STAT_DONE|CEC_STAT_ERROR_INIT)) == (CEC_STAT_DONE|CEC_STAT_ERROR_INIT)) { ++ pr_info("dw_hdmi_cec_hardirq: stat=%02x LOW_DRIVE\n", stat); ++ cec->tx_status = CEC_TX_STATUS_LOW_DRIVE; + cec->tx_done = true; + ret = IRQ_WAKE_THREAD; + } else if (stat & CEC_STAT_DONE) { +@@ -141,6 +150,10 @@ static irqreturn_t dw_hdmi_cec_hardirq(int irq, void *data) + cec->tx_status = CEC_TX_STATUS_NACK; + cec->tx_done = true; + ret = IRQ_WAKE_THREAD; ++ } else if (stat & CEC_STAT_ERROR_INIT) { ++ cec->tx_status = CEC_TX_STATUS_ERROR; ++ cec->tx_done = true; ++ ret = IRQ_WAKE_THREAD; + } + + if (stat & CEC_STAT_EOM) { +@@ -173,6 +186,8 @@ static irqreturn_t dw_hdmi_cec_thread(int irq, void *data) + + if (cec->tx_done) { + cec->tx_done = false; ++ if (cec->tx_status == CEC_TX_STATUS_LOW_DRIVE) ++ msleep(100); + cec_transmit_attempt_done(adap, cec->tx_status); + } + if (cec->rx_done) { + +From f482feeeeedc41f34892a05a0594d23924a0571a Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 18 Jul 2020 20:54:38 +0000 +Subject: [PATCH] asdf + +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c | 36 +++++++++++++++---- + drivers/media/cec/core/cec-adap.c | 2 +- + 2 files changed, 30 insertions(+), 8 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c +index f6a85f73b90d..e6953219beee 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c +@@ -58,6 +58,7 @@ struct dw_hdmi_cec { + u32 addresses; + struct cec_adapter *adap; + struct cec_msg rx_msg; ++ unsigned int tx_attempts; + unsigned int tx_status; + bool tx_done; + bool rx_done; +@@ -96,6 +97,8 @@ static int dw_hdmi_cec_transmit(struct cec_adapter *adap, u8 attempts, + struct dw_hdmi_cec *cec = cec_get_drvdata(adap); + unsigned int i, ctrl; + ++ pr_info("%s: attempts=%u signal_free_time=%u msg=%*ph (sequence: %u)\n", __func__, attempts, signal_free_time, msg->len, msg->msg, msg->sequence); ++ + switch (signal_free_time) { + case CEC_SIGNAL_FREE_TIME_RETRY: + ctrl = CEC_CTRL_RETRY; +@@ -131,26 +134,35 @@ static irqreturn_t dw_hdmi_cec_hardirq(int irq, void *data) + dw_hdmi_write(cec, stat, HDMI_IH_CEC_STAT0); + + /* +- * Status with both done and error_initiator bits have been seen +- * on Rockchip RK3328 devices, transmit attempt seems to have failed +- * when this happens, report as low drive and block cec-framework ++ * Status with both done and error_initiator bits have been observed ++ * on Rockchip RK3328/RK3399 devices, transmit attempt seems to have ++ * failed when this happens, report as low drive and block cec-framework + * 100ms before core retransmits the failed message, this seems to + * mitigate the issue with failed transmit attempts. + */ + if ((stat & (CEC_STAT_DONE|CEC_STAT_ERROR_INIT)) == (CEC_STAT_DONE|CEC_STAT_ERROR_INIT)) { +- pr_info("dw_hdmi_cec_hardirq: stat=%02x LOW_DRIVE\n", stat); ++ if (!cec->tx_attempts) ++ cec->tx_attempts = 2; + cec->tx_status = CEC_TX_STATUS_LOW_DRIVE; + cec->tx_done = true; + ret = IRQ_WAKE_THREAD; ++ } else if (stat & CEC_STAT_ARBLOST) { ++ cec->tx_attempts = 0; ++ cec->tx_status = CEC_TX_STATUS_ARB_LOST; ++ cec->tx_done = true; ++ ret = IRQ_WAKE_THREAD; + } else if (stat & CEC_STAT_DONE) { ++ cec->tx_attempts = 0; + cec->tx_status = CEC_TX_STATUS_OK; + cec->tx_done = true; + ret = IRQ_WAKE_THREAD; + } else if (stat & CEC_STAT_NACK) { ++ cec->tx_attempts = 0; + cec->tx_status = CEC_TX_STATUS_NACK; + cec->tx_done = true; + ret = IRQ_WAKE_THREAD; + } else if (stat & CEC_STAT_ERROR_INIT) { ++ cec->tx_attempts = 0; + cec->tx_status = CEC_TX_STATUS_ERROR; + cec->tx_done = true; + ret = IRQ_WAKE_THREAD; +@@ -176,6 +188,8 @@ static irqreturn_t dw_hdmi_cec_hardirq(int irq, void *data) + ret = IRQ_WAKE_THREAD; + } + ++ pr_info("%s: stat=%x ret=%x tx_done=%d rx_done=%d tx_status=%u tx_attempts=%u\n", __func__, stat, ret, cec->tx_done, cec->rx_done, cec->tx_status, cec->tx_attempts); ++ + return ret; + } + +@@ -184,11 +198,19 @@ static irqreturn_t dw_hdmi_cec_thread(int irq, void *data) + struct cec_adapter *adap = data; + struct dw_hdmi_cec *cec = cec_get_drvdata(adap); + ++ //pr_info("%s: tx_done=%d rx_done=%d tx_status=%u tx_attempts=%u\n", __func__, cec->tx_done, cec->rx_done, cec->tx_status, cec->tx_attempts); ++ + if (cec->tx_done) { + cec->tx_done = false; + if (cec->tx_status == CEC_TX_STATUS_LOW_DRIVE) + msleep(100); +- cec_transmit_attempt_done(adap, cec->tx_status); ++ if (cec->tx_attempts > 1) { ++ cec->tx_attempts--; ++ dw_hdmi_write(cec, CEC_CTRL_RETRY | CEC_CTRL_START, HDMI_CEC_CTRL); ++ } else { ++ cec->tx_attempts = 0; ++ cec_transmit_attempt_done(adap, cec->tx_status); ++ } + } + if (cec->rx_done) { + cec->rx_done = false; +@@ -219,8 +241,8 @@ static int dw_hdmi_cec_enable(struct cec_adapter *adap, bool enable) + + cec->ops->enable(cec->hdmi); + +- irqs = CEC_STAT_ERROR_INIT | CEC_STAT_NACK | CEC_STAT_EOM | +- CEC_STAT_DONE; ++ irqs = CEC_STAT_ERROR_INIT | CEC_STAT_ARBLOST | CEC_STAT_NACK | ++ CEC_STAT_EOM | CEC_STAT_DONE; + dw_hdmi_write(cec, irqs, HDMI_CEC_POLARITY); + dw_hdmi_write(cec, ~irqs, HDMI_CEC_MASK); + dw_hdmi_write(cec, ~irqs, HDMI_IH_MUTE_CEC_STAT0); +diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c +index 6a04d19a96b2..3d12f9d30bd0 100644 +--- a/drivers/media/cec/core/cec-adap.c ++++ b/drivers/media/cec/core/cec-adap.c +@@ -599,7 +599,6 @@ void cec_transmit_done_ts(struct cec_adapter *adap, u8 status, + unsigned int attempts_made = arb_lost_cnt + nack_cnt + + low_drive_cnt + error_cnt; + +- dprintk(2, "%s: status 0x%02x\n", __func__, status); + if (attempts_made < 1) + attempts_made = 1; + +@@ -620,6 +619,7 @@ void cec_transmit_done_ts(struct cec_adapter *adap, u8 status, + adap->transmit_in_progress = false; + + msg = &data->msg; ++ dprintk(2, "%s: %*ph (sequence: %u, attempts: %d, status: %02x)\n", __func__, msg->len, msg->msg, msg->sequence, attempts_made, status); + + /* Drivers must fill in the status! */ + WARN_ON(status == 0); + +From 7abf7a462dd2e503dd816277628ed09a46dc8c55 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 20 Jul 2020 11:44:01 +0000 +Subject: [PATCH] cec dprintk revert + +--- + drivers/media/cec/core/cec-adap.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c +index 3d12f9d30bd0..6a04d19a96b2 100644 +--- a/drivers/media/cec/core/cec-adap.c ++++ b/drivers/media/cec/core/cec-adap.c +@@ -599,6 +599,7 @@ void cec_transmit_done_ts(struct cec_adapter *adap, u8 status, + unsigned int attempts_made = arb_lost_cnt + nack_cnt + + low_drive_cnt + error_cnt; + ++ dprintk(2, "%s: status 0x%02x\n", __func__, status); + if (attempts_made < 1) + attempts_made = 1; + +@@ -619,7 +620,6 @@ void cec_transmit_done_ts(struct cec_adapter *adap, u8 status, + adap->transmit_in_progress = false; + + msg = &data->msg; +- dprintk(2, "%s: %*ph (sequence: %u, attempts: %d, status: %02x)\n", __func__, msg->len, msg->msg, msg->sequence, attempts_made, status); + + /* Drivers must fill in the status! */ + WARN_ON(status == 0); + +From 8ca2d36b31a5921a9f7e0e1deba847915eac55bf Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 20 Jul 2020 12:33:01 +0000 +Subject: [PATCH] Revert "fixup! WIP: drm/rockchip: vop: max_output" + +This reverts commit c69612ca6820500cd1a0a3e4f8eb8c6f7b971cda. +--- + drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +index 106b38ea12df..138f449924f8 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +@@ -1184,8 +1184,19 @@ static bool vop_crtc_mode_fixup(struct drm_crtc *crtc, + struct drm_display_mode *adjusted_mode) + { + struct vop *vop = to_vop(crtc); ++ const struct vop_rect *max_output = &vop->data->max_output; + unsigned long rate; + ++ if (max_output->width && max_output->height) { ++ enum drm_mode_status status; ++ ++ status = drm_mode_validate_size(adjusted_mode, ++ max_output->width, ++ max_output->height); ++ if (status != MODE_OK) ++ return false; ++ } ++ + /* + * Clock craziness. + * + +From fff7adceb4d87d2fa0b4f108dbcd39748dfd0689 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 15 Jul 2020 15:24:47 +0000 +Subject: [PATCH] drm/rockchip: vop: fix crtc duplicate state + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +index 138f449924f8..0a25de483515 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +@@ -1578,7 +1578,11 @@ static struct drm_crtc_state *vop_crtc_duplicate_state(struct drm_crtc *crtc) + { + struct rockchip_crtc_state *rockchip_state; + +- rockchip_state = kzalloc(sizeof(*rockchip_state), GFP_KERNEL); ++ if (WARN_ON(!crtc->state)) ++ return NULL; ++ ++ rockchip_state = kmemdup(to_rockchip_crtc_state(crtc->state), ++ sizeof(*rockchip_state), GFP_KERNEL); + if (!rockchip_state) + return NULL; + + +From 36a518702d98bb3c22276352f648ee1d206db475 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 20 Jul 2020 15:15:50 +0000 +Subject: [PATCH] WIP: drm/rockchip: vop: filter interlaced modes + +--- + drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +index 0a25de483515..5ab1412173a7 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +@@ -1160,6 +1160,9 @@ static enum drm_mode_status vop_crtc_mode_valid(struct drm_crtc *crtc, + if (s->output_type != DRM_MODE_CONNECTOR_HDMIA) + return MODE_OK; + ++ if (mode->flags & DRM_MODE_FLAG_INTERLACE) ++ return MODE_NO_INTERLACE; ++ + rounded_rate = clk_round_rate(vop->dclk, mode->clock * 1000 + 999); + if (rounded_rate < 0) + return MODE_NOCLOCK; + +From 14ba7a75af03d8e3fd7274cfe8a21dd867b23ce5 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Fri, 20 Dec 2019 08:12:42 +0000 +Subject: [PATCH] drm/rockchip: dw-hdmi: add bridge and switch to + drm_bridge_funcs + +Switch the dw-hdmi driver to drm_bridge_funcs by implementing +a new local bridge, connecting it to the dw-hdmi bridge. + +Also enable bridge format negotiation by implementing +atomic_get_input_bus_fmts and support for 8-bit RGB 4:4:4. + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 138 ++++++++++++++------ + 1 file changed, 95 insertions(+), 43 deletions(-) + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index cc20a83fa9b8..745fd1c13cef 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -68,6 +68,7 @@ struct rockchip_hdmi { + struct device *dev; + struct regmap *regmap; + struct drm_encoder encoder; ++ struct drm_bridge bridge; + const struct rockchip_hdmi_chip_data *chip_data; + struct clk *vpll_clk; + struct clk *grf_clk; +@@ -228,30 +229,20 @@ dw_hdmi_rockchip_mode_valid(struct dw_hdmi *hdmi, void *data, + return drm_mode_validate_size(mode, 3840, 2160); + } + +-static void dw_hdmi_rockchip_encoder_disable(struct drm_encoder *encoder) ++static void ++dw_hdmi_rockchip_bridge_mode_set(struct drm_bridge *bridge, ++ const struct drm_display_mode *mode, ++ const struct drm_display_mode *adjusted_mode) + { +-} ++ struct rockchip_hdmi *hdmi = to_rockchip_hdmi(bridge); + +-static bool +-dw_hdmi_rockchip_encoder_mode_fixup(struct drm_encoder *encoder, +- const struct drm_display_mode *mode, +- struct drm_display_mode *adj_mode) +-{ +- return true; ++ clk_set_rate(hdmi->vpll_clk, adjusted_mode->clock * 1000); + } + +-static void dw_hdmi_rockchip_encoder_mode_set(struct drm_encoder *encoder, +- struct drm_display_mode *mode, +- struct drm_display_mode *adj_mode) ++static void dw_hdmi_rockchip_bridge_enable(struct drm_bridge *bridge) + { +- struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); +- +- clk_set_rate(hdmi->vpll_clk, adj_mode->clock * 1000); +-} +- +-static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder) +-{ +- struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); ++ struct rockchip_hdmi *hdmi = to_rockchip_hdmi(bridge); ++ struct drm_encoder *encoder = bridge->encoder; + u32 val; + int ret; + +@@ -279,10 +270,21 @@ static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder) + ret ? "LIT" : "BIG"); + } + ++static bool is_rgb(u32 format) ++{ ++ switch (format) { ++ case MEDIA_BUS_FMT_RGB888_1X24: ++ return true; ++ default: ++ return false; ++ } ++} ++ + static int +-dw_hdmi_rockchip_encoder_atomic_check(struct drm_encoder *encoder, +- struct drm_crtc_state *crtc_state, +- struct drm_connector_state *conn_state) ++dw_hdmi_rockchip_bridge_atomic_check(struct drm_bridge *bridge, ++ struct drm_bridge_state *bridge_state, ++ struct drm_crtc_state *crtc_state, ++ struct drm_connector_state *conn_state) + { + struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); + +@@ -292,12 +294,38 @@ dw_hdmi_rockchip_encoder_atomic_check(struct drm_encoder *encoder, + return 0; + } + +-static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_funcs = { +- .mode_fixup = dw_hdmi_rockchip_encoder_mode_fixup, +- .mode_set = dw_hdmi_rockchip_encoder_mode_set, +- .enable = dw_hdmi_rockchip_encoder_enable, +- .disable = dw_hdmi_rockchip_encoder_disable, +- .atomic_check = dw_hdmi_rockchip_encoder_atomic_check, ++static u32 *dw_hdmi_rockchip_get_input_bus_fmts(struct drm_bridge *bridge, ++ struct drm_bridge_state *bridge_state, ++ struct drm_crtc_state *crtc_state, ++ struct drm_connector_state *conn_state, ++ u32 output_fmt, ++ unsigned int *num_input_fmts) ++{ ++ u32 *input_fmt; ++ ++ *num_input_fmts = 0; ++ ++ if (!is_rgb(output_fmt)) ++ return NULL; ++ ++ input_fmt = kzalloc(sizeof(*input_fmt), GFP_KERNEL); ++ if (!input_fmt) ++ return NULL; ++ ++ *num_input_fmts = 1; ++ *input_fmt = output_fmt; ++ ++ return input_fmt; ++} ++ ++static const struct drm_bridge_funcs dw_hdmi_rockchip_bridge_funcs = { ++ .mode_set = dw_hdmi_rockchip_bridge_mode_set, ++ .enable = dw_hdmi_rockchip_bridge_enable, ++ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, ++ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, ++ .atomic_get_input_bus_fmts = dw_hdmi_rockchip_get_input_bus_fmts, ++ .atomic_check = dw_hdmi_rockchip_bridge_atomic_check, ++ .atomic_reset = drm_atomic_helper_bridge_reset, + }; + + static int dw_hdmi_rockchip_genphy_init(struct dw_hdmi *dw_hdmi, void *data, +@@ -476,6 +504,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, + struct dw_hdmi_plat_data *plat_data; + const struct of_device_id *match; + struct drm_device *drm = data; ++ struct drm_bridge *next_bridge; + struct drm_encoder *encoder; + struct rockchip_hdmi *hdmi; + int ret; +@@ -516,8 +545,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, + + ret = clk_prepare_enable(hdmi->vpll_clk); + if (ret) { +- DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI vpll: %d\n", +- ret); ++ DRM_DEV_ERROR(hdmi->dev, "Failed to enable vpll: %d\n", ret); + return ret; + } + +@@ -525,27 +553,51 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, + if (IS_ERR(hdmi->phy)) { + ret = PTR_ERR(hdmi->phy); + if (ret != -EPROBE_DEFER) +- DRM_DEV_ERROR(hdmi->dev, "failed to get phy\n"); +- return ret; ++ DRM_DEV_ERROR(hdmi->dev, "Failed to get phy: %d\n", ret); ++ goto err_disable_clk; + } + +- drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs); +- drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); ++ ret = drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); ++ if (ret) { ++ DRM_DEV_ERROR(hdmi->dev, "Failed to init encoder: %d\n", ret); ++ goto err_disable_clk; ++ } + +- platform_set_drvdata(pdev, hdmi); ++ hdmi->bridge.funcs = &dw_hdmi_rockchip_bridge_funcs; ++ drm_bridge_attach(encoder, &hdmi->bridge, NULL, 0); + +- hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data); ++ platform_set_drvdata(pdev, hdmi); + +- /* +- * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(), +- * which would have called the encoder cleanup. Do it manually. +- */ ++ hdmi->hdmi = dw_hdmi_probe(pdev, plat_data); + if (IS_ERR(hdmi->hdmi)) { + ret = PTR_ERR(hdmi->hdmi); +- drm_encoder_cleanup(encoder); +- clk_disable_unprepare(hdmi->vpll_clk); ++ if (ret != -EPROBE_DEFER) ++ DRM_DEV_ERROR(hdmi->dev, "Failed to init dw-hdmi bridge: %d\n", ret); ++ goto err_encoder_cleanup; ++ } ++ ++ next_bridge = of_drm_find_bridge(pdev->dev.of_node); ++ if (!next_bridge) { ++ ret = -EPROBE_DEFER; ++ goto err_dw_hdmi_remove; ++ } ++ ++ ret = drm_bridge_attach(encoder, next_bridge, &hdmi->bridge, 0); ++ if (ret) { ++ if (ret != -EPROBE_DEFER) ++ DRM_DEV_ERROR(hdmi->dev, "Failed to attach dw-hdmi bridge: %d\n", ret); ++ goto err_dw_hdmi_remove; + } + ++ return 0; ++ ++err_dw_hdmi_remove: ++ dw_hdmi_remove(hdmi->hdmi); ++err_encoder_cleanup: ++ drm_encoder_cleanup(encoder); ++err_disable_clk: ++ clk_disable_unprepare(hdmi->vpll_clk); ++ + return ret; + } + +@@ -554,7 +606,7 @@ static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master, + { + struct rockchip_hdmi *hdmi = dev_get_drvdata(dev); + +- dw_hdmi_unbind(hdmi->hdmi); ++ dw_hdmi_remove(hdmi->hdmi); + clk_disable_unprepare(hdmi->vpll_clk); + } + + +From ffded51c4e7a79cca7d97b4fe0d98ee4b0b74e34 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 20 Jul 2020 18:00:44 +0000 +Subject: [PATCH] drm/bridge: dw-hdmi: add mtmdsclock parameter to phy + configure ops + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 10 ++++++---- + drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c | 3 ++- + include/drm/bridge/dw_hdmi.h | 3 ++- + 3 files changed, 10 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 748df1cacd2b..c25d5ac7bb07 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -137,7 +137,8 @@ struct dw_hdmi_phy_data { + bool has_svsret; + int (*configure)(struct dw_hdmi *hdmi, + const struct dw_hdmi_plat_data *pdata, +- unsigned long mpixelclock); ++ unsigned long mpixelclock, ++ unsigned long mtmdsclock); + }; + + struct dw_hdmi { +@@ -1441,7 +1442,8 @@ static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi) + */ + static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi, + const struct dw_hdmi_plat_data *pdata, +- unsigned long mpixelclock) ++ unsigned long mpixelclock, ++ unsigned long mtmdsclock) + { + const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg; + const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr; +@@ -1516,9 +1518,9 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, + + /* Write to the PHY as configured by the platform */ + if (pdata->configure_phy) +- ret = pdata->configure_phy(hdmi, pdata->priv_data, mpixelclock); ++ ret = pdata->configure_phy(hdmi, pdata->priv_data, mpixelclock, mtmdsclock); + else +- ret = phy->configure(hdmi, pdata, mpixelclock); ++ ret = phy->configure(hdmi, pdata, mpixelclock, mtmdsclock); + if (ret) { + dev_err(hdmi->dev, "PHY configuration failed (clock %lu)\n", + mpixelclock); +diff --git a/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c b/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c +index 7b8ec8310699..539d86131fd4 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c ++++ b/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c +@@ -53,7 +53,8 @@ rcar_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, + } + + static int rcar_hdmi_phy_configure(struct dw_hdmi *hdmi, void *data, +- unsigned long mpixelclock) ++ unsigned long mpixelclock, ++ unsigned long mtmdsclock) + { + const struct rcar_hdmi_phy_params *params = rcar_hdmi_phy_params; + +diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h +index ea34ca146b82..4f61ede6486d 100644 +--- a/include/drm/bridge/dw_hdmi.h ++++ b/include/drm/bridge/dw_hdmi.h +@@ -152,7 +152,8 @@ struct dw_hdmi_plat_data { + const struct dw_hdmi_curr_ctrl *cur_ctr; + const struct dw_hdmi_phy_config *phy_config; + int (*configure_phy)(struct dw_hdmi *hdmi, void *data, +- unsigned long mpixelclock); ++ unsigned long mpixelclock, ++ unsigned long mtmdsclock); + }; + + struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev, + +From e3c32df45f5d84f541586a6c382008be538528ba Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 20 Jul 2020 21:34:48 +0000 +Subject: [PATCH] drm/bridge: dw-hdmi: support configuring phy for deep color + +Q: Should we rename dw_hdmi_curr_ctrl and dw_hdmi_phy_config mpixelclock to mtmdsclock ? + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index c25d5ac7bb07..bcdd823907c2 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -1448,6 +1448,7 @@ static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi, + const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg; + const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr; + const struct dw_hdmi_phy_config *phy_config = pdata->phy_config; ++ int depth; + + /* TOFIX Will need 420 specific PHY configuration tables */ + +@@ -1457,11 +1458,11 @@ static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi, + break; + + for (; curr_ctrl->mpixelclock != ~0UL; curr_ctrl++) +- if (mpixelclock <= curr_ctrl->mpixelclock) ++ if (mtmdsclock <= curr_ctrl->mpixelclock) + break; + + for (; phy_config->mpixelclock != ~0UL; phy_config++) +- if (mpixelclock <= phy_config->mpixelclock) ++ if (mtmdsclock <= phy_config->mpixelclock) + break; + + if (mpll_config->mpixelclock == ~0UL || +@@ -1469,11 +1470,17 @@ static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi, + phy_config->mpixelclock == ~0UL) + return -EINVAL; + +- dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].cpce, ++ depth = hdmi_bus_fmt_color_depth(hdmi->hdmi_data.enc_out_bus_format); ++ if (depth > 8 && mpixelclock != mtmdsclock) ++ depth = fls(depth - 8) - 1; ++ else ++ depth = 0; ++ ++ dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[depth].cpce, + HDMI_3D_TX_PHY_CPCE_CTRL); +- dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].gmp, ++ dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[depth].gmp, + HDMI_3D_TX_PHY_GMPCTRL); +- dw_hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[0], ++ dw_hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[depth], + HDMI_3D_TX_PHY_CURRCTRL); + + dw_hdmi_phy_i2c_write(hdmi, 0, HDMI_3D_TX_PHY_PLLPHBYCTRL); + +From d391dfb202b03bad6d52efe7d0aa46225febe3c5 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 20 Jul 2020 22:25:15 +0000 +Subject: [PATCH] drm/bridge: dw-hdmi: add mpll_cfg_420 for ycbcr420 mode + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 4 +++- + include/drm/bridge/dw_hdmi.h | 1 + + 2 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index bcdd823907c2..f5d048adf649 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -1450,7 +1450,9 @@ static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi, + const struct dw_hdmi_phy_config *phy_config = pdata->phy_config; + int depth; + +- /* TOFIX Will need 420 specific PHY configuration tables */ ++ if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format) && ++ pdata->mpll_cfg_420) ++ mpll_config = pdata->mpll_cfg_420; + + /* PLL/MPLL Cfg - always match on final entry */ + for (; mpll_config->mpixelclock != ~0UL; mpll_config++) +diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h +index 4f61ede6486d..0ebe01835d2a 100644 +--- a/include/drm/bridge/dw_hdmi.h ++++ b/include/drm/bridge/dw_hdmi.h +@@ -149,6 +149,7 @@ struct dw_hdmi_plat_data { + + /* Synopsys PHY support */ + const struct dw_hdmi_mpll_config *mpll_cfg; ++ const struct dw_hdmi_mpll_config *mpll_cfg_420; + const struct dw_hdmi_curr_ctrl *cur_ctr; + const struct dw_hdmi_phy_config *phy_config; + int (*configure_phy)(struct dw_hdmi *hdmi, void *data, + +From 08b2f123efe8bb641671ad038dd0dc37f877794d Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 15 Jul 2020 09:49:21 +0000 +Subject: [PATCH] drm/rockchip: dw-hdmi: mode_valid: allow 420 clock rate + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index 745fd1c13cef..9784111ea746 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -222,8 +222,15 @@ dw_hdmi_rockchip_mode_valid(struct dw_hdmi *hdmi, void *data, + const struct drm_display_info *info, + const struct drm_display_mode *mode) + { +- if (mode->clock > 340000 || +- (info->max_tmds_clock && mode->clock > info->max_tmds_clock)) ++ struct dw_hdmi_plat_data *pdata = (struct dw_hdmi_plat_data *)data; ++ int clock = mode->clock; ++ ++ if (pdata->ycbcr_420_allowed && drm_mode_is_420(info, mode) && ++ (info->color_formats & DRM_COLOR_FORMAT_YCRCB420)) ++ clock /= 2; ++ ++ if (clock > 340000 || ++ (info->max_tmds_clock && clock > info->max_tmds_clock)) + return MODE_CLOCK_HIGH; + + return drm_mode_validate_size(mode, 3840, 2160); +@@ -524,6 +531,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, + + hdmi->dev = &pdev->dev; + hdmi->chip_data = plat_data->phy_data; ++ plat_data->priv_data = plat_data; + plat_data->phy_data = hdmi; + encoder = &hdmi->encoder; + + +From e8f87de2fef5c2be3110fcd23fa1b09325bbd041 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 20 Jul 2020 22:26:19 +0000 +Subject: [PATCH] drm/rockchip: dw-hdmi: rk3399: add mpll_cfg_420 + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 41 +++++++++++++++++++++ + 1 file changed, 41 insertions(+) + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index 9784111ea746..e7fbeb9132fb 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -166,6 +166,46 @@ static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = { + } + }; + ++static const struct dw_hdmi_mpll_config rockchip_mpll_cfg_420[] = { ++ { ++ 30666000, { ++ { 0x00b7, 0x0000 }, ++ { 0x2157, 0x0000 }, ++ { 0x40f7, 0x0000 }, ++ }, ++ }, { ++ 92000000, { ++ { 0x00b7, 0x0000 }, ++ { 0x2143, 0x0001 }, ++ { 0x40a3, 0x0001 }, ++ }, ++ }, { ++ 184000000, { ++ { 0x0073, 0x0001 }, ++ { 0x2146, 0x0002 }, ++ { 0x4062, 0x0002 }, ++ }, ++ }, { ++ 340000000, { ++ { 0x0052, 0x0003 }, ++ { 0x214d, 0x0003 }, ++ { 0x4065, 0x0003 }, ++ }, ++ }, { ++ 600000000, { ++ { 0x0041, 0x0003 }, ++ { 0x3b4d, 0x0003 }, ++ { 0x5a65, 0x0003 }, ++ }, ++ }, { ++ ~0UL, { ++ { 0x0000, 0x0000 }, ++ { 0x0000, 0x0000 }, ++ { 0x0000, 0x0000 }, ++ }, ++ } ++}; ++ + static const struct dw_hdmi_curr_ctrl rockchip_cur_ctr[] = { + /* pixelclk bpp8 bpp10 bpp12 */ + { +@@ -481,6 +521,7 @@ static struct rockchip_hdmi_chip_data rk3399_chip_data = { + static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = { + .mode_valid = dw_hdmi_rockchip_mode_valid, + .mpll_cfg = rockchip_mpll_cfg, ++ .mpll_cfg_420 = rockchip_mpll_cfg_420, + .cur_ctr = rockchip_cur_ctr, + .phy_config = rockchip_phy_config, + .phy_data = &rk3399_chip_data, + +From 90cd0a2b9a02f11488bddcc9fe7dad15c04a8d36 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Fri, 20 Dec 2019 08:12:43 +0000 +Subject: [PATCH] WIP: drm/bridge: dw-hdmi: limit mode and bus format to + max_tmds_clock + +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 120 ++++++++++++++-------- + 1 file changed, 76 insertions(+), 44 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index f5d048adf649..26c64cf2d00a 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -1859,6 +1859,21 @@ static void hdmi_config_drm_infoframe(struct dw_hdmi *hdmi, + HDMI_FC_PACKET_TX_EN_DRM_MASK, HDMI_FC_PACKET_TX_EN); + } + ++static unsigned int ++hdmi_get_tmdsclock(unsigned int bus_format, unsigned int pixelclock) ++{ ++ int color_depth = hdmi_bus_fmt_color_depth(bus_format); ++ unsigned int tmdsclock = pixelclock; ++ ++ if (!hdmi_bus_fmt_is_yuv422(bus_format) && color_depth > 8) ++ tmdsclock = (u64)pixelclock * color_depth / 8; ++ ++ if (hdmi_bus_fmt_is_yuv420(bus_format)) ++ tmdsclock /= 2; ++ ++ return tmdsclock; ++} ++ + static void hdmi_av_composer(struct dw_hdmi *hdmi, + const struct drm_display_info *display, + const struct drm_display_mode *mode) +@@ -1870,29 +1885,11 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi, + unsigned int vdisplay, hdisplay; + + vmode->mpixelclock = mode->clock * 1000; ++ vmode->mtmdsclock = ++ hdmi_get_tmdsclock(hdmi->hdmi_data.enc_out_bus_format, ++ vmode->mpixelclock); + + dev_dbg(hdmi->dev, "final pixclk = %d\n", vmode->mpixelclock); +- +- vmode->mtmdsclock = vmode->mpixelclock; +- +- if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format)) { +- switch (hdmi_bus_fmt_color_depth( +- hdmi->hdmi_data.enc_out_bus_format)) { +- case 16: +- vmode->mtmdsclock = vmode->mpixelclock * 2; +- break; +- case 12: +- vmode->mtmdsclock = vmode->mpixelclock * 3 / 2; +- break; +- case 10: +- vmode->mtmdsclock = vmode->mpixelclock * 5 / 4; +- break; +- } +- } +- +- if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format)) +- vmode->mtmdsclock /= 2; +- + dev_dbg(hdmi->dev, "final tmdsclock = %d\n", vmode->mtmdsclock); + + /* Set up HDMI_FC_INVIDCONF */ +@@ -2550,8 +2547,21 @@ static int dw_hdmi_connector_create(struct dw_hdmi *hdmi) + * - MEDIA_BUS_FMT_RGB888_1X24, + */ + +-/* Can return a maximum of 11 possible output formats for a mode/connector */ +-#define MAX_OUTPUT_SEL_FORMATS 11 ++/* Can return a maximum of 15 possible output formats for a mode/connector */ ++#define MAX_OUTPUT_SEL_FORMATS 15 ++ ++static bool is_tmds_allowed(struct drm_display_info *info, ++ struct drm_display_mode *mode, ++ u32 bus_format) ++{ ++ unsigned long tmdsclock = hdmi_get_tmdsclock(bus_format, mode->clock); ++ int max_tmds_clock = info->max_tmds_clock ? info->max_tmds_clock : 340000; ++ ++ if (max_tmds_clock >= tmdsclock) ++ return true; ++ ++ return false; ++} + + static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, +@@ -2563,8 +2573,6 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, + struct drm_display_info *info = &conn->display_info; + struct drm_display_mode *mode = &crtc_state->mode; + u8 max_bpc = conn_state->max_requested_bpc; +- bool is_hdmi2_sink = info->hdmi.scdc.supported || +- (info->color_formats & DRM_COLOR_FORMAT_YCRCB420); + u32 *output_fmts; + unsigned int i = 0; + +@@ -2587,29 +2595,33 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, + * If the current mode enforces 4:2:0, force the output but format + * to 4:2:0 and do not add the YUV422/444/RGB formats + */ +- if (conn->ycbcr_420_allowed && +- (drm_mode_is_420_only(info, mode) || +- (is_hdmi2_sink && drm_mode_is_420_also(info, mode)))) { ++ if (conn->ycbcr_420_allowed && drm_mode_is_420(info, mode) && ++ (info->color_formats & DRM_COLOR_FORMAT_YCRCB420)) { + + /* Order bus formats from 16bit to 8bit if supported */ + if (max_bpc >= 16 && info->bpc == 16 && +- (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_48)) ++ (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_48) && ++ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYYVYY16_0_5X48)) + output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY16_0_5X48; + + if (max_bpc >= 12 && info->bpc >= 12 && +- (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_36)) ++ (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_36) && ++ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYYVYY12_0_5X36)) + output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY12_0_5X36; + + if (max_bpc >= 10 && info->bpc >= 10 && +- (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30)) ++ (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30) && ++ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYYVYY10_0_5X30)) + output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY10_0_5X30; + + /* Default 8bit fallback */ +- output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY8_0_5X24; ++ if (is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYYVYY8_0_5X24)) ++ output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY8_0_5X24; + + *num_output_fmts = i; + +- return output_fmts; ++ if (drm_mode_is_420_only(info, mode)) ++ return output_fmts; + } + + /* +@@ -2618,40 +2630,51 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, + */ + + if (max_bpc >= 16 && info->bpc == 16) { +- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444) ++ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB444) && ++ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_YUV16_1X48)) + output_fmts[i++] = MEDIA_BUS_FMT_YUV16_1X48; + +- output_fmts[i++] = MEDIA_BUS_FMT_RGB161616_1X48; ++ if (is_tmds_allowed(info, mode, MEDIA_BUS_FMT_RGB161616_1X48)) ++ output_fmts[i++] = MEDIA_BUS_FMT_RGB161616_1X48; + } + + if (max_bpc >= 12 && info->bpc >= 12) { +- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422) ++ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB422) && ++ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYVY12_1X24)) + output_fmts[i++] = MEDIA_BUS_FMT_UYVY12_1X24; + +- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444) ++ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB444) && ++ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_YUV12_1X36)) + output_fmts[i++] = MEDIA_BUS_FMT_YUV12_1X36; + +- output_fmts[i++] = MEDIA_BUS_FMT_RGB121212_1X36; ++ if (is_tmds_allowed(info, mode, MEDIA_BUS_FMT_RGB121212_1X36)) ++ output_fmts[i++] = MEDIA_BUS_FMT_RGB121212_1X36; + } + + if (max_bpc >= 10 && info->bpc >= 10) { +- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422) ++ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB422) && ++ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYVY10_1X20)) + output_fmts[i++] = MEDIA_BUS_FMT_UYVY10_1X20; + +- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444) ++ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB444) && ++ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_YUV10_1X30)) + output_fmts[i++] = MEDIA_BUS_FMT_YUV10_1X30; + +- output_fmts[i++] = MEDIA_BUS_FMT_RGB101010_1X30; ++ if (is_tmds_allowed(info, mode, MEDIA_BUS_FMT_RGB101010_1X30)) ++ output_fmts[i++] = MEDIA_BUS_FMT_RGB101010_1X30; + } + +- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422) ++ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB422) && ++ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYVY8_1X16)) + output_fmts[i++] = MEDIA_BUS_FMT_UYVY8_1X16; + +- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444) ++ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB444) && ++ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_YUV8_1X24)) + output_fmts[i++] = MEDIA_BUS_FMT_YUV8_1X24; + + /* Default 8bit RGB fallback */ +- output_fmts[i++] = MEDIA_BUS_FMT_RGB888_1X24; ++ if (is_tmds_allowed(info, mode, MEDIA_BUS_FMT_RGB888_1X24)) ++ output_fmts[i++] = MEDIA_BUS_FMT_RGB888_1X24; + + *num_output_fmts = i; + +@@ -2831,11 +2854,20 @@ dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge, + struct dw_hdmi *hdmi = bridge->driver_private; + const struct dw_hdmi_plat_data *pdata = hdmi->plat_data; + enum drm_mode_status mode_status = MODE_OK; ++ int max_tmds_clock = info->max_tmds_clock ? info->max_tmds_clock : 340000; ++ int clock = mode->clock; + + /* We don't support double-clocked modes */ + if (mode->flags & DRM_MODE_FLAG_DBLCLK) + return MODE_BAD; + ++ if (pdata->ycbcr_420_allowed && drm_mode_is_420(info, mode) && ++ (info->color_formats & DRM_COLOR_FORMAT_YCRCB420)) ++ clock /= 2; ++ ++ if (clock > max_tmds_clock) ++ return MODE_CLOCK_HIGH; ++ + if (pdata->mode_valid) + mode_status = pdata->mode_valid(hdmi, pdata->priv_data, info, + mode); + +From 2960613151591dd65e3b7dac4bc760ad0cddd4b6 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Fri, 20 Dec 2019 08:12:42 +0000 +Subject: [PATCH] WIP: drm/rockchip: dw_hdmi: add 10-bit rgb bus format + +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 41 +++++++++++++++++++++ + drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 2 + + 2 files changed, 43 insertions(+) + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index e7fbeb9132fb..cd87ee8a65c3 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -77,6 +77,7 @@ struct rockchip_hdmi { + }; + + #define to_rockchip_hdmi(x) container_of(x, struct rockchip_hdmi, x) ++#define to_crtc_state(x) container_of(x, struct drm_crtc_state, x) + + static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = { + { +@@ -282,6 +283,11 @@ dw_hdmi_rockchip_bridge_mode_set(struct drm_bridge *bridge, + const struct drm_display_mode *adjusted_mode) + { + struct rockchip_hdmi *hdmi = to_rockchip_hdmi(bridge); ++ struct drm_crtc_state *crtc_state = to_crtc_state(adjusted_mode); ++ struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); ++ ++ if (hdmi->phy) ++ phy_set_bus_width(hdmi->phy, s->bus_width); + + clk_set_rate(hdmi->vpll_clk, adjusted_mode->clock * 1000); + } +@@ -320,6 +326,7 @@ static void dw_hdmi_rockchip_bridge_enable(struct drm_bridge *bridge) + static bool is_rgb(u32 format) + { + switch (format) { ++ case MEDIA_BUS_FMT_RGB101010_1X30: + case MEDIA_BUS_FMT_RGB888_1X24: + return true; + default: +@@ -327,6 +334,16 @@ static bool is_rgb(u32 format) + } + } + ++static bool is_10bit(u32 format) ++{ ++ switch (format) { ++ case MEDIA_BUS_FMT_RGB101010_1X30: ++ return true; ++ default: ++ return false; ++ } ++} ++ + static int + dw_hdmi_rockchip_bridge_atomic_check(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, +@@ -334,9 +351,24 @@ dw_hdmi_rockchip_bridge_atomic_check(struct drm_bridge *bridge, + struct drm_connector_state *conn_state) + { + struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); ++ struct drm_atomic_state *state = bridge_state->base.state; ++ struct drm_crtc_state *old_crtc_state; ++ struct rockchip_crtc_state *old_state; ++ u32 format = bridge_state->output_bus_cfg.format; + + s->output_mode = ROCKCHIP_OUT_MODE_AAAA; + s->output_type = DRM_MODE_CONNECTOR_HDMIA; ++ s->output_bpc = 10; ++ s->bus_format = format; ++ s->bus_width = is_10bit(format) ? 10 : 8; ++ ++ old_crtc_state = drm_atomic_get_old_crtc_state(state, conn_state->crtc); ++ if (old_crtc_state && !crtc_state->mode_changed) { ++ old_state = to_rockchip_crtc_state(old_crtc_state); ++ if (s->bus_format != old_state->bus_format || ++ s->bus_width != old_state->bus_width) ++ crtc_state->mode_changed = true; ++ } + + return 0; + } +@@ -348,10 +380,19 @@ static u32 *dw_hdmi_rockchip_get_input_bus_fmts(struct drm_bridge *bridge, + u32 output_fmt, + unsigned int *num_input_fmts) + { ++ struct rockchip_hdmi *hdmi = to_rockchip_hdmi(bridge); ++ struct drm_encoder *encoder = bridge->encoder; + u32 *input_fmt; ++ bool has_10bit = true; + + *num_input_fmts = 0; + ++ if (drm_of_encoder_active_endpoint_id(hdmi->dev->of_node, encoder)) ++ has_10bit = false; ++ ++ if (!has_10bit && is_10bit(output_fmt)) ++ return NULL; ++ + if (!is_rgb(output_fmt)) + return NULL; + +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +index e33c2dcd0d4b..03944e08b6c7 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +@@ -31,6 +31,8 @@ struct rockchip_crtc_state { + int output_bpc; + int output_flags; + bool enable_afbc; ++ u32 bus_format; ++ int bus_width; + }; + #define to_rockchip_crtc_state(s) \ + container_of(s, struct rockchip_crtc_state, base) + +From 7eda226a69e0c2b4fd8ab41b51ddff08da682073 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 8 Dec 2019 23:42:44 +0000 +Subject: [PATCH] WIP: drm: dw-hdmi: add content type connector property + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 26c64cf2d00a..ffb72e6874c8 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -1646,6 +1646,7 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, + const struct drm_connector *connector, + const struct drm_display_mode *mode) + { ++ const struct drm_connector_state *conn_state = connector->state; + struct hdmi_avi_infoframe frame; + u8 val; + +@@ -1703,6 +1704,8 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, + HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; + } + ++ drm_hdmi_avi_infoframe_content_type(&frame, conn_state); ++ + /* + * The Designware IP uses a different byte format from standard + * AVI info frames, though generally the bits are in the correct +@@ -2437,7 +2440,8 @@ static int dw_hdmi_connector_atomic_check(struct drm_connector *connector, + if (!crtc) + return 0; + +- if (!hdr_metadata_equal(old_state, new_state)) { ++ if (!hdr_metadata_equal(old_state, new_state) || ++ old_state->content_type != new_state->content_type) { + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (IS_ERR(crtc_state)) + return PTR_ERR(crtc_state); +@@ -2505,6 +2509,8 @@ static int dw_hdmi_connector_create(struct dw_hdmi *hdmi) + + drm_connector_attach_max_bpc_property(connector, 8, 16); + ++ drm_connector_attach_content_type_property(connector); ++ + if (hdmi->version >= 0x200a && hdmi->plat_data->use_drm_infoframe) + drm_object_attach_property(&connector->base, + connector->dev->mode_config.hdr_output_metadata_property, 0); + +From 8e94faae53df05c7466387b65edc808218f15277 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Fri, 20 Dec 2019 08:12:43 +0000 +Subject: [PATCH] WIP: drm/rockchip: add yuv444 support + +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 30 ++++++++++++++++++++- + drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 29 ++++++++++++++++++++ + drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 6 +++++ + drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 14 ++++++++++ + 4 files changed, 78 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index cd87ee8a65c3..436a9223e5e4 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -62,6 +62,7 @@ struct rockchip_hdmi_chip_data { + int lcdsel_grf_reg; + u32 lcdsel_big; + u32 lcdsel_lit; ++ bool ycbcr_444_allowed; + }; + + struct rockchip_hdmi { +@@ -334,10 +335,22 @@ static bool is_rgb(u32 format) + } + } + ++static bool is_yuv444(u32 format) ++{ ++ switch (format) { ++ case MEDIA_BUS_FMT_YUV10_1X30: ++ case MEDIA_BUS_FMT_YUV8_1X24: ++ return true; ++ default: ++ return false; ++ } ++} ++ + static bool is_10bit(u32 format) + { + switch (format) { + case MEDIA_BUS_FMT_RGB101010_1X30: ++ case MEDIA_BUS_FMT_YUV10_1X30: + return true; + default: + return false; +@@ -354,12 +367,22 @@ dw_hdmi_rockchip_bridge_atomic_check(struct drm_bridge *bridge, + struct drm_atomic_state *state = bridge_state->base.state; + struct drm_crtc_state *old_crtc_state; + struct rockchip_crtc_state *old_state; ++ struct drm_bridge *next_bridge; ++ struct drm_bridge_state *next_bridge_state; + u32 format = bridge_state->output_bus_cfg.format; + + s->output_mode = ROCKCHIP_OUT_MODE_AAAA; + s->output_type = DRM_MODE_CONNECTOR_HDMIA; + s->output_bpc = 10; + s->bus_format = format; ++ ++ next_bridge = drm_bridge_get_next_bridge(bridge); ++ if (next_bridge) { ++ next_bridge_state = drm_atomic_get_new_bridge_state(state, ++ next_bridge); ++ format = next_bridge_state->output_bus_cfg.format; ++ } ++ + s->bus_width = is_10bit(format) ? 10 : 8; + + old_crtc_state = drm_atomic_get_old_crtc_state(state, conn_state->crtc); +@@ -393,7 +416,10 @@ static u32 *dw_hdmi_rockchip_get_input_bus_fmts(struct drm_bridge *bridge, + if (!has_10bit && is_10bit(output_fmt)) + return NULL; + +- if (!is_rgb(output_fmt)) ++ if (is_yuv444(output_fmt)) { ++ if (!hdmi->chip_data->ycbcr_444_allowed) ++ return NULL; ++ } else if (!is_rgb(output_fmt)) + return NULL; + + input_fmt = kzalloc(sizeof(*input_fmt), GFP_KERNEL); +@@ -542,6 +568,7 @@ static const struct dw_hdmi_phy_ops rk3328_hdmi_phy_ops = { + + static struct rockchip_hdmi_chip_data rk3328_chip_data = { + .lcdsel_grf_reg = -1, ++ .ycbcr_444_allowed = true, + }; + + static const struct dw_hdmi_plat_data rk3328_hdmi_drv_data = { +@@ -557,6 +584,7 @@ static struct rockchip_hdmi_chip_data rk3399_chip_data = { + .lcdsel_grf_reg = RK3399_GRF_SOC_CON20, + .lcdsel_big = HIWORD_UPDATE(0, RK3399_HDMI_LCDC_SEL), + .lcdsel_lit = HIWORD_UPDATE(RK3399_HDMI_LCDC_SEL, RK3399_HDMI_LCDC_SEL), ++ .ycbcr_444_allowed = true, + }; + + static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = { +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +index 5ab1412173a7..a17bd4e90ba7 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +@@ -310,6 +310,17 @@ static int vop_convert_afbc_format(uint32_t format) + return -EINVAL; + } + ++static bool is_yuv_output(uint32_t bus_format) ++{ ++ switch (bus_format) { ++ case MEDIA_BUS_FMT_YUV8_1X24: ++ case MEDIA_BUS_FMT_YUV10_1X30: ++ return true; ++ default: ++ return false; ++ } ++} ++ + static uint16_t scl_vop_cal_scale(enum scale_mode mode, uint32_t src, + uint32_t dst, bool is_horizontal, + int vsu_mode, int *vskiplines) +@@ -1329,6 +1340,7 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, + u16 vact_end = vact_st + vdisplay; + uint32_t pin_pol, val; + int dither_bpc = s->output_bpc ? s->output_bpc : 10; ++ bool yuv_output = is_yuv_output(s->bus_format); + int ret; + + if (old_state && old_state->self_refresh_active) { +@@ -1402,6 +1414,8 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, + !(vop_data->feature & VOP_FEATURE_OUTPUT_RGB10)) + s->output_mode = ROCKCHIP_OUT_MODE_P888; + ++ VOP_REG_SET(vop, common, dsp_data_swap, yuv_output ? 2 : 0); ++ + if (s->output_mode == ROCKCHIP_OUT_MODE_AAAA && dither_bpc <= 8) + VOP_REG_SET(vop, common, pre_dither_down, 1); + else +@@ -1417,6 +1431,21 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, + + VOP_REG_SET(vop, common, out_mode, s->output_mode); + ++ VOP_REG_SET(vop, common, overlay_mode, yuv_output); ++ VOP_REG_SET(vop, common, dsp_out_yuv, yuv_output); ++ ++ /* ++ * Background color is 10bit depth if vop version >= 3.5 ++ */ ++ if (!yuv_output) ++ val = 0; ++ else if (VOP_MAJOR(vop_data->version) == 3 && ++ VOP_MINOR(vop_data->version) >= 5) ++ val = 0x20010200; ++ else ++ val = 0x801080; ++ VOP_REG_SET(vop, common, dsp_background, val); ++ + VOP_REG_SET(vop, modeset, htotal_pw, (htotal << 16) | hsync_len); + val = hact_st << 16; + val |= hact_end; +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +index 1516231bbf93..b820ad3fa091 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +@@ -92,10 +92,16 @@ struct vop_common { + struct vop_reg mmu_en; + struct vop_reg out_mode; + struct vop_reg standby; ++ ++ struct vop_reg overlay_mode; ++ struct vop_reg dsp_data_swap; ++ struct vop_reg dsp_out_yuv; ++ struct vop_reg dsp_background; + }; + + struct vop_misc { + struct vop_reg global_regdone_en; ++ struct vop_reg win_channel[4]; + }; + + struct vop_intr { +diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +index 57c36e9207c1..800b9341dd42 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c ++++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +@@ -644,6 +644,11 @@ static const struct vop_common rk3288_common = { + .dsp_blank = VOP_REG(RK3288_DSP_CTRL0, 0x3, 18), + .out_mode = VOP_REG(RK3288_DSP_CTRL0, 0xf, 0), + .cfg_done = VOP_REG_SYNC(RK3288_REG_CFG_DONE, 0x1, 0), ++ ++ .overlay_mode = VOP_REG(RK3288_SYS_CTRL, 0x1, 16), ++ .dsp_data_swap = VOP_REG(RK3288_DSP_CTRL0, 0x1f, 12), ++ .dsp_out_yuv = VOP_REG(RK3288_POST_SCL_CTRL, 0x1, 2), ++ .dsp_background = VOP_REG(RK3288_DSP_BG, 0xffffffff, 0), + }; + + /* +@@ -996,6 +1001,10 @@ static const struct vop_output rk3328_output = { + + static const struct vop_misc rk3328_misc = { + .global_regdone_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 11), ++ ++ .win_channel[0] = VOP_REG(RK3328_WIN0_CTRL2, 0xff, 0), ++ .win_channel[1] = VOP_REG(RK3328_WIN1_CTRL2, 0xff, 0), ++ .win_channel[2] = VOP_REG(RK3328_WIN2_CTRL2, 0xff, 0), + }; + + static const struct vop_common rk3328_common = { +@@ -1008,6 +1017,11 @@ static const struct vop_common rk3328_common = { + .dsp_blank = VOP_REG(RK3328_DSP_CTRL0, 0x3, 18), + .out_mode = VOP_REG(RK3328_DSP_CTRL0, 0xf, 0), + .cfg_done = VOP_REG_SYNC(RK3328_REG_CFG_DONE, 0x1, 0), ++ ++ .overlay_mode = VOP_REG(RK3328_SYS_CTRL, 0x1, 16), ++ .dsp_data_swap = VOP_REG(RK3328_DSP_CTRL0, 0x1f, 12), ++ .dsp_out_yuv = VOP_REG(RK3328_POST_SCL_CTRL, 0x1, 2), ++ .dsp_background = VOP_REG(RK3328_DSP_BG, 0xffffffff, 0), + }; + + static const struct vop_intr rk3328_vop_intr = { + +From d5563c9163f1a691e73c1b027d39c78672ff3e17 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Fri, 20 Dec 2019 08:12:43 +0000 +Subject: [PATCH] WIP: drm/rockchip: add yuv420 support + +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 23 +++++++++++++++++++++ + drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 18 +++++++++++++++- + drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 10 +++++---- + drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 2 ++ + 4 files changed, 48 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index 436a9223e5e4..1abc46a023a4 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -346,9 +346,21 @@ static bool is_yuv444(u32 format) + } + } + ++static bool is_yuv420(u32 format) ++{ ++ switch (format) { ++ case MEDIA_BUS_FMT_UYYVYY10_0_5X30: ++ case MEDIA_BUS_FMT_UYYVYY8_0_5X24: ++ return true; ++ default: ++ return false; ++ } ++} ++ + static bool is_10bit(u32 format) + { + switch (format) { ++ case MEDIA_BUS_FMT_UYYVYY10_0_5X30: + case MEDIA_BUS_FMT_RGB101010_1X30: + case MEDIA_BUS_FMT_YUV10_1X30: + return true; +@@ -385,6 +397,11 @@ dw_hdmi_rockchip_bridge_atomic_check(struct drm_bridge *bridge, + + s->bus_width = is_10bit(format) ? 10 : 8; + ++ if (is_yuv420(format)) { ++ s->output_mode = ROCKCHIP_OUT_MODE_YUV420; ++ s->bus_width /= 2; ++ } ++ + old_crtc_state = drm_atomic_get_old_crtc_state(state, conn_state->crtc); + if (old_crtc_state && !crtc_state->mode_changed) { + old_state = to_rockchip_crtc_state(old_crtc_state); +@@ -405,6 +422,7 @@ static u32 *dw_hdmi_rockchip_get_input_bus_fmts(struct drm_bridge *bridge, + { + struct rockchip_hdmi *hdmi = to_rockchip_hdmi(bridge); + struct drm_encoder *encoder = bridge->encoder; ++ struct drm_connector *connector = conn_state->connector; + u32 *input_fmt; + bool has_10bit = true; + +@@ -419,6 +437,9 @@ static u32 *dw_hdmi_rockchip_get_input_bus_fmts(struct drm_bridge *bridge, + if (is_yuv444(output_fmt)) { + if (!hdmi->chip_data->ycbcr_444_allowed) + return NULL; ++ } else if (is_yuv420(output_fmt)) { ++ if (!connector->ycbcr_420_allowed) ++ return NULL; + } else if (!is_rgb(output_fmt)) + return NULL; + +@@ -578,6 +599,7 @@ static const struct dw_hdmi_plat_data rk3328_hdmi_drv_data = { + .phy_name = "inno_dw_hdmi_phy2", + .phy_force_vendor = true, + .use_drm_infoframe = true, ++ .ycbcr_420_allowed = true, + }; + + static struct rockchip_hdmi_chip_data rk3399_chip_data = { +@@ -595,6 +617,7 @@ static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = { + .phy_config = rockchip_phy_config, + .phy_data = &rk3399_chip_data, + .use_drm_infoframe = true, ++ .ycbcr_420_allowed = true, + }; + + static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = { +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +index a17bd4e90ba7..5ea8031eb0f7 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +@@ -311,6 +311,19 @@ static int vop_convert_afbc_format(uint32_t format) + } + + static bool is_yuv_output(uint32_t bus_format) ++{ ++ switch (bus_format) { ++ case MEDIA_BUS_FMT_YUV8_1X24: ++ case MEDIA_BUS_FMT_YUV10_1X30: ++ case MEDIA_BUS_FMT_UYYVYY8_0_5X24: ++ case MEDIA_BUS_FMT_UYYVYY10_0_5X30: ++ return true; ++ default: ++ return false; ++ } ++} ++ ++static bool has_uv_swapped(uint32_t bus_format) + { + switch (bus_format) { + case MEDIA_BUS_FMT_YUV8_1X24: +@@ -1414,7 +1427,7 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, + !(vop_data->feature & VOP_FEATURE_OUTPUT_RGB10)) + s->output_mode = ROCKCHIP_OUT_MODE_P888; + +- VOP_REG_SET(vop, common, dsp_data_swap, yuv_output ? 2 : 0); ++ VOP_REG_SET(vop, common, dsp_data_swap, has_uv_swapped(s->bus_format) ? 2 : 0); + + if (s->output_mode == ROCKCHIP_OUT_MODE_AAAA && dither_bpc <= 8) + VOP_REG_SET(vop, common, pre_dither_down, 1); +@@ -1431,6 +1444,9 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, + + VOP_REG_SET(vop, common, out_mode, s->output_mode); + ++ VOP_REG_SET(vop, common, dclk_ddr, ++ s->output_mode == ROCKCHIP_OUT_MODE_YUV420 ? 1 : 0); ++ + VOP_REG_SET(vop, common, overlay_mode, yuv_output); + VOP_REG_SET(vop, common, dsp_out_yuv, yuv_output); + +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +index b820ad3fa091..8e6e999e5163 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +@@ -94,6 +94,7 @@ struct vop_common { + struct vop_reg standby; + + struct vop_reg overlay_mode; ++ struct vop_reg dclk_ddr; + struct vop_reg dsp_data_swap; + struct vop_reg dsp_out_yuv; + struct vop_reg dsp_background; +@@ -257,11 +258,12 @@ struct vop_data { + /* + * display output interface supported by rockchip lcdc + */ +-#define ROCKCHIP_OUT_MODE_P888 0 +-#define ROCKCHIP_OUT_MODE_P666 1 +-#define ROCKCHIP_OUT_MODE_P565 2 ++#define ROCKCHIP_OUT_MODE_P888 0 ++#define ROCKCHIP_OUT_MODE_P666 1 ++#define ROCKCHIP_OUT_MODE_P565 2 ++#define ROCKCHIP_OUT_MODE_YUV420 14 + /* for use special outface */ +-#define ROCKCHIP_OUT_MODE_AAAA 15 ++#define ROCKCHIP_OUT_MODE_AAAA 15 + + /* output flags */ + #define ROCKCHIP_OUTPUT_DSI_DUAL BIT(0) +diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +index 800b9341dd42..dd4546f9f410 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c ++++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +@@ -646,6 +646,7 @@ static const struct vop_common rk3288_common = { + .cfg_done = VOP_REG_SYNC(RK3288_REG_CFG_DONE, 0x1, 0), + + .overlay_mode = VOP_REG(RK3288_SYS_CTRL, 0x1, 16), ++ .dclk_ddr = VOP_REG(RK3288_DSP_CTRL0, 0x1, 8), + .dsp_data_swap = VOP_REG(RK3288_DSP_CTRL0, 0x1f, 12), + .dsp_out_yuv = VOP_REG(RK3288_POST_SCL_CTRL, 0x1, 2), + .dsp_background = VOP_REG(RK3288_DSP_BG, 0xffffffff, 0), +@@ -1019,6 +1020,7 @@ static const struct vop_common rk3328_common = { + .cfg_done = VOP_REG_SYNC(RK3328_REG_CFG_DONE, 0x1, 0), + + .overlay_mode = VOP_REG(RK3328_SYS_CTRL, 0x1, 16), ++ .dclk_ddr = VOP_REG(RK3328_DSP_CTRL0, 0x1, 8), + .dsp_data_swap = VOP_REG(RK3328_DSP_CTRL0, 0x1f, 12), + .dsp_out_yuv = VOP_REG(RK3328_POST_SCL_CTRL, 0x1, 2), + .dsp_background = VOP_REG(RK3328_DSP_BG, 0xffffffff, 0), + +From 1b47a0a13f295cff2a50f6b4af272b7ee1f01534 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 7 Jun 2020 20:25:25 +0000 +Subject: [PATCH] drm: drm_fourcc: add NV20 and NV30 YUV formats + +DRM_FORMAT_NV20 and DRM_FORMAT_NV30 formats is the 2x1 and non-subsampled +variant of NV15, a 10-bit 2-plane YUV format that has no padding between +components. Instead, luminance and chrominance samples are grouped into 4s +so that each group is packed into an integer number of bytes: + +YYYY = UVUV = 4 * 10 bits = 40 bits = 5 bytes + +The '20' and '30' suffix refers to the optimum effective bits per pixel +which is achieved when the total number of luminance samples is a multiple +of 4. + +V2: Added NV30 format + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/drm_fourcc.c | 8 ++++++++ + include/uapi/drm/drm_fourcc.h | 2 ++ + 2 files changed, 10 insertions(+) + +diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c +index 722c7ebe4e88..2daf8a304b53 100644 +--- a/drivers/gpu/drm/drm_fourcc.c ++++ b/drivers/gpu/drm/drm_fourcc.c +@@ -278,6 +278,14 @@ const struct drm_format_info *__drm_format_info(u32 format) + .num_planes = 2, .char_per_block = { 5, 5, 0 }, + .block_w = { 4, 2, 0 }, .block_h = { 1, 1, 0 }, .hsub = 2, + .vsub = 2, .is_yuv = true }, ++ { .format = DRM_FORMAT_NV20, .depth = 0, ++ .num_planes = 2, .char_per_block = { 5, 5, 0 }, ++ .block_w = { 4, 2, 0 }, .block_h = { 1, 1, 0 }, .hsub = 2, ++ .vsub = 1, .is_yuv = true }, ++ { .format = DRM_FORMAT_NV30, .depth = 0, ++ .num_planes = 2, .char_per_block = { 5, 5, 0 }, ++ .block_w = { 4, 2, 0 }, .block_h = { 1, 1, 0 }, .hsub = 1, ++ .vsub = 1, .is_yuv = true }, + { .format = DRM_FORMAT_Q410, .depth = 0, + .num_planes = 3, .char_per_block = { 2, 2, 2 }, + .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 }, .hsub = 0, +diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h +index 82f327801267..d8e6159213dc 100644 +--- a/include/uapi/drm/drm_fourcc.h ++++ b/include/uapi/drm/drm_fourcc.h +@@ -242,6 +242,8 @@ extern "C" { + * index 1 = Cr:Cb plane, [39:0] Cr1:Cb1:Cr0:Cb0 little endian + */ + #define DRM_FORMAT_NV15 fourcc_code('N', 'V', '1', '5') /* 2x2 subsampled Cr:Cb plane */ ++#define DRM_FORMAT_NV20 fourcc_code('N', 'V', '2', '0') /* 2x1 subsampled Cr:Cb plane */ ++#define DRM_FORMAT_NV30 fourcc_code('N', 'V', '3', '0') /* non-subsampled Cr:Cb plane */ + + /* + * 2 plane YCbCr MSB aligned + +From 6c52f23c9f8215a7a5a99d6ac299701baa85a8cb Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 7 Jun 2020 20:25:26 +0000 +Subject: [PATCH] drm: rockchip: add NV15, NV20 and NV30 support + +Add support for displaying 10-bit 4:2:0 and 4:2:2 formats produced by the +Rockchip Video Decoder on RK322X, RK3288, RK3328, RK3368 and RK3399. +Also add support for 10-bit 4:4:4 format while at it. + +V2: Added NV30 support + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 29 +++++++++++++++++-- + drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 1 + + drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 32 +++++++++++++++++---- + 3 files changed, 54 insertions(+), 8 deletions(-) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +index 5ea8031eb0f7..413534cf1a93 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +@@ -261,6 +261,18 @@ static bool has_rb_swapped(uint32_t format) + } + } + ++static bool is_fmt_10(uint32_t format) ++{ ++ switch (format) { ++ case DRM_FORMAT_NV15: ++ case DRM_FORMAT_NV20: ++ case DRM_FORMAT_NV30: ++ return true; ++ default: ++ return false; ++ } ++} ++ + static enum vop_data_format vop_convert_format(uint32_t format) + { + switch (format) { +@@ -276,10 +288,13 @@ static enum vop_data_format vop_convert_format(uint32_t format) + case DRM_FORMAT_BGR565: + return VOP_FMT_RGB565; + case DRM_FORMAT_NV12: ++ case DRM_FORMAT_NV15: + return VOP_FMT_YUV420SP; + case DRM_FORMAT_NV16: ++ case DRM_FORMAT_NV20: + return VOP_FMT_YUV422SP; + case DRM_FORMAT_NV24: ++ case DRM_FORMAT_NV30: + return VOP_FMT_YUV444SP; + default: + DRM_ERROR("unsupported format[%08x]\n", format); +@@ -946,7 +961,12 @@ static void vop_plane_atomic_update(struct drm_plane *plane, + dsp_sty = dest->y1 + crtc->mode.vtotal - crtc->mode.vsync_start; + dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff); + +- offset = (src->x1 >> 16) * fb->format->cpp[0]; ++ if (fb->format->block_w[0]) ++ offset = (src->x1 >> 16) * fb->format->char_per_block[0] / ++ fb->format->block_w[0]; ++ else ++ offset = (src->x1 >> 16) * fb->format->cpp[0]; ++ + offset += (src->y1 >> 16) * fb->pitches[0]; + dma_addr = rk_obj->dma_addr + offset + fb->offsets[0]; + +@@ -972,6 +992,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane, + } + + VOP_WIN_SET(vop, win, format, format); ++ VOP_WIN_SET(vop, win, fmt_10, is_fmt_10(fb->format->format)); + VOP_WIN_SET(vop, win, yrgb_vir, DIV_ROUND_UP(fb->pitches[0], 4)); + VOP_WIN_SET(vop, win, yrgb_mst, dma_addr); + VOP_WIN_YUV2YUV_SET(vop, win_yuv2yuv, y2r_en, is_yuv); +@@ -988,7 +1009,11 @@ static void vop_plane_atomic_update(struct drm_plane *plane, + uv_obj = fb->obj[1]; + rk_uv_obj = to_rockchip_obj(uv_obj); + +- offset = (src->x1 >> 16) * bpp / hsub; ++ if (fb->format->block_w[1]) ++ offset = (src->x1 >> 16) * bpp / ++ fb->format->block_w[1] / hsub; ++ else ++ offset = (src->x1 >> 16) * bpp / hsub; + offset += (src->y1 >> 16) * fb->pitches[1] / vsub; + + dma_addr = rk_uv_obj->dma_addr + offset + fb->offsets[1]; +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +index 8e6e999e5163..9f50e0e00127 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +@@ -161,6 +161,7 @@ struct vop_win_phy { + struct vop_reg enable; + struct vop_reg gate; + struct vop_reg format; ++ struct vop_reg fmt_10; + struct vop_reg rb_swap; + struct vop_reg act_info; + struct vop_reg dsp_info; +diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +index dd4546f9f410..7d5191421ddf 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c ++++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +@@ -50,6 +50,23 @@ static const uint32_t formats_win_full[] = { + DRM_FORMAT_NV24, + }; + ++static const uint32_t formats_win_full_10[] = { ++ DRM_FORMAT_XRGB8888, ++ DRM_FORMAT_ARGB8888, ++ DRM_FORMAT_XBGR8888, ++ DRM_FORMAT_ABGR8888, ++ DRM_FORMAT_RGB888, ++ DRM_FORMAT_BGR888, ++ DRM_FORMAT_RGB565, ++ DRM_FORMAT_BGR565, ++ DRM_FORMAT_NV12, ++ DRM_FORMAT_NV16, ++ DRM_FORMAT_NV24, ++ DRM_FORMAT_NV15, ++ DRM_FORMAT_NV20, ++ DRM_FORMAT_NV30, ++}; ++ + static const uint64_t format_modifiers_win_full[] = { + DRM_FORMAT_MOD_LINEAR, + DRM_FORMAT_MOD_INVALID, +@@ -579,11 +596,12 @@ static const struct vop_scl_regs rk3288_win_full_scl = { + + static const struct vop_win_phy rk3288_win01_data = { + .scl = &rk3288_win_full_scl, +- .data_formats = formats_win_full, +- .nformats = ARRAY_SIZE(formats_win_full), ++ .data_formats = formats_win_full_10, ++ .nformats = ARRAY_SIZE(formats_win_full_10), + .format_modifiers = format_modifiers_win_full, + .enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0), + .format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1), ++ .fmt_10 = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 4), + .rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12), + .act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0), + .dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0), +@@ -720,11 +738,12 @@ static const struct vop_intr rk3368_vop_intr = { + + static const struct vop_win_phy rk3368_win01_data = { + .scl = &rk3288_win_full_scl, +- .data_formats = formats_win_full, +- .nformats = ARRAY_SIZE(formats_win_full), ++ .data_formats = formats_win_full_10, ++ .nformats = ARRAY_SIZE(formats_win_full_10), + .format_modifiers = format_modifiers_win_full, + .enable = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 0), + .format = VOP_REG(RK3368_WIN0_CTRL0, 0x7, 1), ++ .fmt_10 = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 4), + .rb_swap = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 12), + .x_mir_en = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 21), + .y_mir_en = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 22), +@@ -871,11 +890,12 @@ static const struct vop_win_yuv2yuv_data rk3399_vop_big_win_yuv2yuv_data[] = { + + static const struct vop_win_phy rk3399_win01_data = { + .scl = &rk3288_win_full_scl, +- .data_formats = formats_win_full, +- .nformats = ARRAY_SIZE(formats_win_full), ++ .data_formats = formats_win_full_10, ++ .nformats = ARRAY_SIZE(formats_win_full_10), + .format_modifiers = format_modifiers_win_full_afbc, + .enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0), + .format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1), ++ .fmt_10 = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 4), + .rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12), + .y_mir_en = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 22), + .act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0), + +From 82b749d252ad0a50a36ad7ca93335e8d8e5416b7 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sat, 15 Aug 2020 21:11:08 +0200 +Subject: [PATCH] drm/rockchip: rk3368's vop does not support 10-bit formats - + neither as input nor as output + +--- + drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +index 7d5191421ddf..20c3e6248ec7 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c ++++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +@@ -738,8 +738,8 @@ static const struct vop_intr rk3368_vop_intr = { + + static const struct vop_win_phy rk3368_win01_data = { + .scl = &rk3288_win_full_scl, +- .data_formats = formats_win_full_10, +- .nformats = ARRAY_SIZE(formats_win_full_10), ++ .data_formats = formats_win_full, ++ .nformats = ARRAY_SIZE(formats_win_full), + .format_modifiers = format_modifiers_win_full, + .enable = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 0), + .format = VOP_REG(RK3368_WIN0_CTRL0, 0x7, 1), + +From 74b287a1526a234bd9450461087f7b3ae53ead5f Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sat, 15 Aug 2020 23:20:34 +0200 +Subject: [PATCH] drm/rockchip: enable ycbcr_420_allowed and ycbcr_444_allowed + for RK3228 + +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index 1abc46a023a4..64a79b33ff18 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -555,6 +555,7 @@ static const struct dw_hdmi_phy_ops rk3228_hdmi_phy_ops = { + + static struct rockchip_hdmi_chip_data rk3228_chip_data = { + .lcdsel_grf_reg = -1, ++ .ycbcr_444_allowed = true, + }; + + static const struct dw_hdmi_plat_data rk3228_hdmi_drv_data = { +@@ -563,6 +564,7 @@ static const struct dw_hdmi_plat_data rk3228_hdmi_drv_data = { + .phy_ops = &rk3228_hdmi_phy_ops, + .phy_name = "inno_dw_hdmi_phy2", + .phy_force_vendor = true, ++ .ycbcr_420_allowed = true, + }; + + static struct rockchip_hdmi_chip_data rk3288_chip_data = { + +From 93f930ae209a684210098a2612df72b19b8db88a Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Wed, 22 Jul 2020 20:13:28 +0200 +Subject: [PATCH] drm: rockchip: add scaling for RK3036 win1 + +Add the registers needed to make scaling work on RK3036's win1. + +Signed-off-by: Alex Bee +--- + drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +index 20c3e6248ec7..93a00b6ac295 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c ++++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +@@ -94,15 +94,20 @@ static const uint64_t format_modifiers_win_lite[] = { + DRM_FORMAT_MOD_INVALID, + }; + +-static const struct vop_scl_regs rk3036_win_scl = { ++static const struct vop_scl_regs rk3036_win0_scl = { + .scale_yrgb_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0), + .scale_yrgb_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 16), + .scale_cbcr_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0), + .scale_cbcr_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 16), + }; + ++static const struct vop_scl_regs rk3036_win1_scl = { ++ .scale_yrgb_x = VOP_REG(RK3036_WIN1_SCL_FACTOR_YRGB, 0xffff, 0x0), ++ .scale_yrgb_y = VOP_REG(RK3036_WIN1_SCL_FACTOR_YRGB, 0xffff, 16), ++}; ++ + static const struct vop_win_phy rk3036_win0_data = { +- .scl = &rk3036_win_scl, ++ .scl = &rk3036_win0_scl, + .data_formats = formats_win_full, + .nformats = ARRAY_SIZE(formats_win_full), + .format_modifiers = format_modifiers_win_full, +@@ -119,6 +124,7 @@ static const struct vop_win_phy rk3036_win0_data = { + }; + + static const struct vop_win_phy rk3036_win1_data = { ++ .scl = &rk3036_win1_scl, + .data_formats = formats_win_lite, + .nformats = ARRAY_SIZE(formats_win_lite), + .format_modifiers = format_modifiers_win_lite, + +From 5251b3cefd51bbf0c28da354b8e59e4f540d4b94 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Wed, 22 Jul 2020 20:13:29 +0200 +Subject: [PATCH] drm: rockchip: add missing registers for RK3188 + +Add dither_up, dsp_lut_en and data_blank registers to enable their +respective functionality for RK3188's VOP. + +Signed-off-by: Alex Bee +--- + drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +index 93a00b6ac295..2638d084f9ce 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c ++++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +@@ -529,6 +529,9 @@ static const struct vop_common rk3188_common = { + .dither_down_en = VOP_REG(RK3188_DSP_CTRL0, 0x1, 11), + .dither_down_mode = VOP_REG(RK3188_DSP_CTRL0, 0x1, 10), + .dsp_blank = VOP_REG(RK3188_DSP_CTRL1, 0x3, 24), ++ .dither_up = VOP_REG(RK3188_DSP_CTRL0, 0x1, 9), ++ .dsp_lut_en = VOP_REG(RK3188_SYS_CTRL, 0x1, 28), ++ .data_blank = VOP_REG(RK3188_DSP_CTRL1, 0x1, 25), + }; + + static const struct vop_win_data rk3188_vop_win_data[] = { + +From cb6d552767e2ce4b79be85cdb3a1526869d11ce4 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Wed, 22 Jul 2020 20:13:30 +0200 +Subject: [PATCH] drm: rockchip: add alpha support for RK3036, RK3066, RK3126 + and RK3188 + +With commit 2aae8ed1f390 +("drm/rockchip: Add per-pixel alpha support for the PX30 VOP") alpha +support was introduced for PX30's VOP. +RK3036, RK3066, RK3126 and RK3188 VOPs support alpha blending in the +same manner. +With the exception of RK3066 all of them support pre-multiplied alpha. + +Lets add these registers to make this work for those VOPs as well. + +Signed-off-by: Alex Bee +--- + drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 21 +++++++++++++++++++++ + drivers/gpu/drm/rockchip/rockchip_vop_reg.h | 1 + + 2 files changed, 22 insertions(+) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +index 2638d084f9ce..e1db4e57c51a 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c ++++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +@@ -121,6 +121,9 @@ static const struct vop_win_phy rk3036_win0_data = { + .uv_mst = VOP_REG(RK3036_WIN0_CBR_MST, 0xffffffff, 0), + .yrgb_vir = VOP_REG(RK3036_WIN0_VIR, 0xffff, 0), + .uv_vir = VOP_REG(RK3036_WIN0_VIR, 0x1fff, 16), ++ .alpha_mode = VOP_REG(RK3036_DSP_CTRL0, 0x1, 18), ++ .alpha_en = VOP_REG(RK3036_ALPHA_CTRL, 0x1, 0), ++ .alpha_pre_mul = VOP_REG(RK3036_DSP_CTRL0, 0x1, 29), + }; + + static const struct vop_win_phy rk3036_win1_data = { +@@ -136,6 +139,9 @@ static const struct vop_win_phy rk3036_win1_data = { + .dsp_st = VOP_REG(RK3036_WIN1_DSP_ST, 0x1fff1fff, 0), + .yrgb_mst = VOP_REG(RK3036_WIN1_MST, 0xffffffff, 0), + .yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0), ++ .alpha_mode = VOP_REG(RK3036_DSP_CTRL0, 0x1, 19), ++ .alpha_en = VOP_REG(RK3036_ALPHA_CTRL, 0x1, 1), ++ .alpha_pre_mul = VOP_REG(RK3036_DSP_CTRL0, 0x1, 29), + }; + + static const struct vop_win_data rk3036_vop_win_data[] = { +@@ -202,6 +208,9 @@ static const struct vop_win_phy rk3126_win1_data = { + .dsp_st = VOP_REG(RK3126_WIN1_DSP_ST, 0x1fff1fff, 0), + .yrgb_mst = VOP_REG(RK3126_WIN1_MST, 0xffffffff, 0), + .yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0), ++ .alpha_mode = VOP_REG(RK3036_DSP_CTRL0, 0x1, 19), ++ .alpha_en = VOP_REG(RK3036_ALPHA_CTRL, 0x1, 1), ++ .alpha_pre_mul = VOP_REG(RK3036_DSP_CTRL0, 0x1, 29), + }; + + static const struct vop_win_data rk3126_vop_win_data[] = { +@@ -381,6 +390,8 @@ static const struct vop_win_phy rk3066_win0_data = { + .uv_mst = VOP_REG(RK3066_WIN0_CBR_MST0, 0xffffffff, 0), + .yrgb_vir = VOP_REG(RK3066_WIN0_VIR, 0xffff, 0), + .uv_vir = VOP_REG(RK3066_WIN0_VIR, 0x1fff, 16), ++ .alpha_mode = VOP_REG(RK3066_DSP_CTRL0, 0x1, 21), ++ .alpha_en = VOP_REG(RK3066_BLEND_CTRL, 0x1, 0), + }; + + static const struct vop_win_phy rk3066_win1_data = { +@@ -398,6 +409,8 @@ static const struct vop_win_phy rk3066_win1_data = { + .uv_mst = VOP_REG(RK3066_WIN1_CBR_MST, 0xffffffff, 0), + .yrgb_vir = VOP_REG(RK3066_WIN1_VIR, 0xffff, 0), + .uv_vir = VOP_REG(RK3066_WIN1_VIR, 0x1fff, 16), ++ .alpha_mode = VOP_REG(RK3066_DSP_CTRL0, 0x1, 22), ++ .alpha_en = VOP_REG(RK3066_BLEND_CTRL, 0x1, 1), + }; + + static const struct vop_win_phy rk3066_win2_data = { +@@ -411,6 +424,8 @@ static const struct vop_win_phy rk3066_win2_data = { + .dsp_st = VOP_REG(RK3066_WIN2_DSP_ST, 0x1fff1fff, 0), + .yrgb_mst = VOP_REG(RK3066_WIN2_MST, 0xffffffff, 0), + .yrgb_vir = VOP_REG(RK3066_WIN2_VIR, 0xffff, 0), ++ .alpha_mode = VOP_REG(RK3066_DSP_CTRL0, 0x1, 23), ++ .alpha_en = VOP_REG(RK3066_BLEND_CTRL, 0x1, 2), + }; + + static const struct vop_modeset rk3066_modeset = { +@@ -493,6 +508,9 @@ static const struct vop_win_phy rk3188_win0_data = { + .yrgb_mst = VOP_REG(RK3188_WIN0_YRGB_MST0, 0xffffffff, 0), + .uv_mst = VOP_REG(RK3188_WIN0_CBR_MST0, 0xffffffff, 0), + .yrgb_vir = VOP_REG(RK3188_WIN_VIR, 0x1fff, 0), ++ .alpha_mode = VOP_REG(RK3188_DSP_CTRL0, 0x1, 18), ++ .alpha_en = VOP_REG(RK3188_ALPHA_CTRL, 0x1, 0), ++ .alpha_pre_mul = VOP_REG(RK3188_DSP_CTRL0, 0x1, 29), + }; + + static const struct vop_win_phy rk3188_win1_data = { +@@ -507,6 +525,9 @@ static const struct vop_win_phy rk3188_win1_data = { + .dsp_st = VOP_REG(RK3188_WIN1_DSP_ST, 0x0fff0fff, 0), + .yrgb_mst = VOP_REG(RK3188_WIN1_MST, 0xffffffff, 0), + .yrgb_vir = VOP_REG(RK3188_WIN_VIR, 0x1fff, 16), ++ .alpha_mode = VOP_REG(RK3188_DSP_CTRL0, 0x1, 19), ++ .alpha_en = VOP_REG(RK3188_ALPHA_CTRL, 0x1, 1), ++ .alpha_pre_mul = VOP_REG(RK3188_DSP_CTRL0, 0x1, 29), + }; + + static const struct vop_modeset rk3188_modeset = { +diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h +index 6e9fa5815d4d..0b3cd65ba5c1 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h ++++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h +@@ -955,6 +955,7 @@ + #define RK3188_DSP_CTRL0 0x04 + #define RK3188_DSP_CTRL1 0x08 + #define RK3188_INT_STATUS 0x10 ++#define RK3188_ALPHA_CTRL 0x14 + #define RK3188_WIN0_YRGB_MST0 0x20 + #define RK3188_WIN0_CBR_MST0 0x24 + #define RK3188_WIN0_YRGB_MST1 0x28 + +From 931fd5e26f3b2dd7a758124dc9c024e944eeedb4 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Wed, 22 Jul 2020 20:13:31 +0200 +Subject: [PATCH] drm: rockchip: set alpha_en to 0 if it is not used + +alpha_en should be set to 0 if it is not used, i.e. to disable alpha +blending if it was enabled before and should be disabled now. + +Fixes: 2aae8ed1f390 ("drm/rockchip: Add per-pixel alpha support for the PX30 VOP") + +Signed-off-by: Alex Bee +--- + drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +index 413534cf1a93..9b1cc0f413fc 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +@@ -1062,6 +1062,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane, + VOP_WIN_SET(vop, win, alpha_en, 1); + } else { + VOP_WIN_SET(vop, win, src_alpha_ctl, SRC_ALPHA_EN(0)); ++ VOP_WIN_SET(vop, win, alpha_en, 0); + } + + VOP_WIN_SET(vop, win, enable, 1); + +From 87f111b8511eb1236c53ea4369502cf4c6847303 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sat, 15 Aug 2020 23:38:05 +0200 +Subject: [PATCH] rockchip/drm: add dsp_data_swap register for RK3188 + +--- + drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +index e1db4e57c51a..e10cb2d33951 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c ++++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +@@ -553,6 +553,7 @@ static const struct vop_common rk3188_common = { + .dither_up = VOP_REG(RK3188_DSP_CTRL0, 0x1, 9), + .dsp_lut_en = VOP_REG(RK3188_SYS_CTRL, 0x1, 28), + .data_blank = VOP_REG(RK3188_DSP_CTRL1, 0x1, 25), ++ .dsp_data_swap = VOP_REG(RK3188_DSP_CTRL1, 0x1f, 26), + }; + + static const struct vop_win_data rk3188_vop_win_data[] = { + +From 75e43e951351c5f0d269d7b788a9469a1ccadb48 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sun, 16 Aug 2020 00:55:19 +0200 +Subject: [PATCH] drm/rockchip: inno hdmi - add audio support - add required + aclk - fix video timing - fix phy pre-emphasis + +--- + .../display/rockchip/inno_hdmi-rockchip.txt | 6 +- + arch/arm/boot/dts/rk3036.dtsi | 24 +- + drivers/gpu/drm/rockchip/inno_hdmi.c | 266 +++++++++++++++++- + drivers/gpu/drm/rockchip/inno_hdmi.h | 2 + + 4 files changed, 279 insertions(+), 19 deletions(-) + +diff --git a/Documentation/devicetree/bindings/display/rockchip/inno_hdmi-rockchip.txt b/Documentation/devicetree/bindings/display/rockchip/inno_hdmi-rockchip.txt +index cec21714f0e0..b022c931e186 100644 +--- a/Documentation/devicetree/bindings/display/rockchip/inno_hdmi-rockchip.txt ++++ b/Documentation/devicetree/bindings/display/rockchip/inno_hdmi-rockchip.txt +@@ -7,7 +7,7 @@ Required properties: + - reg: + Physical base address and length of the controller's registers. + - clocks, clock-names: +- Phandle to hdmi controller clock, name should be "pclk" ++ Phandle to hdmi controller clock, name should be "aclk" and "pclk". + - interrupts: + HDMI interrupt number + - ports: +@@ -21,8 +21,8 @@ hdmi: hdmi@20034000 { + compatible = "rockchip,rk3036-inno-hdmi"; + reg = <0x20034000 0x4000>; + interrupts = ; +- clocks = <&cru PCLK_HDMI>; +- clock-names = "pclk"; ++ clocks = <&cru ACLK_VIO>, <&cru PCLK_HDMI>; ++ clock-names = "aclk", "pclk"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmi_ctl>; + +diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi +index dda5a1f79aca..6be6d9d134fe 100644 +--- a/arch/arm/boot/dts/rk3036.dtsi ++++ b/arch/arm/boot/dts/rk3036.dtsi +@@ -344,11 +344,14 @@ hdmi: hdmi@20034000 { + compatible = "rockchip,rk3036-inno-hdmi"; + reg = <0x20034000 0x4000>; + interrupts = ; +- clocks = <&cru PCLK_HDMI>; +- clock-names = "pclk"; ++ clocks = <&cru ACLK_VIO>, <&cru PCLK_HDMI>; ++ clock-names = "aclk", "pclk"; + rockchip,grf = <&grf>; + pinctrl-names = "default"; + pinctrl-0 = <&hdmi_ctl>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ #sound-dai-cells = <0>; + status = "disabled"; + + hdmi_in: port { +@@ -361,6 +364,23 @@ hdmi_in_vop: endpoint@0 { + }; + }; + ++ hdmi_sound: hdmi-sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,name = "HDMI"; ++ status = "disabled"; ++ ++ simple-audio-card,dai-link { ++ format = "i2s"; ++ mclk-fs = <256>; ++ cpu { ++ sound-dai = <&i2s>; ++ }; ++ codec { ++ sound-dai = <&hdmi>; ++ }; ++ }; ++ }; ++ + timer: timer@20044000 { + compatible = "rockchip,rk3036-timer", "rockchip,rk3288-timer"; + reg = <0x20044000 0x20>; +diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c +index 7afdc54eb3ec..7e93208609a0 100644 +--- a/drivers/gpu/drm/rockchip/inno_hdmi.c ++++ b/drivers/gpu/drm/rockchip/inno_hdmi.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -21,6 +22,8 @@ + #include + #include + ++#include ++ + #include "rockchip_drm_drv.h" + #include "rockchip_drm_vop.h" + +@@ -28,6 +31,12 @@ + + #define to_inno_hdmi(x) container_of(x, struct inno_hdmi, x) + ++struct audio_info { ++ int sample_rate; ++ int channels; ++ int sample_width; ++}; ++ + struct hdmi_data_info { + int vic; + bool sink_is_hdmi; +@@ -52,8 +61,10 @@ struct inno_hdmi { + struct drm_device *drm_dev; + + int irq; ++ struct clk *aclk; + struct clk *pclk; + void __iomem *regs; ++ struct regmap *regmap; + + struct drm_connector connector; + struct drm_encoder encoder; +@@ -63,6 +74,9 @@ struct inno_hdmi { + + unsigned int tmds_rate; + ++ struct platform_device *audio_pdev; ++ bool audio_enable; ++ + struct hdmi_data_info hdmi_data; + struct drm_display_mode previous_mode; + }; +@@ -189,11 +203,17 @@ static void inno_hdmi_sys_power(struct inno_hdmi *hdmi, bool enable) + + static void inno_hdmi_set_pwr_mode(struct inno_hdmi *hdmi, int mode) + { ++ ++ u8 value; ++ + switch (mode) { + case NORMAL: + inno_hdmi_sys_power(hdmi, false); +- +- hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, 0x6f); ++ if (hdmi->tmds_rate > 140000000) ++ value = 0x6f; ++ else ++ value = 0x3f; ++ hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, value); + hdmi_writeb(hdmi, HDMI_PHY_DRIVER, 0xbb); + + hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15); +@@ -301,6 +321,21 @@ static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi, + return inno_hdmi_upload_frame(hdmi, rc, &frame, INFOFRAME_AVI, 0, 0, 0); + } + ++static int inno_hdmi_config_audio_aai(struct inno_hdmi *hdmi, ++ struct audio_info *audio) ++{ ++ struct hdmi_audio_infoframe *faudio; ++ union hdmi_infoframe frame; ++ int rc; ++ ++ rc = hdmi_audio_infoframe_init(&frame.audio); ++ faudio = (struct hdmi_audio_infoframe *)&frame; ++ ++ faudio->channels = audio->channels; ++ ++ return inno_hdmi_upload_frame(hdmi, rc, &frame, INFOFRAME_AAI, 0, 0, 0); ++} ++ + static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi) + { + struct hdmi_data_info *data = &hdmi->hdmi_data; +@@ -383,6 +418,11 @@ static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi, + { + int value; + ++ value = BIT(20) | BIT(21); ++ value |= mode->flags & DRM_MODE_FLAG_PHSYNC ? BIT(4) : 0; ++ value |= mode->flags & DRM_MODE_FLAG_PVSYNC ? BIT(5) : 0; ++ regmap_write(hdmi->regmap, 0x148, value); ++ + /* Set detail external video timing polarity and interlace mode */ + value = v_EXTERANL_VIDEO(1); + value |= mode->flags & DRM_MODE_FLAG_PHSYNC ? +@@ -402,7 +442,7 @@ static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi, + hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_L, value & 0xFF); + hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_H, (value >> 8) & 0xFF); + +- value = mode->hsync_start - mode->hdisplay; ++ value = mode->htotal - mode->hsync_start; + hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_L, value & 0xFF); + hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_H, (value >> 8) & 0xFF); + +@@ -417,7 +457,7 @@ static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi, + value = mode->vtotal - mode->vdisplay; + hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VBLANK, value & 0xFF); + +- value = mode->vsync_start - mode->vdisplay; ++ value = mode->vtotal - mode->vsync_start; + hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VDELAY, value & 0xFF); + + value = mode->vsync_end - mode->vsync_start; +@@ -473,8 +513,9 @@ static int inno_hdmi_setup(struct inno_hdmi *hdmi, + inno_hdmi_i2c_init(hdmi); + + /* Unmute video and audio output */ +- hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK, +- v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0)); ++ hdmi_modb(hdmi, HDMI_AV_MUTE, m_VIDEO_BLACK, v_VIDEO_MUTE(0)); ++ if (hdmi->audio_enable) ++ hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE, v_AUDIO_MUTE(0)); + + return 0; + } +@@ -521,6 +562,7 @@ inno_hdmi_encoder_atomic_check(struct drm_encoder *encoder, + + s->output_mode = ROCKCHIP_OUT_MODE_P888; + s->output_type = DRM_MODE_CONNECTOR_HDMIA; ++ s->bus_format = MEDIA_BUS_FMT_RGB888_1X24; + + return 0; + } +@@ -597,6 +639,175 @@ static struct drm_connector_helper_funcs inno_hdmi_connector_helper_funcs = { + .mode_valid = inno_hdmi_connector_mode_valid, + }; + ++int inno_hdmi_audio_config_set(struct inno_hdmi *hdmi, struct audio_info *audio) ++{ ++ int rate, N, channel; ++ ++ if (audio->channels < 3) ++ channel = I2S_CHANNEL_1_2; ++ else if (audio->channels < 5) ++ channel = I2S_CHANNEL_3_4; ++ else if (audio->channels < 7) ++ channel = I2S_CHANNEL_5_6; ++ else ++ channel = I2S_CHANNEL_7_8; ++ ++ switch (audio->sample_rate) { ++ case 32000: ++ rate = AUDIO_32K; ++ N = N_32K; ++ break; ++ case 44100: ++ rate = AUDIO_441K; ++ N = N_441K; ++ break; ++ case 48000: ++ rate = AUDIO_48K; ++ N = N_48K; ++ break; ++ case 88200: ++ rate = AUDIO_882K; ++ N = N_882K; ++ break; ++ case 96000: ++ rate = AUDIO_96K; ++ N = N_96K; ++ break; ++ case 176400: ++ rate = AUDIO_1764K; ++ N = N_1764K; ++ break; ++ case 192000: ++ rate = AUDIO_192K; ++ N = N_192K; ++ break; ++ default: ++ dev_err(hdmi->dev, "[%s] not support such sample rate %d\n", ++ __func__, audio->sample_rate); ++ return -ENOENT; ++ } ++ ++ /* set_audio source I2S */ ++ hdmi_writeb(hdmi, HDMI_AUDIO_CTRL1, 0x01); ++ hdmi_writeb(hdmi, AUDIO_SAMPLE_RATE, rate); ++ hdmi_writeb(hdmi, AUDIO_I2S_MODE, v_I2S_MODE(I2S_STANDARD) | ++ v_I2S_CHANNEL(channel)); ++ ++ hdmi_writeb(hdmi, AUDIO_I2S_MAP, 0x00); ++ hdmi_writeb(hdmi, AUDIO_I2S_SWAPS_SPDIF, 0); ++ ++ /* Set N value */ ++ hdmi_writeb(hdmi, AUDIO_N_H, (N >> 16) & 0x0F); ++ hdmi_writeb(hdmi, AUDIO_N_M, (N >> 8) & 0xFF); ++ hdmi_writeb(hdmi, AUDIO_N_L, N & 0xFF); ++ ++ /*Set hdmi nlpcm mode to support hdmi bitstream*/ ++ hdmi_writeb(hdmi, HDMI_AUDIO_CHANNEL_STATUS, v_AUDIO_STATUS_NLPCM(0)); ++ ++ return inno_hdmi_config_audio_aai(hdmi, audio); ++} ++ ++static int inno_hdmi_audio_hw_params(struct device *dev, void *data, ++ struct hdmi_codec_daifmt *daifmt, ++ struct hdmi_codec_params *params) ++{ ++ struct inno_hdmi *hdmi = dev_get_drvdata(dev); ++ struct audio_info audio = { ++ .sample_width = params->sample_width, ++ .sample_rate = params->sample_rate, ++ .channels = params->channels, ++ }; ++ ++ if (!hdmi->hdmi_data.sink_has_audio) { ++ dev_err(hdmi->dev, "Sink do not support audio!\n"); ++ return -ENODEV; ++ } ++ ++ if (!hdmi->encoder.crtc) ++ return -ENODEV; ++ ++ switch (daifmt->fmt) { ++ case HDMI_I2S: ++ break; ++ default: ++ dev_err(dev, "%s: Invalid format %d\n", __func__, daifmt->fmt); ++ return -EINVAL; ++ } ++ ++ return inno_hdmi_audio_config_set(hdmi, &audio); ++} ++ ++static void inno_hdmi_audio_shutdown(struct device *dev, void *data) ++{ ++ /* do nothing */ ++} ++ ++static int inno_hdmi_audio_digital_mute(struct device *dev, void *data, bool mute) ++{ ++ struct inno_hdmi *hdmi = dev_get_drvdata(dev); ++ ++ if (!hdmi->hdmi_data.sink_has_audio) { ++ dev_err(hdmi->dev, "Sink do not support audio!\n"); ++ return -ENODEV; ++ } ++ ++ hdmi->audio_enable = !mute; ++ ++ if (mute) ++ hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_AUDIO_PD, ++ v_AUDIO_MUTE(1) | v_AUDIO_PD(1)); ++ else ++ hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_AUDIO_PD, ++ v_AUDIO_MUTE(0) | v_AUDIO_PD(0)); ++ ++ return 0; ++} ++ ++static int inno_hdmi_audio_get_eld(struct device *dev, void *data, ++ uint8_t *buf, size_t len) ++{ ++ struct inno_hdmi *hdmi = dev_get_drvdata(dev); ++ struct drm_mode_config *config = &hdmi->encoder.dev->mode_config; ++ struct drm_connector *connector; ++ int ret = -ENODEV; ++ ++ mutex_lock(&config->mutex); ++ list_for_each_entry(connector, &config->connector_list, head) { ++ if (&hdmi->encoder == connector->encoder) { ++ memcpy(buf, connector->eld, ++ min(sizeof(connector->eld), len)); ++ ret = 0; ++ } ++ } ++ mutex_unlock(&config->mutex); ++ ++ return ret; ++} ++ ++static const struct hdmi_codec_ops audio_codec_ops = { ++ .hw_params = inno_hdmi_audio_hw_params, ++ .audio_shutdown = inno_hdmi_audio_shutdown, ++ .digital_mute = inno_hdmi_audio_digital_mute, ++ .get_eld = inno_hdmi_audio_get_eld, ++}; ++ ++static int inno_hdmi_audio_codec_init(struct inno_hdmi *hdmi, ++ struct device *dev) ++{ ++ struct hdmi_codec_pdata codec_data = { ++ .i2s = 1, ++ .ops = &audio_codec_ops, ++ .max_i2s_channels = 8, ++ }; ++ ++ hdmi->audio_enable = false; ++ hdmi->audio_pdev = platform_device_register_data( ++ dev, HDMI_CODEC_DRV_NAME, PLATFORM_DEVID_NONE, ++ &codec_data, sizeof(codec_data)); ++ ++ return PTR_ERR_OR_ZERO(hdmi->audio_pdev); ++} ++ + static int inno_hdmi_register(struct drm_device *drm, struct inno_hdmi *hdmi) + { + struct drm_encoder *encoder = &hdmi->encoder; +@@ -627,6 +838,8 @@ static int inno_hdmi_register(struct drm_device *drm, struct inno_hdmi *hdmi) + + drm_connector_attach_encoder(&hdmi->connector, encoder); + ++ inno_hdmi_audio_codec_init(hdmi, dev); ++ + return 0; + } + +@@ -826,23 +1039,44 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, + if (IS_ERR(hdmi->regs)) + return PTR_ERR(hdmi->regs); + ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) ++ return irq; ++ ++ hdmi->aclk = devm_clk_get(hdmi->dev, "aclk"); ++ if (IS_ERR(hdmi->aclk)) { ++ dev_err(hdmi->dev, "Unable to get HDMI aclk clk\n"); ++ return PTR_ERR(hdmi->aclk); ++ } ++ + hdmi->pclk = devm_clk_get(hdmi->dev, "pclk"); + if (IS_ERR(hdmi->pclk)) { + DRM_DEV_ERROR(hdmi->dev, "Unable to get HDMI pclk clk\n"); + return PTR_ERR(hdmi->pclk); + } + ++ ret = clk_prepare_enable(hdmi->aclk); ++ if (ret) { ++ DRM_DEV_ERROR(hdmi->dev, ++ "Cannot enable HDMI aclk clock: %d\n", ret); ++ return ret; ++ } ++ ++ + ret = clk_prepare_enable(hdmi->pclk); + if (ret) { + DRM_DEV_ERROR(hdmi->dev, + "Cannot enable HDMI pclk clock: %d\n", ret); +- return ret; ++ goto err_disable_aclk; + } + +- irq = platform_get_irq(pdev, 0); +- if (irq < 0) { +- ret = irq; +- goto err_disable_clk; ++ hdmi->regmap = ++ syscon_regmap_lookup_by_phandle(hdmi->dev->of_node, ++ "rockchip,grf"); ++ if (IS_ERR(hdmi->regmap)) { ++ dev_err(hdmi->dev, "Unable to get rockchip,grf\n"); ++ ret = PTR_ERR(hdmi->regmap); ++ goto err_disable_aclk; + } + + inno_hdmi_reset(hdmi); +@@ -851,7 +1085,7 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, + if (IS_ERR(hdmi->ddc)) { + ret = PTR_ERR(hdmi->ddc); + hdmi->ddc = NULL; +- goto err_disable_clk; ++ goto err_disable_pclk; + } + + /* +@@ -884,9 +1118,12 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, + hdmi->encoder.funcs->destroy(&hdmi->encoder); + err_put_adapter: + i2c_put_adapter(hdmi->ddc); +-err_disable_clk: ++err_disable_pclk: + clk_disable_unprepare(hdmi->pclk); +- return ret; ++err_disable_aclk: ++ clk_disable_unprepare(hdmi->aclk); ++ ++return ret; + } + + static void inno_hdmi_unbind(struct device *dev, struct device *master, +@@ -899,6 +1136,7 @@ static void inno_hdmi_unbind(struct device *dev, struct device *master, + + i2c_put_adapter(hdmi->ddc); + clk_disable_unprepare(hdmi->pclk); ++ clk_disable_unprepare(hdmi->aclk); + } + + static const struct component_ops inno_hdmi_ops = { +diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.h b/drivers/gpu/drm/rockchip/inno_hdmi.h +index 93245b55f967..b722afc4e41f 100644 +--- a/drivers/gpu/drm/rockchip/inno_hdmi.h ++++ b/drivers/gpu/drm/rockchip/inno_hdmi.h +@@ -96,11 +96,13 @@ enum { + #define HDMI_AV_MUTE 0x05 + #define m_AVMUTE_CLEAR (1 << 7) + #define m_AVMUTE_ENABLE (1 << 6) ++#define m_AUDIO_PD (1 << 2) + #define m_AUDIO_MUTE (1 << 1) + #define m_VIDEO_BLACK (1 << 0) + #define v_AVMUTE_CLEAR(n) (n << 7) + #define v_AVMUTE_ENABLE(n) (n << 6) + #define v_AUDIO_MUTE(n) (n << 1) ++#define v_AUDIO_PD(n) (n << 2) + #define v_VIDEO_MUTE(n) (n << 0) + + #define HDMI_VIDEO_TIMING_CTL 0x08 + +From fd3c78e6eec709b6a70af8a175c6965d0112f372 Mon Sep 17 00:00:00 2001 +From: Phong LE +Date: Wed, 11 Mar 2020 13:51:33 +0100 +Subject: [PATCH] dt-bindings: display: bridge: add it66121 bindings + +Add the ITE bridge HDMI it66121 bindings. + +Signed-off-by: Phong LE +--- + .../bindings/display/bridge/ite,it66121.yaml | 98 +++++++++++++++++++ + 1 file changed, 98 insertions(+) + create mode 100644 Documentation/devicetree/bindings/display/bridge/ite,it66121.yaml + +diff --git a/Documentation/devicetree/bindings/display/bridge/ite,it66121.yaml b/Documentation/devicetree/bindings/display/bridge/ite,it66121.yaml +new file mode 100644 +index 000000000000..1717e880d130 +--- /dev/null ++++ b/Documentation/devicetree/bindings/display/bridge/ite,it66121.yaml +@@ -0,0 +1,98 @@ ++# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/display/bridge/ite,it66121.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: ITE it66121 HDMI bridge Device Tree Bindings ++ ++maintainers: ++ - Phong LE ++ - Neil Armstrong ++ ++description: | ++ The IT66121 is a high-performance and low-power single channel HDMI ++ transmitter, fully compliant with HDMI 1.3a, HDCP 1.2 and backward compatible ++ to DVI 1.0 specifications. ++ ++properties: ++ compatible: ++ const: ite,it66121 ++ ++ reg: ++ maxItems: 1 ++ description: base I2C address of the device ++ ++ reset-gpios: ++ maxItems: 1 ++ description: GPIO connected to active low reset ++ ++ vrf12-supply: ++ maxItems: 1 ++ description: Regulator for 1.2V analog core power. ++ ++ vcn33-supply: ++ maxItems: 1 ++ description: Regulator for 3.3V digital core power. ++ ++ vcn18-supply: ++ maxItems: 1 ++ description: Regulator for 1.8V IO core power. ++ ++ interrupts: ++ maxItems: 1 ++ ++ pclk-dual-edge: ++ maxItems: 1 ++ description: enable pclk dual edge mode. ++ ++ port: ++ type: object ++ ++ properties: ++ endpoint: ++ type: object ++ description: | ++ Input endpoints of the bridge. ++ ++ required: ++ - endpoint ++ ++required: ++ - compatible ++ - reg ++ - reset-gpios ++ - vrf12-supply ++ - vcn33-supply ++ - vcn18-supply ++ - interrupts ++ - port ++ ++additionalProperties: false ++ ++examples: ++ - | ++ i2c6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ it66121hdmitx: it66121hdmitx@4c { ++ compatible = "ite,it66121"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&ite_pins_default>; ++ vcn33-supply = <&mt6358_vcn33_wifi_reg>; ++ vcn18-supply = <&mt6358_vcn18_reg>; ++ vrf12-supply = <&mt6358_vrf12_reg>; ++ reset-gpios = <&pio 160 1 /* GPIO_ACTIVE_LOW */>; ++ interrupt-parent = <&pio>; ++ interrupts = <4 8 /* IRQ_TYPE_LEVEL_LOW */>; ++ reg = <0x4c>; ++ pclk-dual-edge; ++ ++ port { ++ it66121_in: endpoint { ++ remote-endpoint = <&display_out>; ++ }; ++ }; ++ }; ++ }; + +From 28d8fb9319bee0252c3b756966298a065bfa16c5 Mon Sep 17 00:00:00 2001 +From: Phong LE +Date: Wed, 11 Mar 2020 13:51:34 +0100 +Subject: [PATCH] drm: bridge: add it66121 driver + +This commit is a simple driver for bridge HMDI it66121. +The input format is RBG and there is no color conversion. +Audio, HDCP and CEC are not supported yet. + +Signed-off-by: Phong LE +--- + drivers/gpu/drm/bridge/Kconfig | 8 + + drivers/gpu/drm/bridge/Makefile | 1 + + drivers/gpu/drm/bridge/ite-it66121.c | 997 +++++++++++++++++++++++++++ + 3 files changed, 1006 insertions(+) + create mode 100644 drivers/gpu/drm/bridge/ite-it66121.c + +diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig +index 43271c21d3fc..204246d65f44 100644 +--- a/drivers/gpu/drm/bridge/Kconfig ++++ b/drivers/gpu/drm/bridge/Kconfig +@@ -48,6 +48,14 @@ config DRM_DISPLAY_CONNECTOR + on ARM-based platforms. Saying Y here when this driver is not needed + will not cause any issue. + ++config DRM_ITE_IT66121 ++ tristate "ITE IT66121 HDMI bridge" ++ depends on OF ++ select DRM_KMS_HELPER ++ select REGMAP_I2C ++ help ++ Support for ITE IT66121 HDMI bridge. ++ + config DRM_LVDS_CODEC + tristate "Transparent LVDS encoders and decoders support" + depends on OF +diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile +index d63d4b7e4347..ffa91a5a6bda 100644 +--- a/drivers/gpu/drm/bridge/Makefile ++++ b/drivers/gpu/drm/bridge/Makefile +@@ -2,6 +2,7 @@ + obj-$(CONFIG_DRM_CDNS_DSI) += cdns-dsi.o + obj-$(CONFIG_DRM_CHRONTEL_CH7033) += chrontel-ch7033.o + obj-$(CONFIG_DRM_DISPLAY_CONNECTOR) += display-connector.o ++obj-$(CONFIG_DRM_ITE_IT66121) += ite-it66121.o + obj-$(CONFIG_DRM_LVDS_CODEC) += lvds-codec.o + obj-$(CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW) += megachips-stdpxxxx-ge-b850v3-fw.o + obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o +diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c +new file mode 100644 +index 000000000000..7e1a90319a6a +--- /dev/null ++++ b/drivers/gpu/drm/bridge/ite-it66121.c +@@ -0,0 +1,997 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2020 BayLibre, SAS ++ * Author: Phong LE ++ * Copyright (C) 2018-2019, Artem Mygaiev ++ * Copyright (C) 2017, Fresco Logic, Incorporated. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define IT66121_MASTER_SEL_REG 0x10 ++#define IT66121_MASTER_SEL_HOST BIT(0) ++ ++#define IT66121_AFE_DRV_REG 0x61 ++#define IT66121_AFE_DRV_RST BIT(4) ++#define IT66121_AFE_DRV_PWD BIT(5) ++ ++#define IT66121_INPUT_MODE_REG 0x70 ++#define IT66121_INPUT_MODE_RGB (0 << 6) ++#define IT66121_INPUT_MODE_YUV422 BIT(6) ++#define IT66121_INPUT_MODE_YUV444 (2 << 6) ++#define IT66121_INPUT_MODE_CCIR656 BIT(4) ++#define IT66121_INPUT_MODE_SYNCEMB BIT(3) ++#define IT66121_INPUT_MODE_DDR BIT(2) ++ ++#define IT66121_INPUT_CSC_REG 0x72 ++#define IT66121_INPUT_CSC_ENDITHER BIT(7) ++#define IT66121_INPUT_CSC_ENUDFILTER BIT(6) ++#define IT66121_INPUT_CSC_DNFREE_GO BIT(5) ++#define IT66121_INPUT_CSC_RGB_TO_YUV 0x02 ++#define IT66121_INPUT_CSC_YUV_TO_RGB 0x03 ++#define IT66121_INPUT_CSC_NO_CONV 0x00 ++ ++#define IT66121_AFE_XP_REG 0x62 ++#define IT66121_AFE_XP_GAINBIT BIT(7) ++#define IT66121_AFE_XP_PWDPLL BIT(6) ++#define IT66121_AFE_XP_ENI BIT(5) ++#define IT66121_AFE_XP_ENO BIT(4) ++#define IT66121_AFE_XP_RESETB BIT(3) ++#define IT66121_AFE_XP_PWDI BIT(2) ++ ++#define IT66121_AFE_IP_REG 0x64 ++#define IT66121_AFE_IP_GAINBIT BIT(7) ++#define IT66121_AFE_IP_PWDPLL BIT(6) ++#define IT66121_AFE_IP_CKSEL_05 (0 << 4) ++#define IT66121_AFE_IP_CKSEL_1 BIT(4) ++#define IT66121_AFE_IP_CKSEL_2 (2 << 4) ++#define IT66121_AFE_IP_CKSEL_2OR4 (3 << 4) ++#define IT66121_AFE_IP_ER0 BIT(3) ++#define IT66121_AFE_IP_RESETB BIT(2) ++#define IT66121_AFE_IP_ENC BIT(1) ++#define IT66121_AFE_IP_EC1 BIT(0) ++ ++#define IT66121_AFE_XP_EC1_REG 0x68 ++#define IT66121_AFE_XP_EC1_LOWCLK BIT(4) ++ ++#define IT66121_SW_RST_REG 0x04 ++#define IT66121_SW_RST_REF BIT(5) ++#define IT66121_SW_RST_AREF BIT(4) ++#define IT66121_SW_RST_VID BIT(3) ++#define IT66121_SW_RST_AUD BIT(2) ++#define IT66121_SW_RST_HDCP BIT(0) ++ ++#define IT66121_DDC_COMMAND_REG 0x15 ++#define IT66121_DDC_COMMAND_BURST_READ 0x0 ++#define IT66121_DDC_COMMAND_EDID_READ 0x3 ++#define IT66121_DDC_COMMAND_FIFO_CLR 0x9 ++#define IT66121_DDC_COMMAND_SCL_PULSE 0xA ++#define IT66121_DDC_COMMAND_ABORT 0xF ++ ++#define IT66121_HDCP_REG 0x20 ++#define IT66121_HDCP_CPDESIRED BIT(0) ++#define IT66121_HDCP_EN1P1FEAT BIT(1) ++ ++#define IT66121_INT_STATUS1_REG 0x06 ++#define IT66121_INT_STATUS1_AUD_OVF BIT(7) ++#define IT66121_INT_STATUS1_DDC_NOACK BIT(5) ++#define IT66121_INT_STATUS1_DDC_FIFOERR BIT(4) ++#define IT66121_INT_STATUS1_DDC_BUSHANG BIT(2) ++#define IT66121_INT_STATUS1_RX_SENS_STATUS BIT(1) ++#define IT66121_INT_STATUS1_HPD_STATUS BIT(0) ++ ++#define IT66121_DDC_HEADER_REG 0x11 ++#define IT66121_DDC_HEADER_HDCP 0x74 ++#define IT66121_DDC_HEADER_EDID 0xA0 ++ ++#define IT66121_DDC_OFFSET_REG 0x12 ++#define IT66121_DDC_BYTE_REG 0x13 ++#define IT66121_DDC_SEGMENT_REG 0x14 ++#define IT66121_DDC_RD_FIFO_REG 0x17 ++ ++#define IT66121_CLK_BANK_REG 0x0F ++#define IT66121_CLK_BANK_PWROFF_RCLK BIT(6) ++#define IT66121_CLK_BANK_PWROFF_ACLK BIT(5) ++#define IT66121_CLK_BANK_PWROFF_TXCLK BIT(4) ++#define IT66121_CLK_BANK_PWROFF_CRCLK BIT(3) ++#define IT66121_CLK_BANK_0 0 ++#define IT66121_CLK_BANK_1 1 ++ ++#define IT66121_INT_REG 0x05 ++#define IT66121_INT_ACTIVE_HIGH BIT(7) ++#define IT66121_INT_OPEN_DRAIN BIT(6) ++#define IT66121_INT_TX_CLK_OFF BIT(0) ++ ++#define IT66121_INT_MASK1_REG 0x09 ++#define IT66121_INT_MASK1_AUD_OVF BIT(7) ++#define IT66121_INT_MASK1_DDC_NOACK BIT(5) ++#define IT66121_INT_MASK1_DDC_FIFOERR BIT(4) ++#define IT66121_INT_MASK1_DDC_BUSHANG BIT(2) ++#define IT66121_INT_MASK1_RX_SENS BIT(1) ++#define IT66121_INT_MASK1_HPD BIT(0) ++ ++#define IT66121_INT_CLR1_REG 0x0C ++#define IT66121_INT_CLR1_PKTACP BIT(7) ++#define IT66121_INT_CLR1_PKTNULL BIT(6) ++#define IT66121_INT_CLR1_PKTGEN BIT(5) ++#define IT66121_INT_CLR1_KSVLISTCHK BIT(4) ++#define IT66121_INT_CLR1_AUTHDONE BIT(3) ++#define IT66121_INT_CLR1_AUTHFAIL BIT(2) ++#define IT66121_INT_CLR1_RX_SENS BIT(1) ++#define IT66121_INT_CLR1_HPD BIT(0) ++ ++#define IT66121_AV_MUTE_REG 0xC1 ++#define IT66121_AV_MUTE_ON BIT(0) ++#define IT66121_AV_MUTE_BLUESCR BIT(1) ++ ++#define IT66121_PKT_GEN_CTRL_REG 0xC6 ++#define IT66121_PKT_GEN_CTRL_ON BIT(0) ++#define IT66121_PKT_GEN_CTRL_RPT BIT(1) ++ ++#define IT66121_AVIINFO_DB1_REG 0x158 ++#define IT66121_AVIINFO_DB2_REG 0x159 ++#define IT66121_AVIINFO_DB3_REG 0x15A ++#define IT66121_AVIINFO_DB4_REG 0x15B ++#define IT66121_AVIINFO_DB5_REG 0x15C ++#define IT66121_AVIINFO_CSUM_REG 0x15D ++#define IT66121_AVIINFO_DB6_REG 0x15E ++#define IT66121_AVIINFO_DB7_REG 0x15F ++#define IT66121_AVIINFO_DB8_REG 0x160 ++#define IT66121_AVIINFO_DB9_REG 0x161 ++#define IT66121_AVIINFO_DB10_REG 0x162 ++#define IT66121_AVIINFO_DB11_REG 0x163 ++#define IT66121_AVIINFO_DB12_REG 0x164 ++#define IT66121_AVIINFO_DB13_REG 0x165 ++ ++#define IT66121_AVI_INFO_PKT_REG 0xCD ++#define IT66121_AVI_INFO_PKT_ON BIT(0) ++#define IT66121_AVI_INFO_PKT_RPT BIT(1) ++ ++#define IT66121_HDMI_MODE_REG 0xC0 ++#define IT66121_HDMI_MODE_HDMI BIT(0) ++ ++#define IT66121_SYS_STATUS_REG 0x0E ++#define IT66121_SYS_STATUS_ACTIVE_IRQ BIT(7) ++#define IT66121_SYS_STATUS_HPDETECT BIT(6) ++#define IT66121_SYS_STATUS_SENDECTECT BIT(5) ++#define IT66121_SYS_STATUS_VID_STABLE BIT(4) ++#define IT66121_SYS_STATUS_AUD_CTS_CLR BIT(1) ++#define IT66121_SYS_STATUS_CLEAR_IRQ BIT(0) ++ ++#define IT66121_DDC_STATUS_REG 0x16 ++#define IT66121_DDC_STATUS_TX_DONE BIT(7) ++#define IT66121_DDC_STATUS_ACTIVE BIT(6) ++#define IT66121_DDC_STATUS_NOACK BIT(5) ++#define IT66121_DDC_STATUS_WAIT_BUS BIT(4) ++#define IT66121_DDC_STATUS_ARBI_LOSE BIT(3) ++#define IT66121_DDC_STATUS_FIFO_FULL BIT(2) ++#define IT66121_DDC_STATUS_FIFO_EMPTY BIT(1) ++#define IT66121_DDC_STATUS_FIFO_VALID BIT(0) ++ ++#define IT66121_VENDOR_ID0 0x54 ++#define IT66121_VENDOR_ID1 0x49 ++#define IT66121_DEVICE_ID0 0x12 ++#define IT66121_DEVICE_ID1 0x06 ++#define IT66121_DEVICE_MASK 0x0F ++#define IT66121_EDID_SLEEP 20000 ++#define IT66121_EDID_TIMEOUT 200000 ++#define IT66121_EDID_FIFO_SIZE 32 ++#define IT66121_AFE_CLK_HIGH 80000 ++ ++struct it66121_conf { ++ unsigned int input_mode_reg; ++ unsigned int input_conversion_reg; ++}; ++ ++struct it66121_ctx { ++ struct regmap *regmap; ++ struct drm_bridge bridge; ++ struct drm_connector connector; ++ struct device *dev; ++ struct gpio_desc *gpio_reset; ++ struct i2c_client *client; ++ struct regulator_bulk_data supplies[3]; ++ bool dual_edge; ++ const struct it66121_conf *conf; ++ struct mutex lock; /* Protects fields below and device registers */ ++ struct edid *edid; ++ struct hdmi_avi_infoframe hdmi_avi_infoframe; ++}; ++ ++static const struct regmap_range_cfg it66121_regmap_banks[] = { ++ { ++ .name = "it66121", ++ .range_min = 0x00, ++ .range_max = 0x1FF, ++ .selector_reg = IT66121_CLK_BANK_REG, ++ .selector_mask = 0x1, ++ .selector_shift = 0, ++ .window_start = 0x00, ++ .window_len = 0x130, ++ }, ++}; ++ ++static const struct regmap_config it66121_regmap_config = { ++ .val_bits = 8, ++ .reg_bits = 8, ++ .max_register = 0x1FF, ++ .ranges = it66121_regmap_banks, ++ .num_ranges = ARRAY_SIZE(it66121_regmap_banks), ++}; ++ ++static const struct it66121_conf it66121_conf_simple = { ++ .input_mode_reg = IT66121_INPUT_MODE_RGB | IT66121_INPUT_MODE_DDR, ++ .input_conversion_reg = IT66121_INPUT_CSC_NO_CONV, ++}; ++ ++static void it66121_hw_reset(struct it66121_ctx *ctx) ++{ ++ gpiod_set_value(ctx->gpio_reset, 1); ++ msleep(20); ++ gpiod_set_value(ctx->gpio_reset, 0); ++} ++ ++static int ite66121_power_on(struct it66121_ctx *ctx) ++{ ++ return regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); ++} ++ ++static int ite66121_power_off(struct it66121_ctx *ctx) ++{ ++ return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); ++} ++ ++static int it66121_preamble_ddc(struct it66121_ctx *ctx) ++{ ++ return regmap_write(ctx->regmap, IT66121_MASTER_SEL_REG, ++ IT66121_MASTER_SEL_HOST); ++} ++ ++static int it66121_fire_afe(struct it66121_ctx *ctx) ++{ ++ return regmap_write(ctx->regmap, IT66121_AFE_DRV_REG, 0); ++} ++ ++static int it66121_configure_input(struct it66121_ctx *ctx) ++{ ++ int ret; ++ ++ ret = regmap_write(ctx->regmap, IT66121_INPUT_MODE_REG, ++ ctx->conf->input_mode_reg); ++ if (ret) ++ return ret; ++ ++ return regmap_write(ctx->regmap, IT66121_INPUT_CSC_REG, ++ ctx->conf->input_conversion_reg); ++} ++ ++/** ++ * it66121_configure_afe() - Configure the analog front end ++ * @ctx: it66121_ctx object ++ * ++ * RETURNS: ++ * zero if success, a negative error code otherwise. ++ */ ++static int it66121_configure_afe(struct it66121_ctx *ctx, ++ const struct drm_display_mode *mode) ++{ ++ int ret; ++ ++ ret = regmap_write(ctx->regmap, IT66121_AFE_DRV_REG, ++ IT66121_AFE_DRV_RST); ++ if (ret) ++ return ret; ++ ++ if (mode->clock > IT66121_AFE_CLK_HIGH) { ++ ret = regmap_write_bits(ctx->regmap, IT66121_AFE_XP_REG, ++ IT66121_AFE_XP_GAINBIT | ++ IT66121_AFE_XP_ENO, ++ IT66121_AFE_XP_GAINBIT); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write_bits(ctx->regmap, IT66121_AFE_IP_REG, ++ IT66121_AFE_IP_GAINBIT | ++ IT66121_AFE_IP_ER0 | ++ IT66121_AFE_IP_EC1, ++ IT66121_AFE_IP_GAINBIT); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write_bits(ctx->regmap, IT66121_AFE_XP_EC1_REG, ++ IT66121_AFE_XP_EC1_LOWCLK, 0x80); ++ if (ret) ++ return ret; ++ } else { ++ ret = regmap_write_bits(ctx->regmap, IT66121_AFE_XP_REG, ++ IT66121_AFE_XP_GAINBIT | ++ IT66121_AFE_XP_ENO, ++ IT66121_AFE_XP_ENO); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write_bits(ctx->regmap, IT66121_AFE_IP_REG, ++ IT66121_AFE_IP_GAINBIT | ++ IT66121_AFE_IP_ER0 | ++ IT66121_AFE_IP_EC1, IT66121_AFE_IP_ER0 | ++ IT66121_AFE_IP_EC1); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write_bits(ctx->regmap, IT66121_AFE_XP_EC1_REG, ++ IT66121_AFE_XP_EC1_LOWCLK, ++ IT66121_AFE_XP_EC1_LOWCLK); ++ if (ret) ++ return ret; ++ } ++ ++ /* Clear reset flags */ ++ ret = regmap_write_bits(ctx->regmap, IT66121_SW_RST_REG, ++ IT66121_SW_RST_REF | IT66121_SW_RST_VID, ++ ~(IT66121_SW_RST_REF | IT66121_SW_RST_VID) & ++ 0xFF); ++ if (ret) ++ return ret; ++ ++ return it66121_fire_afe(ctx); ++} ++ ++static inline int it66121_wait_ddc_ready(struct it66121_ctx *ctx) ++{ ++ int ret, val; ++ ++ ret = regmap_read_poll_timeout(ctx->regmap, IT66121_DDC_STATUS_REG, ++ val, true, ++ IT66121_EDID_SLEEP, ++ IT66121_EDID_TIMEOUT); ++ if (ret) ++ return ret; ++ ++ if (val & (IT66121_DDC_STATUS_NOACK | IT66121_DDC_STATUS_WAIT_BUS | ++ IT66121_DDC_STATUS_ARBI_LOSE)) ++ return -EAGAIN; ++ ++ return 0; ++} ++ ++static int it66121_clear_ddc_fifo(struct it66121_ctx *ctx) ++{ ++ int ret; ++ ++ ret = it66121_preamble_ddc(ctx); ++ if (ret) ++ return ret; ++ ++ return regmap_write(ctx->regmap, IT66121_DDC_COMMAND_REG, ++ IT66121_DDC_COMMAND_FIFO_CLR); ++} ++ ++static int it66121_abort_ddc_ops(struct it66121_ctx *ctx) ++{ ++ int ret; ++ unsigned int swreset, cpdesire; ++ ++ ret = regmap_read(ctx->regmap, IT66121_SW_RST_REG, &swreset); ++ if (ret) ++ return ret; ++ ++ ret = regmap_read(ctx->regmap, IT66121_HDCP_REG, &cpdesire); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write(ctx->regmap, IT66121_HDCP_REG, ++ cpdesire & (~IT66121_HDCP_CPDESIRED & 0xFF)); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write(ctx->regmap, IT66121_SW_RST_REG, ++ swreset | IT66121_SW_RST_HDCP); ++ if (ret) ++ return ret; ++ ++ ret = it66121_preamble_ddc(ctx); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write(ctx->regmap, IT66121_DDC_COMMAND_REG, ++ IT66121_DDC_COMMAND_ABORT); ++ if (ret) ++ return ret; ++ ++ return it66121_wait_ddc_ready(ctx); ++} ++ ++static int it66121_get_edid_block(void *context, u8 *buf, ++ unsigned int block, size_t len) ++{ ++ struct it66121_ctx *ctx = context; ++ unsigned int val; ++ int remain = len; ++ int offset = 0; ++ int ret, cnt; ++ ++ offset = (block % 2) * len; ++ block = block / 2; ++ ++ ret = regmap_read(ctx->regmap, IT66121_INT_STATUS1_REG, &val); ++ if (ret) ++ return ret; ++ ++ if (val & IT66121_INT_STATUS1_DDC_BUSHANG) { ++ ret = it66121_abort_ddc_ops(ctx); ++ if (ret) ++ return ret; ++ } ++ ++ ret = it66121_clear_ddc_fifo(ctx); ++ if (ret) ++ return ret; ++ ++ while (remain > 0) { ++ cnt = (remain > IT66121_EDID_FIFO_SIZE) ? ++ IT66121_EDID_FIFO_SIZE : remain; ++ ret = it66121_preamble_ddc(ctx); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write(ctx->regmap, IT66121_DDC_COMMAND_REG, ++ IT66121_DDC_COMMAND_FIFO_CLR); ++ if (ret) ++ return ret; ++ ++ ret = it66121_wait_ddc_ready(ctx); ++ if (ret) ++ return ret; ++ ++ ret = regmap_read(ctx->regmap, IT66121_INT_STATUS1_REG, &val); ++ if (ret) ++ return ret; ++ ++ if (val & IT66121_INT_STATUS1_DDC_BUSHANG) { ++ ret = it66121_abort_ddc_ops(ctx); ++ if (ret) ++ return ret; ++ } ++ ++ ret = it66121_preamble_ddc(ctx); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write(ctx->regmap, IT66121_DDC_HEADER_REG, ++ IT66121_DDC_HEADER_EDID); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write(ctx->regmap, IT66121_DDC_OFFSET_REG, offset); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write(ctx->regmap, IT66121_DDC_BYTE_REG, cnt); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write(ctx->regmap, IT66121_DDC_SEGMENT_REG, block); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write(ctx->regmap, IT66121_DDC_COMMAND_REG, ++ IT66121_DDC_COMMAND_EDID_READ); ++ if (ret) ++ return ret; ++ ++ offset += cnt; ++ remain -= cnt; ++ msleep(20); ++ ++ ret = it66121_wait_ddc_ready(ctx); ++ if (ret) ++ return ret; ++ ++ do { ++ ret = regmap_read(ctx->regmap, ++ IT66121_DDC_RD_FIFO_REG, &val); ++ if (ret) ++ return ret; ++ *(buf++) = val; ++ cnt--; ++ } while (cnt > 0); ++ } ++ ++ return 0; ++} ++ ++static int it66121_connector_get_modes(struct drm_connector *connector) ++{ ++ int ret, num_modes = 0; ++ struct it66121_ctx *ctx = container_of(connector, struct it66121_ctx, ++ connector); ++ ++ if (ctx->edid) ++ return drm_add_edid_modes(connector, ctx->edid); ++ ++ mutex_lock(&ctx->lock); ++ ++ ctx->edid = drm_do_get_edid(connector, it66121_get_edid_block, ctx); ++ if (!ctx->edid) { ++ DRM_ERROR("Failed to read EDID\n"); ++ goto unlock; ++ } ++ ++ ret = drm_connector_update_edid_property(connector, ++ ctx->edid); ++ if (ret) { ++ DRM_ERROR("Failed to update EDID property: %d\n", ret); ++ goto unlock; ++ } ++ ++ num_modes = drm_add_edid_modes(connector, ctx->edid); ++ ++unlock: ++ mutex_unlock(&ctx->lock); ++ ++ return num_modes; ++} ++ ++static bool it66121_is_hpd_detect(struct it66121_ctx *ctx) ++{ ++ int val; ++ ++ if (regmap_read(ctx->regmap, IT66121_SYS_STATUS_REG, &val)) ++ return false; ++ ++ return (val & IT66121_SYS_STATUS_HPDETECT); ++} ++ ++static int it66121_connector_detect_ctx(struct drm_connector *connector, ++ struct drm_modeset_acquire_ctx *c, ++ bool force) ++{ ++ struct it66121_ctx *ctx = container_of(connector, struct it66121_ctx, ++ connector); ++ ++ return (it66121_is_hpd_detect(ctx)) ? ++ connector_status_connected : connector_status_disconnected; ++} ++ ++static enum drm_mode_status ++it66121_connector_mode_valid(struct drm_connector *connector, ++ struct drm_display_mode *mode) ++{ ++ unsigned long max_clock; ++ struct it66121_ctx *ctx = container_of(connector, struct it66121_ctx, ++ connector); ++ ++ max_clock = ctx->dual_edge ? 74250 : 148500; ++ ++ if (mode->clock > max_clock) ++ return MODE_CLOCK_HIGH; ++ ++ if (mode->clock < 25000) ++ return MODE_CLOCK_LOW; ++ ++ return MODE_OK; ++} ++ ++static struct drm_connector_helper_funcs it66121_connector_helper_funcs = { ++ .get_modes = it66121_connector_get_modes, ++ .detect_ctx = it66121_connector_detect_ctx, ++ .mode_valid = it66121_connector_mode_valid, ++}; ++ ++static const struct drm_connector_funcs it66121_connector_funcs = { ++ .reset = drm_atomic_helper_connector_reset, ++ .fill_modes = drm_helper_probe_single_connector_modes, ++ .destroy = drm_connector_cleanup, ++ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, ++ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, ++}; ++ ++static int it66121_bridge_attach(struct drm_bridge *bridge, ++ enum drm_bridge_attach_flags flags) ++{ ++ int ret; ++ struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, ++ bridge); ++ ++ if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { ++ DRM_ERROR("Fix bridge driver to make connector optional!"); ++ return -EINVAL; ++ } ++ ++ if (!bridge->encoder) { ++ DRM_ERROR("Parent encoder object not found"); ++ return -ENODEV; ++ } ++ ++ ret = regmap_write_bits(ctx->regmap, IT66121_CLK_BANK_REG, ++ IT66121_CLK_BANK_PWROFF_RCLK, 0); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write_bits(ctx->regmap, IT66121_INT_REG, ++ IT66121_INT_TX_CLK_OFF, 0); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write_bits(ctx->regmap, IT66121_AFE_DRV_REG, ++ IT66121_AFE_DRV_PWD, 0); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write_bits(ctx->regmap, IT66121_AFE_XP_REG, ++ IT66121_AFE_XP_PWDI | IT66121_AFE_XP_PWDPLL, 0); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write_bits(ctx->regmap, IT66121_AFE_IP_REG, ++ IT66121_AFE_IP_PWDPLL, 0); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write_bits(ctx->regmap, IT66121_AFE_DRV_REG, ++ IT66121_AFE_DRV_RST, 0); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write_bits(ctx->regmap, IT66121_AFE_XP_REG, ++ IT66121_AFE_XP_RESETB, IT66121_AFE_XP_RESETB); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write_bits(ctx->regmap, IT66121_AFE_IP_REG, ++ IT66121_AFE_IP_RESETB, IT66121_AFE_IP_RESETB); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write_bits(ctx->regmap, IT66121_SW_RST_REG, ++ IT66121_SW_RST_REF, ++ IT66121_SW_RST_REF); ++ if (ret) ++ return ret; ++ ++ msleep(50); ++ ++ ret = drm_connector_init(bridge->dev, &ctx->connector, ++ &it66121_connector_funcs, ++ DRM_MODE_CONNECTOR_HDMIA); ++ if (ret) ++ return ret; ++ ++ ctx->connector.polled = DRM_CONNECTOR_POLL_HPD; ++ drm_connector_helper_add(&ctx->connector, ++ &it66121_connector_helper_funcs); ++ ++ ret = drm_connector_attach_encoder(&ctx->connector, bridge->encoder); ++ if (ret) ++ return ret; ++ ++ ret = drm_connector_register(&ctx->connector); ++ if (ret) ++ return ret; ++ ++ /* Start interrupts */ ++ return regmap_write_bits(ctx->regmap, IT66121_INT_MASK1_REG, ++ IT66121_INT_MASK1_DDC_NOACK | ++ IT66121_INT_MASK1_HPD | ++ IT66121_INT_MASK1_DDC_FIFOERR | ++ IT66121_INT_MASK1_DDC_BUSHANG, ++ ~(IT66121_INT_MASK1_DDC_NOACK | ++ IT66121_INT_MASK1_HPD | ++ IT66121_INT_MASK1_DDC_FIFOERR | ++ IT66121_INT_MASK1_DDC_BUSHANG) & 0xFF); ++} ++ ++static int it66121_set_mute(struct it66121_ctx *ctx, bool mute) ++{ ++ int ret; ++ unsigned int val; ++ ++ val = mute ? IT66121_AV_MUTE_ON : (~IT66121_AV_MUTE_ON & 0xFF); ++ ret = regmap_write_bits(ctx->regmap, IT66121_AV_MUTE_REG, ++ IT66121_AV_MUTE_ON, val); ++ if (ret) ++ return ret; ++ ++ return regmap_write(ctx->regmap, IT66121_PKT_GEN_CTRL_REG, ++ IT66121_PKT_GEN_CTRL_ON | ++ IT66121_PKT_GEN_CTRL_RPT); ++} ++ ++static void it66121_bridge_enable(struct drm_bridge *bridge) ++{ ++ struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, ++ bridge); ++ ++ it66121_set_mute(ctx, false); ++} ++ ++static void it66121_bridge_disable(struct drm_bridge *bridge) ++{ ++ struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, ++ bridge); ++ ++ it66121_set_mute(ctx, true); ++} ++ ++static ++void it66121_bridge_mode_set(struct drm_bridge *bridge, ++ const struct drm_display_mode *mode, ++ const struct drm_display_mode *adjusted_mode) ++{ ++ int ret, i; ++ u8 buf[HDMI_INFOFRAME_SIZE(AVI)]; ++ struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, ++ bridge); ++ const u16 aviinfo_reg[HDMI_AVI_INFOFRAME_SIZE] = { ++ IT66121_AVIINFO_DB1_REG, ++ IT66121_AVIINFO_DB2_REG, ++ IT66121_AVIINFO_DB3_REG, ++ IT66121_AVIINFO_DB4_REG, ++ IT66121_AVIINFO_DB5_REG, ++ IT66121_AVIINFO_DB6_REG, ++ IT66121_AVIINFO_DB7_REG, ++ IT66121_AVIINFO_DB8_REG, ++ IT66121_AVIINFO_DB9_REG, ++ IT66121_AVIINFO_DB10_REG, ++ IT66121_AVIINFO_DB11_REG, ++ IT66121_AVIINFO_DB12_REG, ++ IT66121_AVIINFO_DB13_REG ++ }; ++ ++ mutex_lock(&ctx->lock); ++ ++ hdmi_avi_infoframe_init(&ctx->hdmi_avi_infoframe); ++ ++ ret = drm_hdmi_avi_infoframe_from_display_mode(&ctx->hdmi_avi_infoframe, ++ &ctx->connector, ++ adjusted_mode); ++ if (ret) { ++ DRM_ERROR("Failed to setup AVI infoframe: %d\n", ret); ++ goto unlock; ++ } ++ ++ ret = hdmi_avi_infoframe_pack(&ctx->hdmi_avi_infoframe, buf, ++ sizeof(buf)); ++ if (ret < 0) { ++ DRM_ERROR("Failed to pack infoframe: %d\n", ret); ++ goto unlock; ++ } ++ ++ /* Write new AVI infoframe packet */ ++ for (i = 0; i < HDMI_AVI_INFOFRAME_SIZE; i++) { ++ if (regmap_write(ctx->regmap, aviinfo_reg[i], ++ buf[i + HDMI_INFOFRAME_HEADER_SIZE])) ++ goto unlock; ++ } ++ if (regmap_write(ctx->regmap, IT66121_AVIINFO_CSUM_REG, buf[3])) ++ goto unlock; ++ ++ /* Enable AVI infoframe */ ++ if (regmap_write(ctx->regmap, IT66121_AVI_INFO_PKT_REG, ++ IT66121_AVI_INFO_PKT_ON | ++ IT66121_AVI_INFO_PKT_RPT)) ++ goto unlock; ++ ++ /* Set TX mode to HDMI */ ++ if (regmap_write(ctx->regmap, IT66121_HDMI_MODE_REG, ++ IT66121_HDMI_MODE_HDMI)) ++ goto unlock; ++ ++ if (regmap_write_bits(ctx->regmap, IT66121_CLK_BANK_REG, ++ IT66121_CLK_BANK_PWROFF_TXCLK, ++ IT66121_CLK_BANK_PWROFF_TXCLK)) ++ goto unlock; ++ ++ if (it66121_configure_input(ctx)) ++ goto unlock; ++ ++ if (it66121_configure_afe(ctx, adjusted_mode)) ++ goto unlock; ++ ++ regmap_write_bits(ctx->regmap, IT66121_CLK_BANK_REG, ++ IT66121_CLK_BANK_PWROFF_TXCLK, ++ ~IT66121_CLK_BANK_PWROFF_TXCLK & 0xFF); ++ ++unlock: ++ mutex_unlock(&ctx->lock); ++} ++ ++static const struct drm_bridge_funcs it66121_bridge_funcs = { ++ .attach = it66121_bridge_attach, ++ .enable = it66121_bridge_enable, ++ .disable = it66121_bridge_disable, ++ .mode_set = it66121_bridge_mode_set, ++}; ++ ++static irqreturn_t it66121_irq_threaded_handler(int irq, void *dev_id) ++{ ++ int ret; ++ unsigned int val; ++ struct it66121_ctx *ctx = dev_id; ++ struct device *dev = ctx->dev; ++ bool event = false; ++ ++ mutex_lock(&ctx->lock); ++ ++ ret = regmap_read(ctx->regmap, IT66121_SYS_STATUS_REG, &val); ++ if (ret) ++ goto unlock; ++ ++ if (val & IT66121_SYS_STATUS_ACTIVE_IRQ) { ++ ret = regmap_read(ctx->regmap, IT66121_INT_STATUS1_REG, &val); ++ if (ret) { ++ dev_err(dev, "Cannot read STATUS1_REG %d\n", ret); ++ } else { ++ if (val & IT66121_INT_STATUS1_DDC_FIFOERR) ++ it66121_clear_ddc_fifo(ctx); ++ if (val & (IT66121_INT_STATUS1_DDC_BUSHANG | ++ IT66121_INT_STATUS1_DDC_NOACK)) ++ it66121_abort_ddc_ops(ctx); ++ if (val & IT66121_INT_STATUS1_HPD_STATUS) { ++ regmap_write_bits(ctx->regmap, ++ IT66121_INT_CLR1_REG, ++ IT66121_INT_CLR1_HPD, ++ IT66121_INT_CLR1_HPD); ++ ++ if (!it66121_is_hpd_detect(ctx)) { ++ kfree(ctx->edid); ++ ctx->edid = NULL; ++ } ++ event = true; ++ } ++ } ++ ++ regmap_write_bits(ctx->regmap, IT66121_SYS_STATUS_REG, ++ IT66121_SYS_STATUS_CLEAR_IRQ, ++ IT66121_SYS_STATUS_CLEAR_IRQ); ++ } ++ ++unlock: ++ mutex_unlock(&ctx->lock); ++ ++ if (event) ++ drm_helper_hpd_irq_event(ctx->bridge.dev); ++ ++ return IRQ_HANDLED; ++} ++ ++static int it66121_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ u8 ids[4]; ++ int i, ret; ++ struct it66121_ctx *ctx; ++ struct device *dev = &client->dev; ++ ++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { ++ dev_err(dev, "I2C check functionality failed.\n"); ++ return -ENXIO; ++ } ++ ++ ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); ++ if (!ctx) ++ return -ENOMEM; ++ ++ ctx->dev = dev; ++ ctx->client = client; ++ i2c_set_clientdata(client, ctx); ++ mutex_init(&ctx->lock); ++ ctx->conf = (struct it66121_conf *)of_device_get_match_data(dev); ++ if (!ctx->conf) ++ return -ENODEV; ++ ++ ctx->supplies[0].supply = "vcn33"; ++ ctx->supplies[1].supply = "vcn18"; ++ ctx->supplies[2].supply = "vrf12"; ++ ret = devm_regulator_bulk_get(ctx->dev, 3, ctx->supplies); ++ if (ret) { ++ dev_err(ctx->dev, "regulator_bulk failed\n"); ++ return ret; ++ } ++ ++ ctx->dual_edge = of_property_read_bool(dev->of_node, "pclk-dual-edge"); ++ ++ ret = ite66121_power_on(ctx); ++ if (ret) ++ return ret; ++ ++ it66121_hw_reset(ctx); ++ ++ ctx->regmap = devm_regmap_init_i2c(client, &it66121_regmap_config); ++ if (IS_ERR(ctx->regmap)) { ++ ite66121_power_off(ctx); ++ return PTR_ERR(ctx); ++ } ++ ++ for (i = 0; i < 4; i++) { ++ regmap_read(ctx->regmap, i, &ret); ++ ids[i] = ret; ++ } ++ ++ if (ids[0] != IT66121_VENDOR_ID0 || ++ ids[1] != IT66121_VENDOR_ID1 || ++ ids[2] != IT66121_DEVICE_ID0 || ++ ((ids[3] & IT66121_DEVICE_MASK) != IT66121_DEVICE_ID1)) { ++ ite66121_power_off(ctx); ++ return -ENODEV; ++ } ++ ++ ctx->bridge.funcs = &it66121_bridge_funcs; ++ ctx->bridge.of_node = dev->of_node; ++ ++ ret = devm_request_threaded_irq(dev, client->irq, NULL, ++ it66121_irq_threaded_handler, ++ IRQF_SHARED | IRQF_TRIGGER_LOW | ++ IRQF_ONESHOT, ++ dev_name(dev), ++ ctx); ++ if (ret < 0) { ++ dev_err(dev, "Failed to request irq %d:%d\n", client->irq, ret); ++ ite66121_power_off(ctx); ++ return ret; ++ } ++ ++ drm_bridge_add(&ctx->bridge); ++ ++ return 0; ++} ++ ++static int it66121_remove(struct i2c_client *client) ++{ ++ struct it66121_ctx *ctx = i2c_get_clientdata(client); ++ ++ ite66121_power_off(ctx); ++ drm_bridge_remove(&ctx->bridge); ++ kfree(ctx->edid); ++ mutex_destroy(&ctx->lock); ++ ++ return 0; ++} ++ ++static const struct of_device_id it66121_dt_match[] = { ++ { .compatible = "ite,it66121", ++ .data = &it66121_conf_simple, ++ }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, it66121_dt_match); ++ ++static const struct i2c_device_id it66121_id[] = { ++ { "it66121", 0 }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(i2c, it66121_id); ++ ++static struct i2c_driver it66121_driver = { ++ .driver = { ++ .name = "it66121", ++ .of_match_table = it66121_dt_match, ++ }, ++ .probe = it66121_probe, ++ .remove = it66121_remove, ++ .id_table = it66121_id, ++}; ++ ++module_i2c_driver(it66121_driver); ++ ++MODULE_AUTHOR("Phong LE"); ++MODULE_DESCRIPTION("IT66121 HDMI transmitter driver"); ++MODULE_LICENSE("GPL v2"); + +From ec5271e4d8d6d57545a284ee5bd365f17990fdc6 Mon Sep 17 00:00:00 2001 +From: Phong LE +Date: Wed, 11 Mar 2020 13:51:35 +0100 +Subject: [PATCH] MAINTAINERS: add it66121 HDMI bridge driver entry + +Add Neil Armstrong and myself as maintainers + +Signed-off-by: Phong LE +--- + MAINTAINERS | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/MAINTAINERS b/MAINTAINERS +index db98a799f409..5a34ca2f0e11 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -9193,6 +9193,14 @@ Q: http://patchwork.linuxtv.org/project/linux-media/list/ + T: git git://linuxtv.org/anttip/media_tree.git + F: drivers/media/tuners/it913x* + ++ITE IT66121 HDMI BRIDGE DRIVER ++M: Phong LE ++M: Neil Armstrong ++S: Maintained ++F: drivers/gpu/drm/bridge/ite-it66121.c ++T: git git://anongit.freedesktop.org/drm/drm-misc ++F: Documentation/devicetree/bindings/display/bridge/ite,it66121.yaml ++ + IVTV VIDEO4LINUX DRIVER + M: Andy Walls + L: linux-media@vger.kernel.org + +From b8f225a1145ac25cd5df830d557e5be6d212a798 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Tue, 26 May 2020 13:48:12 +0200 +Subject: [PATCH] drm: bridge: it66121: add IT66121FN variant + +--- + drivers/gpu/drm/bridge/ite-it66121.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c +index 7e1a90319a6a..68f7e50fdddd 100644 +--- a/drivers/gpu/drm/bridge/ite-it66121.c ++++ b/drivers/gpu/drm/bridge/ite-it66121.c +@@ -242,6 +242,11 @@ static const struct it66121_conf it66121_conf_simple = { + .input_conversion_reg = IT66121_INPUT_CSC_NO_CONV, + }; + ++static const struct it66121_conf it66121fn_conf_simple = { ++ .input_mode_reg = IT66121_INPUT_MODE_RGB, ++ .input_conversion_reg = IT66121_INPUT_CSC_NO_CONV, ++}; ++ + static void it66121_hw_reset(struct it66121_ctx *ctx) + { + gpiod_set_value(ctx->gpio_reset, 1); +@@ -970,6 +975,9 @@ static const struct of_device_id it66121_dt_match[] = { + { .compatible = "ite,it66121", + .data = &it66121_conf_simple, + }, ++ { .compatible = "ite,it66121fn", ++ .data = &it66121fn_conf_simple, ++ }, + { }, + }; + MODULE_DEVICE_TABLE(of, it66121_dt_match); + +From e7ebcc04f15308b5ece1b5f99689d8577be2625d Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sun, 16 Aug 2020 23:40:24 +0200 +Subject: [PATCH] WIP: ARM: dts: rockchip add vpll clock to RK322Xs hdmi node + +--- + arch/arm/boot/dts/rk322x.dtsi | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi +index 48e6e8d44a1a..b69b5be110c3 100644 +--- a/arch/arm/boot/dts/rk322x.dtsi ++++ b/arch/arm/boot/dts/rk322x.dtsi +@@ -644,8 +644,8 @@ hdmi: hdmi@200a0000 { + interrupts = ; + assigned-clocks = <&cru SCLK_HDMI_PHY>; + assigned-clock-parents = <&hdmi_phy>; +- clocks = <&cru SCLK_HDMI_HDCP>, <&cru PCLK_HDMI_CTRL>, <&cru SCLK_HDMI_CEC>; +- clock-names = "isfr", "iahb", "cec"; ++ clocks = <&cru SCLK_HDMI_HDCP>, <&cru PCLK_HDMI_CTRL>, <&hdmi_phy>, <&cru SCLK_HDMI_CEC>; ++ clock-names = "isfr", "iahb", "vpll", "cec"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmii2c_xfer &hdmi_hpd &hdmi_cec>; + resets = <&cru SRST_HDMI_P>; + +From e1dd22643e8fc82021c3ed8f5355bffa33899b9c Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Tue, 18 Aug 2020 11:19:53 +0200 +Subject: [PATCH] drm/bridge: !cleanup: remove pr_infos + +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c +index e6953219beee..2cfd5b418c05 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c +@@ -97,8 +97,6 @@ static int dw_hdmi_cec_transmit(struct cec_adapter *adap, u8 attempts, + struct dw_hdmi_cec *cec = cec_get_drvdata(adap); + unsigned int i, ctrl; + +- pr_info("%s: attempts=%u signal_free_time=%u msg=%*ph (sequence: %u)\n", __func__, attempts, signal_free_time, msg->len, msg->msg, msg->sequence); +- + switch (signal_free_time) { + case CEC_SIGNAL_FREE_TIME_RETRY: + ctrl = CEC_CTRL_RETRY; +@@ -188,8 +186,6 @@ static irqreturn_t dw_hdmi_cec_hardirq(int irq, void *data) + ret = IRQ_WAKE_THREAD; + } + +- pr_info("%s: stat=%x ret=%x tx_done=%d rx_done=%d tx_status=%u tx_attempts=%u\n", __func__, stat, ret, cec->tx_done, cec->rx_done, cec->tx_status, cec->tx_attempts); +- + return ret; + } + +@@ -198,8 +194,6 @@ static irqreturn_t dw_hdmi_cec_thread(int irq, void *data) + struct cec_adapter *adap = data; + struct dw_hdmi_cec *cec = cec_get_drvdata(adap); + +- //pr_info("%s: tx_done=%d rx_done=%d tx_status=%u tx_attempts=%u\n", __func__, cec->tx_done, cec->rx_done, cec->tx_status, cec->tx_attempts); +- + if (cec->tx_done) { + cec->tx_done = false; + if (cec->tx_status == CEC_TX_STATUS_LOW_DRIVE) diff --git a/patch/kernel/rk322x-current/01-linux-3000-rockchip-v4l-wip.patch b/patch/kernel/rk322x-current/01-linux-3000-rockchip-v4l-wip.patch new file mode 100644 index 000000000..e19954c6d --- /dev/null +++ b/patch/kernel/rk322x-current/01-linux-3000-rockchip-v4l-wip.patch @@ -0,0 +1,4647 @@ +From d9d1bb6e72ad344280be5887718444f110aec86f Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Fri, 22 May 2020 20:42:11 +0000 +Subject: [PATCH] fixup! media: rkvdec: Fix .buf_prepare + +--- + drivers/staging/media/rkvdec/rkvdec.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index f0f28f6a68cf..9edaea98a483 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -599,13 +599,11 @@ static int rkvdec_buf_prepare(struct vb2_buffer *vb) + } + + /* +- * Buffer's bytesused is written by the driver for CAPTURE buffers, +- * or if the application passed zero bytesused on an OUTPUT buffer. ++ * Buffer's bytesused is written by the driver for CAPTURE buffers. + */ +- if (!V4L2_TYPE_IS_OUTPUT(vq->type) || +- (V4L2_TYPE_IS_OUTPUT(vq->type) && !vb2_get_plane_payload(vb, 0))) +- vb2_set_plane_payload(vb, 0, +- f->fmt.pix_mp.plane_fmt[0].sizeimage); ++ if (!V4L2_TYPE_IS_OUTPUT(vq->type)) ++ vb2_set_plane_payload(vb, 0, f->fmt.pix_mp.plane_fmt[0].sizeimage); ++ + return 0; + } + + +From e5c9031e74c1ff2c597654f172c9f1e856810544 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 15 Aug 2020 08:28:56 +0000 +Subject: [PATCH] fixup! media: rkvdec: Add the VP9 backend + +--- + drivers/staging/media/rkvdec/rkvdec.c | 5 ----- + 1 file changed, 5 deletions(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index 9edaea98a483..9accbe889040 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -161,24 +161,19 @@ static const u32 rkvdec_h264_decoded_fmts[] = { + + static const struct rkvdec_ctrl_desc rkvdec_vp9_ctrl_descs[] = { + { +- .per_request = true, + .mandatory = true, + .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_DECODE_PARAMS, + }, + { +- .mandatory = true, + .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(0), + }, + { +- .mandatory = true, + .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(1), + }, + { +- .mandatory = true, + .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(2), + }, + { +- .mandatory = true, + .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(3), + }, + { + +From 9a9b9efc39a879ef65d7f9bec29fd8f0b8ce89fc Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 23 May 2020 10:18:16 +0000 +Subject: [PATCH] WIP: media: rkvdec: continue to gate clock when decoding + finish + +Signed-off-by: Jonas Karlman +--- + drivers/staging/media/rkvdec/rkvdec.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index 9accbe889040..a282b7e6d6e8 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -1079,7 +1079,8 @@ static irqreturn_t rkvdec_irq_handler(int irq, void *priv) + state = (status & RKVDEC_RDY_STA) ? + VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR; + +- writel(0, rkvdec->regs + RKVDEC_REG_INTERRUPT); ++ writel(RKVDEC_CONFIG_DEC_CLK_GATE_E, ++ rkvdec->regs + RKVDEC_REG_INTERRUPT); + if (cancel_delayed_work(&rkvdec->watchdog_work)) { + struct rkvdec_ctx *ctx; + +@@ -1100,7 +1101,8 @@ static void rkvdec_watchdog_func(struct work_struct *work) + ctx = v4l2_m2m_get_curr_priv(rkvdec->m2m_dev); + if (ctx) { + dev_err(rkvdec->dev, "Frame processing timed out!\n"); +- writel(RKVDEC_IRQ_DIS, rkvdec->regs + RKVDEC_REG_INTERRUPT); ++ writel(RKVDEC_CONFIG_DEC_CLK_GATE_E | RKVDEC_IRQ_DIS, ++ rkvdec->regs + RKVDEC_REG_INTERRUPT); + writel(0, rkvdec->regs + RKVDEC_REG_SYSCTRL); + rkvdec_job_finish(ctx, VB2_BUF_STATE_ERROR); + } + +From 126fa7ad4de4368fe4938d59b327813a8649ff3b Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 23 May 2020 10:16:01 +0000 +Subject: [PATCH] WIP: media: rkvdec: pm runtime dont use autosuspend before + disable and cleanup + +Signed-off-by: Jonas Karlman +--- + drivers/staging/media/rkvdec/rkvdec.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index a282b7e6d6e8..658fb6028e72 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -1200,9 +1200,9 @@ static int rkvdec_remove(struct platform_device *pdev) + { + struct rkvdec_dev *rkvdec = platform_get_drvdata(pdev); + +- rkvdec_v4l2_cleanup(rkvdec); +- pm_runtime_disable(&pdev->dev); + pm_runtime_dont_use_autosuspend(&pdev->dev); ++ pm_runtime_disable(&pdev->dev); ++ rkvdec_v4l2_cleanup(rkvdec); + return 0; + } + + +From c7382800a8af054b62ff6edea7d62bc30a160b74 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 23 May 2020 11:23:04 +0000 +Subject: [PATCH] WIP: media: rkvdec: h264: return early when no reference + pictures + +NOTE: also change from a switch statement to access reflists from a pointer array, +should simplify once we add support for field reference list + +Signed-off-by: Jonas Karlman +--- + drivers/staging/media/rkvdec/rkvdec-h264.c | 18 +++++------------- + 1 file changed, 5 insertions(+), 13 deletions(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c +index afc695d32186..1716bfb596ae 100644 +--- a/drivers/staging/media/rkvdec/rkvdec-h264.c ++++ b/drivers/staging/media/rkvdec/rkvdec-h264.c +@@ -734,6 +734,7 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx, + const struct v4l2_ctrl_h264_sps *sps = run->sps; + struct rkvdec_h264_priv_tbl *priv_tbl = h264_ctx->priv_tbl.cpu; + u32 max_frame_num = 1 << (sps->log2_max_frame_num_minus4 + 4); ++ u8 *reflists[3] = { h264_ctx->reflists.p, h264_ctx->reflists.b0, h264_ctx->reflists.b1 }; + + u32 *hw_rps = priv_tbl->rps; + u32 i, j; +@@ -741,6 +742,9 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx, + + memset(hw_rps, 0, sizeof(priv_tbl->rps)); + ++ if (!h264_ctx->reflists.num_valid) ++ return; ++ + /* + * Assign an invalid pic_num if DPB entry at that position is inactive. + * If we assign 0 in that position hardware will treat that as a real +@@ -763,19 +767,7 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx, + for (j = 0; j < RKVDEC_NUM_REFLIST; j++) { + for (i = 0; i < h264_ctx->reflists.num_valid; i++) { + u8 dpb_valid = 0; +- u8 idx = 0; +- +- switch (j) { +- case 0: +- idx = h264_ctx->reflists.p[i]; +- break; +- case 1: +- idx = h264_ctx->reflists.b0[i]; +- break; +- case 2: +- idx = h264_ctx->reflists.b1[i]; +- break; +- } ++ u8 idx = reflists[j][i]; + + if (idx >= ARRAY_SIZE(dec_params->dpb)) + continue; + +From 70eb1d9dfa98bf6a6662280de58e01dffa347add Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 23 May 2020 14:42:27 +0000 +Subject: [PATCH] WIP: media: rkvdec: h264: add field decoding support + +Signed-off-by: Jonas Karlman +--- + drivers/staging/media/rkvdec/rkvdec-h264.c | 79 ++++++++++++++++++---- + 1 file changed, 64 insertions(+), 15 deletions(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c +index 1716bfb596ae..c388bf3da079 100644 +--- a/drivers/staging/media/rkvdec/rkvdec-h264.c ++++ b/drivers/staging/media/rkvdec/rkvdec-h264.c +@@ -737,7 +737,7 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx, + u8 *reflists[3] = { h264_ctx->reflists.p, h264_ctx->reflists.b0, h264_ctx->reflists.b1 }; + + u32 *hw_rps = priv_tbl->rps; +- u32 i, j; ++ u32 i, j, k; + u16 *p = (u16 *)hw_rps; + + memset(hw_rps, 0, sizeof(priv_tbl->rps)); +@@ -764,18 +764,71 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx, + p[i] = dpb[i].frame_num - max_frame_num; + } + +- for (j = 0; j < RKVDEC_NUM_REFLIST; j++) { +- for (i = 0; i < h264_ctx->reflists.num_valid; i++) { +- u8 dpb_valid = 0; +- u8 idx = reflists[j][i]; ++ if (!(dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC)) { ++ for (j = 0; j < RKVDEC_NUM_REFLIST; j++) { ++ for (i = 0; i < h264_ctx->reflists.num_valid; i++) { ++ u8 dpb_valid = 0; ++ u8 idx = reflists[j][i]; + +- if (idx >= ARRAY_SIZE(dec_params->dpb)) +- continue; +- dpb_valid = !!(dpb[idx].flags & +- V4L2_H264_DPB_ENTRY_FLAG_ACTIVE); ++ if (idx >= ARRAY_SIZE(dec_params->dpb)) ++ continue; ++ dpb_valid = !!(dpb[idx].flags & ++ V4L2_H264_DPB_ENTRY_FLAG_ACTIVE); + +- set_ps_field(hw_rps, DPB_INFO(i, j), +- idx | dpb_valid << 4); ++ set_ps_field(hw_rps, DPB_INFO(i, j), ++ idx | dpb_valid << 4); ++ } ++ } ++ return; ++ } ++ ++ for (j = 0; j < RKVDEC_NUM_REFLIST; j++) { ++ enum v4l2_h264_field_reference a_parity = ++ (dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD) ++ ? V4L2_H264_BOTTOM_FIELD_REF : V4L2_H264_TOP_FIELD_REF; ++ enum v4l2_h264_field_reference b_parity = ++ (dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD) ++ ? V4L2_H264_TOP_FIELD_REF : V4L2_H264_BOTTOM_FIELD_REF; ++ u32 flags = V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM; ++ i = 0; ++ ++ for (k = 0; k < 2; k++) { ++ u8 a = 0; ++ u8 b = 0; ++ u32 long_term = k ? V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM : 0; ++ ++ while (a < h264_ctx->reflists.num_valid || b < h264_ctx->reflists.num_valid) { ++ for (; a < h264_ctx->reflists.num_valid; a++) { ++ u8 idx = reflists[j][a]; ++ if (idx >= ARRAY_SIZE(dec_params->dpb)) ++ continue; ++ if ((dpb[idx].reference & a_parity) == a_parity && ++ (dpb[idx].flags & flags) == long_term) { ++ set_ps_field(hw_rps, DPB_INFO(i, j), ++ idx | (1 << 4)); ++ set_ps_field(hw_rps, BOTTOM_FLAG(i, j), ++ a_parity == V4L2_H264_BOTTOM_FIELD_REF); ++ i++; ++ a++; ++ break; ++ } ++ } ++ for (; b < h264_ctx->reflists.num_valid; b++) { ++ u8 idx = reflists[j][b]; ++ if (idx >= ARRAY_SIZE(dec_params->dpb)) ++ continue; ++ if ((dpb[idx].reference & b_parity) == b_parity && ++ (dpb[idx].flags & flags) == long_term) { ++ set_ps_field(hw_rps, DPB_INFO(i, j), ++ idx | (1 << 4)); ++ set_ps_field(hw_rps, BOTTOM_FLAG(i, j), ++ b_parity == V4L2_H264_BOTTOM_FIELD_REF); ++ i++; ++ b++; ++ break; ++ } ++ } ++ } + } + } + } +@@ -968,10 +1021,6 @@ static void config_registers(struct rkvdec_ctx *ctx, + rkvdec->regs + RKVDEC_REG_H264_BASE_REFER15); + } + +- /* +- * Since support frame mode only +- * top_field_order_cnt is the same as bottom_field_order_cnt +- */ + reg = RKVDEC_CUR_POC(dec_params->top_field_order_cnt); + writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_CUR_POC0); + + +From 7032b50b559ff869d47ae06ec94cf7b50f7a8eb1 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 26 Oct 2019 13:55:15 +0200 +Subject: [PATCH] media: uapi: hevc: Add scaling matrix control + +HEVC has a scaling matrix concept. Add support for it. + +Signed-off-by: Jernej Skrabec +--- + .../media/v4l/ext-ctrls-codec.rst | 41 +++++++++++++++++++ + .../media/v4l/pixfmt-compressed.rst | 1 + + drivers/media/v4l2-core/v4l2-ctrls.c | 10 +++++ + include/media/hevc-ctrls.h | 11 +++++ + 4 files changed, 63 insertions(+) + +diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +index ca13b141d8c2..578de53ff929 100644 +--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst ++++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +@@ -4777,6 +4777,47 @@ enum v4l2_mpeg_video_hevc_size_of_length_field - + - ``padding[6]`` + - Applications and drivers must set this to zero. + ++``V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX (struct)`` ++ Specifies the scaling matrix (as extracted from the bitstream) for ++ the associated HEVC slice data. The bitstream parameters are ++ defined according to :ref:`hevc`, section 7.4.5 "Scaling list ++ data semantics". For further documentation, refer to the above ++ specification, unless there is an explicit comment stating ++ otherwise. ++ ++ .. note:: ++ ++ This compound control is not yet part of the public kernel API and ++ it is expected to change. ++ ++.. c:type:: v4l2_ctrl_hevc_scaling_matrix ++ ++.. cssclass:: longtable ++ ++.. flat-table:: struct v4l2_ctrl_hevc_scaling_matrix ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - __u8 ++ - ``scaling_list_4x4[6][16]`` ++ - ++ * - __u8 ++ - ``scaling_list_8x8[6][64]`` ++ - ++ * - __u8 ++ - ``scaling_list_16x16[6][64]`` ++ - ++ * - __u8 ++ - ``scaling_list_32x32[2][64]`` ++ - ++ * - __u8 ++ - ``scaling_list_dc_coef_16x16[6]`` ++ - ++ * - __u8 ++ - ``scaling_list_dc_coef_32x32[2]`` ++ - ++ + ``V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE (enum)`` + Specifies the decoding mode to use. Currently exposes slice-based and + frame-based decoding but new modes might be added later on. +diff --git a/Documentation/userspace-api/media/v4l/pixfmt-compressed.rst b/Documentation/userspace-api/media/v4l/pixfmt-compressed.rst +index 3828bb79225d..a77560204c21 100644 +--- a/Documentation/userspace-api/media/v4l/pixfmt-compressed.rst ++++ b/Documentation/userspace-api/media/v4l/pixfmt-compressed.rst +@@ -207,6 +207,7 @@ Compressed Formats + * ``V4L2_CID_MPEG_VIDEO_HEVC_SPS`` + * ``V4L2_CID_MPEG_VIDEO_HEVC_PPS`` + * ``V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS`` ++ * ``V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX`` + See the :ref:`associated Codec Control IDs `. + Buffers associated with this pixel format must contain the appropriate + number of macroblocks to decode a full corresponding frame. +diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c +index 5913088cbc6f..6f7df51cb633 100644 +--- a/drivers/media/v4l2-core/v4l2-ctrls.c ++++ b/drivers/media/v4l2-core/v4l2-ctrls.c +@@ -995,6 +995,7 @@ const char *v4l2_ctrl_get_name(u32 id) + case V4L2_CID_MPEG_VIDEO_HEVC_SPS: return "HEVC Sequence Parameter Set"; + case V4L2_CID_MPEG_VIDEO_HEVC_PPS: return "HEVC Picture Parameter Set"; + case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS: return "HEVC Slice Parameters"; ++ case V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX: return "HEVC Scaling Matrix"; + case V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE: return "HEVC Decode Mode"; + case V4L2_CID_MPEG_VIDEO_HEVC_START_CODE: return "HEVC Start Code"; + +@@ -1442,6 +1443,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, + case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS: + *type = V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS; + break; ++ case V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX: ++ *type = V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX; ++ break; + case V4L2_CID_UNIT_CELL_SIZE: + *type = V4L2_CTRL_TYPE_AREA; + *flags |= V4L2_CTRL_FLAG_READ_ONLY; +@@ -2134,6 +2138,9 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, + zero_padding(*p_hevc_slice_params); + break; + ++ case V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX: ++ break; ++ + case V4L2_CTRL_TYPE_AREA: + area = p; + if (!area->width || !area->height) +@@ -2832,6 +2839,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, + case V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS: + elem_size = sizeof(struct v4l2_ctrl_hevc_slice_params); + break; ++ case V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX: ++ elem_size = sizeof(struct v4l2_ctrl_hevc_scaling_matrix); ++ break; + case V4L2_CTRL_TYPE_AREA: + elem_size = sizeof(struct v4l2_area); + break; +diff --git a/include/media/hevc-ctrls.h b/include/media/hevc-ctrls.h +index 1009cf0891cc..1592e52c3614 100644 +--- a/include/media/hevc-ctrls.h ++++ b/include/media/hevc-ctrls.h +@@ -19,6 +19,7 @@ + #define V4L2_CID_MPEG_VIDEO_HEVC_SPS (V4L2_CID_MPEG_BASE + 1008) + #define V4L2_CID_MPEG_VIDEO_HEVC_PPS (V4L2_CID_MPEG_BASE + 1009) + #define V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS (V4L2_CID_MPEG_BASE + 1010) ++#define V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX (V4L2_CID_MPEG_BASE + 1011) + #define V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE (V4L2_CID_MPEG_BASE + 1015) + #define V4L2_CID_MPEG_VIDEO_HEVC_START_CODE (V4L2_CID_MPEG_BASE + 1016) + +@@ -26,6 +27,7 @@ + #define V4L2_CTRL_TYPE_HEVC_SPS 0x0120 + #define V4L2_CTRL_TYPE_HEVC_PPS 0x0121 + #define V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS 0x0122 ++#define V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX 0x0123 + + enum v4l2_mpeg_video_hevc_decode_mode { + V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED, +@@ -209,4 +211,13 @@ struct v4l2_ctrl_hevc_slice_params { + __u64 flags; + }; + ++struct v4l2_ctrl_hevc_scaling_matrix { ++ __u8 scaling_list_4x4[6][16]; ++ __u8 scaling_list_8x8[6][64]; ++ __u8 scaling_list_16x16[6][64]; ++ __u8 scaling_list_32x32[2][64]; ++ __u8 scaling_list_dc_coef_16x16[6]; ++ __u8 scaling_list_dc_coef_32x32[2]; ++}; ++ + #endif + +From e8b0441e3d60b0e936b975f2467d1604158a1d6c Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 26 Oct 2019 15:42:28 +0200 +Subject: [PATCH] media: uapi: hevc: Add segment address field + +If HEVC frame consists of multiple slices, segment address has to be +known in order to properly decode it. + +Add segment address field to slice parameters. + +Signed-off-by: Jernej Skrabec +--- + Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst | 5 ++++- + include/media/hevc-ctrls.h | 5 ++++- + 2 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +index 578de53ff929..bca71e38b85d 100644 +--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst ++++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +@@ -4572,6 +4572,9 @@ enum v4l2_mpeg_video_hevc_size_of_length_field - + * - __u32 + - ``data_bit_offset`` + - Offset (in bits) to the video data in the current slice data. ++ * - __u32 ++ - ``slice_segment_addr`` ++ - + * - __u8 + - ``nal_unit_type`` + - +@@ -4649,7 +4652,7 @@ enum v4l2_mpeg_video_hevc_size_of_length_field - + - ``num_rps_poc_lt_curr`` + - The number of reference pictures in the long-term set. + * - __u8 +- - ``padding[7]`` ++ - ``padding[5]`` + - Applications and drivers must set this to zero. + * - struct :c:type:`v4l2_hevc_dpb_entry` + - ``dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]`` +diff --git a/include/media/hevc-ctrls.h b/include/media/hevc-ctrls.h +index 1592e52c3614..3e2e32098312 100644 +--- a/include/media/hevc-ctrls.h ++++ b/include/media/hevc-ctrls.h +@@ -167,6 +167,9 @@ struct v4l2_ctrl_hevc_slice_params { + __u32 bit_size; + __u32 data_bit_offset; + ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ ++ __u32 slice_segment_addr; ++ + /* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */ + __u8 nal_unit_type; + __u8 nuh_temporal_id_plus1; +@@ -200,7 +203,7 @@ struct v4l2_ctrl_hevc_slice_params { + __u8 num_rps_poc_st_curr_after; + __u8 num_rps_poc_lt_curr; + +- __u8 padding; ++ __u8 padding[5]; + + /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ + struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; + +From 180280b4b2e59865227ac90235ae902ce8088369 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 23 May 2020 15:03:46 +0000 +Subject: [PATCH] WIP: media: uapi: hevc: add fields needed for rkvdec + +NOTE: these fields are used by rkvdec hevc backend + +Signed-off-by: Jonas Karlman +--- + include/media/hevc-ctrls.h | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/include/media/hevc-ctrls.h b/include/media/hevc-ctrls.h +index 3e2e32098312..3cc3b47e1417 100644 +--- a/include/media/hevc-ctrls.h ++++ b/include/media/hevc-ctrls.h +@@ -56,6 +56,9 @@ enum v4l2_mpeg_video_hevc_start_code { + /* The controls are not stable at the moment and will likely be reworked. */ + struct v4l2_ctrl_hevc_sps { + /* ISO/IEC 23008-2, ITU-T Rec. H.265: Sequence parameter set */ ++ __u8 video_parameter_set_id; ++ __u8 seq_parameter_set_id; ++ __u8 chroma_format_idc; + __u16 pic_width_in_luma_samples; + __u16 pic_height_in_luma_samples; + __u8 bit_depth_luma_minus8; +@@ -76,9 +79,8 @@ struct v4l2_ctrl_hevc_sps { + __u8 log2_diff_max_min_pcm_luma_coding_block_size; + __u8 num_short_term_ref_pic_sets; + __u8 num_long_term_ref_pics_sps; +- __u8 chroma_format_idc; + +- __u8 padding; ++ __u8 padding[7]; + + __u64 flags; + }; +@@ -105,7 +107,10 @@ struct v4l2_ctrl_hevc_sps { + + struct v4l2_ctrl_hevc_pps { + /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture parameter set */ ++ __u8 pic_parameter_set_id; + __u8 num_extra_slice_header_bits; ++ __u8 num_ref_idx_l0_default_active_minus1; ++ __u8 num_ref_idx_l1_default_active_minus1; + __s8 init_qp_minus26; + __u8 diff_cu_qp_delta_depth; + __s8 pps_cb_qp_offset; +@@ -118,7 +123,7 @@ struct v4l2_ctrl_hevc_pps { + __s8 pps_tc_offset_div2; + __u8 log2_parallel_merge_level_minus2; + +- __u8 padding[4]; ++ __u8 padding; + __u64 flags; + }; + +@@ -203,7 +208,10 @@ struct v4l2_ctrl_hevc_slice_params { + __u8 num_rps_poc_st_curr_after; + __u8 num_rps_poc_lt_curr; + +- __u8 padding[5]; ++ __u16 short_term_ref_pic_set_size; ++ __u16 long_term_ref_pic_set_size; ++ ++ __u8 padding; + + /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ + struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; + +From 80ec0ecb1f7555aae1daa174cde084b3d9f42459 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 23 May 2020 15:07:15 +0000 +Subject: [PATCH] HACK: media: uapi: hevc: tiles and num_slices + +--- + include/media/hevc-ctrls.h | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/include/media/hevc-ctrls.h b/include/media/hevc-ctrls.h +index 3cc3b47e1417..b33e1a8141e1 100644 +--- a/include/media/hevc-ctrls.h ++++ b/include/media/hevc-ctrls.h +@@ -80,7 +80,8 @@ struct v4l2_ctrl_hevc_sps { + __u8 num_short_term_ref_pic_sets; + __u8 num_long_term_ref_pics_sps; + +- __u8 padding[7]; ++ __u8 num_slices; ++ __u8 padding[6]; + + __u64 flags; + }; +@@ -174,6 +175,7 @@ struct v4l2_ctrl_hevc_slice_params { + + /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ + __u32 slice_segment_addr; ++ __u32 num_entry_point_offsets; + + /* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */ + __u8 nal_unit_type; +@@ -211,7 +213,9 @@ struct v4l2_ctrl_hevc_slice_params { + __u16 short_term_ref_pic_set_size; + __u16 long_term_ref_pic_set_size; + +- __u8 padding; ++ __u8 padding[5]; ++ ++ __u32 entry_point_offset_minus1[256]; + + /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ + struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; + +From f35f02f322ebb97970d021bc82d9cad0b6432e15 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 23 May 2020 15:17:45 +0000 +Subject: [PATCH] WIP: media: rkvdec: add HEVC backend + +NOTE: cabac table and scailing list code is copied 1:1 from mpp +TODO: fix lowdelay flag and rework the scaling list part + +Signed-off-by: Jonas Karlman +--- + drivers/staging/media/rkvdec/Makefile | 2 +- + drivers/staging/media/rkvdec/rkvdec-hevc.c | 2522 ++++++++++++++++++++ + drivers/staging/media/rkvdec/rkvdec-regs.h | 1 + + drivers/staging/media/rkvdec/rkvdec.c | 70 + + drivers/staging/media/rkvdec/rkvdec.h | 1 + + 5 files changed, 2595 insertions(+), 1 deletion(-) + create mode 100644 drivers/staging/media/rkvdec/rkvdec-hevc.c + +diff --git a/drivers/staging/media/rkvdec/Makefile b/drivers/staging/media/rkvdec/Makefile +index cb86b429cfaa..a77122641d14 100644 +--- a/drivers/staging/media/rkvdec/Makefile ++++ b/drivers/staging/media/rkvdec/Makefile +@@ -1,3 +1,3 @@ + obj-$(CONFIG_VIDEO_ROCKCHIP_VDEC) += rockchip-vdec.o + +-rockchip-vdec-y += rkvdec.o rkvdec-h264.o rkvdec-vp9.o ++rockchip-vdec-y += rkvdec.o rkvdec-h264.o rkvdec-hevc.o rkvdec-vp9.o +diff --git a/drivers/staging/media/rkvdec/rkvdec-hevc.c b/drivers/staging/media/rkvdec/rkvdec-hevc.c +new file mode 100644 +index 000000000000..03ba848411c6 +--- /dev/null ++++ b/drivers/staging/media/rkvdec/rkvdec-hevc.c +@@ -0,0 +1,2522 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Rockchip Video Decoder HEVC backend ++ * ++ * Copyright (C) 2019 Collabora, Ltd. ++ * Boris Brezillon ++ * ++ * Copyright (C) 2016 Rockchip Electronics Co., Ltd. ++ * Jeffy Chen ++ */ ++ ++#include ++ ++#include "rkvdec.h" ++#include "rkvdec-regs.h" ++ ++/* Size in u8/u32 units. */ ++#define RKV_CABAC_TABLE_SIZE 27456 ++#define RKV_SCALING_LIST_SIZE 1360 ++#define RKV_PPS_SIZE (80 / 4) ++#define RKV_PPS_LEN 64 ++#define RKV_RPS_SIZE (32 / 4) ++#define RKV_RPS_LEN 600 ++ ++struct rkvdec_sps_pps_packet { ++ u32 info[RKV_PPS_SIZE]; ++}; ++ ++struct rkvdec_rps_packet { ++ u32 info[RKV_RPS_SIZE]; ++}; ++ ++struct rkvdec_ps_field { ++ u16 offset; ++ u8 len; ++}; ++ ++#define PS_FIELD(_offset, _len) \ ++ ((struct rkvdec_ps_field){ _offset, _len }) ++ ++/* SPS */ ++#define VIDEO_PARAMETER_SET_ID PS_FIELD(0, 4) ++#define SEQ_PARAMETER_SET_ID PS_FIELD(4, 4) ++#define CHROMA_FORMAT_IDC PS_FIELD(8, 2) ++#define PIC_WIDTH_IN_LUMA_SAMPLES PS_FIELD(10, 13) ++#define PIC_HEIGHT_IN_LUMA_SAMPLES PS_FIELD(23, 13) ++#define BIT_DEPTH_LUMA PS_FIELD(36, 4) ++#define BIT_DEPTH_CHROMA PS_FIELD(40, 4) ++#define LOG2_MAX_PIC_ORDER_CNT_LSB PS_FIELD(44, 5) ++#define LOG2_DIFF_MAX_MIN_LUMA_CODING_BLOCK_SIZE PS_FIELD(49, 2) ++#define LOG2_MIN_LUMA_CODING_BLOCK_SIZE PS_FIELD(51, 3) ++#define LOG2_MIN_TRANSFORM_BLOCK_SIZE PS_FIELD(54, 3) ++#define LOG2_DIFF_MAX_MIN_LUMA_TRANSFORM_BLOCK_SIZE PS_FIELD(57, 2) ++#define MAX_TRANSFORM_HIERARCHY_DEPTH_INTER PS_FIELD(59, 3) ++#define MAX_TRANSFORM_HIERARCHY_DEPTH_INTRA PS_FIELD(62, 3) ++#define SCALING_LIST_ENABLED_FLAG PS_FIELD(65, 1) ++#define AMP_ENABLED_FLAG PS_FIELD(66, 1) ++#define SAMPLE_ADAPTIVE_OFFSET_ENABLED_FLAG PS_FIELD(67, 1) ++#define PCM_ENABLED_FLAG PS_FIELD(68, 1) ++#define PCM_SAMPLE_BIT_DEPTH_LUMA PS_FIELD(69, 4) ++#define PCM_SAMPLE_BIT_DEPTH_CHROMA PS_FIELD(73, 4) ++#define PCM_LOOP_FILTER_DISABLED_FLAG PS_FIELD(77, 1) ++#define LOG2_DIFF_MAX_MIN_PCM_LUMA_CODING_BLOCK_SIZE PS_FIELD(78, 3) ++#define LOG2_MIN_PCM_LUMA_CODING_BLOCK_SIZE PS_FIELD(81, 3) ++#define NUM_SHORT_TERM_REF_PIC_SETS PS_FIELD(84, 7) ++#define LONG_TERM_REF_PICS_PRESENT_FLAG PS_FIELD(91, 1) ++#define NUM_LONG_TERM_REF_PICS_SPS PS_FIELD(92, 6) ++#define SPS_TEMPORAL_MVP_ENABLED_FLAG PS_FIELD(98, 1) ++#define STRONG_INTRA_SMOOTHING_ENABLED_FLAG PS_FIELD(99, 1) ++/* PPS */ ++#define PIC_PARAMETER_SET_ID PS_FIELD(128, 6) ++#define PPS_SEQ_PARAMETER_SET_ID PS_FIELD(134, 4) ++#define DEPENDENT_SLICE_SEGMENTS_ENABLED_FLAG PS_FIELD(138, 1) ++#define OUTPUT_FLAG_PRESENT_FLAG PS_FIELD(139, 1) ++#define NUM_EXTRA_SLICE_HEADER_BITS PS_FIELD(140, 13) ++#define SIGN_DATA_HIDING_ENABLED_FLAG PS_FIELD(153, 1) ++#define CABAC_INIT_PRESENT_FLAG PS_FIELD(154, 1) ++#define NUM_REF_IDX_L0_DEFAULT_ACTIVE PS_FIELD(155, 4) ++#define NUM_REF_IDX_L1_DEFAULT_ACTIVE PS_FIELD(159, 4) ++#define INIT_QP_MINUS26 PS_FIELD(163, 7) ++#define CONSTRAINED_INTRA_PRED_FLAG PS_FIELD(170, 1) ++#define TRANSFORM_SKIP_ENABLED_FLAG PS_FIELD(171, 1) ++#define CU_QP_DELTA_ENABLED_FLAG PS_FIELD(172, 1) ++#define LOG2_MIN_CU_QP_DELTA_SIZE PS_FIELD(173, 3) ++#define PPS_CB_QP_OFFSET PS_FIELD(176, 5) ++#define PPS_CR_QP_OFFSET PS_FIELD(181, 5) ++#define PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT_FLAG PS_FIELD(186, 1) ++#define WEIGHTED_PRED_FLAG PS_FIELD(187, 1) ++#define WEIGHTED_BIPRED_FLAG PS_FIELD(188, 1) ++#define TRANSQUANT_BYPASS_ENABLED_FLAG PS_FIELD(189, 1) ++#define TILES_ENABLED_FLAG PS_FIELD(190, 1) ++#define ENTROPY_CODING_SYNC_ENABLED_FLAG PS_FIELD(191, 1) ++#define PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG PS_FIELD(192, 1) ++#define LOOP_FILTER_ACROSS_TILES_ENABLED_FLAG PS_FIELD(193, 1) ++#define DEBLOCKING_FILTER_OVERRIDE_ENABLED_FLAG PS_FIELD(194, 1) ++#define PPS_DEBLOCKING_FILTER_DISABLED_FLAG PS_FIELD(195, 1) ++#define PPS_BETA_OFFSET_DIV2 PS_FIELD(196, 4) ++#define PPS_TC_OFFSET_DIV2 PS_FIELD(200, 4) ++#define LISTS_MODIFICATION_PRESENT_FLAG PS_FIELD(204, 1) ++#define LOG2_PARALLEL_MERGE_LEVEL PS_FIELD(205, 3) ++#define SLICE_SEGMENT_HEADER_EXTENSION_PRESENT_FLAG PS_FIELD(208, 1) ++#define NUM_TILE_COLUMNS PS_FIELD(212, 5) ++#define NUM_TILE_ROWS PS_FIELD(217, 5) ++#define COLUMN_WIDTH(i) PS_FIELD(256 + (i * 8), 8) ++#define ROW_HEIGHT(i) PS_FIELD(416 + (i * 8), 8) ++#define SCALING_LIST_ADDRESS PS_FIELD(592, 32) ++ ++/* Data structure describing auxiliary buffer format. */ ++struct rkvdec_hevc_priv_tbl { ++ u8 cabac_table[RKV_CABAC_TABLE_SIZE]; ++ u8 scaling_list[RKV_SCALING_LIST_SIZE]; ++ struct rkvdec_sps_pps_packet param_set[RKV_PPS_LEN]; ++ struct rkvdec_rps_packet rps[RKV_RPS_LEN]; ++}; ++ ++struct rkvdec_hevc_run { ++ struct rkvdec_run base; ++ const struct v4l2_ctrl_hevc_slice_params *slices_params; ++ const struct v4l2_ctrl_hevc_sps *sps; ++ const struct v4l2_ctrl_hevc_pps *pps; ++ const struct v4l2_ctrl_hevc_scaling_matrix *scaling_matrix; ++ int num_slices; ++}; ++ ++struct rkvdec_hevc_ctx { ++ struct rkvdec_aux_buf priv_tbl; ++ struct v4l2_ctrl_hevc_scaling_matrix scaling_matrix_cache; ++}; ++ ++// TODO: refactor scaling list code, was copied 1:1 from mpp ++ ++typedef struct ScalingList { ++ /* This is a little wasteful, since sizeID 0 only needs 8 coeffs, ++ * and size ID 3 only has 2 arrays, not 6. */ ++ u8 sl[4][6][64]; ++ u8 sl_dc[2][6]; ++} scalingList_t; ++ ++typedef struct ScalingFactor_Model { ++ u8 scalingfactor0[1248]; ++ u8 scalingfactor1[96]; /*4X4 TU Rotate, total 16X4*/ ++ u8 scalingdc[12]; /*N1005 Vienna Meeting*/ ++ u8 reserverd[4]; /*16Bytes align*/ ++} scalingFactor_t; ++ ++#define SCALING_LIST_SIZE_NUM 4 ++ ++static void ++hal_record_scaling_list(scalingFactor_t *pScalingFactor_out, ++ scalingList_t *pScalingList) ++{ ++ int i; ++ u32 g_scalingListNum_model[SCALING_LIST_SIZE_NUM] = {6, 6, 6, 2}; // from C Model ++ u32 nIndex = 0; ++ u32 sizeId, matrixId, listId; ++ u8 *p = pScalingFactor_out->scalingfactor0; ++ u8 tmpBuf[8 * 8]; ++ ++ //output non-default scalingFactor Table (1248 BYTES) ++ for (sizeId = 0; sizeId < SCALING_LIST_SIZE_NUM; sizeId++) { ++ for (listId = 0; listId < g_scalingListNum_model[sizeId]; listId++) { ++ if (sizeId < 3) { ++ for (i = 0; i < (sizeId == 0 ? 16 : 64); i++) { ++ pScalingFactor_out->scalingfactor0[nIndex++] = (u8)pScalingList->sl[sizeId][listId][i]; ++ } ++ } else { ++ for (i = 0; i < 64; i ++) { ++ pScalingFactor_out->scalingfactor0[nIndex++] = (u8)pScalingList->sl[sizeId][listId][i]; ++ } ++ for (i = 0; i < 128; i ++) { ++ pScalingFactor_out->scalingfactor0[nIndex++] = 0; ++ } ++ } ++ } ++ } ++ //output non-default scalingFactor Table Rotation(96 Bytes) ++ nIndex = 0; ++ for (listId = 0; listId < g_scalingListNum_model[0]; listId++) { ++ u8 temp16[16] = {0}; ++ for (i = 0; i < 16; i ++) { ++ temp16[i] = (u8)pScalingList->sl[0][listId][i]; ++ } ++ for (i = 0; i < 4; i ++) { ++ pScalingFactor_out->scalingfactor1[nIndex++] = temp16[i]; ++ pScalingFactor_out->scalingfactor1[nIndex++] = temp16[i + 4]; ++ pScalingFactor_out->scalingfactor1[nIndex++] = temp16[i + 8]; ++ pScalingFactor_out->scalingfactor1[nIndex++] = temp16[i + 12]; ++ } ++ } ++ //output non-default ScalingList_DC_Coeff (12 BYTES) ++ nIndex = 0; ++ for (listId = 0; listId < g_scalingListNum_model[2]; listId++) { //sizeId = 2 ++ pScalingFactor_out->scalingdc[nIndex++] = (u8)pScalingList->sl_dc[0][listId];// zrh warning: sl_dc differed from scalingList->getScalingListDC ++ } ++ for (listId = 0; listId < g_scalingListNum_model[3]; listId++) { //sizeId = 3 ++ pScalingFactor_out->scalingdc[nIndex++] = (u8)pScalingList->sl_dc[1][listId];// zrh warning: sl_dc differed from scalingList->getScalingListDC ++ pScalingFactor_out->scalingdc[nIndex++] = 0; ++ pScalingFactor_out->scalingdc[nIndex++] = 0; ++ } ++ ++ //align 16X address ++ nIndex = 0; ++ for (i = 0; i < 4; i ++) { ++ pScalingFactor_out->reserverd[nIndex++] = 0; ++ } ++ ++ //----------------------All above code show the normal store way in HM-------------------------- ++ //--------from now on, the scalingfactor0 is rotated 90', the scalingfactor1 is also rotated 90' ++ ++ //sizeId == 0 ++ for (matrixId = 0; matrixId < 6; matrixId++) { ++ p = pScalingFactor_out->scalingfactor0 + matrixId * 16; ++ ++ for (i = 0; i < 4; i++) { ++ tmpBuf[4 * 0 + i] = p[i * 4 + 0]; ++ tmpBuf[4 * 1 + i] = p[i * 4 + 1]; ++ tmpBuf[4 * 2 + i] = p[i * 4 + 2]; ++ tmpBuf[4 * 3 + i] = p[i * 4 + 3]; ++ } ++ memcpy(p, tmpBuf, 4 * 4 * sizeof(u8)); ++ } ++ //sizeId == 1 ++ for (matrixId = 0; matrixId < 6; matrixId++) { ++ p = pScalingFactor_out->scalingfactor0 + 6 * 16 + matrixId * 64; ++ ++ for (i = 0; i < 8; i++) { ++ tmpBuf[8 * 0 + i] = p[i * 8 + 0]; ++ tmpBuf[8 * 1 + i] = p[i * 8 + 1]; ++ tmpBuf[8 * 2 + i] = p[i * 8 + 2]; ++ tmpBuf[8 * 3 + i] = p[i * 8 + 3]; ++ tmpBuf[8 * 4 + i] = p[i * 8 + 4]; ++ tmpBuf[8 * 5 + i] = p[i * 8 + 5]; ++ tmpBuf[8 * 6 + i] = p[i * 8 + 6]; ++ tmpBuf[8 * 7 + i] = p[i * 8 + 7]; ++ } ++ memcpy(p, tmpBuf, 8 * 8 * sizeof(u8)); ++ } ++ //sizeId == 2 ++ for (matrixId = 0; matrixId < 6; matrixId++) { ++ p = pScalingFactor_out->scalingfactor0 + 6 * 16 + 6 * 64 + matrixId * 64; ++ ++ for (i = 0; i < 8; i++) { ++ tmpBuf[8 * 0 + i] = p[i * 8 + 0]; ++ tmpBuf[8 * 1 + i] = p[i * 8 + 1]; ++ tmpBuf[8 * 2 + i] = p[i * 8 + 2]; ++ tmpBuf[8 * 3 + i] = p[i * 8 + 3]; ++ tmpBuf[8 * 4 + i] = p[i * 8 + 4]; ++ tmpBuf[8 * 5 + i] = p[i * 8 + 5]; ++ tmpBuf[8 * 6 + i] = p[i * 8 + 6]; ++ tmpBuf[8 * 7 + i] = p[i * 8 + 7]; ++ } ++ memcpy(p, tmpBuf, 8 * 8 * sizeof(u8)); ++ } ++ //sizeId == 3 ++ for (matrixId = 0; matrixId < 6; matrixId++) { ++ p = pScalingFactor_out->scalingfactor0 + 6 * 16 + 6 * 64 + 6 * 64 + matrixId * 64; ++ ++ for (i = 0; i < 8; i++) { ++ tmpBuf[8 * 0 + i] = p[i * 8 + 0]; ++ tmpBuf[8 * 1 + i] = p[i * 8 + 1]; ++ tmpBuf[8 * 2 + i] = p[i * 8 + 2]; ++ tmpBuf[8 * 3 + i] = p[i * 8 + 3]; ++ tmpBuf[8 * 4 + i] = p[i * 8 + 4]; ++ tmpBuf[8 * 5 + i] = p[i * 8 + 5]; ++ tmpBuf[8 * 6 + i] = p[i * 8 + 6]; ++ tmpBuf[8 * 7 + i] = p[i * 8 + 7]; ++ } ++ memcpy(p, tmpBuf, 8 * 8 * sizeof(u8)); ++ } ++ ++ //sizeId == 0 ++ for (matrixId = 0; matrixId < 6; matrixId++) { ++ p = pScalingFactor_out->scalingfactor1 + matrixId * 16; ++ ++ for (i = 0; i < 4; i++) { ++ tmpBuf[4 * 0 + i] = p[i * 4 + 0]; ++ tmpBuf[4 * 1 + i] = p[i * 4 + 1]; ++ tmpBuf[4 * 2 + i] = p[i * 4 + 2]; ++ tmpBuf[4 * 3 + i] = p[i * 4 + 3]; ++ } ++ memcpy(p, tmpBuf, 4 * 4 * sizeof(u8)); ++ } ++} ++ ++static const u8 rkvdec_hevc_cabac_table[RKV_CABAC_TABLE_SIZE] = { ++ 0x07, 0x0f, 0x48, 0x58, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0f, 0x40, 0x40, 0x40, 0x0f, 0x68, ++ 0x48, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x40, 0x40, 0x68, ++ 0x58, 0x60, 0x40, 0x1f, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x48, 0x48, 0x60, 0x60, 0x50, 0x58, ++ 0x50, 0x07, 0x58, 0x68, 0x50, 0x58, 0x68, 0x68, 0x68, 0x68, 0x68, 0x50, 0x48, 0x68, 0x60, 0x60, ++ 0x50, 0x58, 0x50, 0x07, 0x58, 0x68, 0x50, 0x58, 0x68, 0x68, 0x68, 0x68, 0x68, 0x50, 0x48, 0x68, ++ 0x48, 0x48, 0x1f, 0x58, 0x68, 0x68, 0x58, 0x60, 0x60, 0x60, 0x50, 0x50, 0x50, 0x48, 0x58, 0x58, ++ 0x37, 0x07, 0x58, 0x48, 0x58, 0x58, 0x37, 0x07, 0x58, 0x48, 0x58, 0x58, 0x37, 0x07, 0x58, 0x50, ++ 0x48, 0x1f, 0x1f, 0x0f, 0x0f, 0x0f, 0x0f, 0x07, 0x0f, 0x48, 0x68, 0x0f, 0x48, 0x68, 0x40, 0x40, ++ 0x50, 0x50, 0x07, 0x40, 0x50, 0x0f, 0x40, 0x48, 0x07, 0x40, 0x27, 0x50, 0x48, 0x48, 0x40, 0x0f, ++ 0x50, 0x37, 0x1f, 0x1f, 0x50, 0x37, 0x40, 0x27, 0x40, 0x07, 0x0f, 0x17, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x0f, 0x47, 0x57, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0f, 0x40, 0x40, 0x40, 0x0f, 0x66, ++ 0x47, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x00, 0x00, 0x67, ++ 0x57, 0x5e, 0x00, 0x1f, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x47, 0x47, 0x5f, 0x5f, 0x4f, 0x57, ++ 0x4f, 0x07, 0x57, 0x67, 0x4f, 0x57, 0x67, 0x67, 0x67, 0x67, 0x66, 0x4f, 0x47, 0x66, 0x5f, 0x5f, ++ 0x4f, 0x57, 0x4f, 0x07, 0x57, 0x67, 0x4f, 0x57, 0x67, 0x67, 0x67, 0x67, 0x66, 0x4f, 0x47, 0x66, ++ 0x46, 0x48, 0x20, 0x57, 0x67, 0x67, 0x57, 0x5f, 0x5f, 0x5e, 0x4f, 0x4f, 0x4f, 0x47, 0x57, 0x57, ++ 0x37, 0x07, 0x57, 0x47, 0x57, 0x57, 0x37, 0x07, 0x57, 0x47, 0x57, 0x57, 0x37, 0x07, 0x57, 0x4f, ++ 0x47, 0x1f, 0x1f, 0x0f, 0x10, 0x0f, 0x10, 0x07, 0x10, 0x47, 0x67, 0x10, 0x47, 0x67, 0x40, 0x40, ++ 0x4f, 0x4e, 0x08, 0x00, 0x4f, 0x0f, 0x00, 0x47, 0x07, 0x01, 0x27, 0x4e, 0x47, 0x47, 0x00, 0x0f, ++ 0x4f, 0x37, 0x1f, 0x1f, 0x4f, 0x36, 0x00, 0x27, 0x00, 0x07, 0x10, 0x17, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x0e, 0x47, 0x57, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0e, 0x40, 0x40, 0x40, 0x0e, 0x64, ++ 0x47, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x00, 0x00, 0x66, ++ 0x57, 0x5d, 0x00, 0x1e, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x47, 0x47, 0x5e, 0x5e, 0x4e, 0x56, ++ 0x4f, 0x07, 0x56, 0x66, 0x4f, 0x56, 0x66, 0x67, 0x66, 0x66, 0x64, 0x4e, 0x46, 0x64, 0x5e, 0x5e, ++ 0x4e, 0x56, 0x4f, 0x07, 0x56, 0x66, 0x4f, 0x56, 0x66, 0x67, 0x66, 0x66, 0x64, 0x4e, 0x46, 0x64, ++ 0x45, 0x48, 0x20, 0x57, 0x66, 0x66, 0x56, 0x5e, 0x5e, 0x5d, 0x4e, 0x4e, 0x4e, 0x46, 0x56, 0x57, ++ 0x36, 0x07, 0x56, 0x46, 0x56, 0x57, 0x36, 0x07, 0x56, 0x46, 0x56, 0x57, 0x36, 0x07, 0x56, 0x4f, ++ 0x47, 0x1e, 0x1e, 0x0f, 0x10, 0x0f, 0x10, 0x07, 0x10, 0x47, 0x66, 0x10, 0x47, 0x66, 0x40, 0x40, ++ 0x4f, 0x4d, 0x08, 0x00, 0x4f, 0x0f, 0x00, 0x47, 0x07, 0x03, 0x27, 0x4d, 0x47, 0x46, 0x01, 0x0f, ++ 0x4f, 0x36, 0x1f, 0x1e, 0x4f, 0x34, 0x01, 0x26, 0x00, 0x07, 0x10, 0x17, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x0d, 0x47, 0x57, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0e, 0x40, 0x40, 0x40, 0x0e, 0x62, ++ 0x47, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x00, 0x00, 0x65, ++ 0x57, 0x5c, 0x00, 0x1e, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x47, 0x47, 0x5d, 0x5d, 0x4e, 0x56, ++ 0x4f, 0x07, 0x56, 0x66, 0x4f, 0x55, 0x65, 0x67, 0x66, 0x65, 0x63, 0x4d, 0x46, 0x62, 0x5d, 0x5d, ++ 0x4e, 0x56, 0x4f, 0x07, 0x56, 0x66, 0x4f, 0x55, 0x65, 0x67, 0x66, 0x65, 0x63, 0x4d, 0x46, 0x62, ++ 0x44, 0x48, 0x20, 0x57, 0x65, 0x65, 0x56, 0x5d, 0x5d, 0x5c, 0x4e, 0x4d, 0x4e, 0x45, 0x56, 0x57, ++ 0x36, 0x07, 0x56, 0x45, 0x56, 0x57, 0x36, 0x07, 0x56, 0x45, 0x56, 0x57, 0x36, 0x07, 0x56, 0x4f, ++ 0x47, 0x1e, 0x1e, 0x0f, 0x10, 0x0f, 0x10, 0x07, 0x10, 0x47, 0x65, 0x10, 0x47, 0x65, 0x40, 0x40, ++ 0x4f, 0x4c, 0x08, 0x00, 0x4f, 0x0f, 0x00, 0x47, 0x07, 0x04, 0x27, 0x4c, 0x47, 0x45, 0x01, 0x0f, ++ 0x4f, 0x36, 0x1f, 0x1e, 0x4f, 0x33, 0x01, 0x25, 0x00, 0x07, 0x10, 0x17, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x0c, 0x46, 0x56, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0d, 0x40, 0x40, 0x40, 0x0d, 0x60, ++ 0x46, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x01, 0x01, 0x64, ++ 0x56, 0x5b, 0x01, 0x1d, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x46, 0x46, 0x5c, 0x5c, 0x4d, 0x55, ++ 0x4e, 0x07, 0x55, 0x65, 0x4e, 0x54, 0x64, 0x66, 0x65, 0x64, 0x61, 0x4c, 0x45, 0x60, 0x5c, 0x5c, ++ 0x4d, 0x55, 0x4e, 0x07, 0x55, 0x65, 0x4e, 0x54, 0x64, 0x66, 0x65, 0x64, 0x61, 0x4c, 0x45, 0x60, ++ 0x43, 0x49, 0x21, 0x56, 0x64, 0x64, 0x55, 0x5c, 0x5c, 0x5b, 0x4d, 0x4c, 0x4d, 0x44, 0x55, 0x56, ++ 0x35, 0x07, 0x55, 0x44, 0x55, 0x56, 0x35, 0x07, 0x55, 0x44, 0x55, 0x56, 0x35, 0x07, 0x55, 0x4e, ++ 0x46, 0x1d, 0x1d, 0x0f, 0x11, 0x0f, 0x11, 0x07, 0x11, 0x46, 0x64, 0x11, 0x46, 0x64, 0x40, 0x40, ++ 0x4e, 0x4b, 0x09, 0x01, 0x4e, 0x0f, 0x01, 0x46, 0x07, 0x06, 0x27, 0x4b, 0x46, 0x44, 0x02, 0x0f, ++ 0x4e, 0x35, 0x1e, 0x1d, 0x4e, 0x31, 0x02, 0x24, 0x01, 0x07, 0x11, 0x16, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x0b, 0x46, 0x56, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0c, 0x40, 0x40, 0x40, 0x0c, 0x5e, ++ 0x46, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x01, 0x01, 0x63, ++ 0x56, 0x59, 0x01, 0x1c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x46, 0x46, 0x5b, 0x5b, 0x4c, 0x54, ++ 0x4e, 0x07, 0x54, 0x64, 0x4e, 0x53, 0x63, 0x66, 0x64, 0x63, 0x60, 0x4b, 0x44, 0x5e, 0x5b, 0x5b, ++ 0x4c, 0x54, 0x4e, 0x07, 0x54, 0x64, 0x4e, 0x53, 0x63, 0x66, 0x64, 0x63, 0x60, 0x4b, 0x44, 0x5e, ++ 0x41, 0x49, 0x21, 0x56, 0x63, 0x63, 0x54, 0x5b, 0x5b, 0x59, 0x4c, 0x4b, 0x4c, 0x43, 0x54, 0x56, ++ 0x34, 0x07, 0x54, 0x43, 0x54, 0x56, 0x34, 0x07, 0x54, 0x43, 0x54, 0x56, 0x34, 0x07, 0x54, 0x4e, ++ 0x46, 0x1c, 0x1c, 0x0f, 0x11, 0x0f, 0x11, 0x07, 0x11, 0x46, 0x63, 0x11, 0x46, 0x63, 0x40, 0x40, ++ 0x4e, 0x49, 0x09, 0x01, 0x4e, 0x0f, 0x01, 0x46, 0x07, 0x07, 0x27, 0x49, 0x46, 0x43, 0x03, 0x0f, ++ 0x4e, 0x34, 0x1e, 0x1c, 0x4e, 0x30, 0x03, 0x23, 0x01, 0x07, 0x11, 0x16, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x0a, 0x46, 0x56, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0c, 0x40, 0x40, 0x40, 0x0c, 0x5c, ++ 0x46, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x01, 0x01, 0x62, ++ 0x56, 0x58, 0x01, 0x1c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x46, 0x46, 0x5a, 0x5a, 0x4c, 0x54, ++ 0x4e, 0x07, 0x54, 0x64, 0x4e, 0x52, 0x62, 0x66, 0x64, 0x62, 0x5e, 0x4a, 0x44, 0x5c, 0x5a, 0x5a, ++ 0x4c, 0x54, 0x4e, 0x07, 0x54, 0x64, 0x4e, 0x52, 0x62, 0x66, 0x64, 0x62, 0x5e, 0x4a, 0x44, 0x5c, ++ 0x40, 0x49, 0x21, 0x56, 0x62, 0x62, 0x54, 0x5a, 0x5a, 0x58, 0x4c, 0x4a, 0x4c, 0x42, 0x54, 0x56, ++ 0x34, 0x07, 0x54, 0x42, 0x54, 0x56, 0x34, 0x07, 0x54, 0x42, 0x54, 0x56, 0x34, 0x07, 0x54, 0x4e, ++ 0x46, 0x1c, 0x1c, 0x0f, 0x11, 0x0f, 0x11, 0x07, 0x11, 0x46, 0x62, 0x11, 0x46, 0x62, 0x40, 0x40, ++ 0x4e, 0x48, 0x09, 0x01, 0x4e, 0x0f, 0x01, 0x46, 0x07, 0x09, 0x27, 0x48, 0x46, 0x42, 0x03, 0x0f, ++ 0x4e, 0x34, 0x1e, 0x1c, 0x4e, 0x2e, 0x03, 0x22, 0x01, 0x07, 0x11, 0x16, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x09, 0x45, 0x55, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0b, 0x40, 0x40, 0x40, 0x0b, 0x5a, ++ 0x45, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x02, 0x02, 0x61, ++ 0x55, 0x57, 0x02, 0x1b, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x45, 0x45, 0x59, 0x59, 0x4b, 0x53, ++ 0x4d, 0x07, 0x53, 0x63, 0x4d, 0x51, 0x61, 0x65, 0x63, 0x61, 0x5d, 0x49, 0x43, 0x5a, 0x59, 0x59, ++ 0x4b, 0x53, 0x4d, 0x07, 0x53, 0x63, 0x4d, 0x51, 0x61, 0x65, 0x63, 0x61, 0x5d, 0x49, 0x43, 0x5a, ++ 0x00, 0x4a, 0x22, 0x55, 0x61, 0x61, 0x53, 0x59, 0x59, 0x57, 0x4b, 0x49, 0x4b, 0x41, 0x53, 0x55, ++ 0x33, 0x07, 0x53, 0x41, 0x53, 0x55, 0x33, 0x07, 0x53, 0x41, 0x53, 0x55, 0x33, 0x07, 0x53, 0x4d, ++ 0x45, 0x1b, 0x1b, 0x0f, 0x12, 0x0f, 0x12, 0x07, 0x12, 0x45, 0x61, 0x12, 0x45, 0x61, 0x40, 0x40, ++ 0x4d, 0x47, 0x0a, 0x02, 0x4d, 0x0f, 0x02, 0x45, 0x07, 0x0a, 0x27, 0x47, 0x45, 0x41, 0x04, 0x0f, ++ 0x4d, 0x33, 0x1d, 0x1b, 0x4d, 0x2d, 0x04, 0x21, 0x02, 0x07, 0x12, 0x15, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x08, 0x45, 0x55, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0a, 0x40, 0x40, 0x40, 0x0a, 0x59, ++ 0x45, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x02, 0x02, 0x60, ++ 0x55, 0x56, 0x02, 0x1a, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x45, 0x45, 0x58, 0x58, 0x4b, 0x53, ++ 0x4d, 0x07, 0x53, 0x63, 0x4d, 0x50, 0x60, 0x65, 0x63, 0x60, 0x5b, 0x48, 0x43, 0x59, 0x58, 0x58, ++ 0x4b, 0x53, 0x4d, 0x07, 0x53, 0x63, 0x4d, 0x50, 0x60, 0x65, 0x63, 0x60, 0x5b, 0x48, 0x43, 0x59, ++ 0x01, 0x4a, 0x22, 0x55, 0x60, 0x60, 0x53, 0x58, 0x58, 0x56, 0x4b, 0x48, 0x4b, 0x40, 0x53, 0x55, ++ 0x32, 0x07, 0x53, 0x40, 0x53, 0x55, 0x32, 0x07, 0x53, 0x40, 0x53, 0x55, 0x32, 0x07, 0x53, 0x4d, ++ 0x45, 0x1a, 0x1a, 0x0f, 0x12, 0x0f, 0x12, 0x07, 0x12, 0x45, 0x60, 0x12, 0x45, 0x60, 0x40, 0x40, ++ 0x4d, 0x46, 0x0a, 0x02, 0x4d, 0x0f, 0x02, 0x45, 0x07, 0x0c, 0x27, 0x46, 0x45, 0x40, 0x04, 0x0f, ++ 0x4d, 0x32, 0x1d, 0x1a, 0x4d, 0x2b, 0x04, 0x20, 0x02, 0x07, 0x12, 0x15, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x07, 0x45, 0x55, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0a, 0x40, 0x40, 0x40, 0x0a, 0x57, ++ 0x45, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x02, 0x02, 0x5f, ++ 0x55, 0x54, 0x02, 0x1a, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x45, 0x45, 0x57, 0x57, 0x4a, 0x52, ++ 0x4d, 0x07, 0x52, 0x62, 0x4d, 0x4f, 0x5f, 0x65, 0x62, 0x5f, 0x59, 0x47, 0x42, 0x57, 0x57, 0x57, ++ 0x4a, 0x52, 0x4d, 0x07, 0x52, 0x62, 0x4d, 0x4f, 0x5f, 0x65, 0x62, 0x5f, 0x59, 0x47, 0x42, 0x57, ++ 0x03, 0x4a, 0x22, 0x55, 0x5f, 0x5f, 0x52, 0x57, 0x57, 0x54, 0x4a, 0x47, 0x4a, 0x00, 0x52, 0x55, ++ 0x32, 0x07, 0x52, 0x00, 0x52, 0x55, 0x32, 0x07, 0x52, 0x00, 0x52, 0x55, 0x32, 0x07, 0x52, 0x4d, ++ 0x45, 0x1a, 0x1a, 0x0f, 0x12, 0x0f, 0x12, 0x07, 0x12, 0x45, 0x5f, 0x12, 0x45, 0x5f, 0x40, 0x40, ++ 0x4d, 0x44, 0x0a, 0x02, 0x4d, 0x0f, 0x02, 0x45, 0x07, 0x0e, 0x27, 0x44, 0x45, 0x00, 0x05, 0x0f, ++ 0x4d, 0x32, 0x1d, 0x1a, 0x4d, 0x29, 0x05, 0x1f, 0x02, 0x07, 0x12, 0x15, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x06, 0x44, 0x54, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x09, 0x40, 0x40, 0x40, 0x09, 0x55, ++ 0x44, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x03, 0x03, 0x5e, ++ 0x54, 0x53, 0x03, 0x19, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x44, 0x44, 0x56, 0x56, 0x49, 0x51, ++ 0x4c, 0x07, 0x51, 0x61, 0x4c, 0x4e, 0x5e, 0x64, 0x61, 0x5e, 0x58, 0x46, 0x41, 0x55, 0x56, 0x56, ++ 0x49, 0x51, 0x4c, 0x07, 0x51, 0x61, 0x4c, 0x4e, 0x5e, 0x64, 0x61, 0x5e, 0x58, 0x46, 0x41, 0x55, ++ 0x04, 0x4b, 0x23, 0x54, 0x5e, 0x5e, 0x51, 0x56, 0x56, 0x53, 0x49, 0x46, 0x49, 0x01, 0x51, 0x54, ++ 0x31, 0x07, 0x51, 0x01, 0x51, 0x54, 0x31, 0x07, 0x51, 0x01, 0x51, 0x54, 0x31, 0x07, 0x51, 0x4c, ++ 0x44, 0x19, 0x19, 0x0f, 0x13, 0x0f, 0x13, 0x07, 0x13, 0x44, 0x5e, 0x13, 0x44, 0x5e, 0x40, 0x40, ++ 0x4c, 0x43, 0x0b, 0x03, 0x4c, 0x0f, 0x03, 0x44, 0x07, 0x0f, 0x27, 0x43, 0x44, 0x01, 0x06, 0x0f, ++ 0x4c, 0x31, 0x1c, 0x19, 0x4c, 0x28, 0x06, 0x1e, 0x03, 0x07, 0x13, 0x14, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x05, 0x44, 0x54, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x09, 0x40, 0x40, 0x40, 0x09, 0x53, ++ 0x44, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x03, 0x03, 0x5d, ++ 0x54, 0x52, 0x03, 0x19, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x44, 0x44, 0x55, 0x55, 0x49, 0x51, ++ 0x4c, 0x07, 0x51, 0x61, 0x4c, 0x4d, 0x5d, 0x64, 0x61, 0x5d, 0x56, 0x45, 0x41, 0x53, 0x55, 0x55, ++ 0x49, 0x51, 0x4c, 0x07, 0x51, 0x61, 0x4c, 0x4d, 0x5d, 0x64, 0x61, 0x5d, 0x56, 0x45, 0x41, 0x53, ++ 0x05, 0x4b, 0x23, 0x54, 0x5d, 0x5d, 0x51, 0x55, 0x55, 0x52, 0x49, 0x45, 0x49, 0x02, 0x51, 0x54, ++ 0x31, 0x07, 0x51, 0x02, 0x51, 0x54, 0x31, 0x07, 0x51, 0x02, 0x51, 0x54, 0x31, 0x07, 0x51, 0x4c, ++ 0x44, 0x19, 0x19, 0x0f, 0x13, 0x0f, 0x13, 0x07, 0x13, 0x44, 0x5d, 0x13, 0x44, 0x5d, 0x40, 0x40, ++ 0x4c, 0x42, 0x0b, 0x03, 0x4c, 0x0f, 0x03, 0x44, 0x07, 0x11, 0x27, 0x42, 0x44, 0x02, 0x06, 0x0f, ++ 0x4c, 0x31, 0x1c, 0x19, 0x4c, 0x26, 0x06, 0x1d, 0x03, 0x07, 0x13, 0x14, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x04, 0x44, 0x54, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x08, 0x40, 0x40, 0x40, 0x08, 0x51, ++ 0x44, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x03, 0x03, 0x5c, ++ 0x54, 0x51, 0x03, 0x18, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x44, 0x44, 0x54, 0x54, 0x48, 0x50, ++ 0x4c, 0x07, 0x50, 0x60, 0x4c, 0x4c, 0x5c, 0x64, 0x60, 0x5c, 0x55, 0x44, 0x40, 0x51, 0x54, 0x54, ++ 0x48, 0x50, 0x4c, 0x07, 0x50, 0x60, 0x4c, 0x4c, 0x5c, 0x64, 0x60, 0x5c, 0x55, 0x44, 0x40, 0x51, ++ 0x06, 0x4b, 0x23, 0x54, 0x5c, 0x5c, 0x50, 0x54, 0x54, 0x51, 0x48, 0x44, 0x48, 0x03, 0x50, 0x54, ++ 0x30, 0x07, 0x50, 0x03, 0x50, 0x54, 0x30, 0x07, 0x50, 0x03, 0x50, 0x54, 0x30, 0x07, 0x50, 0x4c, ++ 0x44, 0x18, 0x18, 0x0f, 0x13, 0x0f, 0x13, 0x07, 0x13, 0x44, 0x5c, 0x13, 0x44, 0x5c, 0x40, 0x40, ++ 0x4c, 0x41, 0x0b, 0x03, 0x4c, 0x0f, 0x03, 0x44, 0x07, 0x12, 0x27, 0x41, 0x44, 0x03, 0x07, 0x0f, ++ 0x4c, 0x30, 0x1c, 0x18, 0x4c, 0x25, 0x07, 0x1c, 0x03, 0x07, 0x13, 0x14, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x03, 0x43, 0x53, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x40, 0x40, 0x40, 0x07, 0x4f, ++ 0x43, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x04, 0x04, 0x5b, ++ 0x53, 0x4f, 0x04, 0x17, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x43, 0x43, 0x53, 0x53, 0x47, 0x4f, ++ 0x4b, 0x07, 0x4f, 0x5f, 0x4b, 0x4b, 0x5b, 0x63, 0x5f, 0x5b, 0x53, 0x43, 0x00, 0x4f, 0x53, 0x53, ++ 0x47, 0x4f, 0x4b, 0x07, 0x4f, 0x5f, 0x4b, 0x4b, 0x5b, 0x63, 0x5f, 0x5b, 0x53, 0x43, 0x00, 0x4f, ++ 0x08, 0x4c, 0x24, 0x53, 0x5b, 0x5b, 0x4f, 0x53, 0x53, 0x4f, 0x47, 0x43, 0x47, 0x04, 0x4f, 0x53, ++ 0x2f, 0x07, 0x4f, 0x04, 0x4f, 0x53, 0x2f, 0x07, 0x4f, 0x04, 0x4f, 0x53, 0x2f, 0x07, 0x4f, 0x4b, ++ 0x43, 0x17, 0x17, 0x0f, 0x14, 0x0f, 0x14, 0x07, 0x14, 0x43, 0x5b, 0x14, 0x43, 0x5b, 0x40, 0x40, ++ 0x4b, 0x00, 0x0c, 0x04, 0x4b, 0x0f, 0x04, 0x43, 0x07, 0x14, 0x27, 0x00, 0x43, 0x04, 0x08, 0x0f, ++ 0x4b, 0x2f, 0x1b, 0x17, 0x4b, 0x23, 0x08, 0x1b, 0x04, 0x07, 0x14, 0x13, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x02, 0x43, 0x53, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x40, 0x40, 0x40, 0x07, 0x4d, ++ 0x43, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x04, 0x04, 0x5a, ++ 0x53, 0x4e, 0x04, 0x17, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x43, 0x43, 0x52, 0x52, 0x47, 0x4f, ++ 0x4b, 0x07, 0x4f, 0x5f, 0x4b, 0x4a, 0x5a, 0x63, 0x5f, 0x5a, 0x52, 0x42, 0x00, 0x4d, 0x52, 0x52, ++ 0x47, 0x4f, 0x4b, 0x07, 0x4f, 0x5f, 0x4b, 0x4a, 0x5a, 0x63, 0x5f, 0x5a, 0x52, 0x42, 0x00, 0x4d, ++ 0x09, 0x4c, 0x24, 0x53, 0x5a, 0x5a, 0x4f, 0x52, 0x52, 0x4e, 0x47, 0x42, 0x47, 0x05, 0x4f, 0x53, ++ 0x2f, 0x07, 0x4f, 0x05, 0x4f, 0x53, 0x2f, 0x07, 0x4f, 0x05, 0x4f, 0x53, 0x2f, 0x07, 0x4f, 0x4b, ++ 0x43, 0x17, 0x17, 0x0f, 0x14, 0x0f, 0x14, 0x07, 0x14, 0x43, 0x5a, 0x14, 0x43, 0x5a, 0x40, 0x40, ++ 0x4b, 0x01, 0x0c, 0x04, 0x4b, 0x0f, 0x04, 0x43, 0x07, 0x15, 0x27, 0x01, 0x43, 0x05, 0x08, 0x0f, ++ 0x4b, 0x2f, 0x1b, 0x17, 0x4b, 0x22, 0x08, 0x1a, 0x04, 0x07, 0x14, 0x13, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x01, 0x43, 0x53, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x06, 0x40, 0x40, 0x40, 0x06, 0x4b, ++ 0x43, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x04, 0x04, 0x59, ++ 0x53, 0x4d, 0x04, 0x16, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x43, 0x43, 0x51, 0x51, 0x46, 0x4e, ++ 0x4b, 0x07, 0x4e, 0x5e, 0x4b, 0x49, 0x59, 0x63, 0x5e, 0x59, 0x50, 0x41, 0x01, 0x4b, 0x51, 0x51, ++ 0x46, 0x4e, 0x4b, 0x07, 0x4e, 0x5e, 0x4b, 0x49, 0x59, 0x63, 0x5e, 0x59, 0x50, 0x41, 0x01, 0x4b, ++ 0x0a, 0x4c, 0x24, 0x53, 0x59, 0x59, 0x4e, 0x51, 0x51, 0x4d, 0x46, 0x41, 0x46, 0x06, 0x4e, 0x53, ++ 0x2e, 0x07, 0x4e, 0x06, 0x4e, 0x53, 0x2e, 0x07, 0x4e, 0x06, 0x4e, 0x53, 0x2e, 0x07, 0x4e, 0x4b, ++ 0x43, 0x16, 0x16, 0x0f, 0x14, 0x0f, 0x14, 0x07, 0x14, 0x43, 0x59, 0x14, 0x43, 0x59, 0x40, 0x40, ++ 0x4b, 0x02, 0x0c, 0x04, 0x4b, 0x0f, 0x04, 0x43, 0x07, 0x17, 0x27, 0x02, 0x43, 0x06, 0x09, 0x0f, ++ 0x4b, 0x2e, 0x1b, 0x16, 0x4b, 0x20, 0x09, 0x19, 0x04, 0x07, 0x14, 0x13, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x00, 0x43, 0x53, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x05, 0x40, 0x40, 0x40, 0x05, 0x4a, ++ 0x43, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x04, 0x04, 0x59, ++ 0x53, 0x4c, 0x04, 0x15, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x43, 0x43, 0x51, 0x51, 0x46, 0x4e, ++ 0x4b, 0x07, 0x4e, 0x5e, 0x4b, 0x49, 0x59, 0x63, 0x5e, 0x59, 0x4f, 0x41, 0x01, 0x4a, 0x51, 0x51, ++ 0x46, 0x4e, 0x4b, 0x07, 0x4e, 0x5e, 0x4b, 0x49, 0x59, 0x63, 0x5e, 0x59, 0x4f, 0x41, 0x01, 0x4a, ++ 0x0b, 0x4d, 0x24, 0x53, 0x59, 0x59, 0x4e, 0x51, 0x51, 0x4c, 0x46, 0x41, 0x46, 0x06, 0x4e, 0x53, ++ 0x2d, 0x07, 0x4e, 0x06, 0x4e, 0x53, 0x2d, 0x07, 0x4e, 0x06, 0x4e, 0x53, 0x2d, 0x07, 0x4e, 0x4b, ++ 0x43, 0x15, 0x15, 0x0f, 0x14, 0x0f, 0x14, 0x07, 0x14, 0x43, 0x59, 0x14, 0x43, 0x59, 0x40, 0x40, ++ 0x4b, 0x03, 0x0c, 0x04, 0x4b, 0x0f, 0x04, 0x43, 0x07, 0x18, 0x27, 0x03, 0x43, 0x06, 0x09, 0x0f, ++ 0x4b, 0x2d, 0x1a, 0x15, 0x4b, 0x1e, 0x09, 0x18, 0x04, 0x07, 0x14, 0x12, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x00, 0x42, 0x52, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x05, 0x40, 0x40, 0x40, 0x05, 0x48, ++ 0x42, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x05, 0x05, 0x58, ++ 0x52, 0x4a, 0x05, 0x15, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x42, 0x42, 0x50, 0x50, 0x45, 0x4d, ++ 0x4a, 0x07, 0x4d, 0x5d, 0x4a, 0x48, 0x58, 0x62, 0x5d, 0x58, 0x4d, 0x40, 0x02, 0x48, 0x50, 0x50, ++ 0x45, 0x4d, 0x4a, 0x07, 0x4d, 0x5d, 0x4a, 0x48, 0x58, 0x62, 0x5d, 0x58, 0x4d, 0x40, 0x02, 0x48, ++ 0x0d, 0x4d, 0x25, 0x52, 0x58, 0x58, 0x4d, 0x50, 0x50, 0x4a, 0x45, 0x40, 0x45, 0x07, 0x4d, 0x52, ++ 0x2d, 0x07, 0x4d, 0x07, 0x4d, 0x52, 0x2d, 0x07, 0x4d, 0x07, 0x4d, 0x52, 0x2d, 0x07, 0x4d, 0x4a, ++ 0x42, 0x15, 0x15, 0x0f, 0x15, 0x0f, 0x15, 0x07, 0x15, 0x42, 0x58, 0x15, 0x42, 0x58, 0x40, 0x40, ++ 0x4a, 0x05, 0x0d, 0x05, 0x4a, 0x0f, 0x05, 0x42, 0x07, 0x1a, 0x27, 0x05, 0x42, 0x07, 0x0a, 0x0f, ++ 0x4a, 0x2d, 0x1a, 0x15, 0x4a, 0x1d, 0x0a, 0x18, 0x05, 0x07, 0x15, 0x12, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x40, 0x42, 0x52, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x04, 0x40, 0x40, 0x40, 0x04, 0x46, ++ 0x42, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x05, 0x05, 0x57, ++ 0x52, 0x49, 0x05, 0x14, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x42, 0x42, 0x4f, 0x4f, 0x44, 0x4c, ++ 0x4a, 0x07, 0x4c, 0x5c, 0x4a, 0x47, 0x57, 0x62, 0x5c, 0x57, 0x4b, 0x00, 0x03, 0x46, 0x4f, 0x4f, ++ 0x44, 0x4c, 0x4a, 0x07, 0x4c, 0x5c, 0x4a, 0x47, 0x57, 0x62, 0x5c, 0x57, 0x4b, 0x00, 0x03, 0x46, ++ 0x0e, 0x4d, 0x25, 0x52, 0x57, 0x57, 0x4c, 0x4f, 0x4f, 0x49, 0x44, 0x00, 0x44, 0x08, 0x4c, 0x52, ++ 0x2c, 0x07, 0x4c, 0x08, 0x4c, 0x52, 0x2c, 0x07, 0x4c, 0x08, 0x4c, 0x52, 0x2c, 0x07, 0x4c, 0x4a, ++ 0x42, 0x14, 0x14, 0x0f, 0x15, 0x0f, 0x15, 0x07, 0x15, 0x42, 0x57, 0x15, 0x42, 0x57, 0x40, 0x40, ++ 0x4a, 0x06, 0x0d, 0x05, 0x4a, 0x0f, 0x05, 0x42, 0x07, 0x1c, 0x27, 0x06, 0x42, 0x08, 0x0b, 0x0f, ++ 0x4a, 0x2c, 0x1a, 0x14, 0x4a, 0x1b, 0x0b, 0x17, 0x05, 0x07, 0x15, 0x12, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x41, 0x42, 0x52, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x04, 0x40, 0x40, 0x40, 0x04, 0x44, ++ 0x42, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x05, 0x05, 0x56, ++ 0x52, 0x48, 0x05, 0x14, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x42, 0x42, 0x4e, 0x4e, 0x44, 0x4c, ++ 0x4a, 0x07, 0x4c, 0x5c, 0x4a, 0x46, 0x56, 0x62, 0x5c, 0x56, 0x4a, 0x01, 0x03, 0x44, 0x4e, 0x4e, ++ 0x44, 0x4c, 0x4a, 0x07, 0x4c, 0x5c, 0x4a, 0x46, 0x56, 0x62, 0x5c, 0x56, 0x4a, 0x01, 0x03, 0x44, ++ 0x0f, 0x4d, 0x25, 0x52, 0x56, 0x56, 0x4c, 0x4e, 0x4e, 0x48, 0x44, 0x01, 0x44, 0x09, 0x4c, 0x52, ++ 0x2c, 0x07, 0x4c, 0x09, 0x4c, 0x52, 0x2c, 0x07, 0x4c, 0x09, 0x4c, 0x52, 0x2c, 0x07, 0x4c, 0x4a, ++ 0x42, 0x14, 0x14, 0x0f, 0x15, 0x0f, 0x15, 0x07, 0x15, 0x42, 0x56, 0x15, 0x42, 0x56, 0x40, 0x40, ++ 0x4a, 0x07, 0x0d, 0x05, 0x4a, 0x0f, 0x05, 0x42, 0x07, 0x1d, 0x27, 0x07, 0x42, 0x09, 0x0b, 0x0f, ++ 0x4a, 0x2c, 0x1a, 0x14, 0x4a, 0x1a, 0x0b, 0x16, 0x05, 0x07, 0x15, 0x12, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x42, 0x41, 0x51, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x03, 0x40, 0x40, 0x40, 0x03, 0x42, ++ 0x41, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x06, 0x06, 0x55, ++ 0x51, 0x47, 0x06, 0x13, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4d, 0x4d, 0x43, 0x4b, ++ 0x49, 0x07, 0x4b, 0x5b, 0x49, 0x45, 0x55, 0x61, 0x5b, 0x55, 0x48, 0x02, 0x04, 0x42, 0x4d, 0x4d, ++ 0x43, 0x4b, 0x49, 0x07, 0x4b, 0x5b, 0x49, 0x45, 0x55, 0x61, 0x5b, 0x55, 0x48, 0x02, 0x04, 0x42, ++ 0x10, 0x4e, 0x26, 0x51, 0x55, 0x55, 0x4b, 0x4d, 0x4d, 0x47, 0x43, 0x02, 0x43, 0x0a, 0x4b, 0x51, ++ 0x2b, 0x07, 0x4b, 0x0a, 0x4b, 0x51, 0x2b, 0x07, 0x4b, 0x0a, 0x4b, 0x51, 0x2b, 0x07, 0x4b, 0x49, ++ 0x41, 0x13, 0x13, 0x0f, 0x16, 0x0f, 0x16, 0x07, 0x16, 0x41, 0x55, 0x16, 0x41, 0x55, 0x40, 0x40, ++ 0x49, 0x08, 0x0e, 0x06, 0x49, 0x0f, 0x06, 0x41, 0x07, 0x1f, 0x27, 0x08, 0x41, 0x0a, 0x0c, 0x0f, ++ 0x49, 0x2b, 0x19, 0x13, 0x49, 0x18, 0x0c, 0x15, 0x06, 0x07, 0x16, 0x11, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x43, 0x41, 0x51, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x02, 0x40, 0x40, 0x40, 0x02, 0x40, ++ 0x41, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x06, 0x06, 0x54, ++ 0x51, 0x45, 0x06, 0x12, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4c, 0x4c, 0x42, 0x4a, ++ 0x49, 0x07, 0x4a, 0x5a, 0x49, 0x44, 0x54, 0x61, 0x5a, 0x54, 0x47, 0x03, 0x05, 0x40, 0x4c, 0x4c, ++ 0x42, 0x4a, 0x49, 0x07, 0x4a, 0x5a, 0x49, 0x44, 0x54, 0x61, 0x5a, 0x54, 0x47, 0x03, 0x05, 0x40, ++ 0x12, 0x4e, 0x26, 0x51, 0x54, 0x54, 0x4a, 0x4c, 0x4c, 0x45, 0x42, 0x03, 0x42, 0x0b, 0x4a, 0x51, ++ 0x2a, 0x07, 0x4a, 0x0b, 0x4a, 0x51, 0x2a, 0x07, 0x4a, 0x0b, 0x4a, 0x51, 0x2a, 0x07, 0x4a, 0x49, ++ 0x41, 0x12, 0x12, 0x0f, 0x16, 0x0f, 0x16, 0x07, 0x16, 0x41, 0x54, 0x16, 0x41, 0x54, 0x40, 0x40, ++ 0x49, 0x0a, 0x0e, 0x06, 0x49, 0x0f, 0x06, 0x41, 0x07, 0x20, 0x27, 0x0a, 0x41, 0x0b, 0x0d, 0x0f, ++ 0x49, 0x2a, 0x19, 0x12, 0x49, 0x17, 0x0d, 0x14, 0x06, 0x07, 0x16, 0x11, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x44, 0x41, 0x51, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x02, 0x40, 0x40, 0x40, 0x02, 0x01, ++ 0x41, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x06, 0x06, 0x53, ++ 0x51, 0x44, 0x06, 0x12, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4b, 0x4b, 0x42, 0x4a, ++ 0x49, 0x07, 0x4a, 0x5a, 0x49, 0x43, 0x53, 0x61, 0x5a, 0x53, 0x45, 0x04, 0x05, 0x01, 0x4b, 0x4b, ++ 0x42, 0x4a, 0x49, 0x07, 0x4a, 0x5a, 0x49, 0x43, 0x53, 0x61, 0x5a, 0x53, 0x45, 0x04, 0x05, 0x01, ++ 0x13, 0x4e, 0x26, 0x51, 0x53, 0x53, 0x4a, 0x4b, 0x4b, 0x44, 0x42, 0x04, 0x42, 0x0c, 0x4a, 0x51, ++ 0x2a, 0x07, 0x4a, 0x0c, 0x4a, 0x51, 0x2a, 0x07, 0x4a, 0x0c, 0x4a, 0x51, 0x2a, 0x07, 0x4a, 0x49, ++ 0x41, 0x12, 0x12, 0x0f, 0x16, 0x0f, 0x16, 0x07, 0x16, 0x41, 0x53, 0x16, 0x41, 0x53, 0x40, 0x40, ++ 0x49, 0x0b, 0x0e, 0x06, 0x49, 0x0f, 0x06, 0x41, 0x07, 0x22, 0x27, 0x0b, 0x41, 0x0c, 0x0d, 0x0f, ++ 0x49, 0x2a, 0x19, 0x12, 0x49, 0x15, 0x0d, 0x13, 0x06, 0x07, 0x16, 0x11, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x45, 0x40, 0x50, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x01, 0x40, 0x40, 0x40, 0x01, 0x03, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x07, 0x07, 0x52, ++ 0x50, 0x43, 0x07, 0x11, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4a, 0x4a, 0x41, 0x49, ++ 0x48, 0x07, 0x49, 0x59, 0x48, 0x42, 0x52, 0x60, 0x59, 0x52, 0x44, 0x05, 0x06, 0x03, 0x4a, 0x4a, ++ 0x41, 0x49, 0x48, 0x07, 0x49, 0x59, 0x48, 0x42, 0x52, 0x60, 0x59, 0x52, 0x44, 0x05, 0x06, 0x03, ++ 0x14, 0x4f, 0x27, 0x50, 0x52, 0x52, 0x49, 0x4a, 0x4a, 0x43, 0x41, 0x05, 0x41, 0x0d, 0x49, 0x50, ++ 0x29, 0x07, 0x49, 0x0d, 0x49, 0x50, 0x29, 0x07, 0x49, 0x0d, 0x49, 0x50, 0x29, 0x07, 0x49, 0x48, ++ 0x40, 0x11, 0x11, 0x0f, 0x17, 0x0f, 0x17, 0x07, 0x17, 0x40, 0x52, 0x17, 0x40, 0x52, 0x40, 0x40, ++ 0x48, 0x0c, 0x0f, 0x07, 0x48, 0x0f, 0x07, 0x40, 0x07, 0x23, 0x27, 0x0c, 0x40, 0x0d, 0x0e, 0x0f, ++ 0x48, 0x29, 0x18, 0x11, 0x48, 0x14, 0x0e, 0x12, 0x07, 0x07, 0x17, 0x10, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x46, 0x40, 0x50, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, 0x04, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x07, 0x07, 0x51, ++ 0x50, 0x42, 0x07, 0x10, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x49, 0x49, 0x41, 0x49, ++ 0x48, 0x07, 0x49, 0x59, 0x48, 0x41, 0x51, 0x60, 0x59, 0x51, 0x42, 0x06, 0x06, 0x04, 0x49, 0x49, ++ 0x41, 0x49, 0x48, 0x07, 0x49, 0x59, 0x48, 0x41, 0x51, 0x60, 0x59, 0x51, 0x42, 0x06, 0x06, 0x04, ++ 0x15, 0x4f, 0x27, 0x50, 0x51, 0x51, 0x49, 0x49, 0x49, 0x42, 0x41, 0x06, 0x41, 0x0e, 0x49, 0x50, ++ 0x28, 0x07, 0x49, 0x0e, 0x49, 0x50, 0x28, 0x07, 0x49, 0x0e, 0x49, 0x50, 0x28, 0x07, 0x49, 0x48, ++ 0x40, 0x10, 0x10, 0x0f, 0x17, 0x0f, 0x17, 0x07, 0x17, 0x40, 0x51, 0x17, 0x40, 0x51, 0x40, 0x40, ++ 0x48, 0x0d, 0x0f, 0x07, 0x48, 0x0f, 0x07, 0x40, 0x07, 0x25, 0x27, 0x0d, 0x40, 0x0e, 0x0e, 0x0f, ++ 0x48, 0x28, 0x18, 0x10, 0x48, 0x12, 0x0e, 0x11, 0x07, 0x07, 0x17, 0x10, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x47, 0x40, 0x50, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, 0x06, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x07, 0x07, 0x50, ++ 0x50, 0x40, 0x07, 0x10, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x48, 0x48, 0x40, 0x48, ++ 0x48, 0x07, 0x48, 0x58, 0x48, 0x40, 0x50, 0x60, 0x58, 0x50, 0x40, 0x07, 0x07, 0x06, 0x48, 0x48, ++ 0x40, 0x48, 0x48, 0x07, 0x48, 0x58, 0x48, 0x40, 0x50, 0x60, 0x58, 0x50, 0x40, 0x07, 0x07, 0x06, ++ 0x17, 0x4f, 0x27, 0x50, 0x50, 0x50, 0x48, 0x48, 0x48, 0x40, 0x40, 0x07, 0x40, 0x0f, 0x48, 0x50, ++ 0x28, 0x07, 0x48, 0x0f, 0x48, 0x50, 0x28, 0x07, 0x48, 0x0f, 0x48, 0x50, 0x28, 0x07, 0x48, 0x48, ++ 0x40, 0x10, 0x10, 0x0f, 0x17, 0x0f, 0x17, 0x07, 0x17, 0x40, 0x50, 0x17, 0x40, 0x50, 0x40, 0x40, ++ 0x48, 0x0f, 0x0f, 0x07, 0x48, 0x0f, 0x07, 0x40, 0x07, 0x27, 0x27, 0x0f, 0x40, 0x0f, 0x0f, 0x0f, ++ 0x48, 0x28, 0x18, 0x10, 0x48, 0x10, 0x0f, 0x10, 0x07, 0x07, 0x17, 0x10, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x48, 0x00, 0x4f, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x08, ++ 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x08, 0x08, 0x4f, ++ 0x4f, 0x00, 0x08, 0x0f, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x47, 0x47, 0x00, 0x47, ++ 0x47, 0x07, 0x47, 0x57, 0x47, 0x00, 0x4f, 0x5f, 0x57, 0x4f, 0x00, 0x08, 0x08, 0x08, 0x47, 0x47, ++ 0x00, 0x47, 0x47, 0x07, 0x47, 0x57, 0x47, 0x00, 0x4f, 0x5f, 0x57, 0x4f, 0x00, 0x08, 0x08, 0x08, ++ 0x18, 0x50, 0x28, 0x4f, 0x4f, 0x4f, 0x47, 0x47, 0x47, 0x00, 0x00, 0x08, 0x00, 0x10, 0x47, 0x4f, ++ 0x27, 0x07, 0x47, 0x10, 0x47, 0x4f, 0x27, 0x07, 0x47, 0x10, 0x47, 0x4f, 0x27, 0x07, 0x47, 0x47, ++ 0x00, 0x0f, 0x0f, 0x0f, 0x18, 0x0f, 0x18, 0x07, 0x18, 0x00, 0x4f, 0x18, 0x00, 0x4f, 0x40, 0x40, ++ 0x47, 0x10, 0x10, 0x08, 0x47, 0x0f, 0x08, 0x00, 0x07, 0x28, 0x27, 0x10, 0x00, 0x10, 0x10, 0x0f, ++ 0x47, 0x27, 0x17, 0x0f, 0x47, 0x0f, 0x10, 0x0f, 0x08, 0x07, 0x18, 0x0f, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x49, 0x00, 0x4f, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0a, ++ 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x08, 0x08, 0x4e, ++ 0x4f, 0x01, 0x08, 0x0f, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x46, 0x46, 0x00, 0x47, ++ 0x47, 0x07, 0x47, 0x57, 0x47, 0x01, 0x4e, 0x5f, 0x57, 0x4e, 0x02, 0x09, 0x08, 0x0a, 0x46, 0x46, ++ 0x00, 0x47, 0x47, 0x07, 0x47, 0x57, 0x47, 0x01, 0x4e, 0x5f, 0x57, 0x4e, 0x02, 0x09, 0x08, 0x0a, ++ 0x19, 0x50, 0x28, 0x4f, 0x4e, 0x4e, 0x47, 0x46, 0x46, 0x01, 0x00, 0x09, 0x00, 0x11, 0x47, 0x4f, ++ 0x27, 0x07, 0x47, 0x11, 0x47, 0x4f, 0x27, 0x07, 0x47, 0x11, 0x47, 0x4f, 0x27, 0x07, 0x47, 0x47, ++ 0x00, 0x0f, 0x0f, 0x0f, 0x18, 0x0f, 0x18, 0x07, 0x18, 0x00, 0x4e, 0x18, 0x00, 0x4e, 0x40, 0x40, ++ 0x47, 0x11, 0x10, 0x08, 0x47, 0x0f, 0x08, 0x00, 0x07, 0x2a, 0x27, 0x11, 0x00, 0x11, 0x10, 0x0f, ++ 0x47, 0x27, 0x17, 0x0f, 0x47, 0x0d, 0x10, 0x0e, 0x08, 0x07, 0x18, 0x0f, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4a, 0x00, 0x4f, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x40, 0x40, 0x40, 0x41, 0x0c, ++ 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x08, 0x08, 0x4d, ++ 0x4f, 0x02, 0x08, 0x0e, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x45, 0x45, 0x01, 0x46, ++ 0x47, 0x07, 0x46, 0x56, 0x47, 0x02, 0x4d, 0x5f, 0x56, 0x4d, 0x03, 0x0a, 0x09, 0x0c, 0x45, 0x45, ++ 0x01, 0x46, 0x47, 0x07, 0x46, 0x56, 0x47, 0x02, 0x4d, 0x5f, 0x56, 0x4d, 0x03, 0x0a, 0x09, 0x0c, ++ 0x1a, 0x50, 0x28, 0x4f, 0x4d, 0x4d, 0x46, 0x45, 0x45, 0x02, 0x01, 0x0a, 0x01, 0x12, 0x46, 0x4f, ++ 0x26, 0x07, 0x46, 0x12, 0x46, 0x4f, 0x26, 0x07, 0x46, 0x12, 0x46, 0x4f, 0x26, 0x07, 0x46, 0x47, ++ 0x00, 0x0e, 0x0e, 0x0f, 0x18, 0x0f, 0x18, 0x07, 0x18, 0x00, 0x4d, 0x18, 0x00, 0x4d, 0x40, 0x40, ++ 0x47, 0x12, 0x10, 0x08, 0x47, 0x0f, 0x08, 0x00, 0x07, 0x2b, 0x27, 0x12, 0x00, 0x12, 0x11, 0x0f, ++ 0x47, 0x26, 0x17, 0x0e, 0x47, 0x0c, 0x11, 0x0d, 0x08, 0x07, 0x18, 0x0f, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4b, 0x01, 0x4e, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x42, 0x40, 0x40, 0x40, 0x42, 0x0e, ++ 0x01, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x09, 0x09, 0x4c, ++ 0x4e, 0x04, 0x09, 0x0d, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x01, 0x01, 0x44, 0x44, 0x02, 0x45, ++ 0x46, 0x07, 0x45, 0x55, 0x46, 0x03, 0x4c, 0x5e, 0x55, 0x4c, 0x05, 0x0b, 0x0a, 0x0e, 0x44, 0x44, ++ 0x02, 0x45, 0x46, 0x07, 0x45, 0x55, 0x46, 0x03, 0x4c, 0x5e, 0x55, 0x4c, 0x05, 0x0b, 0x0a, 0x0e, ++ 0x1c, 0x51, 0x29, 0x4e, 0x4c, 0x4c, 0x45, 0x44, 0x44, 0x04, 0x02, 0x0b, 0x02, 0x13, 0x45, 0x4e, ++ 0x25, 0x07, 0x45, 0x13, 0x45, 0x4e, 0x25, 0x07, 0x45, 0x13, 0x45, 0x4e, 0x25, 0x07, 0x45, 0x46, ++ 0x01, 0x0d, 0x0d, 0x0f, 0x19, 0x0f, 0x19, 0x07, 0x19, 0x01, 0x4c, 0x19, 0x01, 0x4c, 0x40, 0x40, ++ 0x46, 0x14, 0x11, 0x09, 0x46, 0x0f, 0x09, 0x01, 0x07, 0x2d, 0x27, 0x14, 0x01, 0x13, 0x12, 0x0f, ++ 0x46, 0x25, 0x16, 0x0d, 0x46, 0x0a, 0x12, 0x0c, 0x09, 0x07, 0x19, 0x0e, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4c, 0x01, 0x4e, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x42, 0x40, 0x40, 0x40, 0x42, 0x10, ++ 0x01, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x09, 0x09, 0x4b, ++ 0x4e, 0x05, 0x09, 0x0d, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x01, 0x01, 0x43, 0x43, 0x02, 0x45, ++ 0x46, 0x07, 0x45, 0x55, 0x46, 0x04, 0x4b, 0x5e, 0x55, 0x4b, 0x06, 0x0c, 0x0a, 0x10, 0x43, 0x43, ++ 0x02, 0x45, 0x46, 0x07, 0x45, 0x55, 0x46, 0x04, 0x4b, 0x5e, 0x55, 0x4b, 0x06, 0x0c, 0x0a, 0x10, ++ 0x1d, 0x51, 0x29, 0x4e, 0x4b, 0x4b, 0x45, 0x43, 0x43, 0x05, 0x02, 0x0c, 0x02, 0x14, 0x45, 0x4e, ++ 0x25, 0x07, 0x45, 0x14, 0x45, 0x4e, 0x25, 0x07, 0x45, 0x14, 0x45, 0x4e, 0x25, 0x07, 0x45, 0x46, ++ 0x01, 0x0d, 0x0d, 0x0f, 0x19, 0x0f, 0x19, 0x07, 0x19, 0x01, 0x4b, 0x19, 0x01, 0x4b, 0x40, 0x40, ++ 0x46, 0x15, 0x11, 0x09, 0x46, 0x0f, 0x09, 0x01, 0x07, 0x2e, 0x27, 0x15, 0x01, 0x14, 0x12, 0x0f, ++ 0x46, 0x25, 0x16, 0x0d, 0x46, 0x09, 0x12, 0x0b, 0x09, 0x07, 0x19, 0x0e, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4d, 0x01, 0x4e, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x43, 0x40, 0x40, 0x40, 0x43, 0x12, ++ 0x01, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x09, 0x09, 0x4a, ++ 0x4e, 0x06, 0x09, 0x0c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x01, 0x01, 0x42, 0x42, 0x03, 0x44, ++ 0x46, 0x07, 0x44, 0x54, 0x46, 0x05, 0x4a, 0x5e, 0x54, 0x4a, 0x08, 0x0d, 0x0b, 0x12, 0x42, 0x42, ++ 0x03, 0x44, 0x46, 0x07, 0x44, 0x54, 0x46, 0x05, 0x4a, 0x5e, 0x54, 0x4a, 0x08, 0x0d, 0x0b, 0x12, ++ 0x1e, 0x51, 0x29, 0x4e, 0x4a, 0x4a, 0x44, 0x42, 0x42, 0x06, 0x03, 0x0d, 0x03, 0x15, 0x44, 0x4e, ++ 0x24, 0x07, 0x44, 0x15, 0x44, 0x4e, 0x24, 0x07, 0x44, 0x15, 0x44, 0x4e, 0x24, 0x07, 0x44, 0x46, ++ 0x01, 0x0c, 0x0c, 0x0f, 0x19, 0x0f, 0x19, 0x07, 0x19, 0x01, 0x4a, 0x19, 0x01, 0x4a, 0x40, 0x40, ++ 0x46, 0x16, 0x11, 0x09, 0x46, 0x0f, 0x09, 0x01, 0x07, 0x30, 0x27, 0x16, 0x01, 0x15, 0x13, 0x0f, ++ 0x46, 0x24, 0x16, 0x0c, 0x46, 0x07, 0x13, 0x0a, 0x09, 0x07, 0x19, 0x0e, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4e, 0x01, 0x4e, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x44, 0x40, 0x40, 0x40, 0x44, 0x13, ++ 0x01, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x09, 0x09, 0x4a, ++ 0x4e, 0x07, 0x09, 0x0b, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x01, 0x01, 0x42, 0x42, 0x03, 0x44, ++ 0x46, 0x07, 0x44, 0x54, 0x46, 0x05, 0x4a, 0x5e, 0x54, 0x4a, 0x09, 0x0d, 0x0b, 0x13, 0x42, 0x42, ++ 0x03, 0x44, 0x46, 0x07, 0x44, 0x54, 0x46, 0x05, 0x4a, 0x5e, 0x54, 0x4a, 0x09, 0x0d, 0x0b, 0x13, ++ 0x1f, 0x52, 0x29, 0x4e, 0x4a, 0x4a, 0x44, 0x42, 0x42, 0x07, 0x03, 0x0d, 0x03, 0x15, 0x44, 0x4e, ++ 0x23, 0x07, 0x44, 0x15, 0x44, 0x4e, 0x23, 0x07, 0x44, 0x15, 0x44, 0x4e, 0x23, 0x07, 0x44, 0x46, ++ 0x01, 0x0b, 0x0b, 0x0f, 0x19, 0x0f, 0x19, 0x07, 0x19, 0x01, 0x4a, 0x19, 0x01, 0x4a, 0x40, 0x40, ++ 0x46, 0x17, 0x11, 0x09, 0x46, 0x0f, 0x09, 0x01, 0x07, 0x31, 0x27, 0x17, 0x01, 0x15, 0x13, 0x0f, ++ 0x46, 0x23, 0x15, 0x0b, 0x46, 0x05, 0x13, 0x09, 0x09, 0x07, 0x19, 0x0d, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4e, 0x02, 0x4d, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x44, 0x40, 0x40, 0x40, 0x44, 0x15, ++ 0x02, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0a, 0x0a, 0x49, ++ 0x4d, 0x09, 0x0a, 0x0b, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x02, 0x02, 0x41, 0x41, 0x04, 0x43, ++ 0x45, 0x07, 0x43, 0x53, 0x45, 0x06, 0x49, 0x5d, 0x53, 0x49, 0x0b, 0x0e, 0x0c, 0x15, 0x41, 0x41, ++ 0x04, 0x43, 0x45, 0x07, 0x43, 0x53, 0x45, 0x06, 0x49, 0x5d, 0x53, 0x49, 0x0b, 0x0e, 0x0c, 0x15, ++ 0x21, 0x52, 0x2a, 0x4d, 0x49, 0x49, 0x43, 0x41, 0x41, 0x09, 0x04, 0x0e, 0x04, 0x16, 0x43, 0x4d, ++ 0x23, 0x07, 0x43, 0x16, 0x43, 0x4d, 0x23, 0x07, 0x43, 0x16, 0x43, 0x4d, 0x23, 0x07, 0x43, 0x45, ++ 0x02, 0x0b, 0x0b, 0x0f, 0x1a, 0x0f, 0x1a, 0x07, 0x1a, 0x02, 0x49, 0x1a, 0x02, 0x49, 0x40, 0x40, ++ 0x45, 0x19, 0x12, 0x0a, 0x45, 0x0f, 0x0a, 0x02, 0x07, 0x33, 0x27, 0x19, 0x02, 0x16, 0x14, 0x0f, ++ 0x45, 0x23, 0x15, 0x0b, 0x45, 0x04, 0x14, 0x09, 0x0a, 0x07, 0x1a, 0x0d, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4f, 0x02, 0x4d, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x45, 0x40, 0x40, 0x40, 0x45, 0x17, ++ 0x02, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0a, 0x0a, 0x48, ++ 0x4d, 0x0a, 0x0a, 0x0a, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x02, 0x02, 0x40, 0x40, 0x05, 0x42, ++ 0x45, 0x07, 0x42, 0x52, 0x45, 0x07, 0x48, 0x5d, 0x52, 0x48, 0x0d, 0x0f, 0x0d, 0x17, 0x40, 0x40, ++ 0x05, 0x42, 0x45, 0x07, 0x42, 0x52, 0x45, 0x07, 0x48, 0x5d, 0x52, 0x48, 0x0d, 0x0f, 0x0d, 0x17, ++ 0x22, 0x52, 0x2a, 0x4d, 0x48, 0x48, 0x42, 0x40, 0x40, 0x0a, 0x05, 0x0f, 0x05, 0x17, 0x42, 0x4d, ++ 0x22, 0x07, 0x42, 0x17, 0x42, 0x4d, 0x22, 0x07, 0x42, 0x17, 0x42, 0x4d, 0x22, 0x07, 0x42, 0x45, ++ 0x02, 0x0a, 0x0a, 0x0f, 0x1a, 0x0f, 0x1a, 0x07, 0x1a, 0x02, 0x48, 0x1a, 0x02, 0x48, 0x40, 0x40, ++ 0x45, 0x1a, 0x12, 0x0a, 0x45, 0x0f, 0x0a, 0x02, 0x07, 0x35, 0x27, 0x1a, 0x02, 0x17, 0x15, 0x0f, ++ 0x45, 0x22, 0x15, 0x0a, 0x45, 0x02, 0x15, 0x08, 0x0a, 0x07, 0x1a, 0x0d, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x50, 0x02, 0x4d, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x45, 0x40, 0x40, 0x40, 0x45, 0x19, ++ 0x02, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0a, 0x0a, 0x47, ++ 0x4d, 0x0b, 0x0a, 0x0a, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x02, 0x02, 0x00, 0x00, 0x05, 0x42, ++ 0x45, 0x07, 0x42, 0x52, 0x45, 0x08, 0x47, 0x5d, 0x52, 0x47, 0x0e, 0x10, 0x0d, 0x19, 0x00, 0x00, ++ 0x05, 0x42, 0x45, 0x07, 0x42, 0x52, 0x45, 0x08, 0x47, 0x5d, 0x52, 0x47, 0x0e, 0x10, 0x0d, 0x19, ++ 0x23, 0x52, 0x2a, 0x4d, 0x47, 0x47, 0x42, 0x00, 0x00, 0x0b, 0x05, 0x10, 0x05, 0x18, 0x42, 0x4d, ++ 0x22, 0x07, 0x42, 0x18, 0x42, 0x4d, 0x22, 0x07, 0x42, 0x18, 0x42, 0x4d, 0x22, 0x07, 0x42, 0x45, ++ 0x02, 0x0a, 0x0a, 0x0f, 0x1a, 0x0f, 0x1a, 0x07, 0x1a, 0x02, 0x47, 0x1a, 0x02, 0x47, 0x40, 0x40, ++ 0x45, 0x1b, 0x12, 0x0a, 0x45, 0x0f, 0x0a, 0x02, 0x07, 0x36, 0x27, 0x1b, 0x02, 0x18, 0x15, 0x0f, ++ 0x45, 0x22, 0x15, 0x0a, 0x45, 0x01, 0x15, 0x07, 0x0a, 0x07, 0x1a, 0x0d, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x51, 0x03, 0x4c, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x46, 0x40, 0x40, 0x40, 0x46, 0x1b, ++ 0x03, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0b, 0x0b, 0x46, ++ 0x4c, 0x0c, 0x0b, 0x09, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x03, 0x03, 0x01, 0x01, 0x06, 0x41, ++ 0x44, 0x07, 0x41, 0x51, 0x44, 0x09, 0x46, 0x5c, 0x51, 0x46, 0x10, 0x11, 0x0e, 0x1b, 0x01, 0x01, ++ 0x06, 0x41, 0x44, 0x07, 0x41, 0x51, 0x44, 0x09, 0x46, 0x5c, 0x51, 0x46, 0x10, 0x11, 0x0e, 0x1b, ++ 0x24, 0x53, 0x2b, 0x4c, 0x46, 0x46, 0x41, 0x01, 0x01, 0x0c, 0x06, 0x11, 0x06, 0x19, 0x41, 0x4c, ++ 0x21, 0x07, 0x41, 0x19, 0x41, 0x4c, 0x21, 0x07, 0x41, 0x19, 0x41, 0x4c, 0x21, 0x07, 0x41, 0x44, ++ 0x03, 0x09, 0x09, 0x0f, 0x1b, 0x0f, 0x1b, 0x07, 0x1b, 0x03, 0x46, 0x1b, 0x03, 0x46, 0x40, 0x40, ++ 0x44, 0x1c, 0x13, 0x0b, 0x44, 0x0f, 0x0b, 0x03, 0x07, 0x38, 0x27, 0x1c, 0x03, 0x19, 0x16, 0x0f, ++ 0x44, 0x21, 0x14, 0x09, 0x44, 0x40, 0x16, 0x06, 0x0b, 0x07, 0x1b, 0x0c, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x52, 0x03, 0x4c, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x47, 0x40, 0x40, 0x40, 0x47, 0x1d, ++ 0x03, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0b, 0x0b, 0x45, ++ 0x4c, 0x0e, 0x0b, 0x08, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x03, 0x03, 0x02, 0x02, 0x07, 0x40, ++ 0x44, 0x07, 0x40, 0x50, 0x44, 0x0a, 0x45, 0x5c, 0x50, 0x45, 0x11, 0x12, 0x0f, 0x1d, 0x02, 0x02, ++ 0x07, 0x40, 0x44, 0x07, 0x40, 0x50, 0x44, 0x0a, 0x45, 0x5c, 0x50, 0x45, 0x11, 0x12, 0x0f, 0x1d, ++ 0x26, 0x53, 0x2b, 0x4c, 0x45, 0x45, 0x40, 0x02, 0x02, 0x0e, 0x07, 0x12, 0x07, 0x1a, 0x40, 0x4c, ++ 0x20, 0x07, 0x40, 0x1a, 0x40, 0x4c, 0x20, 0x07, 0x40, 0x1a, 0x40, 0x4c, 0x20, 0x07, 0x40, 0x44, ++ 0x03, 0x08, 0x08, 0x0f, 0x1b, 0x0f, 0x1b, 0x07, 0x1b, 0x03, 0x45, 0x1b, 0x03, 0x45, 0x40, 0x40, ++ 0x44, 0x1e, 0x13, 0x0b, 0x44, 0x0f, 0x0b, 0x03, 0x07, 0x39, 0x27, 0x1e, 0x03, 0x1a, 0x17, 0x0f, ++ 0x44, 0x20, 0x14, 0x08, 0x44, 0x41, 0x17, 0x05, 0x0b, 0x07, 0x1b, 0x0c, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x53, 0x03, 0x4c, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x47, 0x40, 0x40, 0x40, 0x47, 0x1f, ++ 0x03, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0b, 0x0b, 0x44, ++ 0x4c, 0x0f, 0x0b, 0x08, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x03, 0x03, 0x03, 0x03, 0x07, 0x40, ++ 0x44, 0x07, 0x40, 0x50, 0x44, 0x0b, 0x44, 0x5c, 0x50, 0x44, 0x13, 0x13, 0x0f, 0x1f, 0x03, 0x03, ++ 0x07, 0x40, 0x44, 0x07, 0x40, 0x50, 0x44, 0x0b, 0x44, 0x5c, 0x50, 0x44, 0x13, 0x13, 0x0f, 0x1f, ++ 0x27, 0x53, 0x2b, 0x4c, 0x44, 0x44, 0x40, 0x03, 0x03, 0x0f, 0x07, 0x13, 0x07, 0x1b, 0x40, 0x4c, ++ 0x20, 0x07, 0x40, 0x1b, 0x40, 0x4c, 0x20, 0x07, 0x40, 0x1b, 0x40, 0x4c, 0x20, 0x07, 0x40, 0x44, ++ 0x03, 0x08, 0x08, 0x0f, 0x1b, 0x0f, 0x1b, 0x07, 0x1b, 0x03, 0x44, 0x1b, 0x03, 0x44, 0x40, 0x40, ++ 0x44, 0x1f, 0x13, 0x0b, 0x44, 0x0f, 0x0b, 0x03, 0x07, 0x3b, 0x27, 0x1f, 0x03, 0x1b, 0x17, 0x0f, ++ 0x44, 0x20, 0x14, 0x08, 0x44, 0x43, 0x17, 0x04, 0x0b, 0x07, 0x1b, 0x0c, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x54, 0x04, 0x4b, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x48, 0x40, 0x40, 0x40, 0x48, 0x21, ++ 0x04, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0c, 0x0c, 0x43, ++ 0x4b, 0x10, 0x0c, 0x07, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x04, 0x04, 0x04, 0x04, 0x08, 0x00, ++ 0x43, 0x07, 0x00, 0x4f, 0x43, 0x0c, 0x43, 0x5b, 0x4f, 0x43, 0x14, 0x14, 0x10, 0x21, 0x04, 0x04, ++ 0x08, 0x00, 0x43, 0x07, 0x00, 0x4f, 0x43, 0x0c, 0x43, 0x5b, 0x4f, 0x43, 0x14, 0x14, 0x10, 0x21, ++ 0x28, 0x54, 0x2c, 0x4b, 0x43, 0x43, 0x00, 0x04, 0x04, 0x10, 0x08, 0x14, 0x08, 0x1c, 0x00, 0x4b, ++ 0x1f, 0x07, 0x00, 0x1c, 0x00, 0x4b, 0x1f, 0x07, 0x00, 0x1c, 0x00, 0x4b, 0x1f, 0x07, 0x00, 0x43, ++ 0x04, 0x07, 0x07, 0x0f, 0x1c, 0x0f, 0x1c, 0x07, 0x1c, 0x04, 0x43, 0x1c, 0x04, 0x43, 0x40, 0x40, ++ 0x43, 0x20, 0x14, 0x0c, 0x43, 0x0f, 0x0c, 0x04, 0x07, 0x3c, 0x27, 0x20, 0x04, 0x1c, 0x18, 0x0f, ++ 0x43, 0x1f, 0x13, 0x07, 0x43, 0x44, 0x18, 0x03, 0x0c, 0x07, 0x1c, 0x0b, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x55, 0x04, 0x4b, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x49, 0x40, 0x40, 0x40, 0x49, 0x22, ++ 0x04, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0c, 0x0c, 0x42, ++ 0x4b, 0x11, 0x0c, 0x06, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x04, 0x04, 0x05, 0x05, 0x08, 0x00, ++ 0x43, 0x07, 0x00, 0x4f, 0x43, 0x0d, 0x42, 0x5b, 0x4f, 0x42, 0x16, 0x15, 0x10, 0x22, 0x05, 0x05, ++ 0x08, 0x00, 0x43, 0x07, 0x00, 0x4f, 0x43, 0x0d, 0x42, 0x5b, 0x4f, 0x42, 0x16, 0x15, 0x10, 0x22, ++ 0x29, 0x54, 0x2c, 0x4b, 0x42, 0x42, 0x00, 0x05, 0x05, 0x11, 0x08, 0x15, 0x08, 0x1d, 0x00, 0x4b, ++ 0x1e, 0x07, 0x00, 0x1d, 0x00, 0x4b, 0x1e, 0x07, 0x00, 0x1d, 0x00, 0x4b, 0x1e, 0x07, 0x00, 0x43, ++ 0x04, 0x06, 0x06, 0x0f, 0x1c, 0x0f, 0x1c, 0x07, 0x1c, 0x04, 0x42, 0x1c, 0x04, 0x42, 0x40, 0x40, ++ 0x43, 0x21, 0x14, 0x0c, 0x43, 0x0f, 0x0c, 0x04, 0x07, 0x3e, 0x27, 0x21, 0x04, 0x1d, 0x18, 0x0f, ++ 0x43, 0x1e, 0x13, 0x06, 0x43, 0x46, 0x18, 0x02, 0x0c, 0x07, 0x1c, 0x0b, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x56, 0x04, 0x4b, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x49, 0x40, 0x40, 0x40, 0x49, 0x24, ++ 0x04, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0c, 0x0c, 0x41, ++ 0x4b, 0x13, 0x0c, 0x06, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x04, 0x04, 0x06, 0x06, 0x09, 0x01, ++ 0x43, 0x07, 0x01, 0x4e, 0x43, 0x0e, 0x41, 0x5b, 0x4e, 0x41, 0x18, 0x16, 0x11, 0x24, 0x06, 0x06, ++ 0x09, 0x01, 0x43, 0x07, 0x01, 0x4e, 0x43, 0x0e, 0x41, 0x5b, 0x4e, 0x41, 0x18, 0x16, 0x11, 0x24, ++ 0x2b, 0x54, 0x2c, 0x4b, 0x41, 0x41, 0x01, 0x06, 0x06, 0x13, 0x09, 0x16, 0x09, 0x1e, 0x01, 0x4b, ++ 0x1e, 0x07, 0x01, 0x1e, 0x01, 0x4b, 0x1e, 0x07, 0x01, 0x1e, 0x01, 0x4b, 0x1e, 0x07, 0x01, 0x43, ++ 0x04, 0x06, 0x06, 0x0f, 0x1c, 0x0f, 0x1c, 0x07, 0x1c, 0x04, 0x41, 0x1c, 0x04, 0x41, 0x40, 0x40, ++ 0x43, 0x23, 0x14, 0x0c, 0x43, 0x0f, 0x0c, 0x04, 0x07, 0x3e, 0x27, 0x23, 0x04, 0x1e, 0x19, 0x0f, ++ 0x43, 0x1e, 0x13, 0x06, 0x43, 0x48, 0x19, 0x01, 0x0c, 0x07, 0x1c, 0x0b, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x57, 0x05, 0x4a, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4a, 0x40, 0x40, 0x40, 0x4a, 0x26, ++ 0x05, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0d, 0x0d, 0x40, ++ 0x4a, 0x14, 0x0d, 0x05, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x05, 0x05, 0x07, 0x07, 0x0a, 0x02, ++ 0x42, 0x07, 0x02, 0x4d, 0x42, 0x0f, 0x40, 0x5a, 0x4d, 0x40, 0x19, 0x17, 0x12, 0x26, 0x07, 0x07, ++ 0x0a, 0x02, 0x42, 0x07, 0x02, 0x4d, 0x42, 0x0f, 0x40, 0x5a, 0x4d, 0x40, 0x19, 0x17, 0x12, 0x26, ++ 0x2c, 0x55, 0x2d, 0x4a, 0x40, 0x40, 0x02, 0x07, 0x07, 0x14, 0x0a, 0x17, 0x0a, 0x1f, 0x02, 0x4a, ++ 0x1d, 0x07, 0x02, 0x1f, 0x02, 0x4a, 0x1d, 0x07, 0x02, 0x1f, 0x02, 0x4a, 0x1d, 0x07, 0x02, 0x42, ++ 0x05, 0x05, 0x05, 0x0f, 0x1d, 0x0f, 0x1d, 0x07, 0x1d, 0x05, 0x40, 0x1d, 0x05, 0x40, 0x40, 0x40, ++ 0x42, 0x24, 0x15, 0x0d, 0x42, 0x0f, 0x0d, 0x05, 0x07, 0x3e, 0x27, 0x24, 0x05, 0x1f, 0x1a, 0x0f, ++ 0x42, 0x1d, 0x12, 0x05, 0x42, 0x49, 0x1a, 0x00, 0x0d, 0x07, 0x1d, 0x0a, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x58, 0x05, 0x4a, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4a, 0x40, 0x40, 0x40, 0x4a, 0x28, ++ 0x05, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0d, 0x0d, 0x00, ++ 0x4a, 0x15, 0x0d, 0x05, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x05, 0x05, 0x08, 0x08, 0x0a, 0x02, ++ 0x42, 0x07, 0x02, 0x4d, 0x42, 0x10, 0x00, 0x5a, 0x4d, 0x00, 0x1b, 0x18, 0x12, 0x28, 0x08, 0x08, ++ 0x0a, 0x02, 0x42, 0x07, 0x02, 0x4d, 0x42, 0x10, 0x00, 0x5a, 0x4d, 0x00, 0x1b, 0x18, 0x12, 0x28, ++ 0x2d, 0x55, 0x2d, 0x4a, 0x00, 0x00, 0x02, 0x08, 0x08, 0x15, 0x0a, 0x18, 0x0a, 0x20, 0x02, 0x4a, ++ 0x1d, 0x07, 0x02, 0x20, 0x02, 0x4a, 0x1d, 0x07, 0x02, 0x20, 0x02, 0x4a, 0x1d, 0x07, 0x02, 0x42, ++ 0x05, 0x05, 0x05, 0x0f, 0x1d, 0x0f, 0x1d, 0x07, 0x1d, 0x05, 0x00, 0x1d, 0x05, 0x00, 0x40, 0x40, ++ 0x42, 0x25, 0x15, 0x0d, 0x42, 0x0f, 0x0d, 0x05, 0x07, 0x3e, 0x27, 0x25, 0x05, 0x20, 0x1a, 0x0f, ++ 0x42, 0x1d, 0x12, 0x05, 0x42, 0x4b, 0x1a, 0x40, 0x0d, 0x07, 0x1d, 0x0a, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x59, 0x05, 0x4a, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4b, 0x40, 0x40, 0x40, 0x4b, 0x2a, ++ 0x05, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0d, 0x0d, 0x01, ++ 0x4a, 0x16, 0x0d, 0x04, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x05, 0x05, 0x09, 0x09, 0x0b, 0x03, ++ 0x42, 0x07, 0x03, 0x4c, 0x42, 0x11, 0x01, 0x5a, 0x4c, 0x01, 0x1c, 0x19, 0x13, 0x2a, 0x09, 0x09, ++ 0x0b, 0x03, 0x42, 0x07, 0x03, 0x4c, 0x42, 0x11, 0x01, 0x5a, 0x4c, 0x01, 0x1c, 0x19, 0x13, 0x2a, ++ 0x2e, 0x55, 0x2d, 0x4a, 0x01, 0x01, 0x03, 0x09, 0x09, 0x16, 0x0b, 0x19, 0x0b, 0x21, 0x03, 0x4a, ++ 0x1c, 0x07, 0x03, 0x21, 0x03, 0x4a, 0x1c, 0x07, 0x03, 0x21, 0x03, 0x4a, 0x1c, 0x07, 0x03, 0x42, ++ 0x05, 0x04, 0x04, 0x0f, 0x1d, 0x0f, 0x1d, 0x07, 0x1d, 0x05, 0x01, 0x1d, 0x05, 0x01, 0x40, 0x40, ++ 0x42, 0x26, 0x15, 0x0d, 0x42, 0x0f, 0x0d, 0x05, 0x07, 0x3e, 0x27, 0x26, 0x05, 0x21, 0x1b, 0x0f, ++ 0x42, 0x1c, 0x12, 0x04, 0x42, 0x4c, 0x1b, 0x41, 0x0d, 0x07, 0x1d, 0x0a, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x5a, 0x06, 0x49, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4c, 0x40, 0x40, 0x40, 0x4c, 0x2c, ++ 0x06, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0e, 0x0e, 0x02, ++ 0x49, 0x18, 0x0e, 0x03, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x06, 0x06, 0x0a, 0x0a, 0x0c, 0x04, ++ 0x41, 0x07, 0x04, 0x4b, 0x41, 0x12, 0x02, 0x59, 0x4b, 0x02, 0x1e, 0x1a, 0x14, 0x2c, 0x0a, 0x0a, ++ 0x0c, 0x04, 0x41, 0x07, 0x04, 0x4b, 0x41, 0x12, 0x02, 0x59, 0x4b, 0x02, 0x1e, 0x1a, 0x14, 0x2c, ++ 0x30, 0x56, 0x2e, 0x49, 0x02, 0x02, 0x04, 0x0a, 0x0a, 0x18, 0x0c, 0x1a, 0x0c, 0x22, 0x04, 0x49, ++ 0x1b, 0x07, 0x04, 0x22, 0x04, 0x49, 0x1b, 0x07, 0x04, 0x22, 0x04, 0x49, 0x1b, 0x07, 0x04, 0x41, ++ 0x06, 0x03, 0x03, 0x0f, 0x1e, 0x0f, 0x1e, 0x07, 0x1e, 0x06, 0x02, 0x1e, 0x06, 0x02, 0x40, 0x40, ++ 0x41, 0x28, 0x16, 0x0e, 0x41, 0x0f, 0x0e, 0x06, 0x07, 0x3e, 0x27, 0x28, 0x06, 0x22, 0x1c, 0x0f, ++ 0x41, 0x1b, 0x11, 0x03, 0x41, 0x4e, 0x1c, 0x42, 0x0e, 0x07, 0x1e, 0x09, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x5b, 0x06, 0x49, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4c, 0x40, 0x40, 0x40, 0x4c, 0x2e, ++ 0x06, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0e, 0x0e, 0x03, ++ 0x49, 0x19, 0x0e, 0x03, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x06, 0x06, 0x0b, 0x0b, 0x0c, 0x04, ++ 0x41, 0x07, 0x04, 0x4b, 0x41, 0x13, 0x03, 0x59, 0x4b, 0x03, 0x1f, 0x1b, 0x14, 0x2e, 0x0b, 0x0b, ++ 0x0c, 0x04, 0x41, 0x07, 0x04, 0x4b, 0x41, 0x13, 0x03, 0x59, 0x4b, 0x03, 0x1f, 0x1b, 0x14, 0x2e, ++ 0x31, 0x56, 0x2e, 0x49, 0x03, 0x03, 0x04, 0x0b, 0x0b, 0x19, 0x0c, 0x1b, 0x0c, 0x23, 0x04, 0x49, ++ 0x1b, 0x07, 0x04, 0x23, 0x04, 0x49, 0x1b, 0x07, 0x04, 0x23, 0x04, 0x49, 0x1b, 0x07, 0x04, 0x41, ++ 0x06, 0x03, 0x03, 0x0f, 0x1e, 0x0f, 0x1e, 0x07, 0x1e, 0x06, 0x03, 0x1e, 0x06, 0x03, 0x40, 0x40, ++ 0x41, 0x29, 0x16, 0x0e, 0x41, 0x0f, 0x0e, 0x06, 0x07, 0x3e, 0x27, 0x29, 0x06, 0x23, 0x1c, 0x0f, ++ 0x41, 0x1b, 0x11, 0x03, 0x41, 0x4f, 0x1c, 0x43, 0x0e, 0x07, 0x1e, 0x09, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x5c, 0x06, 0x49, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4d, 0x40, 0x40, 0x40, 0x4d, 0x30, ++ 0x06, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0e, 0x0e, 0x04, ++ 0x49, 0x1a, 0x0e, 0x02, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x06, 0x06, 0x0c, 0x0c, 0x0d, 0x05, ++ 0x41, 0x07, 0x05, 0x4a, 0x41, 0x14, 0x04, 0x59, 0x4a, 0x04, 0x21, 0x1c, 0x15, 0x30, 0x0c, 0x0c, ++ 0x0d, 0x05, 0x41, 0x07, 0x05, 0x4a, 0x41, 0x14, 0x04, 0x59, 0x4a, 0x04, 0x21, 0x1c, 0x15, 0x30, ++ 0x32, 0x56, 0x2e, 0x49, 0x04, 0x04, 0x05, 0x0c, 0x0c, 0x1a, 0x0d, 0x1c, 0x0d, 0x24, 0x05, 0x49, ++ 0x1a, 0x07, 0x05, 0x24, 0x05, 0x49, 0x1a, 0x07, 0x05, 0x24, 0x05, 0x49, 0x1a, 0x07, 0x05, 0x41, ++ 0x06, 0x02, 0x02, 0x0f, 0x1e, 0x0f, 0x1e, 0x07, 0x1e, 0x06, 0x04, 0x1e, 0x06, 0x04, 0x40, 0x40, ++ 0x41, 0x2a, 0x16, 0x0e, 0x41, 0x0f, 0x0e, 0x06, 0x07, 0x3e, 0x27, 0x2a, 0x06, 0x24, 0x1d, 0x0f, ++ 0x41, 0x1a, 0x11, 0x02, 0x41, 0x51, 0x1d, 0x44, 0x0e, 0x07, 0x1e, 0x09, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x5d, 0x06, 0x49, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4e, 0x40, 0x40, 0x40, 0x4e, 0x31, ++ 0x06, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0e, 0x0e, 0x04, ++ 0x49, 0x1b, 0x0e, 0x01, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x06, 0x06, 0x0c, 0x0c, 0x0d, 0x05, ++ 0x41, 0x07, 0x05, 0x4a, 0x41, 0x14, 0x04, 0x59, 0x4a, 0x04, 0x22, 0x1c, 0x15, 0x31, 0x0c, 0x0c, ++ 0x0d, 0x05, 0x41, 0x07, 0x05, 0x4a, 0x41, 0x14, 0x04, 0x59, 0x4a, 0x04, 0x22, 0x1c, 0x15, 0x31, ++ 0x33, 0x57, 0x2e, 0x49, 0x04, 0x04, 0x05, 0x0c, 0x0c, 0x1b, 0x0d, 0x1c, 0x0d, 0x24, 0x05, 0x49, ++ 0x19, 0x07, 0x05, 0x24, 0x05, 0x49, 0x19, 0x07, 0x05, 0x24, 0x05, 0x49, 0x19, 0x07, 0x05, 0x41, ++ 0x06, 0x01, 0x01, 0x0f, 0x1e, 0x0f, 0x1e, 0x07, 0x1e, 0x06, 0x04, 0x1e, 0x06, 0x04, 0x40, 0x40, ++ 0x41, 0x2b, 0x16, 0x0e, 0x41, 0x0f, 0x0e, 0x06, 0x07, 0x3e, 0x27, 0x2b, 0x06, 0x24, 0x1d, 0x0f, ++ 0x41, 0x19, 0x10, 0x01, 0x41, 0x53, 0x1d, 0x45, 0x0e, 0x07, 0x1e, 0x08, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x5d, 0x07, 0x48, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4e, 0x40, 0x40, 0x40, 0x4e, 0x33, ++ 0x07, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0f, 0x0f, 0x05, ++ 0x48, 0x1d, 0x0f, 0x01, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x07, 0x0d, 0x0d, 0x0e, 0x06, ++ 0x40, 0x07, 0x06, 0x49, 0x40, 0x15, 0x05, 0x58, 0x49, 0x05, 0x24, 0x1d, 0x16, 0x33, 0x0d, 0x0d, ++ 0x0e, 0x06, 0x40, 0x07, 0x06, 0x49, 0x40, 0x15, 0x05, 0x58, 0x49, 0x05, 0x24, 0x1d, 0x16, 0x33, ++ 0x35, 0x57, 0x2f, 0x48, 0x05, 0x05, 0x06, 0x0d, 0x0d, 0x1d, 0x0e, 0x1d, 0x0e, 0x25, 0x06, 0x48, ++ 0x19, 0x07, 0x06, 0x25, 0x06, 0x48, 0x19, 0x07, 0x06, 0x25, 0x06, 0x48, 0x19, 0x07, 0x06, 0x40, ++ 0x07, 0x01, 0x01, 0x0f, 0x1f, 0x0f, 0x1f, 0x07, 0x1f, 0x07, 0x05, 0x1f, 0x07, 0x05, 0x40, 0x40, ++ 0x40, 0x2d, 0x17, 0x0f, 0x40, 0x0f, 0x0f, 0x07, 0x07, 0x3e, 0x27, 0x2d, 0x07, 0x25, 0x1e, 0x0f, ++ 0x40, 0x19, 0x10, 0x01, 0x40, 0x54, 0x1e, 0x45, 0x0f, 0x07, 0x1f, 0x08, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x5e, 0x07, 0x48, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4f, 0x40, 0x40, 0x40, 0x4f, 0x35, ++ 0x07, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0f, 0x0f, 0x06, ++ 0x48, 0x1e, 0x0f, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x07, 0x0e, 0x0e, 0x0f, 0x07, ++ 0x40, 0x07, 0x07, 0x48, 0x40, 0x16, 0x06, 0x58, 0x48, 0x06, 0x26, 0x1e, 0x17, 0x35, 0x0e, 0x0e, ++ 0x0f, 0x07, 0x40, 0x07, 0x07, 0x48, 0x40, 0x16, 0x06, 0x58, 0x48, 0x06, 0x26, 0x1e, 0x17, 0x35, ++ 0x36, 0x57, 0x2f, 0x48, 0x06, 0x06, 0x07, 0x0e, 0x0e, 0x1e, 0x0f, 0x1e, 0x0f, 0x26, 0x07, 0x48, ++ 0x18, 0x07, 0x07, 0x26, 0x07, 0x48, 0x18, 0x07, 0x07, 0x26, 0x07, 0x48, 0x18, 0x07, 0x07, 0x40, ++ 0x07, 0x00, 0x00, 0x0f, 0x1f, 0x0f, 0x1f, 0x07, 0x1f, 0x07, 0x06, 0x1f, 0x07, 0x06, 0x40, 0x40, ++ 0x40, 0x2e, 0x17, 0x0f, 0x40, 0x0f, 0x0f, 0x07, 0x07, 0x3e, 0x27, 0x2e, 0x07, 0x26, 0x1f, 0x0f, ++ 0x40, 0x18, 0x10, 0x00, 0x40, 0x56, 0x1f, 0x46, 0x0f, 0x07, 0x1f, 0x08, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x5f, 0x07, 0x48, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4f, 0x40, 0x40, 0x40, 0x4f, 0x37, ++ 0x07, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0f, 0x0f, 0x07, ++ 0x48, 0x1f, 0x0f, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x07, 0x0f, 0x0f, 0x0f, 0x07, ++ 0x40, 0x07, 0x07, 0x48, 0x40, 0x17, 0x07, 0x58, 0x48, 0x07, 0x27, 0x1f, 0x17, 0x37, 0x0f, 0x0f, ++ 0x0f, 0x07, 0x40, 0x07, 0x07, 0x48, 0x40, 0x17, 0x07, 0x58, 0x48, 0x07, 0x27, 0x1f, 0x17, 0x37, ++ 0x37, 0x57, 0x2f, 0x48, 0x07, 0x07, 0x07, 0x0f, 0x0f, 0x1f, 0x0f, 0x1f, 0x0f, 0x27, 0x07, 0x48, ++ 0x18, 0x07, 0x07, 0x27, 0x07, 0x48, 0x18, 0x07, 0x07, 0x27, 0x07, 0x48, 0x18, 0x07, 0x07, 0x40, ++ 0x07, 0x00, 0x00, 0x0f, 0x1f, 0x0f, 0x1f, 0x07, 0x1f, 0x07, 0x07, 0x1f, 0x07, 0x07, 0x40, 0x40, ++ 0x40, 0x2f, 0x17, 0x0f, 0x40, 0x0f, 0x0f, 0x07, 0x07, 0x3e, 0x27, 0x2f, 0x07, 0x27, 0x1f, 0x0f, ++ 0x40, 0x18, 0x10, 0x00, 0x40, 0x57, 0x1f, 0x47, 0x0f, 0x07, 0x1f, 0x08, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x07, 0x48, 0x48, 0x60, 0x40, 0x27, 0x07, 0x07, 0x27, 0x40, 0x48, 0x40, 0x40, 0x40, 0x0f, ++ 0x48, 0x68, 0x60, 0x40, 0x68, 0x68, 0x68, 0x68, 0x68, 0x07, 0x07, 0x0f, 0x50, 0x40, 0x60, 0x07, ++ 0x68, 0x27, 0x48, 0x17, 0x40, 0x50, 0x1f, 0x40, 0x40, 0x40, 0x48, 0x48, 0x58, 0x60, 0x60, 0x60, ++ 0x68, 0x68, 0x58, 0x68, 0x60, 0x60, 0x60, 0x68, 0x68, 0x68, 0x60, 0x50, 0x48, 0x50, 0x58, 0x60, ++ 0x60, 0x60, 0x68, 0x68, 0x58, 0x68, 0x60, 0x60, 0x60, 0x68, 0x68, 0x68, 0x60, 0x50, 0x48, 0x50, ++ 0x07, 0x50, 0x58, 0x40, 0x48, 0x40, 0x48, 0x07, 0x48, 0x48, 0x48, 0x68, 0x07, 0x1f, 0x17, 0x50, ++ 0x0f, 0x07, 0x40, 0x1f, 0x17, 0x50, 0x0f, 0x07, 0x40, 0x1f, 0x17, 0x50, 0x0f, 0x07, 0x40, 0x40, ++ 0x07, 0x48, 0x48, 0x48, 0x07, 0x48, 0x07, 0x17, 0x17, 0x17, 0x50, 0x17, 0x17, 0x50, 0x40, 0x40, ++ 0x40, 0x2f, 0x2f, 0x17, 0x40, 0x0f, 0x17, 0x1f, 0x1f, 0x1f, 0x27, 0x0f, 0x07, 0x07, 0x0f, 0x07, ++ 0x07, 0x3e, 0x1f, 0x17, 0x40, 0x17, 0x07, 0x1f, 0x48, 0x17, 0x48, 0x40, 0x48, 0x17, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x07, 0x47, 0x47, 0x5f, 0x40, 0x27, 0x07, 0x07, 0x27, 0x40, 0x47, 0x40, 0x40, 0x40, 0x0f, ++ 0x47, 0x66, 0x5f, 0x00, 0x66, 0x66, 0x66, 0x65, 0x65, 0x07, 0x07, 0x0f, 0x4f, 0x00, 0x5e, 0x07, ++ 0x67, 0x27, 0x47, 0x17, 0x40, 0x4f, 0x1f, 0x40, 0x40, 0x40, 0x47, 0x47, 0x57, 0x5f, 0x5e, 0x5f, ++ 0x66, 0x66, 0x57, 0x67, 0x5f, 0x5e, 0x5f, 0x67, 0x67, 0x66, 0x5e, 0x4f, 0x47, 0x4f, 0x57, 0x5f, ++ 0x5e, 0x5f, 0x66, 0x66, 0x57, 0x67, 0x5f, 0x5e, 0x5f, 0x67, 0x67, 0x66, 0x5e, 0x4f, 0x47, 0x4f, ++ 0x08, 0x4f, 0x56, 0x40, 0x48, 0x40, 0x47, 0x07, 0x47, 0x47, 0x47, 0x66, 0x07, 0x1f, 0x17, 0x4f, ++ 0x10, 0x07, 0x40, 0x1f, 0x17, 0x4f, 0x10, 0x07, 0x40, 0x1f, 0x17, 0x4f, 0x10, 0x07, 0x40, 0x40, ++ 0x07, 0x47, 0x47, 0x47, 0x08, 0x47, 0x08, 0x17, 0x17, 0x17, 0x4f, 0x17, 0x17, 0x4f, 0x40, 0x40, ++ 0x40, 0x2f, 0x2f, 0x17, 0x40, 0x0f, 0x17, 0x1f, 0x1f, 0x20, 0x27, 0x10, 0x07, 0x08, 0x10, 0x08, ++ 0x07, 0x3e, 0x1f, 0x17, 0x40, 0x17, 0x08, 0x1f, 0x47, 0x17, 0x46, 0x00, 0x47, 0x17, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x06, 0x46, 0x47, 0x5e, 0x40, 0x26, 0x06, 0x06, 0x27, 0x40, 0x47, 0x40, 0x40, 0x40, 0x0f, ++ 0x47, 0x64, 0x5e, 0x01, 0x65, 0x64, 0x64, 0x63, 0x63, 0x07, 0x07, 0x0f, 0x4e, 0x00, 0x5d, 0x07, ++ 0x66, 0x27, 0x46, 0x17, 0x40, 0x4f, 0x1e, 0x40, 0x40, 0x40, 0x47, 0x47, 0x56, 0x5e, 0x5d, 0x5e, ++ 0x65, 0x64, 0x56, 0x66, 0x5e, 0x5c, 0x5e, 0x66, 0x66, 0x65, 0x5d, 0x4e, 0x46, 0x4e, 0x56, 0x5e, ++ 0x5d, 0x5e, 0x65, 0x64, 0x56, 0x66, 0x5e, 0x5c, 0x5e, 0x66, 0x66, 0x65, 0x5d, 0x4e, 0x46, 0x4e, ++ 0x09, 0x4f, 0x54, 0x40, 0x48, 0x40, 0x47, 0x07, 0x47, 0x46, 0x46, 0x64, 0x07, 0x1f, 0x16, 0x4f, ++ 0x10, 0x07, 0x40, 0x1f, 0x16, 0x4f, 0x10, 0x07, 0x40, 0x1f, 0x16, 0x4f, 0x10, 0x07, 0x40, 0x40, ++ 0x07, 0x46, 0x46, 0x46, 0x09, 0x46, 0x09, 0x17, 0x17, 0x16, 0x4f, 0x17, 0x16, 0x4f, 0x40, 0x40, ++ 0x40, 0x2e, 0x2e, 0x17, 0x40, 0x0f, 0x17, 0x1e, 0x1e, 0x20, 0x27, 0x10, 0x07, 0x09, 0x10, 0x08, ++ 0x07, 0x3e, 0x1f, 0x17, 0x40, 0x17, 0x08, 0x1e, 0x46, 0x17, 0x45, 0x01, 0x46, 0x17, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x06, 0x45, 0x47, 0x5e, 0x40, 0x25, 0x06, 0x05, 0x27, 0x40, 0x47, 0x40, 0x40, 0x40, 0x0f, ++ 0x47, 0x63, 0x5d, 0x01, 0x64, 0x63, 0x62, 0x60, 0x60, 0x07, 0x07, 0x0f, 0x4e, 0x00, 0x5c, 0x07, ++ 0x65, 0x27, 0x45, 0x17, 0x40, 0x4f, 0x1d, 0x40, 0x40, 0x40, 0x47, 0x47, 0x56, 0x5d, 0x5c, 0x5d, ++ 0x64, 0x63, 0x56, 0x65, 0x5d, 0x5b, 0x5d, 0x65, 0x65, 0x64, 0x5c, 0x4d, 0x46, 0x4d, 0x56, 0x5d, ++ 0x5c, 0x5d, 0x64, 0x63, 0x56, 0x65, 0x5d, 0x5b, 0x5d, 0x65, 0x65, 0x64, 0x5c, 0x4d, 0x46, 0x4d, ++ 0x09, 0x4f, 0x52, 0x40, 0x48, 0x40, 0x47, 0x07, 0x47, 0x46, 0x46, 0x62, 0x07, 0x1f, 0x16, 0x4f, ++ 0x10, 0x07, 0x40, 0x1f, 0x16, 0x4f, 0x10, 0x07, 0x40, 0x1f, 0x16, 0x4f, 0x10, 0x07, 0x40, 0x40, ++ 0x07, 0x46, 0x46, 0x45, 0x09, 0x45, 0x09, 0x17, 0x17, 0x16, 0x4f, 0x17, 0x16, 0x4f, 0x40, 0x40, ++ 0x40, 0x2d, 0x2d, 0x17, 0x40, 0x0f, 0x17, 0x1e, 0x1e, 0x20, 0x27, 0x10, 0x07, 0x09, 0x10, 0x08, ++ 0x07, 0x3d, 0x1f, 0x17, 0x40, 0x17, 0x08, 0x1e, 0x45, 0x17, 0x44, 0x01, 0x45, 0x17, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x05, 0x44, 0x46, 0x5d, 0x40, 0x24, 0x05, 0x04, 0x27, 0x40, 0x46, 0x40, 0x40, 0x40, 0x0f, ++ 0x46, 0x61, 0x5c, 0x02, 0x63, 0x61, 0x60, 0x5e, 0x5e, 0x07, 0x07, 0x0e, 0x4d, 0x01, 0x5b, 0x07, ++ 0x64, 0x27, 0x44, 0x16, 0x40, 0x4e, 0x1c, 0x40, 0x40, 0x40, 0x46, 0x46, 0x55, 0x5c, 0x5b, 0x5c, ++ 0x63, 0x61, 0x55, 0x64, 0x5c, 0x59, 0x5c, 0x64, 0x64, 0x63, 0x5b, 0x4c, 0x45, 0x4c, 0x55, 0x5c, ++ 0x5b, 0x5c, 0x63, 0x61, 0x55, 0x64, 0x5c, 0x59, 0x5c, 0x64, 0x64, 0x63, 0x5b, 0x4c, 0x45, 0x4c, ++ 0x0a, 0x4e, 0x50, 0x40, 0x48, 0x40, 0x46, 0x07, 0x46, 0x45, 0x45, 0x60, 0x07, 0x1e, 0x15, 0x4e, ++ 0x11, 0x07, 0x40, 0x1e, 0x15, 0x4e, 0x11, 0x07, 0x40, 0x1e, 0x15, 0x4e, 0x11, 0x07, 0x40, 0x41, ++ 0x07, 0x45, 0x45, 0x44, 0x0a, 0x44, 0x0a, 0x16, 0x17, 0x15, 0x4e, 0x17, 0x15, 0x4e, 0x40, 0x40, ++ 0x40, 0x2c, 0x2c, 0x16, 0x40, 0x0f, 0x16, 0x1d, 0x1d, 0x21, 0x27, 0x11, 0x07, 0x0a, 0x11, 0x09, ++ 0x06, 0x3c, 0x1e, 0x16, 0x40, 0x16, 0x09, 0x1d, 0x44, 0x16, 0x43, 0x02, 0x44, 0x16, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x04, 0x43, 0x46, 0x5c, 0x40, 0x23, 0x04, 0x03, 0x27, 0x40, 0x46, 0x40, 0x40, 0x40, 0x0f, ++ 0x46, 0x60, 0x5b, 0x03, 0x61, 0x60, 0x5e, 0x5b, 0x5b, 0x07, 0x07, 0x0e, 0x4c, 0x01, 0x59, 0x07, ++ 0x63, 0x27, 0x43, 0x16, 0x40, 0x4e, 0x1b, 0x40, 0x40, 0x40, 0x46, 0x46, 0x54, 0x5b, 0x59, 0x5b, ++ 0x61, 0x60, 0x54, 0x63, 0x5b, 0x58, 0x5b, 0x63, 0x63, 0x61, 0x59, 0x4b, 0x44, 0x4b, 0x54, 0x5b, ++ 0x59, 0x5b, 0x61, 0x60, 0x54, 0x63, 0x5b, 0x58, 0x5b, 0x63, 0x63, 0x61, 0x59, 0x4b, 0x44, 0x4b, ++ 0x0b, 0x4e, 0x4e, 0x40, 0x48, 0x40, 0x46, 0x07, 0x46, 0x44, 0x44, 0x5e, 0x07, 0x1e, 0x14, 0x4e, ++ 0x11, 0x07, 0x40, 0x1e, 0x14, 0x4e, 0x11, 0x07, 0x40, 0x1e, 0x14, 0x4e, 0x11, 0x07, 0x40, 0x41, ++ 0x07, 0x44, 0x44, 0x43, 0x0b, 0x43, 0x0b, 0x16, 0x17, 0x14, 0x4e, 0x17, 0x14, 0x4e, 0x40, 0x40, ++ 0x40, 0x2b, 0x2b, 0x16, 0x40, 0x0f, 0x16, 0x1c, 0x1c, 0x21, 0x27, 0x11, 0x07, 0x0b, 0x11, 0x09, ++ 0x06, 0x3b, 0x1e, 0x16, 0x40, 0x16, 0x09, 0x1c, 0x43, 0x16, 0x41, 0x03, 0x43, 0x16, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x04, 0x42, 0x46, 0x5c, 0x40, 0x22, 0x04, 0x02, 0x27, 0x40, 0x46, 0x40, 0x40, 0x40, 0x0f, ++ 0x46, 0x5e, 0x5a, 0x03, 0x60, 0x5e, 0x5c, 0x59, 0x59, 0x07, 0x07, 0x0e, 0x4c, 0x01, 0x58, 0x07, ++ 0x62, 0x27, 0x42, 0x16, 0x40, 0x4e, 0x1a, 0x40, 0x40, 0x40, 0x46, 0x46, 0x54, 0x5a, 0x58, 0x5a, ++ 0x60, 0x5e, 0x54, 0x62, 0x5a, 0x56, 0x5a, 0x62, 0x62, 0x60, 0x58, 0x4a, 0x44, 0x4a, 0x54, 0x5a, ++ 0x58, 0x5a, 0x60, 0x5e, 0x54, 0x62, 0x5a, 0x56, 0x5a, 0x62, 0x62, 0x60, 0x58, 0x4a, 0x44, 0x4a, ++ 0x0b, 0x4e, 0x4c, 0x40, 0x48, 0x40, 0x46, 0x07, 0x46, 0x44, 0x44, 0x5c, 0x07, 0x1e, 0x14, 0x4e, ++ 0x11, 0x07, 0x40, 0x1e, 0x14, 0x4e, 0x11, 0x07, 0x40, 0x1e, 0x14, 0x4e, 0x11, 0x07, 0x40, 0x41, ++ 0x07, 0x44, 0x44, 0x42, 0x0b, 0x42, 0x0b, 0x16, 0x17, 0x14, 0x4e, 0x17, 0x14, 0x4e, 0x40, 0x40, ++ 0x40, 0x2a, 0x2a, 0x16, 0x40, 0x0f, 0x16, 0x1c, 0x1c, 0x21, 0x27, 0x11, 0x07, 0x0b, 0x11, 0x09, ++ 0x06, 0x3a, 0x1e, 0x16, 0x40, 0x16, 0x09, 0x1c, 0x42, 0x16, 0x40, 0x03, 0x42, 0x16, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x03, 0x41, 0x45, 0x5b, 0x40, 0x21, 0x03, 0x01, 0x27, 0x40, 0x45, 0x40, 0x40, 0x40, 0x0f, ++ 0x45, 0x5d, 0x59, 0x04, 0x5f, 0x5d, 0x5a, 0x56, 0x56, 0x07, 0x07, 0x0d, 0x4b, 0x02, 0x57, 0x07, ++ 0x61, 0x27, 0x41, 0x15, 0x40, 0x4d, 0x19, 0x40, 0x40, 0x40, 0x45, 0x45, 0x53, 0x59, 0x57, 0x59, ++ 0x5f, 0x5d, 0x53, 0x61, 0x59, 0x55, 0x59, 0x61, 0x61, 0x5f, 0x57, 0x49, 0x43, 0x49, 0x53, 0x59, ++ 0x57, 0x59, 0x5f, 0x5d, 0x53, 0x61, 0x59, 0x55, 0x59, 0x61, 0x61, 0x5f, 0x57, 0x49, 0x43, 0x49, ++ 0x0c, 0x4d, 0x4a, 0x40, 0x48, 0x40, 0x45, 0x07, 0x45, 0x43, 0x43, 0x5a, 0x07, 0x1d, 0x13, 0x4d, ++ 0x12, 0x07, 0x40, 0x1d, 0x13, 0x4d, 0x12, 0x07, 0x40, 0x1d, 0x13, 0x4d, 0x12, 0x07, 0x40, 0x42, ++ 0x07, 0x43, 0x43, 0x41, 0x0c, 0x41, 0x0c, 0x15, 0x17, 0x13, 0x4d, 0x17, 0x13, 0x4d, 0x40, 0x40, ++ 0x40, 0x29, 0x29, 0x15, 0x40, 0x0f, 0x15, 0x1b, 0x1b, 0x22, 0x27, 0x12, 0x07, 0x0c, 0x12, 0x0a, ++ 0x05, 0x39, 0x1d, 0x15, 0x40, 0x15, 0x0a, 0x1b, 0x41, 0x15, 0x00, 0x04, 0x41, 0x15, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x02, 0x40, 0x45, 0x5b, 0x40, 0x20, 0x02, 0x00, 0x27, 0x40, 0x45, 0x40, 0x40, 0x40, 0x0f, ++ 0x45, 0x5b, 0x58, 0x04, 0x5e, 0x5b, 0x59, 0x54, 0x54, 0x07, 0x07, 0x0d, 0x4b, 0x02, 0x56, 0x07, ++ 0x60, 0x27, 0x40, 0x15, 0x40, 0x4d, 0x18, 0x40, 0x40, 0x40, 0x45, 0x45, 0x53, 0x58, 0x56, 0x58, ++ 0x5e, 0x5b, 0x53, 0x60, 0x58, 0x53, 0x58, 0x60, 0x60, 0x5e, 0x56, 0x48, 0x43, 0x48, 0x53, 0x58, ++ 0x56, 0x58, 0x5e, 0x5b, 0x53, 0x60, 0x58, 0x53, 0x58, 0x60, 0x60, 0x5e, 0x56, 0x48, 0x43, 0x48, ++ 0x0c, 0x4d, 0x49, 0x40, 0x48, 0x40, 0x45, 0x07, 0x45, 0x43, 0x43, 0x59, 0x07, 0x1d, 0x12, 0x4d, ++ 0x12, 0x07, 0x40, 0x1d, 0x12, 0x4d, 0x12, 0x07, 0x40, 0x1d, 0x12, 0x4d, 0x12, 0x07, 0x40, 0x42, ++ 0x07, 0x43, 0x43, 0x40, 0x0c, 0x40, 0x0c, 0x15, 0x17, 0x12, 0x4d, 0x17, 0x12, 0x4d, 0x40, 0x40, ++ 0x40, 0x28, 0x28, 0x15, 0x40, 0x0f, 0x15, 0x1a, 0x1a, 0x22, 0x27, 0x12, 0x07, 0x0c, 0x12, 0x0a, ++ 0x05, 0x38, 0x1d, 0x15, 0x40, 0x15, 0x0a, 0x1a, 0x40, 0x15, 0x01, 0x04, 0x40, 0x15, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x02, 0x00, 0x45, 0x5a, 0x40, 0x1f, 0x02, 0x40, 0x27, 0x40, 0x45, 0x40, 0x40, 0x40, 0x0f, ++ 0x45, 0x59, 0x57, 0x05, 0x5c, 0x59, 0x57, 0x51, 0x51, 0x07, 0x07, 0x0d, 0x4a, 0x02, 0x54, 0x07, ++ 0x5f, 0x27, 0x00, 0x15, 0x40, 0x4d, 0x17, 0x40, 0x40, 0x40, 0x45, 0x45, 0x52, 0x57, 0x54, 0x57, ++ 0x5c, 0x59, 0x52, 0x5f, 0x57, 0x51, 0x57, 0x5f, 0x5f, 0x5c, 0x54, 0x47, 0x42, 0x47, 0x52, 0x57, ++ 0x54, 0x57, 0x5c, 0x59, 0x52, 0x5f, 0x57, 0x51, 0x57, 0x5f, 0x5f, 0x5c, 0x54, 0x47, 0x42, 0x47, ++ 0x0d, 0x4d, 0x47, 0x40, 0x48, 0x40, 0x45, 0x07, 0x45, 0x42, 0x42, 0x57, 0x07, 0x1d, 0x12, 0x4d, ++ 0x12, 0x07, 0x40, 0x1d, 0x12, 0x4d, 0x12, 0x07, 0x40, 0x1d, 0x12, 0x4d, 0x12, 0x07, 0x40, 0x42, ++ 0x07, 0x42, 0x42, 0x00, 0x0d, 0x00, 0x0d, 0x15, 0x17, 0x12, 0x4d, 0x17, 0x12, 0x4d, 0x40, 0x40, ++ 0x40, 0x27, 0x27, 0x15, 0x40, 0x0f, 0x15, 0x1a, 0x1a, 0x22, 0x27, 0x12, 0x07, 0x0d, 0x12, 0x0a, ++ 0x05, 0x37, 0x1d, 0x15, 0x40, 0x15, 0x0a, 0x1a, 0x00, 0x15, 0x03, 0x05, 0x00, 0x15, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x01, 0x01, 0x44, 0x59, 0x40, 0x1e, 0x01, 0x41, 0x27, 0x40, 0x44, 0x40, 0x40, 0x40, 0x0f, ++ 0x44, 0x58, 0x56, 0x06, 0x5b, 0x58, 0x55, 0x4f, 0x4f, 0x07, 0x07, 0x0c, 0x49, 0x03, 0x53, 0x07, ++ 0x5e, 0x27, 0x01, 0x14, 0x40, 0x4c, 0x16, 0x40, 0x40, 0x40, 0x44, 0x44, 0x51, 0x56, 0x53, 0x56, ++ 0x5b, 0x58, 0x51, 0x5e, 0x56, 0x50, 0x56, 0x5e, 0x5e, 0x5b, 0x53, 0x46, 0x41, 0x46, 0x51, 0x56, ++ 0x53, 0x56, 0x5b, 0x58, 0x51, 0x5e, 0x56, 0x50, 0x56, 0x5e, 0x5e, 0x5b, 0x53, 0x46, 0x41, 0x46, ++ 0x0e, 0x4c, 0x45, 0x40, 0x48, 0x40, 0x44, 0x07, 0x44, 0x41, 0x41, 0x55, 0x07, 0x1c, 0x11, 0x4c, ++ 0x13, 0x07, 0x40, 0x1c, 0x11, 0x4c, 0x13, 0x07, 0x40, 0x1c, 0x11, 0x4c, 0x13, 0x07, 0x40, 0x43, ++ 0x07, 0x41, 0x41, 0x01, 0x0e, 0x01, 0x0e, 0x14, 0x17, 0x11, 0x4c, 0x17, 0x11, 0x4c, 0x40, 0x40, ++ 0x40, 0x26, 0x26, 0x14, 0x40, 0x0f, 0x14, 0x19, 0x19, 0x23, 0x27, 0x13, 0x07, 0x0e, 0x13, 0x0b, ++ 0x04, 0x36, 0x1c, 0x14, 0x40, 0x14, 0x0b, 0x19, 0x01, 0x14, 0x04, 0x06, 0x01, 0x14, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x01, 0x02, 0x44, 0x59, 0x40, 0x1d, 0x01, 0x42, 0x27, 0x40, 0x44, 0x40, 0x40, 0x40, 0x0f, ++ 0x44, 0x56, 0x55, 0x06, 0x5a, 0x56, 0x53, 0x4c, 0x4c, 0x07, 0x07, 0x0c, 0x49, 0x03, 0x52, 0x07, ++ 0x5d, 0x27, 0x02, 0x14, 0x40, 0x4c, 0x15, 0x40, 0x40, 0x40, 0x44, 0x44, 0x51, 0x55, 0x52, 0x55, ++ 0x5a, 0x56, 0x51, 0x5d, 0x55, 0x4e, 0x55, 0x5d, 0x5d, 0x5a, 0x52, 0x45, 0x41, 0x45, 0x51, 0x55, ++ 0x52, 0x55, 0x5a, 0x56, 0x51, 0x5d, 0x55, 0x4e, 0x55, 0x5d, 0x5d, 0x5a, 0x52, 0x45, 0x41, 0x45, ++ 0x0e, 0x4c, 0x43, 0x40, 0x48, 0x40, 0x44, 0x07, 0x44, 0x41, 0x41, 0x53, 0x07, 0x1c, 0x11, 0x4c, ++ 0x13, 0x07, 0x40, 0x1c, 0x11, 0x4c, 0x13, 0x07, 0x40, 0x1c, 0x11, 0x4c, 0x13, 0x07, 0x40, 0x43, ++ 0x07, 0x41, 0x41, 0x02, 0x0e, 0x02, 0x0e, 0x14, 0x17, 0x11, 0x4c, 0x17, 0x11, 0x4c, 0x40, 0x40, ++ 0x40, 0x25, 0x25, 0x14, 0x40, 0x0f, 0x14, 0x19, 0x19, 0x23, 0x27, 0x13, 0x07, 0x0e, 0x13, 0x0b, ++ 0x04, 0x35, 0x1c, 0x14, 0x40, 0x14, 0x0b, 0x19, 0x02, 0x14, 0x05, 0x06, 0x02, 0x14, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x00, 0x03, 0x44, 0x58, 0x40, 0x1c, 0x00, 0x43, 0x27, 0x40, 0x44, 0x40, 0x40, 0x40, 0x0f, ++ 0x44, 0x55, 0x54, 0x07, 0x59, 0x55, 0x51, 0x4a, 0x4a, 0x07, 0x07, 0x0c, 0x48, 0x03, 0x51, 0x07, ++ 0x5c, 0x27, 0x03, 0x14, 0x40, 0x4c, 0x14, 0x40, 0x40, 0x40, 0x44, 0x44, 0x50, 0x54, 0x51, 0x54, ++ 0x59, 0x55, 0x50, 0x5c, 0x54, 0x4d, 0x54, 0x5c, 0x5c, 0x59, 0x51, 0x44, 0x40, 0x44, 0x50, 0x54, ++ 0x51, 0x54, 0x59, 0x55, 0x50, 0x5c, 0x54, 0x4d, 0x54, 0x5c, 0x5c, 0x59, 0x51, 0x44, 0x40, 0x44, ++ 0x0f, 0x4c, 0x41, 0x40, 0x48, 0x40, 0x44, 0x07, 0x44, 0x40, 0x40, 0x51, 0x07, 0x1c, 0x10, 0x4c, ++ 0x13, 0x07, 0x40, 0x1c, 0x10, 0x4c, 0x13, 0x07, 0x40, 0x1c, 0x10, 0x4c, 0x13, 0x07, 0x40, 0x43, ++ 0x07, 0x40, 0x40, 0x03, 0x0f, 0x03, 0x0f, 0x14, 0x17, 0x10, 0x4c, 0x17, 0x10, 0x4c, 0x40, 0x40, ++ 0x40, 0x24, 0x24, 0x14, 0x40, 0x0f, 0x14, 0x18, 0x18, 0x23, 0x27, 0x13, 0x07, 0x0f, 0x13, 0x0b, ++ 0x04, 0x34, 0x1c, 0x14, 0x40, 0x14, 0x0b, 0x18, 0x03, 0x14, 0x06, 0x07, 0x03, 0x14, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x40, 0x04, 0x43, 0x57, 0x40, 0x1b, 0x40, 0x44, 0x27, 0x40, 0x43, 0x40, 0x40, 0x40, 0x0f, ++ 0x43, 0x53, 0x53, 0x08, 0x57, 0x53, 0x4f, 0x47, 0x47, 0x07, 0x07, 0x0b, 0x47, 0x04, 0x4f, 0x07, ++ 0x5b, 0x27, 0x04, 0x13, 0x40, 0x4b, 0x13, 0x40, 0x40, 0x40, 0x43, 0x43, 0x4f, 0x53, 0x4f, 0x53, ++ 0x57, 0x53, 0x4f, 0x5b, 0x53, 0x4b, 0x53, 0x5b, 0x5b, 0x57, 0x4f, 0x43, 0x00, 0x43, 0x4f, 0x53, ++ 0x4f, 0x53, 0x57, 0x53, 0x4f, 0x5b, 0x53, 0x4b, 0x53, 0x5b, 0x5b, 0x57, 0x4f, 0x43, 0x00, 0x43, ++ 0x10, 0x4b, 0x00, 0x40, 0x48, 0x40, 0x43, 0x07, 0x43, 0x00, 0x00, 0x4f, 0x07, 0x1b, 0x0f, 0x4b, ++ 0x14, 0x07, 0x40, 0x1b, 0x0f, 0x4b, 0x14, 0x07, 0x40, 0x1b, 0x0f, 0x4b, 0x14, 0x07, 0x40, 0x44, ++ 0x07, 0x00, 0x00, 0x04, 0x10, 0x04, 0x10, 0x13, 0x17, 0x0f, 0x4b, 0x17, 0x0f, 0x4b, 0x40, 0x40, ++ 0x40, 0x23, 0x23, 0x13, 0x40, 0x0f, 0x13, 0x17, 0x17, 0x24, 0x27, 0x14, 0x07, 0x10, 0x14, 0x0c, ++ 0x03, 0x33, 0x1b, 0x13, 0x40, 0x13, 0x0c, 0x17, 0x04, 0x13, 0x08, 0x08, 0x04, 0x13, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x40, 0x05, 0x43, 0x57, 0x40, 0x1a, 0x40, 0x45, 0x27, 0x40, 0x43, 0x40, 0x40, 0x40, 0x0f, ++ 0x43, 0x52, 0x52, 0x08, 0x56, 0x52, 0x4d, 0x45, 0x45, 0x07, 0x07, 0x0b, 0x47, 0x04, 0x4e, 0x07, ++ 0x5a, 0x27, 0x05, 0x13, 0x40, 0x4b, 0x12, 0x40, 0x40, 0x40, 0x43, 0x43, 0x4f, 0x52, 0x4e, 0x52, ++ 0x56, 0x52, 0x4f, 0x5a, 0x52, 0x4a, 0x52, 0x5a, 0x5a, 0x56, 0x4e, 0x42, 0x00, 0x42, 0x4f, 0x52, ++ 0x4e, 0x52, 0x56, 0x52, 0x4f, 0x5a, 0x52, 0x4a, 0x52, 0x5a, 0x5a, 0x56, 0x4e, 0x42, 0x00, 0x42, ++ 0x10, 0x4b, 0x02, 0x40, 0x48, 0x40, 0x43, 0x07, 0x43, 0x00, 0x00, 0x4d, 0x07, 0x1b, 0x0f, 0x4b, ++ 0x14, 0x07, 0x40, 0x1b, 0x0f, 0x4b, 0x14, 0x07, 0x40, 0x1b, 0x0f, 0x4b, 0x14, 0x07, 0x40, 0x44, ++ 0x07, 0x00, 0x00, 0x05, 0x10, 0x05, 0x10, 0x13, 0x17, 0x0f, 0x4b, 0x17, 0x0f, 0x4b, 0x40, 0x40, ++ 0x40, 0x22, 0x22, 0x13, 0x40, 0x0f, 0x13, 0x17, 0x17, 0x24, 0x27, 0x14, 0x07, 0x10, 0x14, 0x0c, ++ 0x03, 0x32, 0x1b, 0x13, 0x40, 0x13, 0x0c, 0x17, 0x05, 0x13, 0x09, 0x08, 0x05, 0x13, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x41, 0x06, 0x43, 0x56, 0x40, 0x19, 0x41, 0x46, 0x27, 0x40, 0x43, 0x40, 0x40, 0x40, 0x0f, ++ 0x43, 0x50, 0x51, 0x09, 0x55, 0x50, 0x4b, 0x42, 0x42, 0x07, 0x07, 0x0b, 0x46, 0x04, 0x4d, 0x07, ++ 0x59, 0x27, 0x06, 0x13, 0x40, 0x4b, 0x11, 0x40, 0x40, 0x40, 0x43, 0x43, 0x4e, 0x51, 0x4d, 0x51, ++ 0x55, 0x50, 0x4e, 0x59, 0x51, 0x48, 0x51, 0x59, 0x59, 0x55, 0x4d, 0x41, 0x01, 0x41, 0x4e, 0x51, ++ 0x4d, 0x51, 0x55, 0x50, 0x4e, 0x59, 0x51, 0x48, 0x51, 0x59, 0x59, 0x55, 0x4d, 0x41, 0x01, 0x41, ++ 0x11, 0x4b, 0x04, 0x40, 0x48, 0x40, 0x43, 0x07, 0x43, 0x01, 0x01, 0x4b, 0x07, 0x1b, 0x0e, 0x4b, ++ 0x14, 0x07, 0x40, 0x1b, 0x0e, 0x4b, 0x14, 0x07, 0x40, 0x1b, 0x0e, 0x4b, 0x14, 0x07, 0x40, 0x44, ++ 0x07, 0x01, 0x01, 0x06, 0x11, 0x06, 0x11, 0x13, 0x17, 0x0e, 0x4b, 0x17, 0x0e, 0x4b, 0x40, 0x40, ++ 0x40, 0x21, 0x21, 0x13, 0x40, 0x0f, 0x13, 0x16, 0x16, 0x24, 0x27, 0x14, 0x07, 0x11, 0x14, 0x0c, ++ 0x03, 0x31, 0x1b, 0x13, 0x40, 0x13, 0x0c, 0x16, 0x06, 0x13, 0x0a, 0x09, 0x06, 0x13, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x42, 0x06, 0x43, 0x56, 0x40, 0x18, 0x42, 0x47, 0x27, 0x40, 0x43, 0x40, 0x40, 0x40, 0x0f, ++ 0x43, 0x4f, 0x51, 0x09, 0x54, 0x4f, 0x4a, 0x40, 0x40, 0x07, 0x07, 0x0a, 0x46, 0x04, 0x4c, 0x07, ++ 0x59, 0x27, 0x06, 0x12, 0x40, 0x4b, 0x10, 0x40, 0x40, 0x40, 0x43, 0x43, 0x4e, 0x51, 0x4c, 0x51, ++ 0x54, 0x4f, 0x4e, 0x59, 0x51, 0x47, 0x51, 0x59, 0x59, 0x54, 0x4c, 0x41, 0x01, 0x41, 0x4e, 0x51, ++ 0x4c, 0x51, 0x54, 0x4f, 0x4e, 0x59, 0x51, 0x47, 0x51, 0x59, 0x59, 0x54, 0x4c, 0x41, 0x01, 0x41, ++ 0x11, 0x4b, 0x05, 0x40, 0x48, 0x40, 0x43, 0x07, 0x43, 0x01, 0x01, 0x4a, 0x07, 0x1a, 0x0d, 0x4b, ++ 0x14, 0x07, 0x40, 0x1a, 0x0d, 0x4b, 0x14, 0x07, 0x40, 0x1a, 0x0d, 0x4b, 0x14, 0x07, 0x40, 0x45, ++ 0x07, 0x01, 0x01, 0x06, 0x11, 0x06, 0x11, 0x12, 0x17, 0x0d, 0x4b, 0x17, 0x0d, 0x4b, 0x40, 0x40, ++ 0x40, 0x20, 0x20, 0x12, 0x40, 0x0f, 0x12, 0x15, 0x15, 0x24, 0x27, 0x14, 0x07, 0x11, 0x14, 0x0c, ++ 0x02, 0x30, 0x1a, 0x12, 0x40, 0x12, 0x0c, 0x15, 0x06, 0x12, 0x0b, 0x09, 0x06, 0x12, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x42, 0x07, 0x42, 0x55, 0x40, 0x18, 0x42, 0x47, 0x27, 0x40, 0x42, 0x40, 0x40, 0x40, 0x0f, ++ 0x42, 0x4d, 0x50, 0x0a, 0x52, 0x4d, 0x48, 0x02, 0x02, 0x07, 0x07, 0x0a, 0x45, 0x05, 0x4a, 0x07, ++ 0x58, 0x27, 0x07, 0x12, 0x40, 0x4a, 0x10, 0x40, 0x40, 0x40, 0x42, 0x42, 0x4d, 0x50, 0x4a, 0x50, ++ 0x52, 0x4d, 0x4d, 0x58, 0x50, 0x45, 0x50, 0x58, 0x58, 0x52, 0x4a, 0x40, 0x02, 0x40, 0x4d, 0x50, ++ 0x4a, 0x50, 0x52, 0x4d, 0x4d, 0x58, 0x50, 0x45, 0x50, 0x58, 0x58, 0x52, 0x4a, 0x40, 0x02, 0x40, ++ 0x12, 0x4a, 0x07, 0x40, 0x48, 0x40, 0x42, 0x07, 0x42, 0x02, 0x02, 0x48, 0x07, 0x1a, 0x0d, 0x4a, ++ 0x15, 0x07, 0x40, 0x1a, 0x0d, 0x4a, 0x15, 0x07, 0x40, 0x1a, 0x0d, 0x4a, 0x15, 0x07, 0x40, 0x45, ++ 0x07, 0x02, 0x02, 0x07, 0x12, 0x07, 0x12, 0x12, 0x17, 0x0d, 0x4a, 0x17, 0x0d, 0x4a, 0x40, 0x40, ++ 0x40, 0x20, 0x20, 0x12, 0x40, 0x0f, 0x12, 0x15, 0x15, 0x25, 0x27, 0x15, 0x07, 0x12, 0x15, 0x0d, ++ 0x02, 0x30, 0x1a, 0x12, 0x40, 0x12, 0x0d, 0x15, 0x07, 0x12, 0x0d, 0x0a, 0x07, 0x12, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x43, 0x08, 0x42, 0x54, 0x40, 0x17, 0x43, 0x48, 0x27, 0x40, 0x42, 0x40, 0x40, 0x40, 0x0f, ++ 0x42, 0x4b, 0x4f, 0x0b, 0x51, 0x4b, 0x46, 0x04, 0x04, 0x07, 0x07, 0x0a, 0x44, 0x05, 0x49, 0x07, ++ 0x57, 0x27, 0x08, 0x12, 0x40, 0x4a, 0x0f, 0x40, 0x40, 0x40, 0x42, 0x42, 0x4c, 0x4f, 0x49, 0x4f, ++ 0x51, 0x4b, 0x4c, 0x57, 0x4f, 0x43, 0x4f, 0x57, 0x57, 0x51, 0x49, 0x00, 0x03, 0x00, 0x4c, 0x4f, ++ 0x49, 0x4f, 0x51, 0x4b, 0x4c, 0x57, 0x4f, 0x43, 0x4f, 0x57, 0x57, 0x51, 0x49, 0x00, 0x03, 0x00, ++ 0x13, 0x4a, 0x09, 0x40, 0x48, 0x40, 0x42, 0x07, 0x42, 0x03, 0x03, 0x46, 0x07, 0x1a, 0x0c, 0x4a, ++ 0x15, 0x07, 0x40, 0x1a, 0x0c, 0x4a, 0x15, 0x07, 0x40, 0x1a, 0x0c, 0x4a, 0x15, 0x07, 0x40, 0x45, ++ 0x07, 0x03, 0x03, 0x08, 0x13, 0x08, 0x13, 0x12, 0x17, 0x0c, 0x4a, 0x17, 0x0c, 0x4a, 0x40, 0x40, ++ 0x40, 0x1f, 0x1f, 0x12, 0x40, 0x0f, 0x12, 0x14, 0x14, 0x25, 0x27, 0x15, 0x07, 0x13, 0x15, 0x0d, ++ 0x02, 0x2f, 0x1a, 0x12, 0x40, 0x12, 0x0d, 0x14, 0x08, 0x12, 0x0e, 0x0b, 0x08, 0x12, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x43, 0x09, 0x42, 0x54, 0x40, 0x16, 0x43, 0x49, 0x27, 0x40, 0x42, 0x40, 0x40, 0x40, 0x0f, ++ 0x42, 0x4a, 0x4e, 0x0b, 0x50, 0x4a, 0x44, 0x07, 0x07, 0x07, 0x07, 0x0a, 0x44, 0x05, 0x48, 0x07, ++ 0x56, 0x27, 0x09, 0x12, 0x40, 0x4a, 0x0e, 0x40, 0x40, 0x40, 0x42, 0x42, 0x4c, 0x4e, 0x48, 0x4e, ++ 0x50, 0x4a, 0x4c, 0x56, 0x4e, 0x42, 0x4e, 0x56, 0x56, 0x50, 0x48, 0x01, 0x03, 0x01, 0x4c, 0x4e, ++ 0x48, 0x4e, 0x50, 0x4a, 0x4c, 0x56, 0x4e, 0x42, 0x4e, 0x56, 0x56, 0x50, 0x48, 0x01, 0x03, 0x01, ++ 0x13, 0x4a, 0x0b, 0x40, 0x48, 0x40, 0x42, 0x07, 0x42, 0x03, 0x03, 0x44, 0x07, 0x1a, 0x0c, 0x4a, ++ 0x15, 0x07, 0x40, 0x1a, 0x0c, 0x4a, 0x15, 0x07, 0x40, 0x1a, 0x0c, 0x4a, 0x15, 0x07, 0x40, 0x45, ++ 0x07, 0x03, 0x03, 0x09, 0x13, 0x09, 0x13, 0x12, 0x17, 0x0c, 0x4a, 0x17, 0x0c, 0x4a, 0x40, 0x40, ++ 0x40, 0x1e, 0x1e, 0x12, 0x40, 0x0f, 0x12, 0x14, 0x14, 0x25, 0x27, 0x15, 0x07, 0x13, 0x15, 0x0d, ++ 0x02, 0x2e, 0x1a, 0x12, 0x40, 0x12, 0x0d, 0x14, 0x09, 0x12, 0x0f, 0x0b, 0x09, 0x12, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x44, 0x0a, 0x41, 0x53, 0x40, 0x15, 0x44, 0x4a, 0x27, 0x40, 0x41, 0x40, 0x40, 0x40, 0x0f, ++ 0x41, 0x48, 0x4d, 0x0c, 0x4f, 0x48, 0x42, 0x09, 0x09, 0x07, 0x07, 0x09, 0x43, 0x06, 0x47, 0x07, ++ 0x55, 0x27, 0x0a, 0x11, 0x40, 0x49, 0x0d, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4b, 0x4d, 0x47, 0x4d, ++ 0x4f, 0x48, 0x4b, 0x55, 0x4d, 0x40, 0x4d, 0x55, 0x55, 0x4f, 0x47, 0x02, 0x04, 0x02, 0x4b, 0x4d, ++ 0x47, 0x4d, 0x4f, 0x48, 0x4b, 0x55, 0x4d, 0x40, 0x4d, 0x55, 0x55, 0x4f, 0x47, 0x02, 0x04, 0x02, ++ 0x14, 0x49, 0x0d, 0x40, 0x48, 0x40, 0x41, 0x07, 0x41, 0x04, 0x04, 0x42, 0x07, 0x19, 0x0b, 0x49, ++ 0x16, 0x07, 0x40, 0x19, 0x0b, 0x49, 0x16, 0x07, 0x40, 0x19, 0x0b, 0x49, 0x16, 0x07, 0x40, 0x46, ++ 0x07, 0x04, 0x04, 0x0a, 0x14, 0x0a, 0x14, 0x11, 0x17, 0x0b, 0x49, 0x17, 0x0b, 0x49, 0x40, 0x40, ++ 0x40, 0x1d, 0x1d, 0x11, 0x40, 0x0f, 0x11, 0x13, 0x13, 0x26, 0x27, 0x16, 0x07, 0x14, 0x16, 0x0e, ++ 0x01, 0x2d, 0x19, 0x11, 0x40, 0x11, 0x0e, 0x13, 0x0a, 0x11, 0x10, 0x0c, 0x0a, 0x11, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x45, 0x0b, 0x41, 0x52, 0x40, 0x14, 0x45, 0x4b, 0x27, 0x40, 0x41, 0x40, 0x40, 0x40, 0x0f, ++ 0x41, 0x47, 0x4c, 0x0d, 0x4d, 0x47, 0x40, 0x0c, 0x0c, 0x07, 0x07, 0x09, 0x42, 0x06, 0x45, 0x07, ++ 0x54, 0x27, 0x0b, 0x11, 0x40, 0x49, 0x0c, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4a, 0x4c, 0x45, 0x4c, ++ 0x4d, 0x47, 0x4a, 0x54, 0x4c, 0x00, 0x4c, 0x54, 0x54, 0x4d, 0x45, 0x03, 0x05, 0x03, 0x4a, 0x4c, ++ 0x45, 0x4c, 0x4d, 0x47, 0x4a, 0x54, 0x4c, 0x00, 0x4c, 0x54, 0x54, 0x4d, 0x45, 0x03, 0x05, 0x03, ++ 0x15, 0x49, 0x0f, 0x40, 0x48, 0x40, 0x41, 0x07, 0x41, 0x05, 0x05, 0x40, 0x07, 0x19, 0x0a, 0x49, ++ 0x16, 0x07, 0x40, 0x19, 0x0a, 0x49, 0x16, 0x07, 0x40, 0x19, 0x0a, 0x49, 0x16, 0x07, 0x40, 0x46, ++ 0x07, 0x05, 0x05, 0x0b, 0x15, 0x0b, 0x15, 0x11, 0x17, 0x0a, 0x49, 0x17, 0x0a, 0x49, 0x40, 0x40, ++ 0x40, 0x1c, 0x1c, 0x11, 0x40, 0x0f, 0x11, 0x12, 0x12, 0x26, 0x27, 0x16, 0x07, 0x15, 0x16, 0x0e, ++ 0x01, 0x2c, 0x19, 0x11, 0x40, 0x11, 0x0e, 0x12, 0x0b, 0x11, 0x12, 0x0d, 0x0b, 0x11, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x45, 0x0c, 0x41, 0x52, 0x40, 0x13, 0x45, 0x4c, 0x27, 0x40, 0x41, 0x40, 0x40, 0x40, 0x0f, ++ 0x41, 0x45, 0x4b, 0x0d, 0x4c, 0x45, 0x01, 0x0e, 0x0e, 0x07, 0x07, 0x09, 0x42, 0x06, 0x44, 0x07, ++ 0x53, 0x27, 0x0c, 0x11, 0x40, 0x49, 0x0b, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4a, 0x4b, 0x44, 0x4b, ++ 0x4c, 0x45, 0x4a, 0x53, 0x4b, 0x02, 0x4b, 0x53, 0x53, 0x4c, 0x44, 0x04, 0x05, 0x04, 0x4a, 0x4b, ++ 0x44, 0x4b, 0x4c, 0x45, 0x4a, 0x53, 0x4b, 0x02, 0x4b, 0x53, 0x53, 0x4c, 0x44, 0x04, 0x05, 0x04, ++ 0x15, 0x49, 0x11, 0x40, 0x48, 0x40, 0x41, 0x07, 0x41, 0x05, 0x05, 0x01, 0x07, 0x19, 0x0a, 0x49, ++ 0x16, 0x07, 0x40, 0x19, 0x0a, 0x49, 0x16, 0x07, 0x40, 0x19, 0x0a, 0x49, 0x16, 0x07, 0x40, 0x46, ++ 0x07, 0x05, 0x05, 0x0c, 0x15, 0x0c, 0x15, 0x11, 0x17, 0x0a, 0x49, 0x17, 0x0a, 0x49, 0x40, 0x40, ++ 0x40, 0x1b, 0x1b, 0x11, 0x40, 0x0f, 0x11, 0x12, 0x12, 0x26, 0x27, 0x16, 0x07, 0x15, 0x16, 0x0e, ++ 0x01, 0x2b, 0x19, 0x11, 0x40, 0x11, 0x0e, 0x12, 0x0c, 0x11, 0x13, 0x0d, 0x0c, 0x11, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x46, 0x0d, 0x40, 0x51, 0x40, 0x12, 0x46, 0x4d, 0x27, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0f, ++ 0x40, 0x44, 0x4a, 0x0e, 0x4b, 0x44, 0x03, 0x11, 0x11, 0x07, 0x07, 0x08, 0x41, 0x07, 0x43, 0x07, ++ 0x52, 0x27, 0x0d, 0x10, 0x40, 0x48, 0x0a, 0x40, 0x40, 0x40, 0x40, 0x40, 0x49, 0x4a, 0x43, 0x4a, ++ 0x4b, 0x44, 0x49, 0x52, 0x4a, 0x03, 0x4a, 0x52, 0x52, 0x4b, 0x43, 0x05, 0x06, 0x05, 0x49, 0x4a, ++ 0x43, 0x4a, 0x4b, 0x44, 0x49, 0x52, 0x4a, 0x03, 0x4a, 0x52, 0x52, 0x4b, 0x43, 0x05, 0x06, 0x05, ++ 0x16, 0x48, 0x13, 0x40, 0x48, 0x40, 0x40, 0x07, 0x40, 0x06, 0x06, 0x03, 0x07, 0x18, 0x09, 0x48, ++ 0x17, 0x07, 0x40, 0x18, 0x09, 0x48, 0x17, 0x07, 0x40, 0x18, 0x09, 0x48, 0x17, 0x07, 0x40, 0x47, ++ 0x07, 0x06, 0x06, 0x0d, 0x16, 0x0d, 0x16, 0x10, 0x17, 0x09, 0x48, 0x17, 0x09, 0x48, 0x40, 0x40, ++ 0x40, 0x1a, 0x1a, 0x10, 0x40, 0x0f, 0x10, 0x11, 0x11, 0x27, 0x27, 0x17, 0x07, 0x16, 0x17, 0x0f, ++ 0x00, 0x2a, 0x18, 0x10, 0x40, 0x10, 0x0f, 0x11, 0x0d, 0x10, 0x14, 0x0e, 0x0d, 0x10, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x47, 0x0e, 0x40, 0x51, 0x40, 0x11, 0x47, 0x4e, 0x27, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0f, ++ 0x40, 0x42, 0x49, 0x0e, 0x4a, 0x42, 0x04, 0x13, 0x13, 0x07, 0x07, 0x08, 0x41, 0x07, 0x42, 0x07, ++ 0x51, 0x27, 0x0e, 0x10, 0x40, 0x48, 0x09, 0x40, 0x40, 0x40, 0x40, 0x40, 0x49, 0x49, 0x42, 0x49, ++ 0x4a, 0x42, 0x49, 0x51, 0x49, 0x05, 0x49, 0x51, 0x51, 0x4a, 0x42, 0x06, 0x06, 0x06, 0x49, 0x49, ++ 0x42, 0x49, 0x4a, 0x42, 0x49, 0x51, 0x49, 0x05, 0x49, 0x51, 0x51, 0x4a, 0x42, 0x06, 0x06, 0x06, ++ 0x16, 0x48, 0x14, 0x40, 0x48, 0x40, 0x40, 0x07, 0x40, 0x06, 0x06, 0x04, 0x07, 0x18, 0x08, 0x48, ++ 0x17, 0x07, 0x40, 0x18, 0x08, 0x48, 0x17, 0x07, 0x40, 0x18, 0x08, 0x48, 0x17, 0x07, 0x40, 0x47, ++ 0x07, 0x06, 0x06, 0x0e, 0x16, 0x0e, 0x16, 0x10, 0x17, 0x08, 0x48, 0x17, 0x08, 0x48, 0x40, 0x40, ++ 0x40, 0x19, 0x19, 0x10, 0x40, 0x0f, 0x10, 0x10, 0x10, 0x27, 0x27, 0x17, 0x07, 0x16, 0x17, 0x0f, ++ 0x00, 0x29, 0x18, 0x10, 0x40, 0x10, 0x0f, 0x10, 0x0e, 0x10, 0x15, 0x0e, 0x0e, 0x10, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x47, 0x0f, 0x40, 0x50, 0x40, 0x10, 0x47, 0x4f, 0x27, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0f, ++ 0x40, 0x40, 0x48, 0x0f, 0x48, 0x40, 0x06, 0x16, 0x16, 0x07, 0x07, 0x08, 0x40, 0x07, 0x40, 0x07, ++ 0x50, 0x27, 0x0f, 0x10, 0x40, 0x48, 0x08, 0x40, 0x40, 0x40, 0x40, 0x40, 0x48, 0x48, 0x40, 0x48, ++ 0x48, 0x40, 0x48, 0x50, 0x48, 0x07, 0x48, 0x50, 0x50, 0x48, 0x40, 0x07, 0x07, 0x07, 0x48, 0x48, ++ 0x40, 0x48, 0x48, 0x40, 0x48, 0x50, 0x48, 0x07, 0x48, 0x50, 0x50, 0x48, 0x40, 0x07, 0x07, 0x07, ++ 0x17, 0x48, 0x16, 0x40, 0x48, 0x40, 0x40, 0x07, 0x40, 0x07, 0x07, 0x06, 0x07, 0x18, 0x08, 0x48, ++ 0x17, 0x07, 0x40, 0x18, 0x08, 0x48, 0x17, 0x07, 0x40, 0x18, 0x08, 0x48, 0x17, 0x07, 0x40, 0x47, ++ 0x07, 0x07, 0x07, 0x0f, 0x17, 0x0f, 0x17, 0x10, 0x17, 0x08, 0x48, 0x17, 0x08, 0x48, 0x40, 0x40, ++ 0x40, 0x18, 0x18, 0x10, 0x40, 0x0f, 0x10, 0x10, 0x10, 0x27, 0x27, 0x17, 0x07, 0x17, 0x17, 0x0f, ++ 0x00, 0x28, 0x18, 0x10, 0x40, 0x10, 0x0f, 0x10, 0x0f, 0x10, 0x17, 0x0f, 0x0f, 0x10, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x48, 0x10, 0x00, 0x4f, 0x40, 0x0f, 0x48, 0x50, 0x27, 0x40, 0x00, 0x40, 0x40, 0x40, 0x0f, ++ 0x00, 0x00, 0x47, 0x10, 0x47, 0x00, 0x08, 0x18, 0x18, 0x07, 0x07, 0x07, 0x00, 0x08, 0x00, 0x07, ++ 0x4f, 0x27, 0x10, 0x0f, 0x40, 0x47, 0x07, 0x40, 0x40, 0x40, 0x00, 0x00, 0x47, 0x47, 0x00, 0x47, ++ 0x47, 0x00, 0x47, 0x4f, 0x47, 0x08, 0x47, 0x4f, 0x4f, 0x47, 0x00, 0x08, 0x08, 0x08, 0x47, 0x47, ++ 0x00, 0x47, 0x47, 0x00, 0x47, 0x4f, 0x47, 0x08, 0x47, 0x4f, 0x4f, 0x47, 0x00, 0x08, 0x08, 0x08, ++ 0x18, 0x47, 0x18, 0x40, 0x48, 0x40, 0x00, 0x07, 0x00, 0x08, 0x08, 0x08, 0x07, 0x17, 0x07, 0x47, ++ 0x18, 0x07, 0x40, 0x17, 0x07, 0x47, 0x18, 0x07, 0x40, 0x17, 0x07, 0x47, 0x18, 0x07, 0x40, 0x48, ++ 0x07, 0x08, 0x08, 0x10, 0x18, 0x10, 0x18, 0x0f, 0x17, 0x07, 0x47, 0x17, 0x07, 0x47, 0x40, 0x40, ++ 0x40, 0x17, 0x17, 0x0f, 0x40, 0x0f, 0x0f, 0x0f, 0x0f, 0x28, 0x27, 0x18, 0x07, 0x18, 0x18, 0x10, ++ 0x40, 0x27, 0x17, 0x0f, 0x40, 0x0f, 0x10, 0x0f, 0x10, 0x0f, 0x18, 0x10, 0x10, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x48, 0x11, 0x00, 0x4f, 0x40, 0x0e, 0x48, 0x51, 0x27, 0x40, 0x00, 0x40, 0x40, 0x40, 0x0f, ++ 0x00, 0x02, 0x46, 0x10, 0x46, 0x02, 0x0a, 0x1b, 0x1b, 0x07, 0x07, 0x07, 0x00, 0x08, 0x01, 0x07, ++ 0x4e, 0x27, 0x11, 0x0f, 0x40, 0x47, 0x06, 0x40, 0x40, 0x40, 0x00, 0x00, 0x47, 0x46, 0x01, 0x46, ++ 0x46, 0x02, 0x47, 0x4e, 0x46, 0x0a, 0x46, 0x4e, 0x4e, 0x46, 0x01, 0x09, 0x08, 0x09, 0x47, 0x46, ++ 0x01, 0x46, 0x46, 0x02, 0x47, 0x4e, 0x46, 0x0a, 0x46, 0x4e, 0x4e, 0x46, 0x01, 0x09, 0x08, 0x09, ++ 0x18, 0x47, 0x1a, 0x40, 0x48, 0x40, 0x00, 0x07, 0x00, 0x08, 0x08, 0x0a, 0x07, 0x17, 0x07, 0x47, ++ 0x18, 0x07, 0x40, 0x17, 0x07, 0x47, 0x18, 0x07, 0x40, 0x17, 0x07, 0x47, 0x18, 0x07, 0x40, 0x48, ++ 0x07, 0x08, 0x08, 0x11, 0x18, 0x11, 0x18, 0x0f, 0x17, 0x07, 0x47, 0x17, 0x07, 0x47, 0x40, 0x40, ++ 0x40, 0x16, 0x16, 0x0f, 0x40, 0x0f, 0x0f, 0x0f, 0x0f, 0x28, 0x27, 0x18, 0x07, 0x18, 0x18, 0x10, ++ 0x40, 0x26, 0x17, 0x0f, 0x40, 0x0f, 0x10, 0x0f, 0x11, 0x0f, 0x19, 0x10, 0x11, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x49, 0x12, 0x00, 0x4e, 0x40, 0x0d, 0x49, 0x52, 0x27, 0x40, 0x00, 0x40, 0x40, 0x40, 0x0f, ++ 0x00, 0x03, 0x45, 0x11, 0x45, 0x03, 0x0c, 0x1d, 0x1d, 0x07, 0x07, 0x07, 0x01, 0x08, 0x02, 0x07, ++ 0x4d, 0x27, 0x12, 0x0f, 0x40, 0x47, 0x05, 0x40, 0x40, 0x40, 0x00, 0x00, 0x46, 0x45, 0x02, 0x45, ++ 0x45, 0x03, 0x46, 0x4d, 0x45, 0x0b, 0x45, 0x4d, 0x4d, 0x45, 0x02, 0x0a, 0x09, 0x0a, 0x46, 0x45, ++ 0x02, 0x45, 0x45, 0x03, 0x46, 0x4d, 0x45, 0x0b, 0x45, 0x4d, 0x4d, 0x45, 0x02, 0x0a, 0x09, 0x0a, ++ 0x19, 0x47, 0x1c, 0x40, 0x48, 0x40, 0x00, 0x07, 0x00, 0x09, 0x09, 0x0c, 0x07, 0x17, 0x06, 0x47, ++ 0x18, 0x07, 0x40, 0x17, 0x06, 0x47, 0x18, 0x07, 0x40, 0x17, 0x06, 0x47, 0x18, 0x07, 0x40, 0x48, ++ 0x07, 0x09, 0x09, 0x12, 0x19, 0x12, 0x19, 0x0f, 0x17, 0x06, 0x47, 0x17, 0x06, 0x47, 0x40, 0x40, ++ 0x40, 0x15, 0x15, 0x0f, 0x40, 0x0f, 0x0f, 0x0e, 0x0e, 0x28, 0x27, 0x18, 0x07, 0x19, 0x18, 0x10, ++ 0x40, 0x25, 0x17, 0x0f, 0x40, 0x0f, 0x10, 0x0e, 0x12, 0x0f, 0x1a, 0x11, 0x12, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4a, 0x13, 0x01, 0x4d, 0x40, 0x0c, 0x4a, 0x53, 0x27, 0x40, 0x01, 0x40, 0x40, 0x40, 0x0f, ++ 0x01, 0x05, 0x44, 0x12, 0x43, 0x05, 0x0e, 0x20, 0x20, 0x07, 0x07, 0x06, 0x02, 0x09, 0x04, 0x07, ++ 0x4c, 0x27, 0x13, 0x0e, 0x40, 0x46, 0x04, 0x40, 0x40, 0x40, 0x01, 0x01, 0x45, 0x44, 0x04, 0x44, ++ 0x43, 0x05, 0x45, 0x4c, 0x44, 0x0d, 0x44, 0x4c, 0x4c, 0x43, 0x04, 0x0b, 0x0a, 0x0b, 0x45, 0x44, ++ 0x04, 0x44, 0x43, 0x05, 0x45, 0x4c, 0x44, 0x0d, 0x44, 0x4c, 0x4c, 0x43, 0x04, 0x0b, 0x0a, 0x0b, ++ 0x1a, 0x46, 0x1e, 0x40, 0x48, 0x40, 0x01, 0x07, 0x01, 0x0a, 0x0a, 0x0e, 0x07, 0x16, 0x05, 0x46, ++ 0x19, 0x07, 0x40, 0x16, 0x05, 0x46, 0x19, 0x07, 0x40, 0x16, 0x05, 0x46, 0x19, 0x07, 0x40, 0x49, ++ 0x07, 0x0a, 0x0a, 0x13, 0x1a, 0x13, 0x1a, 0x0e, 0x17, 0x05, 0x46, 0x17, 0x05, 0x46, 0x40, 0x40, ++ 0x40, 0x14, 0x14, 0x0e, 0x40, 0x0f, 0x0e, 0x0d, 0x0d, 0x29, 0x27, 0x19, 0x07, 0x1a, 0x19, 0x11, ++ 0x41, 0x24, 0x16, 0x0e, 0x40, 0x0e, 0x11, 0x0d, 0x13, 0x0e, 0x1c, 0x12, 0x13, 0x0e, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4a, 0x14, 0x01, 0x4d, 0x40, 0x0b, 0x4a, 0x54, 0x27, 0x40, 0x01, 0x40, 0x40, 0x40, 0x0f, ++ 0x01, 0x06, 0x43, 0x12, 0x42, 0x06, 0x10, 0x22, 0x22, 0x07, 0x07, 0x06, 0x02, 0x09, 0x05, 0x07, ++ 0x4b, 0x27, 0x14, 0x0e, 0x40, 0x46, 0x03, 0x40, 0x40, 0x40, 0x01, 0x01, 0x45, 0x43, 0x05, 0x43, ++ 0x42, 0x06, 0x45, 0x4b, 0x43, 0x0e, 0x43, 0x4b, 0x4b, 0x42, 0x05, 0x0c, 0x0a, 0x0c, 0x45, 0x43, ++ 0x05, 0x43, 0x42, 0x06, 0x45, 0x4b, 0x43, 0x0e, 0x43, 0x4b, 0x4b, 0x42, 0x05, 0x0c, 0x0a, 0x0c, ++ 0x1a, 0x46, 0x20, 0x40, 0x48, 0x40, 0x01, 0x07, 0x01, 0x0a, 0x0a, 0x10, 0x07, 0x16, 0x05, 0x46, ++ 0x19, 0x07, 0x40, 0x16, 0x05, 0x46, 0x19, 0x07, 0x40, 0x16, 0x05, 0x46, 0x19, 0x07, 0x40, 0x49, ++ 0x07, 0x0a, 0x0a, 0x14, 0x1a, 0x14, 0x1a, 0x0e, 0x17, 0x05, 0x46, 0x17, 0x05, 0x46, 0x40, 0x40, ++ 0x40, 0x13, 0x13, 0x0e, 0x40, 0x0f, 0x0e, 0x0d, 0x0d, 0x29, 0x27, 0x19, 0x07, 0x1a, 0x19, 0x11, ++ 0x41, 0x23, 0x16, 0x0e, 0x40, 0x0e, 0x11, 0x0d, 0x14, 0x0e, 0x1d, 0x12, 0x14, 0x0e, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4b, 0x15, 0x01, 0x4c, 0x40, 0x0a, 0x4b, 0x55, 0x27, 0x40, 0x01, 0x40, 0x40, 0x40, 0x0f, ++ 0x01, 0x08, 0x42, 0x13, 0x41, 0x08, 0x12, 0x25, 0x25, 0x07, 0x07, 0x06, 0x03, 0x09, 0x06, 0x07, ++ 0x4a, 0x27, 0x15, 0x0e, 0x40, 0x46, 0x02, 0x40, 0x40, 0x40, 0x01, 0x01, 0x44, 0x42, 0x06, 0x42, ++ 0x41, 0x08, 0x44, 0x4a, 0x42, 0x10, 0x42, 0x4a, 0x4a, 0x41, 0x06, 0x0d, 0x0b, 0x0d, 0x44, 0x42, ++ 0x06, 0x42, 0x41, 0x08, 0x44, 0x4a, 0x42, 0x10, 0x42, 0x4a, 0x4a, 0x41, 0x06, 0x0d, 0x0b, 0x0d, ++ 0x1b, 0x46, 0x22, 0x40, 0x48, 0x40, 0x01, 0x07, 0x01, 0x0b, 0x0b, 0x12, 0x07, 0x16, 0x04, 0x46, ++ 0x19, 0x07, 0x40, 0x16, 0x04, 0x46, 0x19, 0x07, 0x40, 0x16, 0x04, 0x46, 0x19, 0x07, 0x40, 0x49, ++ 0x07, 0x0b, 0x0b, 0x15, 0x1b, 0x15, 0x1b, 0x0e, 0x17, 0x04, 0x46, 0x17, 0x04, 0x46, 0x40, 0x40, ++ 0x40, 0x12, 0x12, 0x0e, 0x40, 0x0f, 0x0e, 0x0c, 0x0c, 0x29, 0x27, 0x19, 0x07, 0x1b, 0x19, 0x11, ++ 0x41, 0x22, 0x16, 0x0e, 0x40, 0x0e, 0x11, 0x0c, 0x15, 0x0e, 0x1e, 0x13, 0x15, 0x0e, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4c, 0x15, 0x01, 0x4c, 0x40, 0x09, 0x4c, 0x56, 0x27, 0x40, 0x01, 0x40, 0x40, 0x40, 0x0f, ++ 0x01, 0x09, 0x42, 0x13, 0x40, 0x09, 0x13, 0x27, 0x27, 0x07, 0x07, 0x05, 0x03, 0x09, 0x07, 0x07, ++ 0x4a, 0x27, 0x15, 0x0d, 0x40, 0x46, 0x01, 0x40, 0x40, 0x40, 0x01, 0x01, 0x44, 0x42, 0x07, 0x42, ++ 0x40, 0x09, 0x44, 0x4a, 0x42, 0x11, 0x42, 0x4a, 0x4a, 0x40, 0x07, 0x0d, 0x0b, 0x0d, 0x44, 0x42, ++ 0x07, 0x42, 0x40, 0x09, 0x44, 0x4a, 0x42, 0x11, 0x42, 0x4a, 0x4a, 0x40, 0x07, 0x0d, 0x0b, 0x0d, ++ 0x1b, 0x46, 0x23, 0x40, 0x48, 0x40, 0x01, 0x07, 0x01, 0x0b, 0x0b, 0x13, 0x07, 0x15, 0x03, 0x46, ++ 0x19, 0x07, 0x40, 0x15, 0x03, 0x46, 0x19, 0x07, 0x40, 0x15, 0x03, 0x46, 0x19, 0x07, 0x40, 0x4a, ++ 0x07, 0x0b, 0x0b, 0x15, 0x1b, 0x15, 0x1b, 0x0d, 0x17, 0x03, 0x46, 0x17, 0x03, 0x46, 0x40, 0x40, ++ 0x40, 0x11, 0x11, 0x0d, 0x40, 0x0f, 0x0d, 0x0b, 0x0b, 0x29, 0x27, 0x19, 0x07, 0x1b, 0x19, 0x11, ++ 0x42, 0x21, 0x15, 0x0d, 0x40, 0x0d, 0x11, 0x0b, 0x15, 0x0d, 0x1f, 0x13, 0x15, 0x0d, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4c, 0x16, 0x02, 0x4b, 0x40, 0x09, 0x4c, 0x56, 0x27, 0x40, 0x02, 0x40, 0x40, 0x40, 0x0f, ++ 0x02, 0x0b, 0x41, 0x14, 0x01, 0x0b, 0x15, 0x2a, 0x2a, 0x07, 0x07, 0x05, 0x04, 0x0a, 0x09, 0x07, ++ 0x49, 0x27, 0x16, 0x0d, 0x40, 0x45, 0x01, 0x40, 0x40, 0x40, 0x02, 0x02, 0x43, 0x41, 0x09, 0x41, ++ 0x01, 0x0b, 0x43, 0x49, 0x41, 0x13, 0x41, 0x49, 0x49, 0x01, 0x09, 0x0e, 0x0c, 0x0e, 0x43, 0x41, ++ 0x09, 0x41, 0x01, 0x0b, 0x43, 0x49, 0x41, 0x13, 0x41, 0x49, 0x49, 0x01, 0x09, 0x0e, 0x0c, 0x0e, ++ 0x1c, 0x45, 0x25, 0x40, 0x48, 0x40, 0x02, 0x07, 0x02, 0x0c, 0x0c, 0x15, 0x07, 0x15, 0x03, 0x45, ++ 0x1a, 0x07, 0x40, 0x15, 0x03, 0x45, 0x1a, 0x07, 0x40, 0x15, 0x03, 0x45, 0x1a, 0x07, 0x40, 0x4a, ++ 0x07, 0x0c, 0x0c, 0x16, 0x1c, 0x16, 0x1c, 0x0d, 0x17, 0x03, 0x45, 0x17, 0x03, 0x45, 0x40, 0x40, ++ 0x40, 0x11, 0x11, 0x0d, 0x40, 0x0f, 0x0d, 0x0b, 0x0b, 0x2a, 0x27, 0x1a, 0x07, 0x1c, 0x1a, 0x12, ++ 0x42, 0x21, 0x15, 0x0d, 0x40, 0x0d, 0x12, 0x0b, 0x16, 0x0d, 0x21, 0x14, 0x16, 0x0d, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4d, 0x17, 0x02, 0x4a, 0x40, 0x08, 0x4d, 0x57, 0x27, 0x40, 0x02, 0x40, 0x40, 0x40, 0x0f, ++ 0x02, 0x0d, 0x40, 0x15, 0x02, 0x0d, 0x17, 0x2c, 0x2c, 0x07, 0x07, 0x05, 0x05, 0x0a, 0x0a, 0x07, ++ 0x48, 0x27, 0x17, 0x0d, 0x40, 0x45, 0x00, 0x40, 0x40, 0x40, 0x02, 0x02, 0x42, 0x40, 0x0a, 0x40, ++ 0x02, 0x0d, 0x42, 0x48, 0x40, 0x15, 0x40, 0x48, 0x48, 0x02, 0x0a, 0x0f, 0x0d, 0x0f, 0x42, 0x40, ++ 0x0a, 0x40, 0x02, 0x0d, 0x42, 0x48, 0x40, 0x15, 0x40, 0x48, 0x48, 0x02, 0x0a, 0x0f, 0x0d, 0x0f, ++ 0x1d, 0x45, 0x27, 0x40, 0x48, 0x40, 0x02, 0x07, 0x02, 0x0d, 0x0d, 0x17, 0x07, 0x15, 0x02, 0x45, ++ 0x1a, 0x07, 0x40, 0x15, 0x02, 0x45, 0x1a, 0x07, 0x40, 0x15, 0x02, 0x45, 0x1a, 0x07, 0x40, 0x4a, ++ 0x07, 0x0d, 0x0d, 0x17, 0x1d, 0x17, 0x1d, 0x0d, 0x17, 0x02, 0x45, 0x17, 0x02, 0x45, 0x40, 0x40, ++ 0x40, 0x10, 0x10, 0x0d, 0x40, 0x0f, 0x0d, 0x0a, 0x0a, 0x2a, 0x27, 0x1a, 0x07, 0x1d, 0x1a, 0x12, ++ 0x42, 0x20, 0x15, 0x0d, 0x40, 0x0d, 0x12, 0x0a, 0x17, 0x0d, 0x22, 0x15, 0x17, 0x0d, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4d, 0x18, 0x02, 0x4a, 0x40, 0x07, 0x4d, 0x58, 0x27, 0x40, 0x02, 0x40, 0x40, 0x40, 0x0f, ++ 0x02, 0x0e, 0x00, 0x15, 0x03, 0x0e, 0x19, 0x2f, 0x2f, 0x07, 0x07, 0x05, 0x05, 0x0a, 0x0b, 0x07, ++ 0x47, 0x27, 0x18, 0x0d, 0x40, 0x45, 0x40, 0x40, 0x40, 0x40, 0x02, 0x02, 0x42, 0x00, 0x0b, 0x00, ++ 0x03, 0x0e, 0x42, 0x47, 0x00, 0x16, 0x00, 0x47, 0x47, 0x03, 0x0b, 0x10, 0x0d, 0x10, 0x42, 0x00, ++ 0x0b, 0x00, 0x03, 0x0e, 0x42, 0x47, 0x00, 0x16, 0x00, 0x47, 0x47, 0x03, 0x0b, 0x10, 0x0d, 0x10, ++ 0x1d, 0x45, 0x29, 0x40, 0x48, 0x40, 0x02, 0x07, 0x02, 0x0d, 0x0d, 0x19, 0x07, 0x15, 0x02, 0x45, ++ 0x1a, 0x07, 0x40, 0x15, 0x02, 0x45, 0x1a, 0x07, 0x40, 0x15, 0x02, 0x45, 0x1a, 0x07, 0x40, 0x4a, ++ 0x07, 0x0d, 0x0d, 0x18, 0x1d, 0x18, 0x1d, 0x0d, 0x17, 0x02, 0x45, 0x17, 0x02, 0x45, 0x40, 0x40, ++ 0x40, 0x0f, 0x0f, 0x0d, 0x40, 0x0f, 0x0d, 0x0a, 0x0a, 0x2a, 0x27, 0x1a, 0x07, 0x1d, 0x1a, 0x12, ++ 0x42, 0x1f, 0x15, 0x0d, 0x40, 0x0d, 0x12, 0x0a, 0x18, 0x0d, 0x23, 0x15, 0x18, 0x0d, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4e, 0x19, 0x03, 0x49, 0x40, 0x06, 0x4e, 0x59, 0x27, 0x40, 0x03, 0x40, 0x40, 0x40, 0x0f, ++ 0x03, 0x10, 0x01, 0x16, 0x04, 0x10, 0x1b, 0x31, 0x31, 0x07, 0x07, 0x04, 0x06, 0x0b, 0x0c, 0x07, ++ 0x46, 0x27, 0x19, 0x0c, 0x40, 0x44, 0x41, 0x40, 0x40, 0x40, 0x03, 0x03, 0x41, 0x01, 0x0c, 0x01, ++ 0x04, 0x10, 0x41, 0x46, 0x01, 0x18, 0x01, 0x46, 0x46, 0x04, 0x0c, 0x11, 0x0e, 0x11, 0x41, 0x01, ++ 0x0c, 0x01, 0x04, 0x10, 0x41, 0x46, 0x01, 0x18, 0x01, 0x46, 0x46, 0x04, 0x0c, 0x11, 0x0e, 0x11, ++ 0x1e, 0x44, 0x2b, 0x40, 0x48, 0x40, 0x03, 0x07, 0x03, 0x0e, 0x0e, 0x1b, 0x07, 0x14, 0x01, 0x44, ++ 0x1b, 0x07, 0x40, 0x14, 0x01, 0x44, 0x1b, 0x07, 0x40, 0x14, 0x01, 0x44, 0x1b, 0x07, 0x40, 0x4b, ++ 0x07, 0x0e, 0x0e, 0x19, 0x1e, 0x19, 0x1e, 0x0c, 0x17, 0x01, 0x44, 0x17, 0x01, 0x44, 0x40, 0x40, ++ 0x40, 0x0e, 0x0e, 0x0c, 0x40, 0x0f, 0x0c, 0x09, 0x09, 0x2b, 0x27, 0x1b, 0x07, 0x1e, 0x1b, 0x13, ++ 0x43, 0x1e, 0x14, 0x0c, 0x40, 0x0c, 0x13, 0x09, 0x19, 0x0c, 0x24, 0x16, 0x19, 0x0c, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4f, 0x1a, 0x03, 0x48, 0x40, 0x05, 0x4f, 0x5a, 0x27, 0x40, 0x03, 0x40, 0x40, 0x40, 0x0f, ++ 0x03, 0x11, 0x02, 0x17, 0x06, 0x11, 0x1d, 0x34, 0x34, 0x07, 0x07, 0x04, 0x07, 0x0b, 0x0e, 0x07, ++ 0x45, 0x27, 0x1a, 0x0c, 0x40, 0x44, 0x42, 0x40, 0x40, 0x40, 0x03, 0x03, 0x40, 0x02, 0x0e, 0x02, ++ 0x06, 0x11, 0x40, 0x45, 0x02, 0x19, 0x02, 0x45, 0x45, 0x06, 0x0e, 0x12, 0x0f, 0x12, 0x40, 0x02, ++ 0x0e, 0x02, 0x06, 0x11, 0x40, 0x45, 0x02, 0x19, 0x02, 0x45, 0x45, 0x06, 0x0e, 0x12, 0x0f, 0x12, ++ 0x1f, 0x44, 0x2d, 0x40, 0x48, 0x40, 0x03, 0x07, 0x03, 0x0f, 0x0f, 0x1d, 0x07, 0x14, 0x00, 0x44, ++ 0x1b, 0x07, 0x40, 0x14, 0x00, 0x44, 0x1b, 0x07, 0x40, 0x14, 0x00, 0x44, 0x1b, 0x07, 0x40, 0x4b, ++ 0x07, 0x0f, 0x0f, 0x1a, 0x1f, 0x1a, 0x1f, 0x0c, 0x17, 0x00, 0x44, 0x17, 0x00, 0x44, 0x40, 0x40, ++ 0x40, 0x0d, 0x0d, 0x0c, 0x40, 0x0f, 0x0c, 0x08, 0x08, 0x2b, 0x27, 0x1b, 0x07, 0x1f, 0x1b, 0x13, ++ 0x43, 0x1d, 0x14, 0x0c, 0x40, 0x0c, 0x13, 0x08, 0x1a, 0x0c, 0x26, 0x17, 0x1a, 0x0c, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4f, 0x1b, 0x03, 0x48, 0x40, 0x04, 0x4f, 0x5b, 0x27, 0x40, 0x03, 0x40, 0x40, 0x40, 0x0f, ++ 0x03, 0x13, 0x03, 0x17, 0x07, 0x13, 0x1f, 0x36, 0x36, 0x07, 0x07, 0x04, 0x07, 0x0b, 0x0f, 0x07, ++ 0x44, 0x27, 0x1b, 0x0c, 0x40, 0x44, 0x43, 0x40, 0x40, 0x40, 0x03, 0x03, 0x40, 0x03, 0x0f, 0x03, ++ 0x07, 0x13, 0x40, 0x44, 0x03, 0x1b, 0x03, 0x44, 0x44, 0x07, 0x0f, 0x13, 0x0f, 0x13, 0x40, 0x03, ++ 0x0f, 0x03, 0x07, 0x13, 0x40, 0x44, 0x03, 0x1b, 0x03, 0x44, 0x44, 0x07, 0x0f, 0x13, 0x0f, 0x13, ++ 0x1f, 0x44, 0x2f, 0x40, 0x48, 0x40, 0x03, 0x07, 0x03, 0x0f, 0x0f, 0x1f, 0x07, 0x14, 0x00, 0x44, ++ 0x1b, 0x07, 0x40, 0x14, 0x00, 0x44, 0x1b, 0x07, 0x40, 0x14, 0x00, 0x44, 0x1b, 0x07, 0x40, 0x4b, ++ 0x07, 0x0f, 0x0f, 0x1b, 0x1f, 0x1b, 0x1f, 0x0c, 0x17, 0x00, 0x44, 0x17, 0x00, 0x44, 0x40, 0x40, ++ 0x40, 0x0c, 0x0c, 0x0c, 0x40, 0x0f, 0x0c, 0x08, 0x08, 0x2b, 0x27, 0x1b, 0x07, 0x1f, 0x1b, 0x13, ++ 0x43, 0x1c, 0x14, 0x0c, 0x40, 0x0c, 0x13, 0x08, 0x1b, 0x0c, 0x27, 0x17, 0x1b, 0x0c, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x50, 0x1c, 0x04, 0x47, 0x40, 0x03, 0x50, 0x5c, 0x27, 0x40, 0x04, 0x40, 0x40, 0x40, 0x0f, ++ 0x04, 0x14, 0x04, 0x18, 0x08, 0x14, 0x21, 0x39, 0x39, 0x07, 0x07, 0x03, 0x08, 0x0c, 0x10, 0x07, ++ 0x43, 0x27, 0x1c, 0x0b, 0x40, 0x43, 0x44, 0x40, 0x40, 0x40, 0x04, 0x04, 0x00, 0x04, 0x10, 0x04, ++ 0x08, 0x14, 0x00, 0x43, 0x04, 0x1c, 0x04, 0x43, 0x43, 0x08, 0x10, 0x14, 0x10, 0x14, 0x00, 0x04, ++ 0x10, 0x04, 0x08, 0x14, 0x00, 0x43, 0x04, 0x1c, 0x04, 0x43, 0x43, 0x08, 0x10, 0x14, 0x10, 0x14, ++ 0x20, 0x43, 0x31, 0x40, 0x48, 0x40, 0x04, 0x07, 0x04, 0x10, 0x10, 0x21, 0x07, 0x13, 0x40, 0x43, ++ 0x1c, 0x07, 0x40, 0x13, 0x40, 0x43, 0x1c, 0x07, 0x40, 0x13, 0x40, 0x43, 0x1c, 0x07, 0x40, 0x4c, ++ 0x07, 0x10, 0x10, 0x1c, 0x20, 0x1c, 0x20, 0x0b, 0x17, 0x40, 0x43, 0x17, 0x40, 0x43, 0x40, 0x40, ++ 0x40, 0x0b, 0x0b, 0x0b, 0x40, 0x0f, 0x0b, 0x07, 0x07, 0x2c, 0x27, 0x1c, 0x07, 0x20, 0x1c, 0x14, ++ 0x44, 0x1b, 0x13, 0x0b, 0x40, 0x0b, 0x14, 0x07, 0x1c, 0x0b, 0x28, 0x18, 0x1c, 0x0b, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x51, 0x1d, 0x04, 0x47, 0x40, 0x02, 0x51, 0x5d, 0x27, 0x40, 0x04, 0x40, 0x40, 0x40, 0x0f, ++ 0x04, 0x16, 0x05, 0x18, 0x09, 0x16, 0x22, 0x3b, 0x3b, 0x07, 0x07, 0x03, 0x08, 0x0c, 0x11, 0x07, ++ 0x42, 0x27, 0x1d, 0x0b, 0x40, 0x43, 0x45, 0x40, 0x40, 0x40, 0x04, 0x04, 0x00, 0x05, 0x11, 0x05, ++ 0x09, 0x16, 0x00, 0x42, 0x05, 0x1e, 0x05, 0x42, 0x42, 0x09, 0x11, 0x15, 0x10, 0x15, 0x00, 0x05, ++ 0x11, 0x05, 0x09, 0x16, 0x00, 0x42, 0x05, 0x1e, 0x05, 0x42, 0x42, 0x09, 0x11, 0x15, 0x10, 0x15, ++ 0x20, 0x43, 0x32, 0x40, 0x48, 0x40, 0x04, 0x07, 0x04, 0x10, 0x10, 0x22, 0x07, 0x13, 0x41, 0x43, ++ 0x1c, 0x07, 0x40, 0x13, 0x41, 0x43, 0x1c, 0x07, 0x40, 0x13, 0x41, 0x43, 0x1c, 0x07, 0x40, 0x4c, ++ 0x07, 0x10, 0x10, 0x1d, 0x20, 0x1d, 0x20, 0x0b, 0x17, 0x41, 0x43, 0x17, 0x41, 0x43, 0x40, 0x40, ++ 0x40, 0x0a, 0x0a, 0x0b, 0x40, 0x0f, 0x0b, 0x06, 0x06, 0x2c, 0x27, 0x1c, 0x07, 0x20, 0x1c, 0x14, ++ 0x44, 0x1a, 0x13, 0x0b, 0x40, 0x0b, 0x14, 0x06, 0x1d, 0x0b, 0x29, 0x18, 0x1d, 0x0b, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x51, 0x1e, 0x04, 0x46, 0x40, 0x01, 0x51, 0x5e, 0x27, 0x40, 0x04, 0x40, 0x40, 0x40, 0x0f, ++ 0x04, 0x18, 0x06, 0x19, 0x0b, 0x18, 0x24, 0x3e, 0x3e, 0x07, 0x07, 0x03, 0x09, 0x0c, 0x13, 0x07, ++ 0x41, 0x27, 0x1e, 0x0b, 0x40, 0x43, 0x46, 0x40, 0x40, 0x40, 0x04, 0x04, 0x01, 0x06, 0x13, 0x06, ++ 0x0b, 0x18, 0x01, 0x41, 0x06, 0x20, 0x06, 0x41, 0x41, 0x0b, 0x13, 0x16, 0x11, 0x16, 0x01, 0x06, ++ 0x13, 0x06, 0x0b, 0x18, 0x01, 0x41, 0x06, 0x20, 0x06, 0x41, 0x41, 0x0b, 0x13, 0x16, 0x11, 0x16, ++ 0x21, 0x43, 0x34, 0x40, 0x48, 0x40, 0x04, 0x07, 0x04, 0x11, 0x11, 0x24, 0x07, 0x13, 0x41, 0x43, ++ 0x1c, 0x07, 0x40, 0x13, 0x41, 0x43, 0x1c, 0x07, 0x40, 0x13, 0x41, 0x43, 0x1c, 0x07, 0x40, 0x4c, ++ 0x07, 0x11, 0x11, 0x1e, 0x21, 0x1e, 0x21, 0x0b, 0x17, 0x41, 0x43, 0x17, 0x41, 0x43, 0x40, 0x40, ++ 0x40, 0x09, 0x09, 0x0b, 0x40, 0x0f, 0x0b, 0x06, 0x06, 0x2c, 0x27, 0x1c, 0x07, 0x21, 0x1c, 0x14, ++ 0x44, 0x19, 0x13, 0x0b, 0x40, 0x0b, 0x14, 0x06, 0x1e, 0x0b, 0x2b, 0x19, 0x1e, 0x0b, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x52, 0x1f, 0x05, 0x45, 0x40, 0x00, 0x52, 0x5f, 0x27, 0x40, 0x05, 0x40, 0x40, 0x40, 0x0f, ++ 0x05, 0x19, 0x07, 0x1a, 0x0c, 0x19, 0x26, 0x3e, 0x3e, 0x07, 0x07, 0x02, 0x0a, 0x0d, 0x14, 0x07, ++ 0x40, 0x27, 0x1f, 0x0a, 0x40, 0x42, 0x47, 0x40, 0x40, 0x40, 0x05, 0x05, 0x02, 0x07, 0x14, 0x07, ++ 0x0c, 0x19, 0x02, 0x40, 0x07, 0x21, 0x07, 0x40, 0x40, 0x0c, 0x14, 0x17, 0x12, 0x17, 0x02, 0x07, ++ 0x14, 0x07, 0x0c, 0x19, 0x02, 0x40, 0x07, 0x21, 0x07, 0x40, 0x40, 0x0c, 0x14, 0x17, 0x12, 0x17, ++ 0x22, 0x42, 0x36, 0x40, 0x48, 0x40, 0x05, 0x07, 0x05, 0x12, 0x12, 0x26, 0x07, 0x12, 0x42, 0x42, ++ 0x1d, 0x07, 0x40, 0x12, 0x42, 0x42, 0x1d, 0x07, 0x40, 0x12, 0x42, 0x42, 0x1d, 0x07, 0x40, 0x4d, ++ 0x07, 0x12, 0x12, 0x1f, 0x22, 0x1f, 0x22, 0x0a, 0x17, 0x42, 0x42, 0x17, 0x42, 0x42, 0x40, 0x40, ++ 0x40, 0x08, 0x08, 0x0a, 0x40, 0x0f, 0x0a, 0x05, 0x05, 0x2d, 0x27, 0x1d, 0x07, 0x22, 0x1d, 0x15, ++ 0x45, 0x18, 0x12, 0x0a, 0x40, 0x0a, 0x15, 0x05, 0x1f, 0x0a, 0x2c, 0x1a, 0x1f, 0x0a, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x52, 0x20, 0x05, 0x45, 0x40, 0x40, 0x52, 0x60, 0x27, 0x40, 0x05, 0x40, 0x40, 0x40, 0x0f, ++ 0x05, 0x1b, 0x08, 0x1a, 0x0d, 0x1b, 0x28, 0x3e, 0x3e, 0x07, 0x07, 0x02, 0x0a, 0x0d, 0x15, 0x07, ++ 0x00, 0x27, 0x20, 0x0a, 0x40, 0x42, 0x48, 0x40, 0x40, 0x40, 0x05, 0x05, 0x02, 0x08, 0x15, 0x08, ++ 0x0d, 0x1b, 0x02, 0x00, 0x08, 0x23, 0x08, 0x00, 0x00, 0x0d, 0x15, 0x18, 0x12, 0x18, 0x02, 0x08, ++ 0x15, 0x08, 0x0d, 0x1b, 0x02, 0x00, 0x08, 0x23, 0x08, 0x00, 0x00, 0x0d, 0x15, 0x18, 0x12, 0x18, ++ 0x22, 0x42, 0x38, 0x40, 0x48, 0x40, 0x05, 0x07, 0x05, 0x12, 0x12, 0x28, 0x07, 0x12, 0x42, 0x42, ++ 0x1d, 0x07, 0x40, 0x12, 0x42, 0x42, 0x1d, 0x07, 0x40, 0x12, 0x42, 0x42, 0x1d, 0x07, 0x40, 0x4d, ++ 0x07, 0x12, 0x12, 0x20, 0x22, 0x20, 0x22, 0x0a, 0x17, 0x42, 0x42, 0x17, 0x42, 0x42, 0x40, 0x40, ++ 0x40, 0x07, 0x07, 0x0a, 0x40, 0x0f, 0x0a, 0x05, 0x05, 0x2d, 0x27, 0x1d, 0x07, 0x22, 0x1d, 0x15, ++ 0x45, 0x17, 0x12, 0x0a, 0x40, 0x0a, 0x15, 0x05, 0x20, 0x0a, 0x2d, 0x1a, 0x20, 0x0a, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x53, 0x21, 0x05, 0x44, 0x40, 0x41, 0x53, 0x61, 0x27, 0x40, 0x05, 0x40, 0x40, 0x40, 0x0f, ++ 0x05, 0x1c, 0x09, 0x1b, 0x0e, 0x1c, 0x2a, 0x3e, 0x3e, 0x07, 0x07, 0x02, 0x0b, 0x0d, 0x16, 0x07, ++ 0x01, 0x27, 0x21, 0x0a, 0x40, 0x42, 0x49, 0x40, 0x40, 0x40, 0x05, 0x05, 0x03, 0x09, 0x16, 0x09, ++ 0x0e, 0x1c, 0x03, 0x01, 0x09, 0x24, 0x09, 0x01, 0x01, 0x0e, 0x16, 0x19, 0x13, 0x19, 0x03, 0x09, ++ 0x16, 0x09, 0x0e, 0x1c, 0x03, 0x01, 0x09, 0x24, 0x09, 0x01, 0x01, 0x0e, 0x16, 0x19, 0x13, 0x19, ++ 0x23, 0x42, 0x3a, 0x40, 0x48, 0x40, 0x05, 0x07, 0x05, 0x13, 0x13, 0x2a, 0x07, 0x12, 0x43, 0x42, ++ 0x1d, 0x07, 0x40, 0x12, 0x43, 0x42, 0x1d, 0x07, 0x40, 0x12, 0x43, 0x42, 0x1d, 0x07, 0x40, 0x4d, ++ 0x07, 0x13, 0x13, 0x21, 0x23, 0x21, 0x23, 0x0a, 0x17, 0x43, 0x42, 0x17, 0x43, 0x42, 0x40, 0x40, ++ 0x40, 0x06, 0x06, 0x0a, 0x40, 0x0f, 0x0a, 0x04, 0x04, 0x2d, 0x27, 0x1d, 0x07, 0x23, 0x1d, 0x15, ++ 0x45, 0x16, 0x12, 0x0a, 0x40, 0x0a, 0x15, 0x04, 0x21, 0x0a, 0x2e, 0x1b, 0x21, 0x0a, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x54, 0x22, 0x06, 0x43, 0x40, 0x42, 0x54, 0x62, 0x27, 0x40, 0x06, 0x40, 0x40, 0x40, 0x0f, ++ 0x06, 0x1e, 0x0a, 0x1c, 0x10, 0x1e, 0x2c, 0x3e, 0x3e, 0x07, 0x07, 0x01, 0x0c, 0x0e, 0x18, 0x07, ++ 0x02, 0x27, 0x22, 0x09, 0x40, 0x41, 0x4a, 0x40, 0x40, 0x40, 0x06, 0x06, 0x04, 0x0a, 0x18, 0x0a, ++ 0x10, 0x1e, 0x04, 0x02, 0x0a, 0x26, 0x0a, 0x02, 0x02, 0x10, 0x18, 0x1a, 0x14, 0x1a, 0x04, 0x0a, ++ 0x18, 0x0a, 0x10, 0x1e, 0x04, 0x02, 0x0a, 0x26, 0x0a, 0x02, 0x02, 0x10, 0x18, 0x1a, 0x14, 0x1a, ++ 0x24, 0x41, 0x3c, 0x40, 0x48, 0x40, 0x06, 0x07, 0x06, 0x14, 0x14, 0x2c, 0x07, 0x11, 0x44, 0x41, ++ 0x1e, 0x07, 0x40, 0x11, 0x44, 0x41, 0x1e, 0x07, 0x40, 0x11, 0x44, 0x41, 0x1e, 0x07, 0x40, 0x4e, ++ 0x07, 0x14, 0x14, 0x22, 0x24, 0x22, 0x24, 0x09, 0x17, 0x44, 0x41, 0x17, 0x44, 0x41, 0x40, 0x40, ++ 0x40, 0x05, 0x05, 0x09, 0x40, 0x0f, 0x09, 0x03, 0x03, 0x2e, 0x27, 0x1e, 0x07, 0x24, 0x1e, 0x16, ++ 0x46, 0x15, 0x11, 0x09, 0x40, 0x09, 0x16, 0x03, 0x22, 0x09, 0x30, 0x1c, 0x22, 0x09, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x54, 0x23, 0x06, 0x43, 0x40, 0x43, 0x54, 0x63, 0x27, 0x40, 0x06, 0x40, 0x40, 0x40, 0x0f, ++ 0x06, 0x1f, 0x0b, 0x1c, 0x11, 0x1f, 0x2e, 0x3e, 0x3e, 0x07, 0x07, 0x01, 0x0c, 0x0e, 0x19, 0x07, ++ 0x03, 0x27, 0x23, 0x09, 0x40, 0x41, 0x4b, 0x40, 0x40, 0x40, 0x06, 0x06, 0x04, 0x0b, 0x19, 0x0b, ++ 0x11, 0x1f, 0x04, 0x03, 0x0b, 0x27, 0x0b, 0x03, 0x03, 0x11, 0x19, 0x1b, 0x14, 0x1b, 0x04, 0x0b, ++ 0x19, 0x0b, 0x11, 0x1f, 0x04, 0x03, 0x0b, 0x27, 0x0b, 0x03, 0x03, 0x11, 0x19, 0x1b, 0x14, 0x1b, ++ 0x24, 0x41, 0x3e, 0x40, 0x48, 0x40, 0x06, 0x07, 0x06, 0x14, 0x14, 0x2e, 0x07, 0x11, 0x44, 0x41, ++ 0x1e, 0x07, 0x40, 0x11, 0x44, 0x41, 0x1e, 0x07, 0x40, 0x11, 0x44, 0x41, 0x1e, 0x07, 0x40, 0x4e, ++ 0x07, 0x14, 0x14, 0x23, 0x24, 0x23, 0x24, 0x09, 0x17, 0x44, 0x41, 0x17, 0x44, 0x41, 0x40, 0x40, ++ 0x40, 0x04, 0x04, 0x09, 0x40, 0x0f, 0x09, 0x03, 0x03, 0x2e, 0x27, 0x1e, 0x07, 0x24, 0x1e, 0x16, ++ 0x46, 0x14, 0x11, 0x09, 0x40, 0x09, 0x16, 0x03, 0x23, 0x09, 0x31, 0x1c, 0x23, 0x09, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x55, 0x24, 0x06, 0x42, 0x40, 0x44, 0x55, 0x64, 0x27, 0x40, 0x06, 0x40, 0x40, 0x40, 0x0f, ++ 0x06, 0x21, 0x0c, 0x1d, 0x12, 0x21, 0x30, 0x3e, 0x3e, 0x07, 0x07, 0x01, 0x0d, 0x0e, 0x1a, 0x07, ++ 0x04, 0x27, 0x24, 0x09, 0x40, 0x41, 0x4c, 0x40, 0x40, 0x40, 0x06, 0x06, 0x05, 0x0c, 0x1a, 0x0c, ++ 0x12, 0x21, 0x05, 0x04, 0x0c, 0x29, 0x0c, 0x04, 0x04, 0x12, 0x1a, 0x1c, 0x15, 0x1c, 0x05, 0x0c, ++ 0x1a, 0x0c, 0x12, 0x21, 0x05, 0x04, 0x0c, 0x29, 0x0c, 0x04, 0x04, 0x12, 0x1a, 0x1c, 0x15, 0x1c, ++ 0x25, 0x41, 0x3e, 0x40, 0x48, 0x40, 0x06, 0x07, 0x06, 0x15, 0x15, 0x30, 0x07, 0x11, 0x45, 0x41, ++ 0x1e, 0x07, 0x40, 0x11, 0x45, 0x41, 0x1e, 0x07, 0x40, 0x11, 0x45, 0x41, 0x1e, 0x07, 0x40, 0x4e, ++ 0x07, 0x15, 0x15, 0x24, 0x25, 0x24, 0x25, 0x09, 0x17, 0x45, 0x41, 0x17, 0x45, 0x41, 0x40, 0x40, ++ 0x40, 0x03, 0x03, 0x09, 0x40, 0x0f, 0x09, 0x02, 0x02, 0x2e, 0x27, 0x1e, 0x07, 0x25, 0x1e, 0x16, ++ 0x46, 0x13, 0x11, 0x09, 0x40, 0x09, 0x16, 0x02, 0x24, 0x09, 0x32, 0x1d, 0x24, 0x09, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x56, 0x24, 0x06, 0x42, 0x40, 0x45, 0x56, 0x65, 0x27, 0x40, 0x06, 0x40, 0x40, 0x40, 0x0f, ++ 0x06, 0x22, 0x0c, 0x1d, 0x13, 0x22, 0x31, 0x3e, 0x3e, 0x07, 0x07, 0x00, 0x0d, 0x0e, 0x1b, 0x07, ++ 0x04, 0x27, 0x24, 0x08, 0x40, 0x41, 0x4d, 0x40, 0x40, 0x40, 0x06, 0x06, 0x05, 0x0c, 0x1b, 0x0c, ++ 0x13, 0x22, 0x05, 0x04, 0x0c, 0x2a, 0x0c, 0x04, 0x04, 0x13, 0x1b, 0x1c, 0x15, 0x1c, 0x05, 0x0c, ++ 0x1b, 0x0c, 0x13, 0x22, 0x05, 0x04, 0x0c, 0x2a, 0x0c, 0x04, 0x04, 0x13, 0x1b, 0x1c, 0x15, 0x1c, ++ 0x25, 0x41, 0x3e, 0x40, 0x48, 0x40, 0x06, 0x07, 0x06, 0x15, 0x15, 0x31, 0x07, 0x10, 0x46, 0x41, ++ 0x1e, 0x07, 0x40, 0x10, 0x46, 0x41, 0x1e, 0x07, 0x40, 0x10, 0x46, 0x41, 0x1e, 0x07, 0x40, 0x4f, ++ 0x07, 0x15, 0x15, 0x24, 0x25, 0x24, 0x25, 0x08, 0x17, 0x46, 0x41, 0x17, 0x46, 0x41, 0x40, 0x40, ++ 0x40, 0x02, 0x02, 0x08, 0x40, 0x0f, 0x08, 0x01, 0x01, 0x2e, 0x27, 0x1e, 0x07, 0x25, 0x1e, 0x16, ++ 0x47, 0x12, 0x10, 0x08, 0x40, 0x08, 0x16, 0x01, 0x24, 0x08, 0x33, 0x1d, 0x24, 0x08, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x56, 0x25, 0x07, 0x41, 0x40, 0x45, 0x56, 0x65, 0x27, 0x40, 0x07, 0x40, 0x40, 0x40, 0x0f, ++ 0x07, 0x24, 0x0d, 0x1e, 0x15, 0x24, 0x33, 0x3e, 0x3e, 0x07, 0x07, 0x00, 0x0e, 0x0f, 0x1d, 0x07, ++ 0x05, 0x27, 0x25, 0x08, 0x40, 0x40, 0x4d, 0x40, 0x40, 0x40, 0x07, 0x07, 0x06, 0x0d, 0x1d, 0x0d, ++ 0x15, 0x24, 0x06, 0x05, 0x0d, 0x2c, 0x0d, 0x05, 0x05, 0x15, 0x1d, 0x1d, 0x16, 0x1d, 0x06, 0x0d, ++ 0x1d, 0x0d, 0x15, 0x24, 0x06, 0x05, 0x0d, 0x2c, 0x0d, 0x05, 0x05, 0x15, 0x1d, 0x1d, 0x16, 0x1d, ++ 0x26, 0x40, 0x3e, 0x40, 0x48, 0x40, 0x07, 0x07, 0x07, 0x16, 0x16, 0x33, 0x07, 0x10, 0x46, 0x40, ++ 0x1f, 0x07, 0x40, 0x10, 0x46, 0x40, 0x1f, 0x07, 0x40, 0x10, 0x46, 0x40, 0x1f, 0x07, 0x40, 0x4f, ++ 0x07, 0x16, 0x16, 0x25, 0x26, 0x25, 0x26, 0x08, 0x17, 0x46, 0x40, 0x17, 0x46, 0x40, 0x40, 0x40, ++ 0x40, 0x02, 0x02, 0x08, 0x40, 0x0f, 0x08, 0x01, 0x01, 0x2f, 0x27, 0x1f, 0x07, 0x26, 0x1f, 0x17, ++ 0x47, 0x12, 0x10, 0x08, 0x40, 0x08, 0x17, 0x01, 0x25, 0x08, 0x35, 0x1e, 0x25, 0x08, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x57, 0x26, 0x07, 0x40, 0x40, 0x46, 0x57, 0x66, 0x27, 0x40, 0x07, 0x40, 0x40, 0x40, 0x0f, ++ 0x07, 0x26, 0x0e, 0x1f, 0x16, 0x26, 0x35, 0x3e, 0x3e, 0x07, 0x07, 0x00, 0x0f, 0x0f, 0x1e, 0x07, ++ 0x06, 0x27, 0x26, 0x08, 0x40, 0x40, 0x4e, 0x40, 0x40, 0x40, 0x07, 0x07, 0x07, 0x0e, 0x1e, 0x0e, ++ 0x16, 0x26, 0x07, 0x06, 0x0e, 0x2e, 0x0e, 0x06, 0x06, 0x16, 0x1e, 0x1e, 0x17, 0x1e, 0x07, 0x0e, ++ 0x1e, 0x0e, 0x16, 0x26, 0x07, 0x06, 0x0e, 0x2e, 0x0e, 0x06, 0x06, 0x16, 0x1e, 0x1e, 0x17, 0x1e, ++ 0x27, 0x40, 0x3e, 0x40, 0x48, 0x40, 0x07, 0x07, 0x07, 0x17, 0x17, 0x35, 0x07, 0x10, 0x47, 0x40, ++ 0x1f, 0x07, 0x40, 0x10, 0x47, 0x40, 0x1f, 0x07, 0x40, 0x10, 0x47, 0x40, 0x1f, 0x07, 0x40, 0x4f, ++ 0x07, 0x17, 0x17, 0x26, 0x27, 0x26, 0x27, 0x08, 0x17, 0x47, 0x40, 0x17, 0x47, 0x40, 0x40, 0x40, ++ 0x40, 0x01, 0x01, 0x08, 0x40, 0x0f, 0x08, 0x00, 0x00, 0x2f, 0x27, 0x1f, 0x07, 0x27, 0x1f, 0x17, ++ 0x47, 0x11, 0x10, 0x08, 0x40, 0x08, 0x17, 0x00, 0x26, 0x08, 0x36, 0x1f, 0x26, 0x08, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x57, 0x27, 0x07, 0x40, 0x40, 0x47, 0x57, 0x67, 0x27, 0x40, 0x07, 0x40, 0x40, 0x40, 0x0f, ++ 0x07, 0x27, 0x0f, 0x1f, 0x17, 0x27, 0x37, 0x3e, 0x3e, 0x07, 0x07, 0x00, 0x0f, 0x0f, 0x1f, 0x07, ++ 0x07, 0x27, 0x27, 0x08, 0x40, 0x40, 0x4f, 0x40, 0x40, 0x40, 0x07, 0x07, 0x07, 0x0f, 0x1f, 0x0f, ++ 0x17, 0x27, 0x07, 0x07, 0x0f, 0x2f, 0x0f, 0x07, 0x07, 0x17, 0x1f, 0x1f, 0x17, 0x1f, 0x07, 0x0f, ++ 0x1f, 0x0f, 0x17, 0x27, 0x07, 0x07, 0x0f, 0x2f, 0x0f, 0x07, 0x07, 0x17, 0x1f, 0x1f, 0x17, 0x1f, ++ 0x27, 0x40, 0x3e, 0x40, 0x48, 0x40, 0x07, 0x07, 0x07, 0x17, 0x17, 0x37, 0x07, 0x10, 0x47, 0x40, ++ 0x1f, 0x07, 0x40, 0x10, 0x47, 0x40, 0x1f, 0x07, 0x40, 0x10, 0x47, 0x40, 0x1f, 0x07, 0x40, 0x4f, ++ 0x07, 0x17, 0x17, 0x27, 0x27, 0x27, 0x27, 0x08, 0x17, 0x47, 0x40, 0x17, 0x47, 0x40, 0x40, 0x40, ++ 0x40, 0x00, 0x00, 0x08, 0x40, 0x0f, 0x08, 0x00, 0x00, 0x2f, 0x27, 0x1f, 0x07, 0x27, 0x1f, 0x17, ++ 0x47, 0x10, 0x10, 0x08, 0x40, 0x08, 0x17, 0x00, 0x27, 0x08, 0x37, 0x1f, 0x27, 0x08, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x48, 0x48, 0x60, 0x40, 0x27, 0x07, 0x07, 0x1f, 0x40, 0x48, 0x40, 0x40, 0x17, 0x0f, ++ 0x48, 0x68, 0x40, 0x07, 0x68, 0x68, 0x68, 0x68, 0x68, 0x07, 0x07, 0x0f, 0x3e, 0x17, 0x40, 0x07, ++ 0x68, 0x27, 0x50, 0x17, 0x40, 0x07, 0x1f, 0x40, 0x40, 0x40, 0x48, 0x48, 0x58, 0x60, 0x50, 0x60, ++ 0x68, 0x60, 0x58, 0x68, 0x68, 0x68, 0x58, 0x60, 0x68, 0x68, 0x68, 0x50, 0x48, 0x58, 0x58, 0x60, ++ 0x50, 0x60, 0x68, 0x60, 0x58, 0x68, 0x68, 0x68, 0x58, 0x60, 0x68, 0x68, 0x68, 0x50, 0x48, 0x58, ++ 0x07, 0x50, 0x58, 0x40, 0x40, 0x40, 0x48, 0x07, 0x48, 0x48, 0x48, 0x68, 0x50, 0x1f, 0x17, 0x50, ++ 0x0f, 0x07, 0x40, 0x1f, 0x17, 0x50, 0x0f, 0x07, 0x40, 0x1f, 0x17, 0x50, 0x0f, 0x07, 0x40, 0x40, ++ 0x07, 0x40, 0x40, 0x40, 0x07, 0x40, 0x07, 0x17, 0x17, 0x17, 0x50, 0x17, 0x17, 0x50, 0x40, 0x40, ++ 0x40, 0x2f, 0x17, 0x17, 0x40, 0x0f, 0x17, 0x1f, 0x1f, 0x1f, 0x27, 0x0f, 0x07, 0x07, 0x0f, 0x40, ++ 0x07, 0x3e, 0x1f, 0x17, 0x40, 0x0f, 0x17, 0x1f, 0x48, 0x17, 0x48, 0x48, 0x48, 0x17, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x47, 0x47, 0x5f, 0x40, 0x27, 0x07, 0x07, 0x20, 0x40, 0x47, 0x40, 0x40, 0x17, 0x0f, ++ 0x47, 0x66, 0x40, 0x08, 0x66, 0x66, 0x66, 0x65, 0x65, 0x07, 0x07, 0x0f, 0x3e, 0x17, 0x00, 0x07, ++ 0x67, 0x27, 0x4e, 0x17, 0x40, 0x07, 0x1f, 0x40, 0x40, 0x40, 0x47, 0x47, 0x57, 0x5f, 0x4f, 0x5f, ++ 0x66, 0x5e, 0x57, 0x67, 0x67, 0x66, 0x57, 0x5f, 0x67, 0x67, 0x66, 0x4f, 0x47, 0x56, 0x57, 0x5f, ++ 0x4f, 0x5f, 0x66, 0x5e, 0x57, 0x67, 0x67, 0x66, 0x57, 0x5f, 0x67, 0x67, 0x66, 0x4f, 0x47, 0x56, ++ 0x08, 0x4f, 0x56, 0x40, 0x40, 0x40, 0x47, 0x07, 0x47, 0x47, 0x47, 0x66, 0x4f, 0x1f, 0x17, 0x4f, ++ 0x10, 0x07, 0x40, 0x1f, 0x17, 0x4f, 0x10, 0x07, 0x40, 0x1f, 0x17, 0x4f, 0x10, 0x07, 0x40, 0x40, ++ 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x17, 0x17, 0x17, 0x4f, 0x17, 0x17, 0x4f, 0x40, 0x40, ++ 0x40, 0x2f, 0x17, 0x17, 0x40, 0x0f, 0x17, 0x1f, 0x1f, 0x20, 0x27, 0x10, 0x07, 0x08, 0x10, 0x00, ++ 0x07, 0x3e, 0x1f, 0x17, 0x40, 0x0f, 0x17, 0x1f, 0x47, 0x17, 0x46, 0x47, 0x47, 0x17, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x46, 0x47, 0x5e, 0x40, 0x26, 0x06, 0x06, 0x20, 0x40, 0x47, 0x40, 0x40, 0x16, 0x0f, ++ 0x47, 0x64, 0x40, 0x08, 0x65, 0x64, 0x64, 0x63, 0x63, 0x07, 0x07, 0x0f, 0x3e, 0x17, 0x01, 0x07, ++ 0x66, 0x27, 0x4d, 0x17, 0x40, 0x07, 0x1e, 0x40, 0x40, 0x40, 0x47, 0x47, 0x56, 0x5e, 0x4e, 0x5e, ++ 0x65, 0x5d, 0x56, 0x66, 0x66, 0x64, 0x56, 0x5e, 0x66, 0x66, 0x64, 0x4e, 0x46, 0x55, 0x56, 0x5e, ++ 0x4e, 0x5e, 0x65, 0x5d, 0x56, 0x66, 0x66, 0x64, 0x56, 0x5e, 0x66, 0x66, 0x64, 0x4e, 0x46, 0x55, ++ 0x09, 0x4f, 0x54, 0x40, 0x40, 0x40, 0x47, 0x07, 0x47, 0x46, 0x46, 0x64, 0x4e, 0x1f, 0x16, 0x4f, ++ 0x10, 0x07, 0x40, 0x1f, 0x16, 0x4f, 0x10, 0x07, 0x40, 0x1f, 0x16, 0x4f, 0x10, 0x07, 0x40, 0x40, ++ 0x07, 0x00, 0x00, 0x01, 0x09, 0x01, 0x09, 0x17, 0x17, 0x16, 0x4f, 0x17, 0x16, 0x4f, 0x40, 0x40, ++ 0x40, 0x2e, 0x17, 0x17, 0x40, 0x0f, 0x17, 0x1e, 0x1e, 0x20, 0x27, 0x10, 0x07, 0x09, 0x10, 0x01, ++ 0x07, 0x3e, 0x1f, 0x17, 0x40, 0x0f, 0x17, 0x1e, 0x46, 0x17, 0x45, 0x46, 0x46, 0x17, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x45, 0x47, 0x5e, 0x40, 0x25, 0x06, 0x05, 0x20, 0x40, 0x47, 0x40, 0x40, 0x16, 0x0f, ++ 0x47, 0x63, 0x40, 0x08, 0x64, 0x63, 0x62, 0x60, 0x60, 0x07, 0x07, 0x0f, 0x3e, 0x17, 0x01, 0x07, ++ 0x65, 0x27, 0x4c, 0x17, 0x40, 0x07, 0x1d, 0x40, 0x40, 0x40, 0x47, 0x47, 0x56, 0x5d, 0x4e, 0x5d, ++ 0x64, 0x5c, 0x56, 0x65, 0x65, 0x63, 0x56, 0x5e, 0x65, 0x65, 0x63, 0x4d, 0x46, 0x54, 0x56, 0x5d, ++ 0x4e, 0x5d, 0x64, 0x5c, 0x56, 0x65, 0x65, 0x63, 0x56, 0x5e, 0x65, 0x65, 0x63, 0x4d, 0x46, 0x54, ++ 0x09, 0x4f, 0x52, 0x40, 0x40, 0x40, 0x47, 0x07, 0x47, 0x46, 0x46, 0x62, 0x4e, 0x1f, 0x16, 0x4f, ++ 0x10, 0x07, 0x40, 0x1f, 0x16, 0x4f, 0x10, 0x07, 0x40, 0x1f, 0x16, 0x4f, 0x10, 0x07, 0x40, 0x40, ++ 0x07, 0x00, 0x00, 0x01, 0x09, 0x01, 0x09, 0x17, 0x17, 0x16, 0x4f, 0x17, 0x16, 0x4f, 0x40, 0x40, ++ 0x40, 0x2d, 0x17, 0x17, 0x40, 0x0f, 0x17, 0x1e, 0x1e, 0x20, 0x27, 0x10, 0x07, 0x09, 0x10, 0x01, ++ 0x07, 0x3e, 0x1f, 0x17, 0x40, 0x0f, 0x17, 0x1e, 0x45, 0x17, 0x44, 0x45, 0x45, 0x17, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x44, 0x46, 0x5d, 0x40, 0x24, 0x05, 0x04, 0x21, 0x40, 0x46, 0x40, 0x40, 0x15, 0x0f, ++ 0x46, 0x61, 0x40, 0x09, 0x63, 0x61, 0x60, 0x5e, 0x5e, 0x07, 0x07, 0x0e, 0x3e, 0x16, 0x02, 0x07, ++ 0x64, 0x27, 0x4b, 0x16, 0x40, 0x06, 0x1c, 0x40, 0x40, 0x40, 0x46, 0x46, 0x55, 0x5c, 0x4d, 0x5c, ++ 0x63, 0x5b, 0x55, 0x64, 0x64, 0x61, 0x55, 0x5d, 0x64, 0x64, 0x61, 0x4c, 0x45, 0x53, 0x55, 0x5c, ++ 0x4d, 0x5c, 0x63, 0x5b, 0x55, 0x64, 0x64, 0x61, 0x55, 0x5d, 0x64, 0x64, 0x61, 0x4c, 0x45, 0x53, ++ 0x0a, 0x4e, 0x50, 0x40, 0x41, 0x40, 0x46, 0x07, 0x46, 0x45, 0x45, 0x60, 0x4d, 0x1e, 0x15, 0x4e, ++ 0x11, 0x07, 0x40, 0x1e, 0x15, 0x4e, 0x11, 0x07, 0x40, 0x1e, 0x15, 0x4e, 0x11, 0x07, 0x40, 0x41, ++ 0x07, 0x01, 0x01, 0x02, 0x0a, 0x02, 0x0a, 0x16, 0x17, 0x15, 0x4e, 0x17, 0x15, 0x4e, 0x40, 0x40, ++ 0x40, 0x2c, 0x16, 0x16, 0x40, 0x0f, 0x16, 0x1d, 0x1d, 0x21, 0x27, 0x11, 0x07, 0x0a, 0x11, 0x02, ++ 0x06, 0x3e, 0x1e, 0x16, 0x40, 0x0f, 0x16, 0x1d, 0x44, 0x16, 0x43, 0x44, 0x44, 0x16, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x43, 0x46, 0x5c, 0x40, 0x23, 0x04, 0x03, 0x21, 0x40, 0x46, 0x40, 0x40, 0x14, 0x0f, ++ 0x46, 0x60, 0x40, 0x09, 0x61, 0x60, 0x5e, 0x5b, 0x5b, 0x07, 0x07, 0x0e, 0x3e, 0x16, 0x03, 0x07, ++ 0x63, 0x27, 0x49, 0x16, 0x40, 0x06, 0x1b, 0x40, 0x40, 0x40, 0x46, 0x46, 0x54, 0x5b, 0x4c, 0x5b, ++ 0x61, 0x59, 0x54, 0x63, 0x63, 0x60, 0x54, 0x5c, 0x63, 0x63, 0x60, 0x4b, 0x44, 0x51, 0x54, 0x5b, ++ 0x4c, 0x5b, 0x61, 0x59, 0x54, 0x63, 0x63, 0x60, 0x54, 0x5c, 0x63, 0x63, 0x60, 0x4b, 0x44, 0x51, ++ 0x0b, 0x4e, 0x4e, 0x40, 0x41, 0x40, 0x46, 0x07, 0x46, 0x44, 0x44, 0x5e, 0x4c, 0x1e, 0x14, 0x4e, ++ 0x11, 0x07, 0x40, 0x1e, 0x14, 0x4e, 0x11, 0x07, 0x40, 0x1e, 0x14, 0x4e, 0x11, 0x07, 0x40, 0x41, ++ 0x07, 0x01, 0x01, 0x03, 0x0b, 0x03, 0x0b, 0x16, 0x17, 0x14, 0x4e, 0x17, 0x14, 0x4e, 0x40, 0x40, ++ 0x40, 0x2b, 0x16, 0x16, 0x40, 0x0f, 0x16, 0x1c, 0x1c, 0x21, 0x27, 0x11, 0x07, 0x0b, 0x11, 0x03, ++ 0x06, 0x3e, 0x1e, 0x16, 0x40, 0x0f, 0x16, 0x1c, 0x43, 0x16, 0x41, 0x43, 0x43, 0x16, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x42, 0x46, 0x5c, 0x40, 0x22, 0x04, 0x02, 0x21, 0x40, 0x46, 0x40, 0x40, 0x14, 0x0f, ++ 0x46, 0x5e, 0x40, 0x09, 0x60, 0x5e, 0x5c, 0x59, 0x59, 0x07, 0x07, 0x0e, 0x3e, 0x16, 0x03, 0x07, ++ 0x62, 0x27, 0x48, 0x16, 0x40, 0x06, 0x1a, 0x40, 0x40, 0x40, 0x46, 0x46, 0x54, 0x5a, 0x4c, 0x5a, ++ 0x60, 0x58, 0x54, 0x62, 0x62, 0x5e, 0x54, 0x5c, 0x62, 0x62, 0x5e, 0x4a, 0x44, 0x50, 0x54, 0x5a, ++ 0x4c, 0x5a, 0x60, 0x58, 0x54, 0x62, 0x62, 0x5e, 0x54, 0x5c, 0x62, 0x62, 0x5e, 0x4a, 0x44, 0x50, ++ 0x0b, 0x4e, 0x4c, 0x40, 0x41, 0x40, 0x46, 0x07, 0x46, 0x44, 0x44, 0x5c, 0x4c, 0x1e, 0x14, 0x4e, ++ 0x11, 0x07, 0x40, 0x1e, 0x14, 0x4e, 0x11, 0x07, 0x40, 0x1e, 0x14, 0x4e, 0x11, 0x07, 0x40, 0x41, ++ 0x07, 0x01, 0x01, 0x03, 0x0b, 0x03, 0x0b, 0x16, 0x17, 0x14, 0x4e, 0x17, 0x14, 0x4e, 0x40, 0x40, ++ 0x40, 0x2a, 0x16, 0x16, 0x40, 0x0f, 0x16, 0x1c, 0x1c, 0x21, 0x27, 0x11, 0x07, 0x0b, 0x11, 0x03, ++ 0x06, 0x3e, 0x1e, 0x16, 0x40, 0x0f, 0x16, 0x1c, 0x42, 0x16, 0x40, 0x42, 0x42, 0x16, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x41, 0x45, 0x5b, 0x40, 0x21, 0x03, 0x01, 0x22, 0x40, 0x45, 0x40, 0x40, 0x13, 0x0f, ++ 0x45, 0x5d, 0x40, 0x0a, 0x5f, 0x5d, 0x5a, 0x56, 0x56, 0x07, 0x07, 0x0d, 0x3e, 0x15, 0x04, 0x07, ++ 0x61, 0x27, 0x47, 0x15, 0x40, 0x05, 0x19, 0x40, 0x40, 0x40, 0x45, 0x45, 0x53, 0x59, 0x4b, 0x59, ++ 0x5f, 0x57, 0x53, 0x61, 0x61, 0x5d, 0x53, 0x5b, 0x61, 0x61, 0x5d, 0x49, 0x43, 0x4f, 0x53, 0x59, ++ 0x4b, 0x59, 0x5f, 0x57, 0x53, 0x61, 0x61, 0x5d, 0x53, 0x5b, 0x61, 0x61, 0x5d, 0x49, 0x43, 0x4f, ++ 0x0c, 0x4d, 0x4a, 0x40, 0x42, 0x40, 0x45, 0x07, 0x45, 0x43, 0x43, 0x5a, 0x4b, 0x1d, 0x13, 0x4d, ++ 0x12, 0x07, 0x40, 0x1d, 0x13, 0x4d, 0x12, 0x07, 0x40, 0x1d, 0x13, 0x4d, 0x12, 0x07, 0x40, 0x42, ++ 0x07, 0x02, 0x02, 0x04, 0x0c, 0x04, 0x0c, 0x15, 0x17, 0x13, 0x4d, 0x17, 0x13, 0x4d, 0x40, 0x40, ++ 0x40, 0x29, 0x15, 0x15, 0x40, 0x0f, 0x15, 0x1b, 0x1b, 0x22, 0x27, 0x12, 0x07, 0x0c, 0x12, 0x04, ++ 0x05, 0x3e, 0x1d, 0x15, 0x40, 0x0f, 0x15, 0x1b, 0x41, 0x15, 0x00, 0x41, 0x41, 0x15, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x40, 0x45, 0x5b, 0x40, 0x20, 0x02, 0x00, 0x22, 0x40, 0x45, 0x40, 0x40, 0x12, 0x0f, ++ 0x45, 0x5b, 0x40, 0x0a, 0x5e, 0x5b, 0x59, 0x54, 0x54, 0x07, 0x07, 0x0d, 0x3e, 0x15, 0x04, 0x07, ++ 0x60, 0x27, 0x46, 0x15, 0x40, 0x05, 0x18, 0x40, 0x40, 0x40, 0x45, 0x45, 0x53, 0x58, 0x4b, 0x58, ++ 0x5e, 0x56, 0x53, 0x60, 0x60, 0x5b, 0x53, 0x5b, 0x60, 0x60, 0x5b, 0x48, 0x43, 0x4e, 0x53, 0x58, ++ 0x4b, 0x58, 0x5e, 0x56, 0x53, 0x60, 0x60, 0x5b, 0x53, 0x5b, 0x60, 0x60, 0x5b, 0x48, 0x43, 0x4e, ++ 0x0c, 0x4d, 0x49, 0x40, 0x42, 0x40, 0x45, 0x07, 0x45, 0x43, 0x43, 0x59, 0x4b, 0x1d, 0x12, 0x4d, ++ 0x12, 0x07, 0x40, 0x1d, 0x12, 0x4d, 0x12, 0x07, 0x40, 0x1d, 0x12, 0x4d, 0x12, 0x07, 0x40, 0x42, ++ 0x07, 0x02, 0x02, 0x04, 0x0c, 0x04, 0x0c, 0x15, 0x17, 0x12, 0x4d, 0x17, 0x12, 0x4d, 0x40, 0x40, ++ 0x40, 0x28, 0x15, 0x15, 0x40, 0x0f, 0x15, 0x1a, 0x1a, 0x22, 0x27, 0x12, 0x07, 0x0c, 0x12, 0x04, ++ 0x05, 0x3e, 0x1d, 0x15, 0x40, 0x0f, 0x15, 0x1a, 0x40, 0x15, 0x01, 0x40, 0x40, 0x15, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x00, 0x45, 0x5a, 0x40, 0x1f, 0x02, 0x40, 0x22, 0x40, 0x45, 0x40, 0x40, 0x12, 0x0f, ++ 0x45, 0x59, 0x40, 0x0a, 0x5c, 0x59, 0x57, 0x51, 0x51, 0x07, 0x07, 0x0d, 0x3e, 0x15, 0x05, 0x07, ++ 0x5f, 0x27, 0x44, 0x15, 0x40, 0x05, 0x17, 0x40, 0x40, 0x40, 0x45, 0x45, 0x52, 0x57, 0x4a, 0x57, ++ 0x5c, 0x54, 0x52, 0x5f, 0x5f, 0x59, 0x52, 0x5a, 0x5f, 0x5f, 0x59, 0x47, 0x42, 0x4c, 0x52, 0x57, ++ 0x4a, 0x57, 0x5c, 0x54, 0x52, 0x5f, 0x5f, 0x59, 0x52, 0x5a, 0x5f, 0x5f, 0x59, 0x47, 0x42, 0x4c, ++ 0x0d, 0x4d, 0x47, 0x40, 0x42, 0x40, 0x45, 0x07, 0x45, 0x42, 0x42, 0x57, 0x4a, 0x1d, 0x12, 0x4d, ++ 0x12, 0x07, 0x40, 0x1d, 0x12, 0x4d, 0x12, 0x07, 0x40, 0x1d, 0x12, 0x4d, 0x12, 0x07, 0x40, 0x42, ++ 0x07, 0x02, 0x02, 0x05, 0x0d, 0x05, 0x0d, 0x15, 0x17, 0x12, 0x4d, 0x17, 0x12, 0x4d, 0x40, 0x40, ++ 0x40, 0x27, 0x15, 0x15, 0x40, 0x0f, 0x15, 0x1a, 0x1a, 0x22, 0x27, 0x12, 0x07, 0x0d, 0x12, 0x05, ++ 0x05, 0x3e, 0x1d, 0x15, 0x40, 0x0f, 0x15, 0x1a, 0x00, 0x15, 0x03, 0x00, 0x00, 0x15, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x01, 0x44, 0x59, 0x40, 0x1e, 0x01, 0x41, 0x23, 0x40, 0x44, 0x40, 0x40, 0x11, 0x0f, ++ 0x44, 0x58, 0x40, 0x0b, 0x5b, 0x58, 0x55, 0x4f, 0x4f, 0x07, 0x07, 0x0c, 0x3e, 0x14, 0x06, 0x07, ++ 0x5e, 0x27, 0x43, 0x14, 0x40, 0x04, 0x16, 0x40, 0x40, 0x40, 0x44, 0x44, 0x51, 0x56, 0x49, 0x56, ++ 0x5b, 0x53, 0x51, 0x5e, 0x5e, 0x58, 0x51, 0x59, 0x5e, 0x5e, 0x58, 0x46, 0x41, 0x4b, 0x51, 0x56, ++ 0x49, 0x56, 0x5b, 0x53, 0x51, 0x5e, 0x5e, 0x58, 0x51, 0x59, 0x5e, 0x5e, 0x58, 0x46, 0x41, 0x4b, ++ 0x0e, 0x4c, 0x45, 0x40, 0x43, 0x40, 0x44, 0x07, 0x44, 0x41, 0x41, 0x55, 0x49, 0x1c, 0x11, 0x4c, ++ 0x13, 0x07, 0x40, 0x1c, 0x11, 0x4c, 0x13, 0x07, 0x40, 0x1c, 0x11, 0x4c, 0x13, 0x07, 0x40, 0x43, ++ 0x07, 0x03, 0x03, 0x06, 0x0e, 0x06, 0x0e, 0x14, 0x17, 0x11, 0x4c, 0x17, 0x11, 0x4c, 0x40, 0x40, ++ 0x40, 0x26, 0x14, 0x14, 0x40, 0x0f, 0x14, 0x19, 0x19, 0x23, 0x27, 0x13, 0x07, 0x0e, 0x13, 0x06, ++ 0x04, 0x3e, 0x1c, 0x14, 0x40, 0x0f, 0x14, 0x19, 0x01, 0x14, 0x04, 0x01, 0x01, 0x14, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x02, 0x44, 0x59, 0x40, 0x1d, 0x01, 0x42, 0x23, 0x40, 0x44, 0x40, 0x40, 0x11, 0x0f, ++ 0x44, 0x56, 0x40, 0x0b, 0x5a, 0x56, 0x53, 0x4c, 0x4c, 0x07, 0x07, 0x0c, 0x3e, 0x14, 0x06, 0x07, ++ 0x5d, 0x27, 0x42, 0x14, 0x40, 0x04, 0x15, 0x40, 0x40, 0x40, 0x44, 0x44, 0x51, 0x55, 0x49, 0x55, ++ 0x5a, 0x52, 0x51, 0x5d, 0x5d, 0x56, 0x51, 0x59, 0x5d, 0x5d, 0x56, 0x45, 0x41, 0x4a, 0x51, 0x55, ++ 0x49, 0x55, 0x5a, 0x52, 0x51, 0x5d, 0x5d, 0x56, 0x51, 0x59, 0x5d, 0x5d, 0x56, 0x45, 0x41, 0x4a, ++ 0x0e, 0x4c, 0x43, 0x40, 0x43, 0x40, 0x44, 0x07, 0x44, 0x41, 0x41, 0x53, 0x49, 0x1c, 0x11, 0x4c, ++ 0x13, 0x07, 0x40, 0x1c, 0x11, 0x4c, 0x13, 0x07, 0x40, 0x1c, 0x11, 0x4c, 0x13, 0x07, 0x40, 0x43, ++ 0x07, 0x03, 0x03, 0x06, 0x0e, 0x06, 0x0e, 0x14, 0x17, 0x11, 0x4c, 0x17, 0x11, 0x4c, 0x40, 0x40, ++ 0x40, 0x25, 0x14, 0x14, 0x40, 0x0f, 0x14, 0x19, 0x19, 0x23, 0x27, 0x13, 0x07, 0x0e, 0x13, 0x06, ++ 0x04, 0x3e, 0x1c, 0x14, 0x40, 0x0f, 0x14, 0x19, 0x02, 0x14, 0x05, 0x02, 0x02, 0x14, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x03, 0x44, 0x58, 0x40, 0x1c, 0x00, 0x43, 0x23, 0x40, 0x44, 0x40, 0x40, 0x10, 0x0f, ++ 0x44, 0x55, 0x40, 0x0b, 0x59, 0x55, 0x51, 0x4a, 0x4a, 0x07, 0x07, 0x0c, 0x3d, 0x14, 0x07, 0x07, ++ 0x5c, 0x27, 0x41, 0x14, 0x40, 0x04, 0x14, 0x40, 0x40, 0x40, 0x44, 0x44, 0x50, 0x54, 0x48, 0x54, ++ 0x59, 0x51, 0x50, 0x5c, 0x5c, 0x55, 0x50, 0x58, 0x5c, 0x5c, 0x55, 0x44, 0x40, 0x49, 0x50, 0x54, ++ 0x48, 0x54, 0x59, 0x51, 0x50, 0x5c, 0x5c, 0x55, 0x50, 0x58, 0x5c, 0x5c, 0x55, 0x44, 0x40, 0x49, ++ 0x0f, 0x4c, 0x41, 0x40, 0x43, 0x40, 0x44, 0x07, 0x44, 0x40, 0x40, 0x51, 0x48, 0x1c, 0x10, 0x4c, ++ 0x13, 0x07, 0x40, 0x1c, 0x10, 0x4c, 0x13, 0x07, 0x40, 0x1c, 0x10, 0x4c, 0x13, 0x07, 0x40, 0x43, ++ 0x07, 0x03, 0x03, 0x07, 0x0f, 0x07, 0x0f, 0x14, 0x17, 0x10, 0x4c, 0x17, 0x10, 0x4c, 0x40, 0x40, ++ 0x40, 0x24, 0x14, 0x14, 0x40, 0x0f, 0x14, 0x18, 0x18, 0x23, 0x27, 0x13, 0x07, 0x0f, 0x13, 0x07, ++ 0x04, 0x3e, 0x1c, 0x14, 0x40, 0x0f, 0x14, 0x18, 0x03, 0x14, 0x06, 0x03, 0x03, 0x14, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x04, 0x43, 0x57, 0x40, 0x1b, 0x40, 0x44, 0x24, 0x40, 0x43, 0x40, 0x40, 0x0f, 0x0f, ++ 0x43, 0x53, 0x40, 0x0c, 0x57, 0x53, 0x4f, 0x47, 0x47, 0x07, 0x07, 0x0b, 0x3b, 0x13, 0x08, 0x07, ++ 0x5b, 0x27, 0x00, 0x13, 0x40, 0x03, 0x13, 0x40, 0x40, 0x40, 0x43, 0x43, 0x4f, 0x53, 0x47, 0x53, ++ 0x57, 0x4f, 0x4f, 0x5b, 0x5b, 0x53, 0x4f, 0x57, 0x5b, 0x5b, 0x53, 0x43, 0x00, 0x47, 0x4f, 0x53, ++ 0x47, 0x53, 0x57, 0x4f, 0x4f, 0x5b, 0x5b, 0x53, 0x4f, 0x57, 0x5b, 0x5b, 0x53, 0x43, 0x00, 0x47, ++ 0x10, 0x4b, 0x00, 0x40, 0x44, 0x40, 0x43, 0x07, 0x43, 0x00, 0x00, 0x4f, 0x47, 0x1b, 0x0f, 0x4b, ++ 0x14, 0x07, 0x40, 0x1b, 0x0f, 0x4b, 0x14, 0x07, 0x40, 0x1b, 0x0f, 0x4b, 0x14, 0x07, 0x40, 0x44, ++ 0x07, 0x04, 0x04, 0x08, 0x10, 0x08, 0x10, 0x13, 0x17, 0x0f, 0x4b, 0x17, 0x0f, 0x4b, 0x40, 0x40, ++ 0x40, 0x23, 0x13, 0x13, 0x40, 0x0f, 0x13, 0x17, 0x17, 0x24, 0x27, 0x14, 0x07, 0x10, 0x14, 0x08, ++ 0x03, 0x3e, 0x1b, 0x13, 0x40, 0x0f, 0x13, 0x17, 0x04, 0x13, 0x08, 0x04, 0x04, 0x13, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x05, 0x43, 0x57, 0x40, 0x1a, 0x40, 0x45, 0x24, 0x40, 0x43, 0x40, 0x40, 0x0f, 0x0f, ++ 0x43, 0x52, 0x40, 0x0c, 0x56, 0x52, 0x4d, 0x45, 0x45, 0x07, 0x07, 0x0b, 0x3a, 0x13, 0x08, 0x07, ++ 0x5a, 0x27, 0x01, 0x13, 0x40, 0x03, 0x12, 0x40, 0x40, 0x40, 0x43, 0x43, 0x4f, 0x52, 0x47, 0x52, ++ 0x56, 0x4e, 0x4f, 0x5a, 0x5a, 0x52, 0x4f, 0x57, 0x5a, 0x5a, 0x52, 0x42, 0x00, 0x46, 0x4f, 0x52, ++ 0x47, 0x52, 0x56, 0x4e, 0x4f, 0x5a, 0x5a, 0x52, 0x4f, 0x57, 0x5a, 0x5a, 0x52, 0x42, 0x00, 0x46, ++ 0x10, 0x4b, 0x02, 0x40, 0x44, 0x40, 0x43, 0x07, 0x43, 0x00, 0x00, 0x4d, 0x47, 0x1b, 0x0f, 0x4b, ++ 0x14, 0x07, 0x40, 0x1b, 0x0f, 0x4b, 0x14, 0x07, 0x40, 0x1b, 0x0f, 0x4b, 0x14, 0x07, 0x40, 0x44, ++ 0x07, 0x04, 0x04, 0x08, 0x10, 0x08, 0x10, 0x13, 0x17, 0x0f, 0x4b, 0x17, 0x0f, 0x4b, 0x40, 0x40, ++ 0x40, 0x22, 0x13, 0x13, 0x40, 0x0f, 0x13, 0x17, 0x17, 0x24, 0x27, 0x14, 0x07, 0x10, 0x14, 0x08, ++ 0x03, 0x3e, 0x1b, 0x13, 0x40, 0x0f, 0x13, 0x17, 0x05, 0x13, 0x09, 0x05, 0x05, 0x13, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x06, 0x43, 0x56, 0x40, 0x19, 0x41, 0x46, 0x24, 0x40, 0x43, 0x40, 0x40, 0x0e, 0x0f, ++ 0x43, 0x50, 0x40, 0x0c, 0x55, 0x50, 0x4b, 0x42, 0x42, 0x07, 0x07, 0x0b, 0x38, 0x13, 0x09, 0x07, ++ 0x59, 0x27, 0x02, 0x13, 0x40, 0x03, 0x11, 0x40, 0x40, 0x40, 0x43, 0x43, 0x4e, 0x51, 0x46, 0x51, ++ 0x55, 0x4d, 0x4e, 0x59, 0x59, 0x50, 0x4e, 0x56, 0x59, 0x59, 0x50, 0x41, 0x01, 0x45, 0x4e, 0x51, ++ 0x46, 0x51, 0x55, 0x4d, 0x4e, 0x59, 0x59, 0x50, 0x4e, 0x56, 0x59, 0x59, 0x50, 0x41, 0x01, 0x45, ++ 0x11, 0x4b, 0x04, 0x40, 0x44, 0x40, 0x43, 0x07, 0x43, 0x01, 0x01, 0x4b, 0x46, 0x1b, 0x0e, 0x4b, ++ 0x14, 0x07, 0x40, 0x1b, 0x0e, 0x4b, 0x14, 0x07, 0x40, 0x1b, 0x0e, 0x4b, 0x14, 0x07, 0x40, 0x44, ++ 0x07, 0x04, 0x04, 0x09, 0x11, 0x09, 0x11, 0x13, 0x17, 0x0e, 0x4b, 0x17, 0x0e, 0x4b, 0x40, 0x40, ++ 0x40, 0x21, 0x13, 0x13, 0x40, 0x0f, 0x13, 0x16, 0x16, 0x24, 0x27, 0x14, 0x07, 0x11, 0x14, 0x09, ++ 0x03, 0x3d, 0x1b, 0x13, 0x40, 0x0f, 0x13, 0x16, 0x06, 0x13, 0x0a, 0x06, 0x06, 0x13, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x06, 0x43, 0x56, 0x40, 0x18, 0x42, 0x47, 0x24, 0x40, 0x43, 0x40, 0x40, 0x0d, 0x0f, ++ 0x43, 0x4f, 0x40, 0x0c, 0x54, 0x4f, 0x4a, 0x40, 0x40, 0x07, 0x07, 0x0a, 0x36, 0x12, 0x09, 0x07, ++ 0x59, 0x27, 0x03, 0x12, 0x40, 0x02, 0x10, 0x40, 0x40, 0x40, 0x43, 0x43, 0x4e, 0x51, 0x46, 0x51, ++ 0x54, 0x4c, 0x4e, 0x59, 0x59, 0x4f, 0x4e, 0x56, 0x59, 0x59, 0x4f, 0x41, 0x01, 0x44, 0x4e, 0x51, ++ 0x46, 0x51, 0x54, 0x4c, 0x4e, 0x59, 0x59, 0x4f, 0x4e, 0x56, 0x59, 0x59, 0x4f, 0x41, 0x01, 0x44, ++ 0x11, 0x4b, 0x05, 0x40, 0x45, 0x40, 0x43, 0x07, 0x43, 0x01, 0x01, 0x4a, 0x46, 0x1a, 0x0d, 0x4b, ++ 0x14, 0x07, 0x40, 0x1a, 0x0d, 0x4b, 0x14, 0x07, 0x40, 0x1a, 0x0d, 0x4b, 0x14, 0x07, 0x40, 0x45, ++ 0x07, 0x04, 0x04, 0x09, 0x11, 0x09, 0x11, 0x12, 0x17, 0x0d, 0x4b, 0x17, 0x0d, 0x4b, 0x40, 0x40, ++ 0x40, 0x20, 0x12, 0x12, 0x40, 0x0f, 0x12, 0x15, 0x15, 0x24, 0x27, 0x14, 0x07, 0x11, 0x14, 0x09, ++ 0x02, 0x3b, 0x1a, 0x12, 0x40, 0x0f, 0x12, 0x15, 0x06, 0x12, 0x0b, 0x06, 0x06, 0x12, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x07, 0x42, 0x55, 0x40, 0x18, 0x42, 0x47, 0x25, 0x40, 0x42, 0x40, 0x40, 0x0d, 0x0f, ++ 0x42, 0x4d, 0x40, 0x0d, 0x52, 0x4d, 0x48, 0x02, 0x02, 0x07, 0x07, 0x0a, 0x35, 0x12, 0x0a, 0x07, ++ 0x58, 0x27, 0x05, 0x12, 0x40, 0x02, 0x10, 0x40, 0x40, 0x40, 0x42, 0x42, 0x4d, 0x50, 0x45, 0x50, ++ 0x52, 0x4a, 0x4d, 0x58, 0x58, 0x4d, 0x4d, 0x55, 0x58, 0x58, 0x4d, 0x40, 0x02, 0x42, 0x4d, 0x50, ++ 0x45, 0x50, 0x52, 0x4a, 0x4d, 0x58, 0x58, 0x4d, 0x4d, 0x55, 0x58, 0x58, 0x4d, 0x40, 0x02, 0x42, ++ 0x12, 0x4a, 0x07, 0x40, 0x45, 0x40, 0x42, 0x07, 0x42, 0x02, 0x02, 0x48, 0x45, 0x1a, 0x0d, 0x4a, ++ 0x15, 0x07, 0x40, 0x1a, 0x0d, 0x4a, 0x15, 0x07, 0x40, 0x1a, 0x0d, 0x4a, 0x15, 0x07, 0x40, 0x45, ++ 0x07, 0x05, 0x05, 0x0a, 0x12, 0x0a, 0x12, 0x12, 0x17, 0x0d, 0x4a, 0x17, 0x0d, 0x4a, 0x40, 0x40, ++ 0x40, 0x20, 0x12, 0x12, 0x40, 0x0f, 0x12, 0x15, 0x15, 0x25, 0x27, 0x15, 0x07, 0x12, 0x15, 0x0a, ++ 0x02, 0x3a, 0x1a, 0x12, 0x40, 0x0f, 0x12, 0x15, 0x07, 0x12, 0x0d, 0x07, 0x07, 0x12, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x08, 0x42, 0x54, 0x40, 0x17, 0x43, 0x48, 0x25, 0x40, 0x42, 0x40, 0x40, 0x0c, 0x0f, ++ 0x42, 0x4b, 0x40, 0x0d, 0x51, 0x4b, 0x46, 0x04, 0x04, 0x07, 0x07, 0x0a, 0x33, 0x12, 0x0b, 0x07, ++ 0x57, 0x27, 0x06, 0x12, 0x40, 0x02, 0x0f, 0x40, 0x40, 0x40, 0x42, 0x42, 0x4c, 0x4f, 0x44, 0x4f, ++ 0x51, 0x49, 0x4c, 0x57, 0x57, 0x4b, 0x4c, 0x54, 0x57, 0x57, 0x4b, 0x00, 0x03, 0x41, 0x4c, 0x4f, ++ 0x44, 0x4f, 0x51, 0x49, 0x4c, 0x57, 0x57, 0x4b, 0x4c, 0x54, 0x57, 0x57, 0x4b, 0x00, 0x03, 0x41, ++ 0x13, 0x4a, 0x09, 0x40, 0x45, 0x40, 0x42, 0x07, 0x42, 0x03, 0x03, 0x46, 0x44, 0x1a, 0x0c, 0x4a, ++ 0x15, 0x07, 0x40, 0x1a, 0x0c, 0x4a, 0x15, 0x07, 0x40, 0x1a, 0x0c, 0x4a, 0x15, 0x07, 0x40, 0x45, ++ 0x07, 0x05, 0x05, 0x0b, 0x13, 0x0b, 0x13, 0x12, 0x17, 0x0c, 0x4a, 0x17, 0x0c, 0x4a, 0x40, 0x40, ++ 0x40, 0x1f, 0x12, 0x12, 0x40, 0x0f, 0x12, 0x14, 0x14, 0x25, 0x27, 0x15, 0x07, 0x13, 0x15, 0x0b, ++ 0x02, 0x39, 0x1a, 0x12, 0x40, 0x0f, 0x12, 0x14, 0x08, 0x12, 0x0e, 0x08, 0x08, 0x12, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x09, 0x42, 0x54, 0x40, 0x16, 0x43, 0x49, 0x25, 0x40, 0x42, 0x40, 0x40, 0x0c, 0x0f, ++ 0x42, 0x4a, 0x40, 0x0d, 0x50, 0x4a, 0x44, 0x07, 0x07, 0x07, 0x07, 0x0a, 0x32, 0x12, 0x0b, 0x07, ++ 0x56, 0x27, 0x07, 0x12, 0x40, 0x02, 0x0e, 0x40, 0x40, 0x40, 0x42, 0x42, 0x4c, 0x4e, 0x44, 0x4e, ++ 0x50, 0x48, 0x4c, 0x56, 0x56, 0x4a, 0x4c, 0x54, 0x56, 0x56, 0x4a, 0x01, 0x03, 0x40, 0x4c, 0x4e, ++ 0x44, 0x4e, 0x50, 0x48, 0x4c, 0x56, 0x56, 0x4a, 0x4c, 0x54, 0x56, 0x56, 0x4a, 0x01, 0x03, 0x40, ++ 0x13, 0x4a, 0x0b, 0x40, 0x45, 0x40, 0x42, 0x07, 0x42, 0x03, 0x03, 0x44, 0x44, 0x1a, 0x0c, 0x4a, ++ 0x15, 0x07, 0x40, 0x1a, 0x0c, 0x4a, 0x15, 0x07, 0x40, 0x1a, 0x0c, 0x4a, 0x15, 0x07, 0x40, 0x45, ++ 0x07, 0x05, 0x05, 0x0b, 0x13, 0x0b, 0x13, 0x12, 0x17, 0x0c, 0x4a, 0x17, 0x0c, 0x4a, 0x40, 0x40, ++ 0x40, 0x1e, 0x12, 0x12, 0x40, 0x0f, 0x12, 0x14, 0x14, 0x25, 0x27, 0x15, 0x07, 0x13, 0x15, 0x0b, ++ 0x02, 0x38, 0x1a, 0x12, 0x40, 0x0f, 0x12, 0x14, 0x09, 0x12, 0x0f, 0x09, 0x09, 0x12, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x0a, 0x41, 0x53, 0x40, 0x15, 0x44, 0x4a, 0x26, 0x40, 0x41, 0x40, 0x40, 0x0b, 0x0f, ++ 0x41, 0x48, 0x40, 0x0e, 0x4f, 0x48, 0x42, 0x09, 0x09, 0x07, 0x07, 0x09, 0x30, 0x11, 0x0c, 0x07, ++ 0x55, 0x27, 0x08, 0x11, 0x40, 0x01, 0x0d, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4b, 0x4d, 0x43, 0x4d, ++ 0x4f, 0x47, 0x4b, 0x55, 0x55, 0x48, 0x4b, 0x53, 0x55, 0x55, 0x48, 0x02, 0x04, 0x00, 0x4b, 0x4d, ++ 0x43, 0x4d, 0x4f, 0x47, 0x4b, 0x55, 0x55, 0x48, 0x4b, 0x53, 0x55, 0x55, 0x48, 0x02, 0x04, 0x00, ++ 0x14, 0x49, 0x0d, 0x40, 0x46, 0x40, 0x41, 0x07, 0x41, 0x04, 0x04, 0x42, 0x43, 0x19, 0x0b, 0x49, ++ 0x16, 0x07, 0x40, 0x19, 0x0b, 0x49, 0x16, 0x07, 0x40, 0x19, 0x0b, 0x49, 0x16, 0x07, 0x40, 0x46, ++ 0x07, 0x06, 0x06, 0x0c, 0x14, 0x0c, 0x14, 0x11, 0x17, 0x0b, 0x49, 0x17, 0x0b, 0x49, 0x40, 0x40, ++ 0x40, 0x1d, 0x11, 0x11, 0x40, 0x0f, 0x11, 0x13, 0x13, 0x26, 0x27, 0x16, 0x07, 0x14, 0x16, 0x0c, ++ 0x01, 0x36, 0x19, 0x11, 0x40, 0x0f, 0x11, 0x13, 0x0a, 0x11, 0x10, 0x0a, 0x0a, 0x11, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x0b, 0x41, 0x52, 0x40, 0x14, 0x45, 0x4b, 0x26, 0x40, 0x41, 0x40, 0x40, 0x0a, 0x0f, ++ 0x41, 0x47, 0x40, 0x0e, 0x4d, 0x47, 0x40, 0x0c, 0x0c, 0x07, 0x07, 0x09, 0x2f, 0x11, 0x0d, 0x07, ++ 0x54, 0x27, 0x0a, 0x11, 0x40, 0x01, 0x0c, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4a, 0x4c, 0x42, 0x4c, ++ 0x4d, 0x45, 0x4a, 0x54, 0x54, 0x47, 0x4a, 0x52, 0x54, 0x54, 0x47, 0x03, 0x05, 0x02, 0x4a, 0x4c, ++ 0x42, 0x4c, 0x4d, 0x45, 0x4a, 0x54, 0x54, 0x47, 0x4a, 0x52, 0x54, 0x54, 0x47, 0x03, 0x05, 0x02, ++ 0x15, 0x49, 0x0f, 0x40, 0x46, 0x40, 0x41, 0x07, 0x41, 0x05, 0x05, 0x40, 0x42, 0x19, 0x0a, 0x49, ++ 0x16, 0x07, 0x40, 0x19, 0x0a, 0x49, 0x16, 0x07, 0x40, 0x19, 0x0a, 0x49, 0x16, 0x07, 0x40, 0x46, ++ 0x07, 0x06, 0x06, 0x0d, 0x15, 0x0d, 0x15, 0x11, 0x17, 0x0a, 0x49, 0x17, 0x0a, 0x49, 0x40, 0x40, ++ 0x40, 0x1c, 0x11, 0x11, 0x40, 0x0f, 0x11, 0x12, 0x12, 0x26, 0x27, 0x16, 0x07, 0x15, 0x16, 0x0d, ++ 0x01, 0x35, 0x19, 0x11, 0x40, 0x0f, 0x11, 0x12, 0x0b, 0x11, 0x12, 0x0b, 0x0b, 0x11, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x0c, 0x41, 0x52, 0x40, 0x13, 0x45, 0x4c, 0x26, 0x40, 0x41, 0x40, 0x40, 0x0a, 0x0f, ++ 0x41, 0x45, 0x40, 0x0e, 0x4c, 0x45, 0x01, 0x0e, 0x0e, 0x07, 0x07, 0x09, 0x2d, 0x11, 0x0d, 0x07, ++ 0x53, 0x27, 0x0b, 0x11, 0x40, 0x01, 0x0b, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4a, 0x4b, 0x42, 0x4b, ++ 0x4c, 0x44, 0x4a, 0x53, 0x53, 0x45, 0x4a, 0x52, 0x53, 0x53, 0x45, 0x04, 0x05, 0x03, 0x4a, 0x4b, ++ 0x42, 0x4b, 0x4c, 0x44, 0x4a, 0x53, 0x53, 0x45, 0x4a, 0x52, 0x53, 0x53, 0x45, 0x04, 0x05, 0x03, ++ 0x15, 0x49, 0x11, 0x40, 0x46, 0x40, 0x41, 0x07, 0x41, 0x05, 0x05, 0x01, 0x42, 0x19, 0x0a, 0x49, ++ 0x16, 0x07, 0x40, 0x19, 0x0a, 0x49, 0x16, 0x07, 0x40, 0x19, 0x0a, 0x49, 0x16, 0x07, 0x40, 0x46, ++ 0x07, 0x06, 0x06, 0x0d, 0x15, 0x0d, 0x15, 0x11, 0x17, 0x0a, 0x49, 0x17, 0x0a, 0x49, 0x40, 0x40, ++ 0x40, 0x1b, 0x11, 0x11, 0x40, 0x0f, 0x11, 0x12, 0x12, 0x26, 0x27, 0x16, 0x07, 0x15, 0x16, 0x0d, ++ 0x01, 0x34, 0x19, 0x11, 0x40, 0x0f, 0x11, 0x12, 0x0c, 0x11, 0x13, 0x0c, 0x0c, 0x11, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x0d, 0x40, 0x51, 0x40, 0x12, 0x46, 0x4d, 0x27, 0x40, 0x40, 0x40, 0x40, 0x09, 0x0f, ++ 0x40, 0x44, 0x40, 0x0f, 0x4b, 0x44, 0x03, 0x11, 0x11, 0x07, 0x07, 0x08, 0x2c, 0x10, 0x0e, 0x07, ++ 0x52, 0x27, 0x0c, 0x10, 0x40, 0x00, 0x0a, 0x40, 0x40, 0x40, 0x40, 0x40, 0x49, 0x4a, 0x41, 0x4a, ++ 0x4b, 0x43, 0x49, 0x52, 0x52, 0x44, 0x49, 0x51, 0x52, 0x52, 0x44, 0x05, 0x06, 0x04, 0x49, 0x4a, ++ 0x41, 0x4a, 0x4b, 0x43, 0x49, 0x52, 0x52, 0x44, 0x49, 0x51, 0x52, 0x52, 0x44, 0x05, 0x06, 0x04, ++ 0x16, 0x48, 0x13, 0x40, 0x47, 0x40, 0x40, 0x07, 0x40, 0x06, 0x06, 0x03, 0x41, 0x18, 0x09, 0x48, ++ 0x17, 0x07, 0x40, 0x18, 0x09, 0x48, 0x17, 0x07, 0x40, 0x18, 0x09, 0x48, 0x17, 0x07, 0x40, 0x47, ++ 0x07, 0x07, 0x07, 0x0e, 0x16, 0x0e, 0x16, 0x10, 0x17, 0x09, 0x48, 0x17, 0x09, 0x48, 0x40, 0x40, ++ 0x40, 0x1a, 0x10, 0x10, 0x40, 0x0f, 0x10, 0x11, 0x11, 0x27, 0x27, 0x17, 0x07, 0x16, 0x17, 0x0e, ++ 0x00, 0x33, 0x18, 0x10, 0x40, 0x0f, 0x10, 0x11, 0x0d, 0x10, 0x14, 0x0d, 0x0d, 0x10, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x0e, 0x40, 0x51, 0x40, 0x11, 0x47, 0x4e, 0x27, 0x40, 0x40, 0x40, 0x40, 0x08, 0x0f, ++ 0x40, 0x42, 0x40, 0x0f, 0x4a, 0x42, 0x04, 0x13, 0x13, 0x07, 0x07, 0x08, 0x2a, 0x10, 0x0e, 0x07, ++ 0x51, 0x27, 0x0d, 0x10, 0x40, 0x00, 0x09, 0x40, 0x40, 0x40, 0x40, 0x40, 0x49, 0x49, 0x41, 0x49, ++ 0x4a, 0x42, 0x49, 0x51, 0x51, 0x42, 0x49, 0x51, 0x51, 0x51, 0x42, 0x06, 0x06, 0x05, 0x49, 0x49, ++ 0x41, 0x49, 0x4a, 0x42, 0x49, 0x51, 0x51, 0x42, 0x49, 0x51, 0x51, 0x51, 0x42, 0x06, 0x06, 0x05, ++ 0x16, 0x48, 0x14, 0x40, 0x47, 0x40, 0x40, 0x07, 0x40, 0x06, 0x06, 0x04, 0x41, 0x18, 0x08, 0x48, ++ 0x17, 0x07, 0x40, 0x18, 0x08, 0x48, 0x17, 0x07, 0x40, 0x18, 0x08, 0x48, 0x17, 0x07, 0x40, 0x47, ++ 0x07, 0x07, 0x07, 0x0e, 0x16, 0x0e, 0x16, 0x10, 0x17, 0x08, 0x48, 0x17, 0x08, 0x48, 0x40, 0x40, ++ 0x40, 0x19, 0x10, 0x10, 0x40, 0x0f, 0x10, 0x10, 0x10, 0x27, 0x27, 0x17, 0x07, 0x16, 0x17, 0x0e, ++ 0x00, 0x31, 0x18, 0x10, 0x40, 0x0f, 0x10, 0x10, 0x0e, 0x10, 0x15, 0x0e, 0x0e, 0x10, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x0f, 0x40, 0x50, 0x40, 0x10, 0x47, 0x4f, 0x27, 0x40, 0x40, 0x40, 0x40, 0x08, 0x0f, ++ 0x40, 0x40, 0x40, 0x0f, 0x48, 0x40, 0x06, 0x16, 0x16, 0x07, 0x07, 0x08, 0x28, 0x10, 0x0f, 0x07, ++ 0x50, 0x27, 0x0f, 0x10, 0x40, 0x00, 0x08, 0x40, 0x40, 0x40, 0x40, 0x40, 0x48, 0x48, 0x40, 0x48, ++ 0x48, 0x40, 0x48, 0x50, 0x50, 0x40, 0x48, 0x50, 0x50, 0x50, 0x40, 0x07, 0x07, 0x07, 0x48, 0x48, ++ 0x40, 0x48, 0x48, 0x40, 0x48, 0x50, 0x50, 0x40, 0x48, 0x50, 0x50, 0x50, 0x40, 0x07, 0x07, 0x07, ++ 0x17, 0x48, 0x16, 0x40, 0x47, 0x40, 0x40, 0x07, 0x40, 0x07, 0x07, 0x06, 0x40, 0x18, 0x08, 0x48, ++ 0x17, 0x07, 0x40, 0x18, 0x08, 0x48, 0x17, 0x07, 0x40, 0x18, 0x08, 0x48, 0x17, 0x07, 0x40, 0x47, ++ 0x07, 0x07, 0x07, 0x0f, 0x17, 0x0f, 0x17, 0x10, 0x17, 0x08, 0x48, 0x17, 0x08, 0x48, 0x40, 0x40, ++ 0x40, 0x18, 0x10, 0x10, 0x40, 0x0f, 0x10, 0x10, 0x10, 0x27, 0x27, 0x17, 0x07, 0x17, 0x17, 0x0f, ++ 0x00, 0x30, 0x18, 0x10, 0x40, 0x0f, 0x10, 0x10, 0x0f, 0x10, 0x17, 0x0f, 0x0f, 0x10, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x10, 0x00, 0x4f, 0x40, 0x0f, 0x48, 0x50, 0x28, 0x40, 0x00, 0x40, 0x40, 0x07, 0x0f, ++ 0x00, 0x00, 0x40, 0x10, 0x47, 0x00, 0x08, 0x18, 0x18, 0x07, 0x07, 0x07, 0x27, 0x0f, 0x10, 0x07, ++ 0x4f, 0x27, 0x10, 0x0f, 0x40, 0x40, 0x07, 0x40, 0x40, 0x40, 0x00, 0x00, 0x47, 0x47, 0x00, 0x47, ++ 0x47, 0x00, 0x47, 0x4f, 0x4f, 0x00, 0x47, 0x4f, 0x4f, 0x4f, 0x00, 0x08, 0x08, 0x08, 0x47, 0x47, ++ 0x00, 0x47, 0x47, 0x00, 0x47, 0x4f, 0x4f, 0x00, 0x47, 0x4f, 0x4f, 0x4f, 0x00, 0x08, 0x08, 0x08, ++ 0x18, 0x47, 0x18, 0x40, 0x48, 0x40, 0x00, 0x07, 0x00, 0x08, 0x08, 0x08, 0x00, 0x17, 0x07, 0x47, ++ 0x18, 0x07, 0x40, 0x17, 0x07, 0x47, 0x18, 0x07, 0x40, 0x17, 0x07, 0x47, 0x18, 0x07, 0x40, 0x48, ++ 0x07, 0x08, 0x08, 0x10, 0x18, 0x10, 0x18, 0x0f, 0x17, 0x07, 0x47, 0x17, 0x07, 0x47, 0x40, 0x40, ++ 0x40, 0x17, 0x0f, 0x0f, 0x40, 0x0f, 0x0f, 0x0f, 0x0f, 0x28, 0x27, 0x18, 0x07, 0x18, 0x18, 0x10, ++ 0x40, 0x2f, 0x17, 0x0f, 0x40, 0x0f, 0x0f, 0x0f, 0x10, 0x0f, 0x18, 0x10, 0x10, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x11, 0x00, 0x4f, 0x40, 0x0e, 0x48, 0x51, 0x28, 0x40, 0x00, 0x40, 0x40, 0x07, 0x0f, ++ 0x00, 0x02, 0x40, 0x10, 0x46, 0x02, 0x0a, 0x1b, 0x1b, 0x07, 0x07, 0x07, 0x25, 0x0f, 0x10, 0x07, ++ 0x4e, 0x27, 0x11, 0x0f, 0x40, 0x40, 0x06, 0x40, 0x40, 0x40, 0x00, 0x00, 0x47, 0x46, 0x00, 0x46, ++ 0x46, 0x01, 0x47, 0x4e, 0x4e, 0x02, 0x47, 0x4f, 0x4e, 0x4e, 0x02, 0x09, 0x08, 0x09, 0x47, 0x46, ++ 0x00, 0x46, 0x46, 0x01, 0x47, 0x4e, 0x4e, 0x02, 0x47, 0x4f, 0x4e, 0x4e, 0x02, 0x09, 0x08, 0x09, ++ 0x18, 0x47, 0x1a, 0x40, 0x48, 0x40, 0x00, 0x07, 0x00, 0x08, 0x08, 0x0a, 0x00, 0x17, 0x07, 0x47, ++ 0x18, 0x07, 0x40, 0x17, 0x07, 0x47, 0x18, 0x07, 0x40, 0x17, 0x07, 0x47, 0x18, 0x07, 0x40, 0x48, ++ 0x07, 0x08, 0x08, 0x10, 0x18, 0x10, 0x18, 0x0f, 0x17, 0x07, 0x47, 0x17, 0x07, 0x47, 0x40, 0x40, ++ 0x40, 0x16, 0x0f, 0x0f, 0x40, 0x0f, 0x0f, 0x0f, 0x0f, 0x28, 0x27, 0x18, 0x07, 0x18, 0x18, 0x10, ++ 0x40, 0x2e, 0x17, 0x0f, 0x40, 0x0f, 0x0f, 0x0f, 0x11, 0x0f, 0x19, 0x11, 0x11, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x12, 0x00, 0x4e, 0x40, 0x0d, 0x49, 0x52, 0x28, 0x40, 0x00, 0x40, 0x40, 0x06, 0x0f, ++ 0x00, 0x03, 0x40, 0x10, 0x45, 0x03, 0x0c, 0x1d, 0x1d, 0x07, 0x07, 0x07, 0x24, 0x0f, 0x11, 0x07, ++ 0x4d, 0x27, 0x12, 0x0f, 0x40, 0x40, 0x05, 0x40, 0x40, 0x40, 0x00, 0x00, 0x46, 0x45, 0x01, 0x45, ++ 0x45, 0x02, 0x46, 0x4d, 0x4d, 0x03, 0x46, 0x4e, 0x4d, 0x4d, 0x03, 0x0a, 0x09, 0x0a, 0x46, 0x45, ++ 0x01, 0x45, 0x45, 0x02, 0x46, 0x4d, 0x4d, 0x03, 0x46, 0x4e, 0x4d, 0x4d, 0x03, 0x0a, 0x09, 0x0a, ++ 0x19, 0x47, 0x1c, 0x40, 0x48, 0x40, 0x00, 0x07, 0x00, 0x09, 0x09, 0x0c, 0x01, 0x17, 0x06, 0x47, ++ 0x18, 0x07, 0x40, 0x17, 0x06, 0x47, 0x18, 0x07, 0x40, 0x17, 0x06, 0x47, 0x18, 0x07, 0x40, 0x48, ++ 0x07, 0x08, 0x08, 0x11, 0x19, 0x11, 0x19, 0x0f, 0x17, 0x06, 0x47, 0x17, 0x06, 0x47, 0x40, 0x40, ++ 0x40, 0x15, 0x0f, 0x0f, 0x40, 0x0f, 0x0f, 0x0e, 0x0e, 0x28, 0x27, 0x18, 0x07, 0x19, 0x18, 0x11, ++ 0x40, 0x2c, 0x17, 0x0f, 0x40, 0x0f, 0x0f, 0x0e, 0x12, 0x0f, 0x1a, 0x12, 0x12, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x13, 0x01, 0x4d, 0x40, 0x0c, 0x4a, 0x53, 0x29, 0x40, 0x01, 0x40, 0x40, 0x05, 0x0f, ++ 0x01, 0x05, 0x40, 0x11, 0x43, 0x05, 0x0e, 0x20, 0x20, 0x07, 0x07, 0x06, 0x22, 0x0e, 0x12, 0x07, ++ 0x4c, 0x27, 0x14, 0x0e, 0x40, 0x41, 0x04, 0x40, 0x40, 0x40, 0x01, 0x01, 0x45, 0x44, 0x02, 0x44, ++ 0x43, 0x04, 0x45, 0x4c, 0x4c, 0x05, 0x45, 0x4d, 0x4c, 0x4c, 0x05, 0x0b, 0x0a, 0x0c, 0x45, 0x44, ++ 0x02, 0x44, 0x43, 0x04, 0x45, 0x4c, 0x4c, 0x05, 0x45, 0x4d, 0x4c, 0x4c, 0x05, 0x0b, 0x0a, 0x0c, ++ 0x1a, 0x46, 0x1e, 0x40, 0x49, 0x40, 0x01, 0x07, 0x01, 0x0a, 0x0a, 0x0e, 0x02, 0x16, 0x05, 0x46, ++ 0x19, 0x07, 0x40, 0x16, 0x05, 0x46, 0x19, 0x07, 0x40, 0x16, 0x05, 0x46, 0x19, 0x07, 0x40, 0x49, ++ 0x07, 0x09, 0x09, 0x12, 0x1a, 0x12, 0x1a, 0x0e, 0x17, 0x05, 0x46, 0x17, 0x05, 0x46, 0x40, 0x40, ++ 0x40, 0x14, 0x0e, 0x0e, 0x40, 0x0f, 0x0e, 0x0d, 0x0d, 0x29, 0x27, 0x19, 0x07, 0x1a, 0x19, 0x12, ++ 0x41, 0x2b, 0x16, 0x0e, 0x40, 0x0f, 0x0e, 0x0d, 0x13, 0x0e, 0x1c, 0x13, 0x13, 0x0e, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x14, 0x01, 0x4d, 0x40, 0x0b, 0x4a, 0x54, 0x29, 0x40, 0x01, 0x40, 0x40, 0x05, 0x0f, ++ 0x01, 0x06, 0x40, 0x11, 0x42, 0x06, 0x10, 0x22, 0x22, 0x07, 0x07, 0x06, 0x21, 0x0e, 0x12, 0x07, ++ 0x4b, 0x27, 0x15, 0x0e, 0x40, 0x41, 0x03, 0x40, 0x40, 0x40, 0x01, 0x01, 0x45, 0x43, 0x02, 0x43, ++ 0x42, 0x05, 0x45, 0x4b, 0x4b, 0x06, 0x45, 0x4d, 0x4b, 0x4b, 0x06, 0x0c, 0x0a, 0x0d, 0x45, 0x43, ++ 0x02, 0x43, 0x42, 0x05, 0x45, 0x4b, 0x4b, 0x06, 0x45, 0x4d, 0x4b, 0x4b, 0x06, 0x0c, 0x0a, 0x0d, ++ 0x1a, 0x46, 0x20, 0x40, 0x49, 0x40, 0x01, 0x07, 0x01, 0x0a, 0x0a, 0x10, 0x02, 0x16, 0x05, 0x46, ++ 0x19, 0x07, 0x40, 0x16, 0x05, 0x46, 0x19, 0x07, 0x40, 0x16, 0x05, 0x46, 0x19, 0x07, 0x40, 0x49, ++ 0x07, 0x09, 0x09, 0x12, 0x1a, 0x12, 0x1a, 0x0e, 0x17, 0x05, 0x46, 0x17, 0x05, 0x46, 0x40, 0x40, ++ 0x40, 0x13, 0x0e, 0x0e, 0x40, 0x0f, 0x0e, 0x0d, 0x0d, 0x29, 0x27, 0x19, 0x07, 0x1a, 0x19, 0x12, ++ 0x41, 0x2a, 0x16, 0x0e, 0x40, 0x0f, 0x0e, 0x0d, 0x14, 0x0e, 0x1d, 0x14, 0x14, 0x0e, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x15, 0x01, 0x4c, 0x40, 0x0a, 0x4b, 0x55, 0x29, 0x40, 0x01, 0x40, 0x40, 0x04, 0x0f, ++ 0x01, 0x08, 0x40, 0x11, 0x41, 0x08, 0x12, 0x25, 0x25, 0x07, 0x07, 0x06, 0x1f, 0x0e, 0x13, 0x07, ++ 0x4a, 0x27, 0x16, 0x0e, 0x40, 0x41, 0x02, 0x40, 0x40, 0x40, 0x01, 0x01, 0x44, 0x42, 0x03, 0x42, ++ 0x41, 0x06, 0x44, 0x4a, 0x4a, 0x08, 0x44, 0x4c, 0x4a, 0x4a, 0x08, 0x0d, 0x0b, 0x0e, 0x44, 0x42, ++ 0x03, 0x42, 0x41, 0x06, 0x44, 0x4a, 0x4a, 0x08, 0x44, 0x4c, 0x4a, 0x4a, 0x08, 0x0d, 0x0b, 0x0e, ++ 0x1b, 0x46, 0x22, 0x40, 0x49, 0x40, 0x01, 0x07, 0x01, 0x0b, 0x0b, 0x12, 0x03, 0x16, 0x04, 0x46, ++ 0x19, 0x07, 0x40, 0x16, 0x04, 0x46, 0x19, 0x07, 0x40, 0x16, 0x04, 0x46, 0x19, 0x07, 0x40, 0x49, ++ 0x07, 0x09, 0x09, 0x13, 0x1b, 0x13, 0x1b, 0x0e, 0x17, 0x04, 0x46, 0x17, 0x04, 0x46, 0x40, 0x40, ++ 0x40, 0x12, 0x0e, 0x0e, 0x40, 0x0f, 0x0e, 0x0c, 0x0c, 0x29, 0x27, 0x19, 0x07, 0x1b, 0x19, 0x13, ++ 0x41, 0x29, 0x16, 0x0e, 0x40, 0x0f, 0x0e, 0x0c, 0x15, 0x0e, 0x1e, 0x15, 0x15, 0x0e, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x15, 0x01, 0x4c, 0x40, 0x09, 0x4c, 0x56, 0x29, 0x40, 0x01, 0x40, 0x40, 0x03, 0x0f, ++ 0x01, 0x09, 0x40, 0x11, 0x40, 0x09, 0x13, 0x27, 0x27, 0x07, 0x07, 0x05, 0x1d, 0x0d, 0x13, 0x07, ++ 0x4a, 0x27, 0x17, 0x0d, 0x40, 0x42, 0x01, 0x40, 0x40, 0x40, 0x01, 0x01, 0x44, 0x42, 0x03, 0x42, ++ 0x40, 0x07, 0x44, 0x4a, 0x4a, 0x09, 0x44, 0x4c, 0x4a, 0x4a, 0x09, 0x0d, 0x0b, 0x0f, 0x44, 0x42, ++ 0x03, 0x42, 0x40, 0x07, 0x44, 0x4a, 0x4a, 0x09, 0x44, 0x4c, 0x4a, 0x4a, 0x09, 0x0d, 0x0b, 0x0f, ++ 0x1b, 0x46, 0x23, 0x40, 0x4a, 0x40, 0x01, 0x07, 0x01, 0x0b, 0x0b, 0x13, 0x03, 0x15, 0x03, 0x46, ++ 0x19, 0x07, 0x40, 0x15, 0x03, 0x46, 0x19, 0x07, 0x40, 0x15, 0x03, 0x46, 0x19, 0x07, 0x40, 0x4a, ++ 0x07, 0x09, 0x09, 0x13, 0x1b, 0x13, 0x1b, 0x0d, 0x17, 0x03, 0x46, 0x17, 0x03, 0x46, 0x40, 0x40, ++ 0x40, 0x11, 0x0d, 0x0d, 0x40, 0x0f, 0x0d, 0x0b, 0x0b, 0x29, 0x27, 0x19, 0x07, 0x1b, 0x19, 0x13, ++ 0x42, 0x27, 0x15, 0x0d, 0x40, 0x0f, 0x0d, 0x0b, 0x15, 0x0d, 0x1f, 0x15, 0x15, 0x0d, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x16, 0x02, 0x4b, 0x40, 0x09, 0x4c, 0x56, 0x2a, 0x40, 0x02, 0x40, 0x40, 0x03, 0x0f, ++ 0x02, 0x0b, 0x40, 0x12, 0x01, 0x0b, 0x15, 0x2a, 0x2a, 0x07, 0x07, 0x05, 0x1c, 0x0d, 0x14, 0x07, ++ 0x49, 0x27, 0x19, 0x0d, 0x40, 0x42, 0x01, 0x40, 0x40, 0x40, 0x02, 0x02, 0x43, 0x41, 0x04, 0x41, ++ 0x01, 0x09, 0x43, 0x49, 0x49, 0x0b, 0x43, 0x4b, 0x49, 0x49, 0x0b, 0x0e, 0x0c, 0x11, 0x43, 0x41, ++ 0x04, 0x41, 0x01, 0x09, 0x43, 0x49, 0x49, 0x0b, 0x43, 0x4b, 0x49, 0x49, 0x0b, 0x0e, 0x0c, 0x11, ++ 0x1c, 0x45, 0x25, 0x40, 0x4a, 0x40, 0x02, 0x07, 0x02, 0x0c, 0x0c, 0x15, 0x04, 0x15, 0x03, 0x45, ++ 0x1a, 0x07, 0x40, 0x15, 0x03, 0x45, 0x1a, 0x07, 0x40, 0x15, 0x03, 0x45, 0x1a, 0x07, 0x40, 0x4a, ++ 0x07, 0x0a, 0x0a, 0x14, 0x1c, 0x14, 0x1c, 0x0d, 0x17, 0x03, 0x45, 0x17, 0x03, 0x45, 0x40, 0x40, ++ 0x40, 0x11, 0x0d, 0x0d, 0x40, 0x0f, 0x0d, 0x0b, 0x0b, 0x2a, 0x27, 0x1a, 0x07, 0x1c, 0x1a, 0x14, ++ 0x42, 0x26, 0x15, 0x0d, 0x40, 0x0f, 0x0d, 0x0b, 0x16, 0x0d, 0x21, 0x16, 0x16, 0x0d, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x17, 0x02, 0x4a, 0x40, 0x08, 0x4d, 0x57, 0x2a, 0x40, 0x02, 0x40, 0x40, 0x02, 0x0f, ++ 0x02, 0x0d, 0x40, 0x12, 0x02, 0x0d, 0x17, 0x2c, 0x2c, 0x07, 0x07, 0x05, 0x1a, 0x0d, 0x15, 0x07, ++ 0x48, 0x27, 0x1a, 0x0d, 0x40, 0x42, 0x00, 0x40, 0x40, 0x40, 0x02, 0x02, 0x42, 0x40, 0x05, 0x40, ++ 0x02, 0x0a, 0x42, 0x48, 0x48, 0x0d, 0x42, 0x4a, 0x48, 0x48, 0x0d, 0x0f, 0x0d, 0x12, 0x42, 0x40, ++ 0x05, 0x40, 0x02, 0x0a, 0x42, 0x48, 0x48, 0x0d, 0x42, 0x4a, 0x48, 0x48, 0x0d, 0x0f, 0x0d, 0x12, ++ 0x1d, 0x45, 0x27, 0x40, 0x4a, 0x40, 0x02, 0x07, 0x02, 0x0d, 0x0d, 0x17, 0x05, 0x15, 0x02, 0x45, ++ 0x1a, 0x07, 0x40, 0x15, 0x02, 0x45, 0x1a, 0x07, 0x40, 0x15, 0x02, 0x45, 0x1a, 0x07, 0x40, 0x4a, ++ 0x07, 0x0a, 0x0a, 0x15, 0x1d, 0x15, 0x1d, 0x0d, 0x17, 0x02, 0x45, 0x17, 0x02, 0x45, 0x40, 0x40, ++ 0x40, 0x10, 0x0d, 0x0d, 0x40, 0x0f, 0x0d, 0x0a, 0x0a, 0x2a, 0x27, 0x1a, 0x07, 0x1d, 0x1a, 0x15, ++ 0x42, 0x25, 0x15, 0x0d, 0x40, 0x0f, 0x0d, 0x0a, 0x17, 0x0d, 0x22, 0x17, 0x17, 0x0d, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x18, 0x02, 0x4a, 0x40, 0x07, 0x4d, 0x58, 0x2a, 0x40, 0x02, 0x40, 0x40, 0x02, 0x0f, ++ 0x02, 0x0e, 0x40, 0x12, 0x03, 0x0e, 0x19, 0x2f, 0x2f, 0x07, 0x07, 0x05, 0x19, 0x0d, 0x15, 0x07, ++ 0x47, 0x27, 0x1b, 0x0d, 0x40, 0x42, 0x40, 0x40, 0x40, 0x40, 0x02, 0x02, 0x42, 0x00, 0x05, 0x00, ++ 0x03, 0x0b, 0x42, 0x47, 0x47, 0x0e, 0x42, 0x4a, 0x47, 0x47, 0x0e, 0x10, 0x0d, 0x13, 0x42, 0x00, ++ 0x05, 0x00, 0x03, 0x0b, 0x42, 0x47, 0x47, 0x0e, 0x42, 0x4a, 0x47, 0x47, 0x0e, 0x10, 0x0d, 0x13, ++ 0x1d, 0x45, 0x29, 0x40, 0x4a, 0x40, 0x02, 0x07, 0x02, 0x0d, 0x0d, 0x19, 0x05, 0x15, 0x02, 0x45, ++ 0x1a, 0x07, 0x40, 0x15, 0x02, 0x45, 0x1a, 0x07, 0x40, 0x15, 0x02, 0x45, 0x1a, 0x07, 0x40, 0x4a, ++ 0x07, 0x0a, 0x0a, 0x15, 0x1d, 0x15, 0x1d, 0x0d, 0x17, 0x02, 0x45, 0x17, 0x02, 0x45, 0x40, 0x40, ++ 0x40, 0x0f, 0x0d, 0x0d, 0x40, 0x0f, 0x0d, 0x0a, 0x0a, 0x2a, 0x27, 0x1a, 0x07, 0x1d, 0x1a, 0x15, ++ 0x42, 0x24, 0x15, 0x0d, 0x40, 0x0f, 0x0d, 0x0a, 0x18, 0x0d, 0x23, 0x18, 0x18, 0x0d, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x19, 0x03, 0x49, 0x40, 0x06, 0x4e, 0x59, 0x2b, 0x40, 0x03, 0x40, 0x40, 0x01, 0x0f, ++ 0x03, 0x10, 0x40, 0x13, 0x04, 0x10, 0x1b, 0x31, 0x31, 0x07, 0x07, 0x04, 0x17, 0x0c, 0x16, 0x07, ++ 0x46, 0x27, 0x1c, 0x0c, 0x40, 0x43, 0x41, 0x40, 0x40, 0x40, 0x03, 0x03, 0x41, 0x01, 0x06, 0x01, ++ 0x04, 0x0c, 0x41, 0x46, 0x46, 0x10, 0x41, 0x49, 0x46, 0x46, 0x10, 0x11, 0x0e, 0x14, 0x41, 0x01, ++ 0x06, 0x01, 0x04, 0x0c, 0x41, 0x46, 0x46, 0x10, 0x41, 0x49, 0x46, 0x46, 0x10, 0x11, 0x0e, 0x14, ++ 0x1e, 0x44, 0x2b, 0x40, 0x4b, 0x40, 0x03, 0x07, 0x03, 0x0e, 0x0e, 0x1b, 0x06, 0x14, 0x01, 0x44, ++ 0x1b, 0x07, 0x40, 0x14, 0x01, 0x44, 0x1b, 0x07, 0x40, 0x14, 0x01, 0x44, 0x1b, 0x07, 0x40, 0x4b, ++ 0x07, 0x0b, 0x0b, 0x16, 0x1e, 0x16, 0x1e, 0x0c, 0x17, 0x01, 0x44, 0x17, 0x01, 0x44, 0x40, 0x40, ++ 0x40, 0x0e, 0x0c, 0x0c, 0x40, 0x0f, 0x0c, 0x09, 0x09, 0x2b, 0x27, 0x1b, 0x07, 0x1e, 0x1b, 0x16, ++ 0x43, 0x22, 0x14, 0x0c, 0x40, 0x0f, 0x0c, 0x09, 0x19, 0x0c, 0x24, 0x19, 0x19, 0x0c, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x1a, 0x03, 0x48, 0x40, 0x05, 0x4f, 0x5a, 0x2b, 0x40, 0x03, 0x40, 0x40, 0x00, 0x0f, ++ 0x03, 0x11, 0x40, 0x13, 0x06, 0x11, 0x1d, 0x34, 0x34, 0x07, 0x07, 0x04, 0x16, 0x0c, 0x17, 0x07, ++ 0x45, 0x27, 0x1e, 0x0c, 0x40, 0x43, 0x42, 0x40, 0x40, 0x40, 0x03, 0x03, 0x40, 0x02, 0x07, 0x02, ++ 0x06, 0x0e, 0x40, 0x45, 0x45, 0x11, 0x40, 0x48, 0x45, 0x45, 0x11, 0x12, 0x0f, 0x16, 0x40, 0x02, ++ 0x07, 0x02, 0x06, 0x0e, 0x40, 0x45, 0x45, 0x11, 0x40, 0x48, 0x45, 0x45, 0x11, 0x12, 0x0f, 0x16, ++ 0x1f, 0x44, 0x2d, 0x40, 0x4b, 0x40, 0x03, 0x07, 0x03, 0x0f, 0x0f, 0x1d, 0x07, 0x14, 0x00, 0x44, ++ 0x1b, 0x07, 0x40, 0x14, 0x00, 0x44, 0x1b, 0x07, 0x40, 0x14, 0x00, 0x44, 0x1b, 0x07, 0x40, 0x4b, ++ 0x07, 0x0b, 0x0b, 0x17, 0x1f, 0x17, 0x1f, 0x0c, 0x17, 0x00, 0x44, 0x17, 0x00, 0x44, 0x40, 0x40, ++ 0x40, 0x0d, 0x0c, 0x0c, 0x40, 0x0f, 0x0c, 0x08, 0x08, 0x2b, 0x27, 0x1b, 0x07, 0x1f, 0x1b, 0x17, ++ 0x43, 0x21, 0x14, 0x0c, 0x40, 0x0f, 0x0c, 0x08, 0x1a, 0x0c, 0x26, 0x1a, 0x1a, 0x0c, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x1b, 0x03, 0x48, 0x40, 0x04, 0x4f, 0x5b, 0x2b, 0x40, 0x03, 0x40, 0x40, 0x00, 0x0f, ++ 0x03, 0x13, 0x40, 0x13, 0x07, 0x13, 0x1f, 0x36, 0x36, 0x07, 0x07, 0x04, 0x14, 0x0c, 0x17, 0x07, ++ 0x44, 0x27, 0x1f, 0x0c, 0x40, 0x43, 0x43, 0x40, 0x40, 0x40, 0x03, 0x03, 0x40, 0x03, 0x07, 0x03, ++ 0x07, 0x0f, 0x40, 0x44, 0x44, 0x13, 0x40, 0x48, 0x44, 0x44, 0x13, 0x13, 0x0f, 0x17, 0x40, 0x03, ++ 0x07, 0x03, 0x07, 0x0f, 0x40, 0x44, 0x44, 0x13, 0x40, 0x48, 0x44, 0x44, 0x13, 0x13, 0x0f, 0x17, ++ 0x1f, 0x44, 0x2f, 0x40, 0x4b, 0x40, 0x03, 0x07, 0x03, 0x0f, 0x0f, 0x1f, 0x07, 0x14, 0x00, 0x44, ++ 0x1b, 0x07, 0x40, 0x14, 0x00, 0x44, 0x1b, 0x07, 0x40, 0x14, 0x00, 0x44, 0x1b, 0x07, 0x40, 0x4b, ++ 0x07, 0x0b, 0x0b, 0x17, 0x1f, 0x17, 0x1f, 0x0c, 0x17, 0x00, 0x44, 0x17, 0x00, 0x44, 0x40, 0x40, ++ 0x40, 0x0c, 0x0c, 0x0c, 0x40, 0x0f, 0x0c, 0x08, 0x08, 0x2b, 0x27, 0x1b, 0x07, 0x1f, 0x1b, 0x17, ++ 0x43, 0x20, 0x14, 0x0c, 0x40, 0x0f, 0x0c, 0x08, 0x1b, 0x0c, 0x27, 0x1b, 0x1b, 0x0c, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x1c, 0x04, 0x47, 0x40, 0x03, 0x50, 0x5c, 0x2c, 0x40, 0x04, 0x40, 0x40, 0x40, 0x0f, ++ 0x04, 0x14, 0x40, 0x14, 0x08, 0x14, 0x21, 0x39, 0x39, 0x07, 0x07, 0x03, 0x13, 0x0b, 0x18, 0x07, ++ 0x43, 0x27, 0x20, 0x0b, 0x40, 0x44, 0x44, 0x40, 0x40, 0x40, 0x04, 0x04, 0x00, 0x04, 0x08, 0x04, ++ 0x08, 0x10, 0x00, 0x43, 0x43, 0x14, 0x00, 0x47, 0x43, 0x43, 0x14, 0x14, 0x10, 0x18, 0x00, 0x04, ++ 0x08, 0x04, 0x08, 0x10, 0x00, 0x43, 0x43, 0x14, 0x00, 0x47, 0x43, 0x43, 0x14, 0x14, 0x10, 0x18, ++ 0x20, 0x43, 0x31, 0x40, 0x4c, 0x40, 0x04, 0x07, 0x04, 0x10, 0x10, 0x21, 0x08, 0x13, 0x40, 0x43, ++ 0x1c, 0x07, 0x40, 0x13, 0x40, 0x43, 0x1c, 0x07, 0x40, 0x13, 0x40, 0x43, 0x1c, 0x07, 0x40, 0x4c, ++ 0x07, 0x0c, 0x0c, 0x18, 0x20, 0x18, 0x20, 0x0b, 0x17, 0x40, 0x43, 0x17, 0x40, 0x43, 0x40, 0x40, ++ 0x40, 0x0b, 0x0b, 0x0b, 0x40, 0x0f, 0x0b, 0x07, 0x07, 0x2c, 0x27, 0x1c, 0x07, 0x20, 0x1c, 0x18, ++ 0x44, 0x1f, 0x13, 0x0b, 0x40, 0x0f, 0x0b, 0x07, 0x1c, 0x0b, 0x28, 0x1c, 0x1c, 0x0b, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x1d, 0x04, 0x47, 0x40, 0x02, 0x51, 0x5d, 0x2c, 0x40, 0x04, 0x40, 0x40, 0x41, 0x0f, ++ 0x04, 0x16, 0x40, 0x14, 0x09, 0x16, 0x22, 0x3b, 0x3b, 0x07, 0x07, 0x03, 0x11, 0x0b, 0x18, 0x07, ++ 0x42, 0x27, 0x21, 0x0b, 0x40, 0x44, 0x45, 0x40, 0x40, 0x40, 0x04, 0x04, 0x00, 0x05, 0x08, 0x05, ++ 0x09, 0x11, 0x00, 0x42, 0x42, 0x16, 0x00, 0x47, 0x42, 0x42, 0x16, 0x15, 0x10, 0x19, 0x00, 0x05, ++ 0x08, 0x05, 0x09, 0x11, 0x00, 0x42, 0x42, 0x16, 0x00, 0x47, 0x42, 0x42, 0x16, 0x15, 0x10, 0x19, ++ 0x20, 0x43, 0x32, 0x40, 0x4c, 0x40, 0x04, 0x07, 0x04, 0x10, 0x10, 0x22, 0x08, 0x13, 0x41, 0x43, ++ 0x1c, 0x07, 0x40, 0x13, 0x41, 0x43, 0x1c, 0x07, 0x40, 0x13, 0x41, 0x43, 0x1c, 0x07, 0x40, 0x4c, ++ 0x07, 0x0c, 0x0c, 0x18, 0x20, 0x18, 0x20, 0x0b, 0x17, 0x41, 0x43, 0x17, 0x41, 0x43, 0x40, 0x40, ++ 0x40, 0x0a, 0x0b, 0x0b, 0x40, 0x0f, 0x0b, 0x06, 0x06, 0x2c, 0x27, 0x1c, 0x07, 0x20, 0x1c, 0x18, ++ 0x44, 0x1d, 0x13, 0x0b, 0x40, 0x0f, 0x0b, 0x06, 0x1d, 0x0b, 0x29, 0x1d, 0x1d, 0x0b, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x1e, 0x04, 0x46, 0x40, 0x01, 0x51, 0x5e, 0x2c, 0x40, 0x04, 0x40, 0x40, 0x41, 0x0f, ++ 0x04, 0x18, 0x40, 0x14, 0x0b, 0x18, 0x24, 0x3e, 0x3e, 0x07, 0x07, 0x03, 0x0f, 0x0b, 0x19, 0x07, ++ 0x41, 0x27, 0x23, 0x0b, 0x40, 0x44, 0x46, 0x40, 0x40, 0x40, 0x04, 0x04, 0x01, 0x06, 0x09, 0x06, ++ 0x0b, 0x13, 0x01, 0x41, 0x41, 0x18, 0x01, 0x46, 0x41, 0x41, 0x18, 0x16, 0x11, 0x1b, 0x01, 0x06, ++ 0x09, 0x06, 0x0b, 0x13, 0x01, 0x41, 0x41, 0x18, 0x01, 0x46, 0x41, 0x41, 0x18, 0x16, 0x11, 0x1b, ++ 0x21, 0x43, 0x34, 0x40, 0x4c, 0x40, 0x04, 0x07, 0x04, 0x11, 0x11, 0x24, 0x09, 0x13, 0x41, 0x43, ++ 0x1c, 0x07, 0x40, 0x13, 0x41, 0x43, 0x1c, 0x07, 0x40, 0x13, 0x41, 0x43, 0x1c, 0x07, 0x40, 0x4c, ++ 0x07, 0x0c, 0x0c, 0x19, 0x21, 0x19, 0x21, 0x0b, 0x17, 0x41, 0x43, 0x17, 0x41, 0x43, 0x40, 0x40, ++ 0x40, 0x09, 0x0b, 0x0b, 0x40, 0x0f, 0x0b, 0x06, 0x06, 0x2c, 0x27, 0x1c, 0x07, 0x21, 0x1c, 0x19, ++ 0x44, 0x1c, 0x13, 0x0b, 0x40, 0x0f, 0x0b, 0x06, 0x1e, 0x0b, 0x2b, 0x1e, 0x1e, 0x0b, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x1f, 0x05, 0x45, 0x40, 0x00, 0x52, 0x5f, 0x2d, 0x40, 0x05, 0x40, 0x40, 0x42, 0x0f, ++ 0x05, 0x19, 0x40, 0x15, 0x0c, 0x19, 0x26, 0x3e, 0x3e, 0x07, 0x07, 0x02, 0x0e, 0x0a, 0x1a, 0x07, ++ 0x40, 0x27, 0x24, 0x0a, 0x40, 0x45, 0x47, 0x40, 0x40, 0x40, 0x05, 0x05, 0x02, 0x07, 0x0a, 0x07, ++ 0x0c, 0x14, 0x02, 0x40, 0x40, 0x19, 0x02, 0x45, 0x40, 0x40, 0x19, 0x17, 0x12, 0x1c, 0x02, 0x07, ++ 0x0a, 0x07, 0x0c, 0x14, 0x02, 0x40, 0x40, 0x19, 0x02, 0x45, 0x40, 0x40, 0x19, 0x17, 0x12, 0x1c, ++ 0x22, 0x42, 0x36, 0x40, 0x4d, 0x40, 0x05, 0x07, 0x05, 0x12, 0x12, 0x26, 0x0a, 0x12, 0x42, 0x42, ++ 0x1d, 0x07, 0x40, 0x12, 0x42, 0x42, 0x1d, 0x07, 0x40, 0x12, 0x42, 0x42, 0x1d, 0x07, 0x40, 0x4d, ++ 0x07, 0x0d, 0x0d, 0x1a, 0x22, 0x1a, 0x22, 0x0a, 0x17, 0x42, 0x42, 0x17, 0x42, 0x42, 0x40, 0x40, ++ 0x40, 0x08, 0x0a, 0x0a, 0x40, 0x0f, 0x0a, 0x05, 0x05, 0x2d, 0x27, 0x1d, 0x07, 0x22, 0x1d, 0x1a, ++ 0x45, 0x1b, 0x12, 0x0a, 0x40, 0x0f, 0x0a, 0x05, 0x1f, 0x0a, 0x2c, 0x1f, 0x1f, 0x0a, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x20, 0x05, 0x45, 0x40, 0x40, 0x52, 0x60, 0x2d, 0x40, 0x05, 0x40, 0x40, 0x42, 0x0f, ++ 0x05, 0x1b, 0x40, 0x15, 0x0d, 0x1b, 0x28, 0x3e, 0x3e, 0x07, 0x07, 0x02, 0x0c, 0x0a, 0x1a, 0x07, ++ 0x00, 0x27, 0x25, 0x0a, 0x40, 0x45, 0x48, 0x40, 0x40, 0x40, 0x05, 0x05, 0x02, 0x08, 0x0a, 0x08, ++ 0x0d, 0x15, 0x02, 0x00, 0x00, 0x1b, 0x02, 0x45, 0x00, 0x00, 0x1b, 0x18, 0x12, 0x1d, 0x02, 0x08, ++ 0x0a, 0x08, 0x0d, 0x15, 0x02, 0x00, 0x00, 0x1b, 0x02, 0x45, 0x00, 0x00, 0x1b, 0x18, 0x12, 0x1d, ++ 0x22, 0x42, 0x38, 0x40, 0x4d, 0x40, 0x05, 0x07, 0x05, 0x12, 0x12, 0x28, 0x0a, 0x12, 0x42, 0x42, ++ 0x1d, 0x07, 0x40, 0x12, 0x42, 0x42, 0x1d, 0x07, 0x40, 0x12, 0x42, 0x42, 0x1d, 0x07, 0x40, 0x4d, ++ 0x07, 0x0d, 0x0d, 0x1a, 0x22, 0x1a, 0x22, 0x0a, 0x17, 0x42, 0x42, 0x17, 0x42, 0x42, 0x40, 0x40, ++ 0x40, 0x07, 0x0a, 0x0a, 0x40, 0x0f, 0x0a, 0x05, 0x05, 0x2d, 0x27, 0x1d, 0x07, 0x22, 0x1d, 0x1a, ++ 0x45, 0x1a, 0x12, 0x0a, 0x40, 0x0f, 0x0a, 0x05, 0x20, 0x0a, 0x2d, 0x20, 0x20, 0x0a, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x21, 0x05, 0x44, 0x40, 0x41, 0x53, 0x61, 0x2d, 0x40, 0x05, 0x40, 0x40, 0x43, 0x0f, ++ 0x05, 0x1c, 0x40, 0x15, 0x0e, 0x1c, 0x2a, 0x3e, 0x3e, 0x07, 0x07, 0x02, 0x0b, 0x0a, 0x1b, 0x07, ++ 0x01, 0x27, 0x26, 0x0a, 0x40, 0x45, 0x49, 0x40, 0x40, 0x40, 0x05, 0x05, 0x03, 0x09, 0x0b, 0x09, ++ 0x0e, 0x16, 0x03, 0x01, 0x01, 0x1c, 0x03, 0x44, 0x01, 0x01, 0x1c, 0x19, 0x13, 0x1e, 0x03, 0x09, ++ 0x0b, 0x09, 0x0e, 0x16, 0x03, 0x01, 0x01, 0x1c, 0x03, 0x44, 0x01, 0x01, 0x1c, 0x19, 0x13, 0x1e, ++ 0x23, 0x42, 0x3a, 0x40, 0x4d, 0x40, 0x05, 0x07, 0x05, 0x13, 0x13, 0x2a, 0x0b, 0x12, 0x43, 0x42, ++ 0x1d, 0x07, 0x40, 0x12, 0x43, 0x42, 0x1d, 0x07, 0x40, 0x12, 0x43, 0x42, 0x1d, 0x07, 0x40, 0x4d, ++ 0x07, 0x0d, 0x0d, 0x1b, 0x23, 0x1b, 0x23, 0x0a, 0x17, 0x43, 0x42, 0x17, 0x43, 0x42, 0x40, 0x40, ++ 0x40, 0x06, 0x0a, 0x0a, 0x40, 0x0f, 0x0a, 0x04, 0x04, 0x2d, 0x27, 0x1d, 0x07, 0x23, 0x1d, 0x1b, ++ 0x45, 0x18, 0x12, 0x0a, 0x40, 0x0f, 0x0a, 0x04, 0x21, 0x0a, 0x2e, 0x21, 0x21, 0x0a, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x22, 0x06, 0x43, 0x40, 0x42, 0x54, 0x62, 0x2e, 0x40, 0x06, 0x40, 0x40, 0x44, 0x0f, ++ 0x06, 0x1e, 0x40, 0x16, 0x10, 0x1e, 0x2c, 0x3e, 0x3e, 0x07, 0x07, 0x01, 0x09, 0x09, 0x1c, 0x07, ++ 0x02, 0x27, 0x28, 0x09, 0x40, 0x46, 0x4a, 0x40, 0x40, 0x40, 0x06, 0x06, 0x04, 0x0a, 0x0c, 0x0a, ++ 0x10, 0x18, 0x04, 0x02, 0x02, 0x1e, 0x04, 0x43, 0x02, 0x02, 0x1e, 0x1a, 0x14, 0x20, 0x04, 0x0a, ++ 0x0c, 0x0a, 0x10, 0x18, 0x04, 0x02, 0x02, 0x1e, 0x04, 0x43, 0x02, 0x02, 0x1e, 0x1a, 0x14, 0x20, ++ 0x24, 0x41, 0x3c, 0x40, 0x4e, 0x40, 0x06, 0x07, 0x06, 0x14, 0x14, 0x2c, 0x0c, 0x11, 0x44, 0x41, ++ 0x1e, 0x07, 0x40, 0x11, 0x44, 0x41, 0x1e, 0x07, 0x40, 0x11, 0x44, 0x41, 0x1e, 0x07, 0x40, 0x4e, ++ 0x07, 0x0e, 0x0e, 0x1c, 0x24, 0x1c, 0x24, 0x09, 0x17, 0x44, 0x41, 0x17, 0x44, 0x41, 0x40, 0x40, ++ 0x40, 0x05, 0x09, 0x09, 0x40, 0x0f, 0x09, 0x03, 0x03, 0x2e, 0x27, 0x1e, 0x07, 0x24, 0x1e, 0x1c, ++ 0x46, 0x17, 0x11, 0x09, 0x40, 0x0f, 0x09, 0x03, 0x22, 0x09, 0x30, 0x22, 0x22, 0x09, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x23, 0x06, 0x43, 0x40, 0x43, 0x54, 0x63, 0x2e, 0x40, 0x06, 0x40, 0x40, 0x44, 0x0f, ++ 0x06, 0x1f, 0x40, 0x16, 0x11, 0x1f, 0x2e, 0x3e, 0x3e, 0x07, 0x07, 0x01, 0x08, 0x09, 0x1c, 0x07, ++ 0x03, 0x27, 0x29, 0x09, 0x40, 0x46, 0x4b, 0x40, 0x40, 0x40, 0x06, 0x06, 0x04, 0x0b, 0x0c, 0x0b, ++ 0x11, 0x19, 0x04, 0x03, 0x03, 0x1f, 0x04, 0x43, 0x03, 0x03, 0x1f, 0x1b, 0x14, 0x21, 0x04, 0x0b, ++ 0x0c, 0x0b, 0x11, 0x19, 0x04, 0x03, 0x03, 0x1f, 0x04, 0x43, 0x03, 0x03, 0x1f, 0x1b, 0x14, 0x21, ++ 0x24, 0x41, 0x3e, 0x40, 0x4e, 0x40, 0x06, 0x07, 0x06, 0x14, 0x14, 0x2e, 0x0c, 0x11, 0x44, 0x41, ++ 0x1e, 0x07, 0x40, 0x11, 0x44, 0x41, 0x1e, 0x07, 0x40, 0x11, 0x44, 0x41, 0x1e, 0x07, 0x40, 0x4e, ++ 0x07, 0x0e, 0x0e, 0x1c, 0x24, 0x1c, 0x24, 0x09, 0x17, 0x44, 0x41, 0x17, 0x44, 0x41, 0x40, 0x40, ++ 0x40, 0x04, 0x09, 0x09, 0x40, 0x0f, 0x09, 0x03, 0x03, 0x2e, 0x27, 0x1e, 0x07, 0x24, 0x1e, 0x1c, ++ 0x46, 0x16, 0x11, 0x09, 0x40, 0x0f, 0x09, 0x03, 0x23, 0x09, 0x31, 0x23, 0x23, 0x09, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x24, 0x06, 0x42, 0x40, 0x44, 0x55, 0x64, 0x2e, 0x40, 0x06, 0x40, 0x40, 0x45, 0x0f, ++ 0x06, 0x21, 0x40, 0x16, 0x12, 0x21, 0x30, 0x3e, 0x3e, 0x07, 0x07, 0x01, 0x06, 0x09, 0x1d, 0x07, ++ 0x04, 0x27, 0x2a, 0x09, 0x40, 0x46, 0x4c, 0x40, 0x40, 0x40, 0x06, 0x06, 0x05, 0x0c, 0x0d, 0x0c, ++ 0x12, 0x1a, 0x05, 0x04, 0x04, 0x21, 0x05, 0x42, 0x04, 0x04, 0x21, 0x1c, 0x15, 0x22, 0x05, 0x0c, ++ 0x0d, 0x0c, 0x12, 0x1a, 0x05, 0x04, 0x04, 0x21, 0x05, 0x42, 0x04, 0x04, 0x21, 0x1c, 0x15, 0x22, ++ 0x25, 0x41, 0x3e, 0x40, 0x4e, 0x40, 0x06, 0x07, 0x06, 0x15, 0x15, 0x30, 0x0d, 0x11, 0x45, 0x41, ++ 0x1e, 0x07, 0x40, 0x11, 0x45, 0x41, 0x1e, 0x07, 0x40, 0x11, 0x45, 0x41, 0x1e, 0x07, 0x40, 0x4e, ++ 0x07, 0x0e, 0x0e, 0x1d, 0x25, 0x1d, 0x25, 0x09, 0x17, 0x45, 0x41, 0x17, 0x45, 0x41, 0x40, 0x40, ++ 0x40, 0x03, 0x09, 0x09, 0x40, 0x0f, 0x09, 0x02, 0x02, 0x2e, 0x27, 0x1e, 0x07, 0x25, 0x1e, 0x1d, ++ 0x46, 0x15, 0x11, 0x09, 0x40, 0x0f, 0x09, 0x02, 0x24, 0x09, 0x32, 0x24, 0x24, 0x09, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x24, 0x06, 0x42, 0x40, 0x45, 0x56, 0x65, 0x2e, 0x40, 0x06, 0x40, 0x40, 0x46, 0x0f, ++ 0x06, 0x22, 0x40, 0x16, 0x13, 0x22, 0x31, 0x3e, 0x3e, 0x07, 0x07, 0x00, 0x04, 0x08, 0x1d, 0x07, ++ 0x04, 0x27, 0x2b, 0x08, 0x40, 0x47, 0x4d, 0x40, 0x40, 0x40, 0x06, 0x06, 0x05, 0x0c, 0x0d, 0x0c, ++ 0x13, 0x1b, 0x05, 0x04, 0x04, 0x22, 0x05, 0x42, 0x04, 0x04, 0x22, 0x1c, 0x15, 0x23, 0x05, 0x0c, ++ 0x0d, 0x0c, 0x13, 0x1b, 0x05, 0x04, 0x04, 0x22, 0x05, 0x42, 0x04, 0x04, 0x22, 0x1c, 0x15, 0x23, ++ 0x25, 0x41, 0x3e, 0x40, 0x4f, 0x40, 0x06, 0x07, 0x06, 0x15, 0x15, 0x31, 0x0d, 0x10, 0x46, 0x41, ++ 0x1e, 0x07, 0x40, 0x10, 0x46, 0x41, 0x1e, 0x07, 0x40, 0x10, 0x46, 0x41, 0x1e, 0x07, 0x40, 0x4f, ++ 0x07, 0x0e, 0x0e, 0x1d, 0x25, 0x1d, 0x25, 0x08, 0x17, 0x46, 0x41, 0x17, 0x46, 0x41, 0x40, 0x40, ++ 0x40, 0x02, 0x08, 0x08, 0x40, 0x0f, 0x08, 0x01, 0x01, 0x2e, 0x27, 0x1e, 0x07, 0x25, 0x1e, 0x1d, ++ 0x47, 0x13, 0x10, 0x08, 0x40, 0x0f, 0x08, 0x01, 0x24, 0x08, 0x33, 0x24, 0x24, 0x08, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x25, 0x07, 0x41, 0x40, 0x45, 0x56, 0x65, 0x2f, 0x40, 0x07, 0x40, 0x40, 0x46, 0x0f, ++ 0x07, 0x24, 0x40, 0x17, 0x15, 0x24, 0x33, 0x3e, 0x3e, 0x07, 0x07, 0x00, 0x03, 0x08, 0x1e, 0x07, ++ 0x05, 0x27, 0x2d, 0x08, 0x40, 0x47, 0x4d, 0x40, 0x40, 0x40, 0x07, 0x07, 0x06, 0x0d, 0x0e, 0x0d, ++ 0x15, 0x1d, 0x06, 0x05, 0x05, 0x24, 0x06, 0x41, 0x05, 0x05, 0x24, 0x1d, 0x16, 0x25, 0x06, 0x0d, ++ 0x0e, 0x0d, 0x15, 0x1d, 0x06, 0x05, 0x05, 0x24, 0x06, 0x41, 0x05, 0x05, 0x24, 0x1d, 0x16, 0x25, ++ 0x26, 0x40, 0x3e, 0x40, 0x4f, 0x40, 0x07, 0x07, 0x07, 0x16, 0x16, 0x33, 0x0e, 0x10, 0x46, 0x40, ++ 0x1f, 0x07, 0x40, 0x10, 0x46, 0x40, 0x1f, 0x07, 0x40, 0x10, 0x46, 0x40, 0x1f, 0x07, 0x40, 0x4f, ++ 0x07, 0x0f, 0x0f, 0x1e, 0x26, 0x1e, 0x26, 0x08, 0x17, 0x46, 0x40, 0x17, 0x46, 0x40, 0x40, 0x40, ++ 0x40, 0x02, 0x08, 0x08, 0x40, 0x0f, 0x08, 0x01, 0x01, 0x2f, 0x27, 0x1f, 0x07, 0x26, 0x1f, 0x1e, ++ 0x47, 0x12, 0x10, 0x08, 0x40, 0x0f, 0x08, 0x01, 0x25, 0x08, 0x35, 0x25, 0x25, 0x08, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x26, 0x07, 0x40, 0x40, 0x46, 0x57, 0x66, 0x2f, 0x40, 0x07, 0x40, 0x40, 0x47, 0x0f, ++ 0x07, 0x26, 0x40, 0x17, 0x16, 0x26, 0x35, 0x3e, 0x3e, 0x07, 0x07, 0x00, 0x01, 0x08, 0x1f, 0x07, ++ 0x06, 0x27, 0x2e, 0x08, 0x40, 0x47, 0x4e, 0x40, 0x40, 0x40, 0x07, 0x07, 0x07, 0x0e, 0x0f, 0x0e, ++ 0x16, 0x1e, 0x07, 0x06, 0x06, 0x26, 0x07, 0x40, 0x06, 0x06, 0x26, 0x1e, 0x17, 0x26, 0x07, 0x0e, ++ 0x0f, 0x0e, 0x16, 0x1e, 0x07, 0x06, 0x06, 0x26, 0x07, 0x40, 0x06, 0x06, 0x26, 0x1e, 0x17, 0x26, ++ 0x27, 0x40, 0x3e, 0x40, 0x4f, 0x40, 0x07, 0x07, 0x07, 0x17, 0x17, 0x35, 0x0f, 0x10, 0x47, 0x40, ++ 0x1f, 0x07, 0x40, 0x10, 0x47, 0x40, 0x1f, 0x07, 0x40, 0x10, 0x47, 0x40, 0x1f, 0x07, 0x40, 0x4f, ++ 0x07, 0x0f, 0x0f, 0x1f, 0x27, 0x1f, 0x27, 0x08, 0x17, 0x47, 0x40, 0x17, 0x47, 0x40, 0x40, 0x40, ++ 0x40, 0x01, 0x08, 0x08, 0x40, 0x0f, 0x08, 0x00, 0x00, 0x2f, 0x27, 0x1f, 0x07, 0x27, 0x1f, 0x1f, ++ 0x47, 0x11, 0x10, 0x08, 0x40, 0x0f, 0x08, 0x00, 0x26, 0x08, 0x36, 0x26, 0x26, 0x08, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x27, 0x07, 0x40, 0x40, 0x47, 0x57, 0x67, 0x2f, 0x40, 0x07, 0x40, 0x40, 0x47, 0x0f, ++ 0x07, 0x27, 0x40, 0x17, 0x17, 0x27, 0x37, 0x3e, 0x3e, 0x07, 0x07, 0x00, 0x00, 0x08, 0x1f, 0x07, ++ 0x07, 0x27, 0x2f, 0x08, 0x40, 0x47, 0x4f, 0x40, 0x40, 0x40, 0x07, 0x07, 0x07, 0x0f, 0x0f, 0x0f, ++ 0x17, 0x1f, 0x07, 0x07, 0x07, 0x27, 0x07, 0x40, 0x07, 0x07, 0x27, 0x1f, 0x17, 0x27, 0x07, 0x0f, ++ 0x0f, 0x0f, 0x17, 0x1f, 0x07, 0x07, 0x07, 0x27, 0x07, 0x40, 0x07, 0x07, 0x27, 0x1f, 0x17, 0x27, ++ 0x27, 0x40, 0x3e, 0x40, 0x4f, 0x40, 0x07, 0x07, 0x07, 0x17, 0x17, 0x37, 0x0f, 0x10, 0x47, 0x40, ++ 0x1f, 0x07, 0x40, 0x10, 0x47, 0x40, 0x1f, 0x07, 0x40, 0x10, 0x47, 0x40, 0x1f, 0x07, 0x40, 0x4f, ++ 0x07, 0x0f, 0x0f, 0x1f, 0x27, 0x1f, 0x27, 0x08, 0x17, 0x47, 0x40, 0x17, 0x47, 0x40, 0x40, 0x40, ++ 0x40, 0x00, 0x08, 0x08, 0x40, 0x0f, 0x08, 0x00, 0x00, 0x2f, 0x27, 0x1f, 0x07, 0x27, 0x1f, 0x1f, ++ 0x47, 0x10, 0x10, 0x08, 0x40, 0x0f, 0x08, 0x00, 0x27, 0x08, 0x37, 0x27, 0x27, 0x08, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++}; ++ ++static void set_ps_field(u32 *buf, struct rkvdec_ps_field field, u32 value) ++{ ++ u8 bit = field.offset % 32, word = field.offset / 32; ++ u64 mask = GENMASK_ULL(bit + field.len - 1, bit); ++ u64 val = ((u64)value << bit) & mask; ++ ++ buf[word] &= ~mask; ++ buf[word] |= val; ++ if (bit + field.len > 32) { ++ buf[word + 1] &= ~(mask >> 32); ++ buf[word + 1] |= val >> 32; ++ } ++} ++ ++static void assemble_hw_pps(struct rkvdec_ctx *ctx, ++ struct rkvdec_hevc_run *run) ++{ ++ struct rkvdec_hevc_ctx *hevc_ctx = ctx->priv; ++ const struct v4l2_ctrl_hevc_sps *sps = run->sps; ++ const struct v4l2_ctrl_hevc_pps *pps = run->pps; ++ struct rkvdec_hevc_priv_tbl *priv_tbl = hevc_ctx->priv_tbl.cpu; ++ struct rkvdec_sps_pps_packet *hw_ps; ++ u32 min_cb_log2_size_y, ctb_log2_size_y, ctb_size_y; ++ u32 log2_min_cu_qp_delta_size; ++ dma_addr_t scaling_list_address; ++ u32 scaling_distance; ++ int i; ++ ++ /* ++ * HW read the SPS/PPS information from PPS packet index by PPS id. ++ * offset from the base can be calculated by PPS_id * 80 (size per PPS ++ * packet unit). so the driver copy SPS/PPS information to the exact PPS ++ * packet unit for HW accessing. ++ */ ++ hw_ps = &priv_tbl->param_set[pps->pic_parameter_set_id]; ++ memset(hw_ps, 0, sizeof(*hw_ps)); ++ ++ min_cb_log2_size_y = sps->log2_min_luma_coding_block_size_minus3 + 3; ++ ctb_log2_size_y = min_cb_log2_size_y + ++ sps->log2_diff_max_min_luma_coding_block_size; ++ ctb_size_y = 1 << ctb_log2_size_y; ++ ++#define WRITE_PPS(value, field) set_ps_field(hw_ps->info, field, value) ++ /* write sps */ ++ WRITE_PPS(sps->video_parameter_set_id, VIDEO_PARAMETER_SET_ID); ++ WRITE_PPS(sps->seq_parameter_set_id, SEQ_PARAMETER_SET_ID); ++ WRITE_PPS(1, CHROMA_FORMAT_IDC); ++ WRITE_PPS(sps->pic_width_in_luma_samples, PIC_WIDTH_IN_LUMA_SAMPLES); ++ WRITE_PPS(sps->pic_height_in_luma_samples, PIC_HEIGHT_IN_LUMA_SAMPLES); ++ WRITE_PPS(sps->bit_depth_luma_minus8 + 8, BIT_DEPTH_LUMA); ++ WRITE_PPS(sps->bit_depth_chroma_minus8 + 8, BIT_DEPTH_CHROMA); ++ WRITE_PPS(sps->log2_max_pic_order_cnt_lsb_minus4 + 4, ++ LOG2_MAX_PIC_ORDER_CNT_LSB); ++ WRITE_PPS(sps->log2_diff_max_min_luma_coding_block_size, ++ LOG2_DIFF_MAX_MIN_LUMA_CODING_BLOCK_SIZE); ++ WRITE_PPS(sps->log2_min_luma_coding_block_size_minus3 + 3, ++ LOG2_MIN_LUMA_CODING_BLOCK_SIZE); ++ WRITE_PPS(sps->log2_min_luma_transform_block_size_minus2 + 2, ++ LOG2_MIN_TRANSFORM_BLOCK_SIZE); ++ WRITE_PPS(sps->log2_diff_max_min_luma_transform_block_size, ++ LOG2_DIFF_MAX_MIN_LUMA_TRANSFORM_BLOCK_SIZE); ++ WRITE_PPS(sps->max_transform_hierarchy_depth_inter, ++ MAX_TRANSFORM_HIERARCHY_DEPTH_INTER); ++ WRITE_PPS(sps->max_transform_hierarchy_depth_intra, ++ MAX_TRANSFORM_HIERARCHY_DEPTH_INTRA); ++ WRITE_PPS(!!(sps->flags & V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED), ++ SCALING_LIST_ENABLED_FLAG); ++ WRITE_PPS(!!(sps->flags & V4L2_HEVC_SPS_FLAG_AMP_ENABLED), ++ AMP_ENABLED_FLAG); ++ WRITE_PPS(!!(sps->flags & V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET), ++ SAMPLE_ADAPTIVE_OFFSET_ENABLED_FLAG); ++ if (sps->flags & V4L2_HEVC_SPS_FLAG_PCM_ENABLED) { ++ WRITE_PPS(1, PCM_ENABLED_FLAG); ++ WRITE_PPS(sps->pcm_sample_bit_depth_luma_minus1 + 1, ++ PCM_SAMPLE_BIT_DEPTH_LUMA); ++ WRITE_PPS(sps->pcm_sample_bit_depth_chroma_minus1 + 1, ++ PCM_SAMPLE_BIT_DEPTH_CHROMA); ++ WRITE_PPS(!!(sps->flags & V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED), ++ PCM_LOOP_FILTER_DISABLED_FLAG); ++ WRITE_PPS(sps->log2_diff_max_min_pcm_luma_coding_block_size, ++ LOG2_DIFF_MAX_MIN_PCM_LUMA_CODING_BLOCK_SIZE); ++ WRITE_PPS(sps->log2_min_pcm_luma_coding_block_size_minus3 + 3, ++ LOG2_MIN_PCM_LUMA_CODING_BLOCK_SIZE); ++ } ++ WRITE_PPS(sps->num_short_term_ref_pic_sets, NUM_SHORT_TERM_REF_PIC_SETS); ++ WRITE_PPS(!!(sps->flags & V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT), ++ LONG_TERM_REF_PICS_PRESENT_FLAG); ++ WRITE_PPS(sps->num_long_term_ref_pics_sps, NUM_LONG_TERM_REF_PICS_SPS); ++ WRITE_PPS(!!(sps->flags & V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED), ++ SPS_TEMPORAL_MVP_ENABLED_FLAG); ++ WRITE_PPS(!!(sps->flags & V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED), ++ STRONG_INTRA_SMOOTHING_ENABLED_FLAG); ++ //WRITE_PPS(0, PS_FIELD(100, 7)); ++ //WRITE_PPS(0x1fffff, PS_FIELD(107, 21)); ++ ++ /* write pps */ ++ WRITE_PPS(pps->pic_parameter_set_id, PIC_PARAMETER_SET_ID); ++ WRITE_PPS(sps->seq_parameter_set_id, PPS_SEQ_PARAMETER_SET_ID); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT), ++ DEPENDENT_SLICE_SEGMENTS_ENABLED_FLAG); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_OUTPUT_FLAG_PRESENT), ++ OUTPUT_FLAG_PRESENT_FLAG); ++ WRITE_PPS(pps->num_extra_slice_header_bits, NUM_EXTRA_SLICE_HEADER_BITS); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED), ++ SIGN_DATA_HIDING_ENABLED_FLAG); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_CABAC_INIT_PRESENT), ++ CABAC_INIT_PRESENT_FLAG); ++ WRITE_PPS(pps->num_ref_idx_l0_default_active_minus1 + 1, ++ NUM_REF_IDX_L0_DEFAULT_ACTIVE); ++ WRITE_PPS(pps->num_ref_idx_l1_default_active_minus1 + 1, ++ NUM_REF_IDX_L1_DEFAULT_ACTIVE); ++ WRITE_PPS(pps->init_qp_minus26, INIT_QP_MINUS26); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED), ++ CONSTRAINED_INTRA_PRED_FLAG); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_TRANSFORM_SKIP_ENABLED), ++ TRANSFORM_SKIP_ENABLED_FLAG); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED), ++ CU_QP_DELTA_ENABLED_FLAG); ++ ++ log2_min_cu_qp_delta_size = ctb_log2_size_y - pps->diff_cu_qp_delta_depth; ++ WRITE_PPS(log2_min_cu_qp_delta_size, LOG2_MIN_CU_QP_DELTA_SIZE); ++ ++ WRITE_PPS(pps->pps_cb_qp_offset, PPS_CB_QP_OFFSET); ++ WRITE_PPS(pps->pps_cr_qp_offset, PPS_CR_QP_OFFSET); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT), ++ PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT_FLAG); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED), ++ WEIGHTED_PRED_FLAG); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED), ++ WEIGHTED_BIPRED_FLAG); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED), ++ TRANSQUANT_BYPASS_ENABLED_FLAG); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_TILES_ENABLED), ++ TILES_ENABLED_FLAG); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED), ++ ENTROPY_CODING_SYNC_ENABLED_FLAG); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED), ++ PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED), ++ LOOP_FILTER_ACROSS_TILES_ENABLED_FLAG); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_OVERRIDE_ENABLED), ++ DEBLOCKING_FILTER_OVERRIDE_ENABLED_FLAG); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_PPS_DISABLE_DEBLOCKING_FILTER), ++ PPS_DEBLOCKING_FILTER_DISABLED_FLAG); ++ WRITE_PPS(pps->pps_beta_offset_div2, PPS_BETA_OFFSET_DIV2); ++ WRITE_PPS(pps->pps_tc_offset_div2, PPS_TC_OFFSET_DIV2); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_LISTS_MODIFICATION_PRESENT), ++ LISTS_MODIFICATION_PRESENT_FLAG); ++ WRITE_PPS(pps->log2_parallel_merge_level_minus2 + 2, LOG2_PARALLEL_MERGE_LEVEL); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_SLICE_SEGMENT_HEADER_EXTENSION_PRESENT), ++ SLICE_SEGMENT_HEADER_EXTENSION_PRESENT_FLAG); ++ //WRITE_PPS(0, PS_FIELD(209, 3)); ++ WRITE_PPS(pps->num_tile_columns_minus1 + 1, NUM_TILE_COLUMNS); ++ WRITE_PPS(pps->num_tile_rows_minus1 + 1, NUM_TILE_ROWS); ++ //WRITE_PPS(0x2, PS_FIELD(222, 2)); ++ //WRITE_PPS(0xffffffff, PS_FIELD(224, 32)); ++ ++ if (pps->flags & V4L2_HEVC_PPS_FLAG_TILES_ENABLED) { ++ for (i = 0; i <= pps->num_tile_columns_minus1; i++) ++ WRITE_PPS(pps->column_width_minus1[i], COLUMN_WIDTH(i)); ++ for (i = 0; i <= pps->num_tile_rows_minus1; i++) ++ WRITE_PPS(pps->row_height_minus1[i], ROW_HEIGHT(i)); ++ } else { ++ WRITE_PPS(round_up(sps->pic_width_in_luma_samples, ctb_size_y) - 1, ++ COLUMN_WIDTH(0)); ++ WRITE_PPS(round_up(sps->pic_height_in_luma_samples, ctb_size_y) - 1, ++ ROW_HEIGHT(0)); ++ } ++ ++ scaling_distance = offsetof(struct rkvdec_hevc_priv_tbl, scaling_list); ++ scaling_list_address = hevc_ctx->priv_tbl.dma + scaling_distance; ++ WRITE_PPS(scaling_list_address, SCALING_LIST_ADDRESS); ++ //WRITE_PPS(0xffff, PS_FIELD(624, 16)); ++} ++ ++static void assemble_hw_rps(struct rkvdec_ctx *ctx, ++ struct rkvdec_hevc_run *run) ++{ ++ const struct v4l2_ctrl_hevc_slice_params *sl_params; ++ const struct v4l2_hevc_dpb_entry *dpb; ++ struct rkvdec_hevc_ctx *hevc_ctx = ctx->priv; ++ struct rkvdec_hevc_priv_tbl *priv_tbl = hevc_ctx->priv_tbl.cpu; ++ struct rkvdec_rps_packet *hw_ps; ++ int i, j; ++ ++#define WRITE_RPS(value, field) set_ps_field(hw_ps->info, field, value) ++ ++#define REF_PIC_LONG_TERM_L0(i) PS_FIELD(i * 5, 1) ++#define REF_PIC_IDX_L0(i) PS_FIELD(1 + (i * 5), 4) ++#define REF_PIC_LONG_TERM_L1(i) PS_FIELD((i < 5 ? 75 : 132) + (i * 5), 1) ++#define REF_PIC_IDX_L1(i) PS_FIELD((i < 4 ? 76 : 128) + (i * 5), 4) ++ ++#define LOWDELAY PS_FIELD(182, 1) ++#define SHORT_TERM_REF_PIC_SET_SIZE PS_FIELD(183, 10) ++#define LONG_TERM_REF_PIC_SET_SIZE PS_FIELD(193, 9) ++#define NUM_RPS_POC PS_FIELD(202, 4) ++ ++ for (j = 0; j < run->num_slices; j++) { ++ sl_params = &run->slices_params[j]; ++ dpb = sl_params->dpb; ++ ++ hw_ps = &priv_tbl->rps[j]; ++ memset(hw_ps, 0, sizeof(*hw_ps)); ++ ++ for (i = 0; i <= sl_params->num_ref_idx_l0_active_minus1; i++) { ++ WRITE_RPS(!!(dpb[sl_params->ref_idx_l0[i]].rps == V4L2_HEVC_DPB_ENTRY_RPS_LT_CURR), ++ REF_PIC_LONG_TERM_L0(i)); ++ WRITE_RPS(sl_params->ref_idx_l0[i], REF_PIC_IDX_L0(i)); ++ } ++ ++ for (i = 0; i <= sl_params->num_ref_idx_l1_active_minus1; i++) { ++ WRITE_RPS(!!(dpb[sl_params->ref_idx_l1[i]].rps == V4L2_HEVC_DPB_ENTRY_RPS_LT_CURR), ++ REF_PIC_LONG_TERM_L1(i)); ++ WRITE_RPS(sl_params->ref_idx_l1[i], REF_PIC_IDX_L1(i)); ++ } ++ ++ //WRITE_RPS(0xffffffff, PS_FIELD(96, 32)); ++ ++ // TODO: lowdelay ++ WRITE_RPS(0, LOWDELAY); ++ ++ // NOTE: these two differs from mpp ++ WRITE_RPS(sl_params->short_term_ref_pic_set_size, ++ SHORT_TERM_REF_PIC_SET_SIZE); ++ WRITE_RPS(sl_params->long_term_ref_pic_set_size, ++ LONG_TERM_REF_PIC_SET_SIZE); ++ ++ WRITE_RPS(sl_params->num_rps_poc_st_curr_before + ++ sl_params->num_rps_poc_st_curr_after + ++ sl_params->num_rps_poc_lt_curr, ++ NUM_RPS_POC); ++ ++ //WRITE_RPS(0x3ffff, PS_FIELD(206, 18)); ++ //WRITE_RPS(0xffffffff, PS_FIELD(224, 32)); ++ } ++} ++ ++static void assemble_hw_scaling_list(struct rkvdec_ctx *ctx, ++ struct rkvdec_hevc_run *run) ++{ ++ const struct v4l2_ctrl_hevc_scaling_matrix *scaling = run->scaling_matrix; ++ struct rkvdec_hevc_ctx *hevc_ctx = ctx->priv; ++ struct rkvdec_hevc_priv_tbl *tbl = hevc_ctx->priv_tbl.cpu; ++ u8 *dst; ++ scalingList_t sl; ++ int i, j; ++ ++ if (!memcmp((void*)&hevc_ctx->scaling_matrix_cache, scaling, ++ sizeof(struct v4l2_ctrl_hevc_scaling_matrix))) ++ return; ++ ++ memset(&sl, 0, sizeof(scalingList_t)); ++ ++ for (i = 0; i < 6; i++) { ++ for (j = 0; j < 16; j++) ++ sl.sl[0][i][j] = scaling->scaling_list_4x4[i][j]; ++ for (j = 0; j < 64; j++) { ++ sl.sl[1][i][j] = scaling->scaling_list_8x8[i][j]; ++ sl.sl[2][i][j] = scaling->scaling_list_16x16[i][j]; ++ if (i < 2) ++ sl.sl[3][i][j] = scaling->scaling_list_32x32[i][j]; ++ } ++ sl.sl_dc[0][i] = scaling->scaling_list_dc_coef_16x16[i]; ++ if (i < 2) ++ sl.sl_dc[1][i] = scaling->scaling_list_dc_coef_32x32[i]; ++ } ++ ++ dst = tbl->scaling_list; ++ hal_record_scaling_list((scalingFactor_t *)dst, &sl); ++ ++ memcpy((void*)&hevc_ctx->scaling_matrix_cache, scaling, ++ sizeof(struct v4l2_ctrl_hevc_scaling_matrix)); ++} ++ ++static struct vb2_buffer * ++get_ref_buf(struct rkvdec_ctx *ctx, struct rkvdec_hevc_run *run, ++ unsigned int dpb_idx) ++{ ++ struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx; ++ const struct v4l2_ctrl_hevc_slice_params *sl_params = &run->slices_params[0]; ++ const struct v4l2_hevc_dpb_entry *dpb = sl_params->dpb; ++ struct vb2_queue *cap_q = &m2m_ctx->cap_q_ctx.q; ++ int buf_idx = -1; ++ ++ if (dpb_idx < sl_params->num_active_dpb_entries) ++ buf_idx = vb2_find_timestamp(cap_q, ++ dpb[dpb_idx].timestamp, 0); ++ ++ /* ++ * If a DPB entry is unused or invalid, address of current destination ++ * buffer is returned. ++ */ ++ if (buf_idx < 0) ++ return &run->base.bufs.dst->vb2_buf; ++ ++ return vb2_get_buffer(cap_q, buf_idx); ++} ++ ++static void config_registers(struct rkvdec_ctx *ctx, ++ struct rkvdec_hevc_run *run) ++{ ++ struct rkvdec_dev *rkvdec = ctx->dev; ++ const struct v4l2_ctrl_hevc_slice_params *sl_params = &run->slices_params[0]; ++ const struct v4l2_hevc_dpb_entry *dpb = sl_params->dpb; ++ struct rkvdec_hevc_ctx *hevc_ctx = ctx->priv; ++ dma_addr_t priv_start_addr = hevc_ctx->priv_tbl.dma; ++ const struct v4l2_pix_format_mplane *dst_fmt; ++ struct vb2_v4l2_buffer *src_buf = run->base.bufs.src; ++ struct vb2_v4l2_buffer *dst_buf = run->base.bufs.dst; ++ const struct v4l2_format *f; ++ dma_addr_t rlc_addr; ++ dma_addr_t refer_addr; ++ u32 rlc_len; ++ u32 hor_virstride; ++ u32 ver_virstride; ++ u32 y_virstride; ++ u32 uv_virstride; ++ u32 yuv_virstride; ++ u32 offset; ++ dma_addr_t dst_addr; ++ u32 reg, i; ++ ++ reg = RKVDEC_MODE(RKVDEC_MODE_HEVC); ++ writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_SYSCTRL); ++ ++ f = &ctx->decoded_fmt; ++ dst_fmt = &f->fmt.pix_mp; ++ hor_virstride = dst_fmt->plane_fmt[0].bytesperline; ++ ver_virstride = dst_fmt->height; ++ y_virstride = hor_virstride * ver_virstride; ++ uv_virstride = y_virstride / 2; ++ yuv_virstride = y_virstride + uv_virstride; ++ ++ reg = RKVDEC_Y_HOR_VIRSTRIDE(hor_virstride / 16) | ++ RKVDEC_UV_HOR_VIRSTRIDE(hor_virstride / 16) | ++ RKVDEC_SLICE_NUM_LOWBITS(run->num_slices); ++ writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_PICPAR); ++ ++ /* config rlc base address */ ++ rlc_addr = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); ++ writel_relaxed(rlc_addr, rkvdec->regs + RKVDEC_REG_STRM_RLC_BASE); ++ ++ rlc_len = vb2_get_plane_payload(&src_buf->vb2_buf, 0); ++ reg = RKVDEC_STRM_LEN(round_up(rlc_len, 16) + 64); ++ writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_STRM_LEN); ++ ++ /* config cabac table */ ++ offset = offsetof(struct rkvdec_hevc_priv_tbl, cabac_table); ++ writel_relaxed(priv_start_addr + offset, ++ rkvdec->regs + RKVDEC_REG_CABACTBL_PROB_BASE); ++ ++ /* config output base address */ ++ dst_addr = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); ++ writel_relaxed(dst_addr, rkvdec->regs + RKVDEC_REG_DECOUT_BASE); ++ ++ reg = RKVDEC_Y_VIRSTRIDE(y_virstride / 16); ++ writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_Y_VIRSTRIDE); ++ ++ reg = RKVDEC_YUV_VIRSTRIDE(yuv_virstride / 16); ++ writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_YUV_VIRSTRIDE); ++ ++ /* config ref pic address */ ++ for (i = 0; i < 15; i++) { ++ struct vb2_buffer *vb_buf = get_ref_buf(ctx, run, i); ++ ++ if (i < 4 && sl_params->num_active_dpb_entries) { ++ reg = GENMASK(sl_params->num_active_dpb_entries - 1, 0); ++ reg = (reg >> (i * 4)) & 0xf; ++ } else ++ reg = 0; ++ ++ refer_addr = vb2_dma_contig_plane_dma_addr(vb_buf, 0); ++ writel_relaxed(refer_addr | reg, ++ rkvdec->regs + RKVDEC_REG_H264_BASE_REFER(i)); ++ ++ reg = RKVDEC_POC_REFER(i < sl_params->num_active_dpb_entries ? dpb[i].pic_order_cnt[0] : 0); ++ writel_relaxed(reg, ++ rkvdec->regs + RKVDEC_REG_H264_POC_REFER0(i)); ++ } ++ ++ reg = RKVDEC_CUR_POC(sl_params->slice_pic_order_cnt); ++ writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_CUR_POC0); ++ ++ /* config hw pps address */ ++ offset = offsetof(struct rkvdec_hevc_priv_tbl, param_set); ++ writel_relaxed(priv_start_addr + offset, ++ rkvdec->regs + RKVDEC_REG_PPS_BASE); ++ ++ /* config hw rps address */ ++ offset = offsetof(struct rkvdec_hevc_priv_tbl, rps); ++ writel_relaxed(priv_start_addr + offset, ++ rkvdec->regs + RKVDEC_REG_RPS_BASE); ++ ++ reg = RKVDEC_AXI_DDR_RDATA(0); ++ writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_AXI_DDR_RDATA); ++ ++ reg = RKVDEC_AXI_DDR_WDATA(0); ++ writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_AXI_DDR_WDATA); ++} ++ ++#define RKVDEC_HEVC_MAX_DEPTH_IN_BYTES 2 ++ ++static int rkvdec_hevc_adjust_fmt(struct rkvdec_ctx *ctx, ++ struct v4l2_format *f) ++{ ++ struct v4l2_pix_format_mplane *fmt = &f->fmt.pix_mp; ++ ++ fmt->num_planes = 1; ++ if (!fmt->plane_fmt[0].sizeimage) ++ fmt->plane_fmt[0].sizeimage = fmt->width * fmt->height * ++ RKVDEC_HEVC_MAX_DEPTH_IN_BYTES; ++ return 0; ++} ++ ++static int rkvdec_hevc_start(struct rkvdec_ctx *ctx) ++{ ++ struct rkvdec_dev *rkvdec = ctx->dev; ++ struct rkvdec_hevc_priv_tbl *priv_tbl; ++ struct rkvdec_hevc_ctx *hevc_ctx; ++ int ret; ++ ++ hevc_ctx = kzalloc(sizeof(*hevc_ctx), GFP_KERNEL); ++ if (!hevc_ctx) ++ return -ENOMEM; ++ ++ priv_tbl = dma_alloc_coherent(rkvdec->dev, sizeof(*priv_tbl), ++ &hevc_ctx->priv_tbl.dma, GFP_KERNEL); ++ if (!priv_tbl) { ++ ret = -ENOMEM; ++ goto err_free_ctx; ++ } ++ ++ hevc_ctx->priv_tbl.size = sizeof(*priv_tbl); ++ hevc_ctx->priv_tbl.cpu = priv_tbl; ++ memset(priv_tbl, 0, sizeof(*priv_tbl)); ++ memcpy(priv_tbl->cabac_table, rkvdec_hevc_cabac_table, ++ sizeof(rkvdec_hevc_cabac_table)); ++ ++ ctx->priv = hevc_ctx; ++ return 0; ++ ++err_free_ctx: ++ kfree(hevc_ctx); ++ return ret; ++} ++ ++static void rkvdec_hevc_stop(struct rkvdec_ctx *ctx) ++{ ++ struct rkvdec_hevc_ctx *hevc_ctx = ctx->priv; ++ struct rkvdec_dev *rkvdec = ctx->dev; ++ ++ dma_free_coherent(rkvdec->dev, hevc_ctx->priv_tbl.size, ++ hevc_ctx->priv_tbl.cpu, hevc_ctx->priv_tbl.dma); ++ kfree(hevc_ctx); ++} ++ ++static void rkvdec_hevc_run_preamble(struct rkvdec_ctx *ctx, ++ struct rkvdec_hevc_run *run) ++{ ++ struct v4l2_ctrl *ctrl; ++ ++ ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, ++ V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS); ++ run->slices_params = ctrl ? ctrl->p_cur.p : NULL; ++ ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, ++ V4L2_CID_MPEG_VIDEO_HEVC_SPS); ++ run->sps = ctrl ? ctrl->p_cur.p : NULL; ++ ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, ++ V4L2_CID_MPEG_VIDEO_HEVC_PPS); ++ run->pps = ctrl ? ctrl->p_cur.p : NULL; ++ ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, ++ V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX); ++ run->scaling_matrix = ctrl ? ctrl->p_cur.p : NULL; ++ ++ rkvdec_run_preamble(ctx, &run->base); ++ ++ // HACK: we need num slices from somewhere ++ run->num_slices = run->sps->num_slices; ++} ++ ++static int rkvdec_hevc_run(struct rkvdec_ctx *ctx) ++{ ++ struct rkvdec_dev *rkvdec = ctx->dev; ++ struct rkvdec_hevc_run run; ++ ++ rkvdec_hevc_run_preamble(ctx, &run); ++ ++ assemble_hw_scaling_list(ctx, &run); ++ assemble_hw_pps(ctx, &run); ++ assemble_hw_rps(ctx, &run); ++ config_registers(ctx, &run); ++ ++ rkvdec_run_postamble(ctx, &run.base); ++ ++ // sw_cabac_error_e - cabac error enable ++ writel_relaxed(0xfdfffffd, rkvdec->regs + RKVDEC_REG_STRMD_ERR_EN); ++ // slice end error enable = BIT(28) ++ // frame end error enable = BIT(29) ++ writel_relaxed(0x30000000, rkvdec->regs + RKVDEC_REG_H264_ERR_E); ++ ++ schedule_delayed_work(&rkvdec->watchdog_work, msecs_to_jiffies(2000)); ++ ++ writel(1, rkvdec->regs + RKVDEC_REG_PREF_LUMA_CACHE_COMMAND); ++ writel(1, rkvdec->regs + RKVDEC_REG_PREF_CHR_CACHE_COMMAND); ++ ++ /* Start decoding! */ ++ writel(RKVDEC_INTERRUPT_DEC_E | RKVDEC_CONFIG_DEC_CLK_GATE_E | ++ RKVDEC_TIMEOUT_E | RKVDEC_BUF_EMPTY_E, ++ rkvdec->regs + RKVDEC_REG_INTERRUPT); ++ ++ return 0; ++} ++ ++const struct rkvdec_coded_fmt_ops rkvdec_hevc_fmt_ops = { ++ .adjust_fmt = rkvdec_hevc_adjust_fmt, ++ .start = rkvdec_hevc_start, ++ .stop = rkvdec_hevc_stop, ++ .run = rkvdec_hevc_run, ++}; +diff --git a/drivers/staging/media/rkvdec/rkvdec-regs.h b/drivers/staging/media/rkvdec/rkvdec-regs.h +index 15b9bee92016..83bf790ed9b7 100644 +--- a/drivers/staging/media/rkvdec/rkvdec-regs.h ++++ b/drivers/staging/media/rkvdec/rkvdec-regs.h +@@ -43,6 +43,7 @@ + #define RKVDEC_RLC_MODE BIT(11) + #define RKVDEC_STRM_START_BIT(x) (((x) & 0x7f) << 12) + #define RKVDEC_MODE(x) (((x) & 0x03) << 20) ++#define RKVDEC_MODE_HEVC 0 + #define RKVDEC_MODE_H264 1 + #define RKVDEC_MODE_VP9 2 + #define RKVDEC_RPS_MODE BIT(24) +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index 658fb6028e72..2141633c7437 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -159,6 +159,61 @@ static const u32 rkvdec_h264_decoded_fmts[] = { + V4L2_PIX_FMT_NV20, + }; + ++static const struct rkvdec_ctrl_desc rkvdec_hevc_ctrl_descs[] = { ++ { ++ .mandatory = true, ++ .cfg.id = V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS, ++ // HACK: match ffmpeg v4l2 request api hwaccel size, ++ // we should support variable length up to 600 slices ++ .cfg.dims = { 16 }, ++ }, ++ { ++ .mandatory = true, ++ .cfg.id = V4L2_CID_MPEG_VIDEO_HEVC_SPS, ++ }, ++ { ++ .mandatory = true, ++ .cfg.id = V4L2_CID_MPEG_VIDEO_HEVC_PPS, ++ }, ++ { ++ .mandatory = true, ++ .cfg.id = V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX, ++ }, ++ { ++ .cfg.id = V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE, ++ .cfg.min = V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_FRAME_BASED, ++ .cfg.max = V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_FRAME_BASED, ++ .cfg.def = V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_FRAME_BASED, ++ }, ++ { ++ .cfg.id = V4L2_CID_MPEG_VIDEO_HEVC_START_CODE, ++ .cfg.min = V4L2_MPEG_VIDEO_HEVC_START_CODE_ANNEX_B, ++ .cfg.def = V4L2_MPEG_VIDEO_HEVC_START_CODE_ANNEX_B, ++ .cfg.max = V4L2_MPEG_VIDEO_HEVC_START_CODE_ANNEX_B, ++ }, ++ { ++ .cfg.id = V4L2_CID_MPEG_VIDEO_HEVC_PROFILE, ++ .cfg.min = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, ++ .cfg.max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10, ++ .cfg.def = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, ++ }, ++ { ++ .cfg.id = V4L2_CID_MPEG_VIDEO_HEVC_LEVEL, ++ .cfg.min = V4L2_MPEG_VIDEO_HEVC_LEVEL_1, ++ .cfg.max = V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1, ++ }, ++}; ++ ++static const struct rkvdec_ctrls rkvdec_hevc_ctrls = { ++ .ctrls = rkvdec_hevc_ctrl_descs, ++ .num_ctrls = ARRAY_SIZE(rkvdec_hevc_ctrl_descs), ++}; ++ ++static const u32 rkvdec_hevc_decoded_fmts[] = { ++ V4L2_PIX_FMT_NV12, ++ V4L2_PIX_FMT_NV15, ++}; ++ + static const struct rkvdec_ctrl_desc rkvdec_vp9_ctrl_descs[] = { + { + .mandatory = true, +@@ -209,6 +264,21 @@ static const struct rkvdec_coded_fmt_desc rkvdec_coded_fmts[] = { + .num_decoded_fmts = ARRAY_SIZE(rkvdec_h264_decoded_fmts), + .decoded_fmts = rkvdec_h264_decoded_fmts, + }, ++ { ++ .fourcc = V4L2_PIX_FMT_HEVC_SLICE, ++ .frmsize = { ++ .min_width = 64, ++ .max_width = 4096, ++ .step_width = 64, ++ .min_height = 64, ++ .max_height = 2304, ++ .step_height = 16, ++ }, ++ .ctrls = &rkvdec_hevc_ctrls, ++ .ops = &rkvdec_hevc_fmt_ops, ++ .num_decoded_fmts = ARRAY_SIZE(rkvdec_hevc_decoded_fmts), ++ .decoded_fmts = rkvdec_hevc_decoded_fmts, ++ }, + { + .fourcc = V4L2_PIX_FMT_VP9_FRAME, + .frmsize = { +diff --git a/drivers/staging/media/rkvdec/rkvdec.h b/drivers/staging/media/rkvdec/rkvdec.h +index 5f66f07acac5..d5600c6a4c17 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.h ++++ b/drivers/staging/media/rkvdec/rkvdec.h +@@ -123,6 +123,7 @@ void rkvdec_run_preamble(struct rkvdec_ctx *ctx, struct rkvdec_run *run); + void rkvdec_run_postamble(struct rkvdec_ctx *ctx, struct rkvdec_run *run); + + extern const struct rkvdec_coded_fmt_ops rkvdec_h264_fmt_ops; ++extern const struct rkvdec_coded_fmt_ops rkvdec_hevc_fmt_ops; + extern const struct rkvdec_coded_fmt_ops rkvdec_vp9_fmt_ops; + + #endif /* RKVDEC_H_ */ + +From 42bf64d9be3b320b3ff6617a63b177f6dae206fb Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 1 Aug 2020 12:24:58 +0000 +Subject: [PATCH] WIP: media: rkvdec: add HEVC format validation + +--- + drivers/staging/media/rkvdec/rkvdec-hevc.c | 11 +++++++++++ + drivers/staging/media/rkvdec/rkvdec.c | 23 +++++++++++++++++++++- + 2 files changed, 33 insertions(+), 1 deletion(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec-hevc.c b/drivers/staging/media/rkvdec/rkvdec-hevc.c +index 03ba848411c6..b8ad7fc2271c 100644 +--- a/drivers/staging/media/rkvdec/rkvdec-hevc.c ++++ b/drivers/staging/media/rkvdec/rkvdec-hevc.c +@@ -2415,6 +2415,16 @@ static int rkvdec_hevc_adjust_fmt(struct rkvdec_ctx *ctx, + return 0; + } + ++static u32 rkvdec_hevc_valid_fmt(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl) ++{ ++ const struct v4l2_ctrl_hevc_sps *sps = ctrl->p_new.p_hevc_sps; ++ ++ if (sps->bit_depth_luma_minus8 == 2) ++ return V4L2_PIX_FMT_NV15; ++ else ++ return V4L2_PIX_FMT_NV12; ++} ++ + static int rkvdec_hevc_start(struct rkvdec_ctx *ctx) + { + struct rkvdec_dev *rkvdec = ctx->dev; +@@ -2516,6 +2526,7 @@ static int rkvdec_hevc_run(struct rkvdec_ctx *ctx) + + const struct rkvdec_coded_fmt_ops rkvdec_hevc_fmt_ops = { + .adjust_fmt = rkvdec_hevc_adjust_fmt, ++ .valid_fmt = rkvdec_hevc_valid_fmt, + .start = rkvdec_hevc_start, + .stop = rkvdec_hevc_stop, + .run = rkvdec_hevc_run, +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index 2141633c7437..869275a411c8 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -76,6 +76,26 @@ static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl) + if (width > ctx->coded_fmt.fmt.pix_mp.width || + height > ctx->coded_fmt.fmt.pix_mp.height) + return -EINVAL; ++ } else if (ctrl->id == V4L2_CID_MPEG_VIDEO_HEVC_SPS) { ++ const struct v4l2_ctrl_hevc_sps *sps = ctrl->p_new.p_hevc_sps; ++ ++ if (sps->chroma_format_idc > 1) ++ /* Only 4:0:0 and 4:2:0 are supported */ ++ return -EINVAL; ++ if (sps->bit_depth_luma_minus8 != sps->bit_depth_chroma_minus8) ++ /* Luma and chroma bit depth mismatch */ ++ return -EINVAL; ++ if (sps->bit_depth_luma_minus8 != 0 && sps->bit_depth_luma_minus8 != 2) ++ /* Only 8-bit and 10-bit is supported */ ++ return -EINVAL; ++ ++ if (ctx->valid_fmt && ctx->valid_fmt != rkvdec_valid_fmt(ctx, ctrl)) ++ /* Only current valid format */ ++ return -EINVAL; ++ ++ if (sps->pic_width_in_luma_samples > ctx->coded_fmt.fmt.pix_mp.width || ++ sps->pic_height_in_luma_samples > ctx->coded_fmt.fmt.pix_mp.height) ++ return -EINVAL; + } + return 0; + } +@@ -84,7 +104,7 @@ static int rkvdec_s_ctrl(struct v4l2_ctrl *ctrl) + { + struct rkvdec_ctx *ctx = container_of(ctrl->handler, struct rkvdec_ctx, ctrl_hdl); + +- if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_SPS && !ctx->valid_fmt) { ++ if (!ctx->valid_fmt) { + ctx->valid_fmt = rkvdec_valid_fmt(ctx, ctrl); + if (ctx->valid_fmt) { + struct v4l2_pix_format_mplane *pix_mp; +@@ -170,6 +190,7 @@ static const struct rkvdec_ctrl_desc rkvdec_hevc_ctrl_descs[] = { + { + .mandatory = true, + .cfg.id = V4L2_CID_MPEG_VIDEO_HEVC_SPS, ++ .cfg.ops = &rkvdec_ctrl_ops, + }, + { + .mandatory = true, + +From d37481b9f7f915f93efaee842548a4b42b2da4ce Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Tue, 29 Oct 2019 01:26:02 +0000 +Subject: [PATCH] RFC: media: hantro: Fix H264 decoding of field encoded + content + +This still need code cleanup and formatting + +Signed-off-by: Jonas Karlman +--- + .../staging/media/hantro/hantro_g1_h264_dec.c | 17 +--- + drivers/staging/media/hantro/hantro_h264.c | 81 ++++++++++++++++--- + drivers/staging/media/hantro/hantro_hw.h | 2 + + 3 files changed, 74 insertions(+), 26 deletions(-) + +diff --git a/drivers/staging/media/hantro/hantro_g1_h264_dec.c b/drivers/staging/media/hantro/hantro_g1_h264_dec.c +index 845bef73d218..869ee261a5db 100644 +--- a/drivers/staging/media/hantro/hantro_g1_h264_dec.c ++++ b/drivers/staging/media/hantro/hantro_g1_h264_dec.c +@@ -130,25 +130,12 @@ static void set_ref(struct hantro_ctx *ctx) + struct v4l2_h264_dpb_entry *dpb = ctx->h264_dec.dpb; + const u8 *b0_reflist, *b1_reflist, *p_reflist; + struct hantro_dev *vpu = ctx->dev; +- u32 dpb_longterm = 0; +- u32 dpb_valid = 0; + int reg_num; + u32 reg; + int i; + +- /* +- * Set up bit maps of valid and long term DPBs. +- * NOTE: The bits are reversed, i.e. MSb is DPB 0. +- */ +- for (i = 0; i < HANTRO_H264_DPB_SIZE; ++i) { +- if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE) +- dpb_valid |= BIT(HANTRO_H264_DPB_SIZE - 1 - i); +- +- if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM) +- dpb_longterm |= BIT(HANTRO_H264_DPB_SIZE - 1 - i); +- } +- vdpu_write_relaxed(vpu, dpb_valid << 16, G1_REG_VALID_REF); +- vdpu_write_relaxed(vpu, dpb_longterm << 16, G1_REG_LT_REF); ++ vdpu_write_relaxed(vpu, ctx->h264_dec.dpb_valid, G1_REG_VALID_REF); ++ vdpu_write_relaxed(vpu, ctx->h264_dec.dpb_longterm, G1_REG_LT_REF); + + /* + * Set up reference frame picture numbers. +diff --git a/drivers/staging/media/hantro/hantro_h264.c b/drivers/staging/media/hantro/hantro_h264.c +index b1bdc00ac262..bc2af450a94c 100644 +--- a/drivers/staging/media/hantro/hantro_h264.c ++++ b/drivers/staging/media/hantro/hantro_h264.c +@@ -227,17 +227,67 @@ static void prepare_table(struct hantro_ctx *ctx) + { + const struct hantro_h264_dec_ctrls *ctrls = &ctx->h264_dec.ctrls; + const struct v4l2_ctrl_h264_decode_params *dec_param = ctrls->decode; ++ const struct v4l2_ctrl_h264_sps *sps = ctrls->sps; + struct hantro_h264_dec_priv_tbl *tbl = ctx->h264_dec.priv.cpu; + const struct v4l2_h264_dpb_entry *dpb = ctx->h264_dec.dpb; ++ u32 dpb_longterm = 0; ++ u32 dpb_valid = 0; + int i; + ++ /* ++ * Set up bit maps of valid and long term DPBs. ++ * NOTE: The bits are reversed, i.e. MSb is DPB 0. ++ */ ++ if ((dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC) || (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD)) { ++ for (i = 0; i < HANTRO_H264_DPB_SIZE * 2; ++i) { ++ // check for correct reference use ++ enum v4l2_h264_field_reference parity = (i & 0x1) ? ++ V4L2_H264_BOTTOM_FIELD_REF : V4L2_H264_TOP_FIELD_REF; ++ if (dpb[i / 2].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE && ++ dpb[i / 2].reference & parity) ++ dpb_valid |= BIT(HANTRO_H264_DPB_SIZE * 2 - 1 - i); ++ ++ if (dpb[i / 2].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM) ++ dpb_longterm |= BIT(HANTRO_H264_DPB_SIZE * 2 - 1 - i); ++ } ++ ++ ctx->h264_dec.dpb_valid = dpb_valid; ++ ctx->h264_dec.dpb_longterm = dpb_longterm; ++ } else { ++ for (i = 0; i < HANTRO_H264_DPB_SIZE; ++i) { ++ if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE) ++ dpb_valid |= BIT(HANTRO_H264_DPB_SIZE - 1 - i); ++ ++ if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM) ++ dpb_longterm |= BIT(HANTRO_H264_DPB_SIZE - 1 - i); ++ } ++ ++ ctx->h264_dec.dpb_valid = dpb_valid << 16; ++ ctx->h264_dec.dpb_longterm = dpb_longterm << 16; ++ } ++ + for (i = 0; i < HANTRO_H264_DPB_SIZE; ++i) { +- tbl->poc[i * 2] = dpb[i].top_field_order_cnt; +- tbl->poc[i * 2 + 1] = dpb[i].bottom_field_order_cnt; ++ if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE) { ++ tbl->poc[i * 2] = dpb[i].top_field_order_cnt; ++ tbl->poc[i * 2 + 1] = dpb[i].bottom_field_order_cnt; ++ } else { ++ tbl->poc[i * 2] = 0; ++ tbl->poc[i * 2 + 1] = 0; ++ } + } + +- tbl->poc[32] = dec_param->top_field_order_cnt; +- tbl->poc[33] = dec_param->bottom_field_order_cnt; ++ if ((dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC) || !(sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD)) { ++ if ((dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC)) ++ tbl->poc[32] = (dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD) ? ++ dec_param->bottom_field_order_cnt : ++ dec_param->top_field_order_cnt; ++ else ++ tbl->poc[32] = min(dec_param->top_field_order_cnt, dec_param->bottom_field_order_cnt); ++ tbl->poc[33] = 0; ++ } else { ++ tbl->poc[32] = dec_param->top_field_order_cnt; ++ tbl->poc[33] = dec_param->bottom_field_order_cnt; ++ } + + assemble_scaling_list(ctx); + } +@@ -245,8 +295,7 @@ static void prepare_table(struct hantro_ctx *ctx) + static bool dpb_entry_match(const struct v4l2_h264_dpb_entry *a, + const struct v4l2_h264_dpb_entry *b) + { +- return a->top_field_order_cnt == b->top_field_order_cnt && +- a->bottom_field_order_cnt == b->bottom_field_order_cnt; ++ return a->reference_ts == b->reference_ts; + } + + static void update_dpb(struct hantro_ctx *ctx) +@@ -260,13 +309,13 @@ static void update_dpb(struct hantro_ctx *ctx) + + /* Disable all entries by default. */ + for (i = 0; i < ARRAY_SIZE(ctx->h264_dec.dpb); i++) +- ctx->h264_dec.dpb[i].flags &= ~V4L2_H264_DPB_ENTRY_FLAG_ACTIVE; ++ ctx->h264_dec.dpb[i].flags = 0; + + /* Try to match new DPB entries with existing ones by their POCs. */ + for (i = 0; i < ARRAY_SIZE(dec_param->dpb); i++) { + const struct v4l2_h264_dpb_entry *ndpb = &dec_param->dpb[i]; + +- if (!(ndpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)) ++ if (!(ndpb->flags & V4L2_H264_DPB_ENTRY_FLAG_VALID)) + continue; + + /* +@@ -277,8 +326,7 @@ static void update_dpb(struct hantro_ctx *ctx) + struct v4l2_h264_dpb_entry *cdpb; + + cdpb = &ctx->h264_dec.dpb[j]; +- if (cdpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE || +- !dpb_entry_match(cdpb, ndpb)) ++ if (!dpb_entry_match(cdpb, ndpb)) + continue; + + *cdpb = *ndpb; +@@ -314,7 +362,10 @@ dma_addr_t hantro_h264_get_ref_buf(struct hantro_ctx *ctx, + unsigned int dpb_idx) + { + struct v4l2_h264_dpb_entry *dpb = ctx->h264_dec.dpb; ++ const struct v4l2_ctrl_h264_decode_params *dec_param = ctx->h264_dec.ctrls.decode; + dma_addr_t dma_addr = 0; ++ s32 cur_poc; ++ u32 flags; + + if (dpb[dpb_idx].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE) + dma_addr = hantro_get_ref(ctx, dpb[dpb_idx].reference_ts); +@@ -332,7 +383,15 @@ dma_addr_t hantro_h264_get_ref_buf(struct hantro_ctx *ctx, + dma_addr = hantro_get_dec_buf_addr(ctx, buf); + } + +- return dma_addr; ++ cur_poc = dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD ? ++ dec_param->bottom_field_order_cnt : ++ dec_param->top_field_order_cnt; ++ flags = dpb[dpb_idx].flags & V4L2_H264_DPB_ENTRY_FLAG_FIELD ? 0x2 : 0; ++ flags |= abs(dpb[dpb_idx].top_field_order_cnt - cur_poc) < ++ abs(dpb[dpb_idx].bottom_field_order_cnt - cur_poc) ? ++ 0x1 : 0; ++ ++ return dma_addr | flags; + } + + int hantro_h264_dec_prepare_run(struct hantro_ctx *ctx) +diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h +index 219283a06f52..7e35140a4f22 100644 +--- a/drivers/staging/media/hantro/hantro_hw.h ++++ b/drivers/staging/media/hantro/hantro_hw.h +@@ -90,6 +90,8 @@ struct hantro_h264_dec_hw_ctx { + struct v4l2_h264_dpb_entry dpb[HANTRO_H264_DPB_SIZE]; + struct hantro_h264_dec_reflists reflists; + struct hantro_h264_dec_ctrls ctrls; ++ u32 dpb_longterm; ++ u32 dpb_valid; + }; + + /** + +From badc3bfbfabd4fd01837498a4dd6bc84420bea79 Mon Sep 17 00:00:00 2001 +From: Randy Li +Date: Sun, 6 Jan 2019 01:48:37 +0800 +Subject: [PATCH] soc: rockchip: power-domain: export idle request + +We need to put the power status of HEVC IP into IDLE unless +we can't reset that IP or the SoC would crash down. +rockchip_pmu_idle_request(dev, true)---> enter idle +rockchip_pmu_idle_request(dev, false)---> exit idle + +Signed-off-by: Caesar Wang +Signed-off-by: Jeffy Chen +Signed-off-by: Randy Li +--- + drivers/soc/rockchip/pm_domains.c | 23 +++++++++++++++++++++++ + include/linux/rockchip_pmu.h | 15 +++++++++++++++ + include/soc/rockchip/pm_domains.h | 18 ++++++++++++++++++ + 3 files changed, 56 insertions(+) + create mode 100644 include/linux/rockchip_pmu.h + create mode 100644 include/soc/rockchip/pm_domains.h + +diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c +index 54eb6cfc5d5b..727af107e6d3 100644 +--- a/drivers/soc/rockchip/pm_domains.c ++++ b/drivers/soc/rockchip/pm_domains.c +@@ -196,6 +196,29 @@ static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd, + return 0; + } + ++int rockchip_pmu_idle_request(struct device *dev, bool idle) ++{ ++ struct generic_pm_domain *genpd; ++ struct rockchip_pm_domain *pd; ++ int ret; ++ ++ if (IS_ERR_OR_NULL(dev)) ++ return -EINVAL; ++ ++ if (IS_ERR_OR_NULL(dev->pm_domain)) ++ return -EINVAL; ++ ++ genpd = pd_to_genpd(dev->pm_domain); ++ pd = to_rockchip_pd(genpd); ++ ++ mutex_lock(&pd->pmu->mutex); ++ ret = rockchip_pmu_set_idle_request(pd, idle); ++ mutex_unlock(&pd->pmu->mutex); ++ ++ return ret; ++} ++EXPORT_SYMBOL(rockchip_pmu_idle_request); ++ + static int rockchip_pmu_save_qos(struct rockchip_pm_domain *pd) + { + int i; +diff --git a/include/linux/rockchip_pmu.h b/include/linux/rockchip_pmu.h +new file mode 100644 +index 000000000000..720b3314e71a +--- /dev/null ++++ b/include/linux/rockchip_pmu.h +@@ -0,0 +1,15 @@ ++/* ++ * pm_domain.h - Definitions and headers related to device power domains. ++ * ++ * Copyright (C) 2017 Randy Li . ++ * ++ * This file is released under the GPLv2. ++ */ ++ ++#ifndef _LINUX_ROCKCHIP_PM_H ++#define _LINUX_ROCKCHIP_PM_H ++#include ++ ++int rockchip_pmu_idle_request(struct device *dev, bool idle); ++ ++#endif /* _LINUX_ROCKCHIP_PM_H */ +diff --git a/include/soc/rockchip/pm_domains.h b/include/soc/rockchip/pm_domains.h +new file mode 100644 +index 000000000000..690db6118636 +--- /dev/null ++++ b/include/soc/rockchip/pm_domains.h +@@ -0,0 +1,18 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++#ifndef __SOC_ROCKCHIP_PM_DOMAINS_H ++#define __SOC_ROCKCHIP_PM_DOMAINS_H ++ ++#include ++ ++struct device; ++ ++#ifdef CONFIG_ROCKCHIP_PM_DOMAINS ++int rockchip_pmu_idle_request(struct device *dev, bool idle); ++#else ++static inline int rockchip_pmu_idle_request(struct device *dev, bool idle) ++{ ++ return -ENOTSUPP; ++} ++#endif ++ ++#endif + +From 495e11bbb264dfb5f1d8b319ed647901fc91dc11 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Wed, 20 May 2020 17:04:47 +0200 +Subject: [PATCH] media: rkvdec: implement reset controls + +--- + .../bindings/media/rockchip,vdec.yaml | 19 ++++++ + drivers/staging/media/rkvdec/rkvdec-regs.h | 5 ++ + drivers/staging/media/rkvdec/rkvdec.c | 60 +++++++++++++++++++ + drivers/staging/media/rkvdec/rkvdec.h | 11 +++- + 4 files changed, 94 insertions(+), 1 deletion(-) + +diff --git a/Documentation/devicetree/bindings/media/rockchip,vdec.yaml b/Documentation/devicetree/bindings/media/rockchip,vdec.yaml +index 8d35c327018b..1e8cfd8e032b 100644 +--- a/Documentation/devicetree/bindings/media/rockchip,vdec.yaml ++++ b/Documentation/devicetree/bindings/media/rockchip,vdec.yaml +@@ -43,6 +43,18 @@ properties: + iommus: + maxItems: 1 + ++ resets: ++ maxItems: 6 ++ ++ reset-names: ++ items: ++ - const: video_h ++ - const: video_a ++ - const: video_core ++ - const: video_cabac ++ - const: niu_a ++ - const: niu_h ++ + required: + - compatible + - reg +@@ -50,6 +62,8 @@ required: + - clocks + - clock-names + - power-domains ++ - resets ++ - reset-names + + additionalProperties: false + +@@ -68,6 +82,11 @@ examples: + clock-names = "axi", "ahb", "cabac", "core"; + power-domains = <&power RK3399_PD_VDU>; + iommus = <&vdec_mmu>; ++ resets = <&cru SRST_H_VDU>, <&cru SRST_A_VDU>, ++ <&cru SRST_VDU_CORE>, <&cru SRST_VDU_CA>, ++ <&cru SRST_A_VDU_NOC>, <&cru SRST_H_VDU_NOC>; ++ reset-names = "video_h", "video_a", "video_core", "video_cabac", ++ "niu_a", "niu_h" + }; + + ... +diff --git a/drivers/staging/media/rkvdec/rkvdec-regs.h b/drivers/staging/media/rkvdec/rkvdec-regs.h +index 83bf790ed9b7..4addfaefdfb4 100644 +--- a/drivers/staging/media/rkvdec/rkvdec-regs.h ++++ b/drivers/staging/media/rkvdec/rkvdec-regs.h +@@ -28,6 +28,11 @@ + #define RKVDEC_SOFTRST_EN_P BIT(20) + #define RKVDEC_FORCE_SOFTRESET_VALID BIT(21) + #define RKVDEC_SOFTRESET_RDY BIT(22) ++#define RKVDEC_ERR_MASK (RKVDEC_BUS_STA \ ++ | RKVDEC_ERR_STA \ ++ | RKVDEC_TIMEOUT_STA \ ++ | RKVDEC_BUF_EMPTY_STA \ ++ | RKVDEC_COLMV_REF_ERR_STA ) + + #define RKVDEC_REG_SYSCTRL 0x008 + #define RKVDEC_IN_ENDIAN BIT(0) +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index 869275a411c8..74f566e65413 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -10,12 +10,15 @@ + */ + + #include ++#include + #include + #include + #include + #include + #include + #include ++#include ++#include + #include + #include + #include +@@ -871,6 +874,11 @@ static void rkvdec_job_finish(struct rkvdec_ctx *ctx, + + pm_runtime_mark_last_busy(rkvdec->dev); + pm_runtime_put_autosuspend(rkvdec->dev); ++ ++ if (result == VB2_BUF_STATE_ERROR && ++ rkvdec->reset_mask == RESET_NONE) ++ rkvdec->reset_mask |= RESET_SOFT; ++ + rkvdec_job_finish_no_pm(ctx, result); + } + +@@ -908,6 +916,40 @@ static void rkvdec_device_run(void *priv) + + if (WARN_ON(!desc)) + return; ++ if (rkvdec->reset_mask != RESET_NONE) { ++ ++ if (rkvdec->reset_mask & RESET_SOFT) { ++ writel(RKVDEC_SOFTRST_EN_P, ++ rkvdec->regs + RKVDEC_REG_INTERRUPT); ++ udelay(RKVDEC_RESET_DELAY); ++ if (readl(rkvdec->regs + RKVDEC_REG_INTERRUPT) ++ & RKVDEC_SOFTRESET_RDY) ++ dev_info_ratelimited(rkvdec->dev, ++ "softreset failed\n"); ++ else ++ dev_notice_ratelimited(rkvdec->dev, ++ "softreset done\n"); ++ } ++ ++ if (rkvdec->reset_mask & RESET_HARD) { ++ pm_runtime_suspend(rkvdec->dev); ++ rockchip_pmu_idle_request(rkvdec->dev, true); ++ ret = reset_control_assert(rkvdec->rstc); ++ if (!ret) { ++ udelay(RKVDEC_RESET_DELAY); ++ ret = reset_control_deassert(rkvdec->rstc); ++ } ++ rockchip_pmu_idle_request(rkvdec->dev, false); ++ if (ret) ++ dev_notice_ratelimited(rkvdec->dev, ++ "hardreset failed\n"); ++ else ++ dev_notice_ratelimited(rkvdec->dev, ++ "hardreset done\n"); ++ } ++ ++ rkvdec->reset_mask = RESET_NONE; ++ } + + ret = pm_runtime_get_sync(rkvdec->dev); + if (ret < 0) { +@@ -1175,6 +1217,11 @@ static irqreturn_t rkvdec_irq_handler(int irq, void *priv) + if (cancel_delayed_work(&rkvdec->watchdog_work)) { + struct rkvdec_ctx *ctx; + ++ if (state == VB2_BUF_STATE_ERROR) { ++ rkvdec->reset_mask |= (status & RKVDEC_ERR_MASK) ? ++ RESET_HARD : RESET_SOFT; ++ } ++ + ctx = v4l2_m2m_get_curr_priv(rkvdec->m2m_dev); + rkvdec_job_finish(ctx, state); + } +@@ -1192,6 +1239,7 @@ static void rkvdec_watchdog_func(struct work_struct *work) + ctx = v4l2_m2m_get_curr_priv(rkvdec->m2m_dev); + if (ctx) { + dev_err(rkvdec->dev, "Frame processing timed out!\n"); ++ rkvdec->reset_mask |= RESET_HARD; + writel(RKVDEC_CONFIG_DEC_CLK_GATE_E | RKVDEC_IRQ_DIS, + rkvdec->regs + RKVDEC_REG_INTERRUPT); + writel(0, rkvdec->regs + RKVDEC_REG_SYSCTRL); +@@ -1271,6 +1319,18 @@ static int rkvdec_probe(struct platform_device *pdev) + return ret; + } + ++ ++ rkvdec->rstc = devm_reset_control_array_get(&pdev->dev, false, true); ++ if (IS_ERR(rkvdec->rstc)) { ++ dev_err(&pdev->dev, ++ "get resets failed %ld\n", PTR_ERR(rkvdec->rstc)); ++ return PTR_ERR(rkvdec->rstc); ++ } else { ++ dev_dbg(&pdev->dev, ++ "requested %d resets\n", ++ reset_control_get_count(&pdev->dev)); ++ } ++ + pm_runtime_set_autosuspend_delay(&pdev->dev, 100); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_enable(&pdev->dev); +diff --git a/drivers/staging/media/rkvdec/rkvdec.h b/drivers/staging/media/rkvdec/rkvdec.h +index d5600c6a4c17..975fe4b5dd68 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.h ++++ b/drivers/staging/media/rkvdec/rkvdec.h +@@ -11,10 +11,11 @@ + #ifndef RKVDEC_H_ + #define RKVDEC_H_ + ++#include + #include ++#include + #include + #include +-#include + + #include + #include +@@ -22,6 +23,12 @@ + #include + #include + ++#define RESET_NONE 0 ++#define RESET_SOFT BIT(0) ++#define RESET_HARD BIT(1) ++ ++#define RKVDEC_RESET_DELAY 5 ++ + struct rkvdec_ctx; + + struct rkvdec_ctrl_desc { +@@ -95,6 +102,8 @@ struct rkvdec_dev { + void __iomem *regs; + struct mutex vdev_lock; /* serializes ioctls */ + struct delayed_work watchdog_work; ++ struct reset_control *rstc; ++ u8 reset_mask; + }; + + struct rkvdec_ctx { + +From 0f3ef2d452750f5688292c232b6c7d28ce2b0095 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Tue, 18 Aug 2020 11:38:04 +0200 +Subject: [PATCH] WIP: arm64: dts: add resets to vdec for RK3399 + +--- + arch/arm64/boot/dts/rockchip/rk3399.dtsi | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi +index 8973bf68d652..1efe2c916508 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi +@@ -1281,6 +1281,11 @@ vdec: video-codec@ff660000 { + clock-names = "axi", "ahb", "cabac", "core"; + iommus = <&vdec_mmu>; + power-domains = <&power RK3399_PD_VDU>; ++ resets = <&cru SRST_H_VDU>, <&cru SRST_A_VDU>, ++ <&cru SRST_VDU_CORE>, <&cru SRST_VDU_CA>, ++ <&cru SRST_A_VDU_NOC>, <&cru SRST_H_VDU_NOC>; ++ reset-names = "video_h", "video_a", "video_core", "video_cabac", ++ "niu_a", "niu_h" + }; + + vdec_mmu: iommu@ff660480 { + +From 98eac32dca51c74be1d223854976b834ac2d9587 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Fri, 24 Apr 2020 12:36:13 +0200 +Subject: [PATCH] media: hantro: add Rockchip RK3228 + +RK3228 has the same VPU IP-Block as RK3399 has and at the current state +the driver can be taken as is. +This adds just a new compatible string to bindings file if any future +ajustment for this SoC is necessary. +--- + Documentation/devicetree/bindings/media/rockchip-vpu.yaml | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml +index 2b629456d75f..4509891a0f0f 100644 +--- a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml ++++ b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml +@@ -16,6 +16,7 @@ description: + properties: + compatible: + enum: ++ - rockchip,rk3228-vpu + - rockchip,rk3288-vpu + - rockchip,rk3328-vpu + - rockchip,rk3399-vpu + +From e47b8ed20a45dcb324b997e5fa74586f71fc71cc Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Fri, 24 Apr 2020 12:38:24 +0200 +Subject: [PATCH] ARM: dts: rockchip: add vpu node for RK322x + +This adds VPU node to RK3228. While at it also add the required power-domain +controller and qos node to make the VPU work on this SoC. +--- + arch/arm/boot/dts/rk322x.dtsi | 35 +++++++++++++++++++++++++++++++++-- + 1 file changed, 33 insertions(+), 2 deletions(-) + +diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi +index b69b5be110c3..0586a89d24d3 100644 +--- a/arch/arm/boot/dts/rk322x.dtsi ++++ b/arch/arm/boot/dts/rk322x.dtsi +@@ -6,6 +6,7 @@ + #include + #include + #include ++#include + + / { + #address-cells = <1>; +@@ -208,6 +209,19 @@ io_domains: io-domains { + status = "disabled"; + }; + ++ power: power-controller { ++ compatible = "rockchip,rk3228-power-controller"; ++ #power-domain-cells = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ pd_vpu@RK3228_PD_VPU { ++ reg = ; ++ clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; ++ pm_qos = <&qos_vpu>; ++ }; ++ }; ++ + u2phy0: usb2-phy@760 { + compatible = "rockchip,rk3228-usb2phy"; + reg = <0x0760 0x0c>; +@@ -561,6 +575,18 @@ gpu: gpu@20000000 { + status = "disabled"; + }; + ++ vpu: video-codec@20020000 { ++ compatible = "rockchip,rk3228-vpu", "rockchip,rk3399-vpu"; ++ reg = <0x20020000 0x800>; ++ interrupts = , ++ ; ++ interrupt-names = "vepu", "vdpu"; ++ clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; ++ clock-names = "aclk", "hclk"; ++ iommus = <&vpu_mmu>; ++ power-domains = <&power RK3228_PD_VPU>; ++ }; ++ + vpu_mmu: iommu@20020800 { + compatible = "rockchip,iommu"; + reg = <0x20020800 0x100>; +@@ -568,8 +594,8 @@ vpu_mmu: iommu@20020800 { + interrupt-names = "vpu_mmu"; + clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; + clock-names = "aclk", "iface"; +- iommu-cells = <0>; +- status = "disabled"; ++ power-domains = <&power RK3228_PD_VPU>; ++ #iommu-cells = <0>; + }; + + vdec_mmu: iommu@20030480 { +@@ -807,6 +833,11 @@ gmac: ethernet@30200000 { + status = "disabled"; + }; + ++ qos_vpu: qos@31040000 { ++ compatible = "syscon"; ++ reg = <0x31040000 0x20>; ++ }; ++ + gic: interrupt-controller@32010000 { + compatible = "arm,gic-400"; + interrupt-controller; + +From 70feb241848426de731a1f8bc5ad0d9c45bf5bfa Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Tue, 26 May 2020 14:11:57 +0200 +Subject: [PATCH] media: hantro: add support for RK3188 + +RK3188s VPU IP-Block is the predecessor from what RK3288 has. + +While most of the registers match in the current state of the driver +there are some HW differences: + - supports resultion up to 1920x1088 only + - has one aclk and one hclk per vdpu/vepu + - doesn't have the 'G1_REG_SOFT_RESET' register + - ACLKs can be clocked up to 300 MHz only + - no MMU for VPU +These make it necessary to add another variant to the driver. + +This should be also reuseable for RK3066 but has not been tested, +so I'm not adding it here. +--- + .../bindings/media/rockchip-vpu.yaml | 7 +- + drivers/staging/media/hantro/hantro_drv.c | 1 + + drivers/staging/media/hantro/hantro_hw.h | 1 + + drivers/staging/media/hantro/rk3288_vpu_hw.c | 116 ++++++++++++++++++ + 4 files changed, 124 insertions(+), 1 deletion(-) + +diff --git a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml +index 4509891a0f0f..d95274bf3b0f 100644 +--- a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml ++++ b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml +@@ -16,6 +16,7 @@ description: + properties: + compatible: + enum: ++ - rockchip,rk3188-vpu + - rockchip,rk3228-vpu + - rockchip,rk3288-vpu + - rockchip,rk3328-vpu +@@ -36,12 +37,16 @@ properties: + - const: vdpu + + clocks: +- maxItems: 2 ++ maxItems: 4 + + clock-names: + items: + - const: aclk ++ - const: aclk_vdpu ++ - const: aclk_vepu + - const: hclk ++ - const: hclk_vdpu ++ - const: hclk_vepu + + power-domains: + maxItems: 1 +diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c +index 3cd00cc0a364..ecc0938b7f35 100644 +--- a/drivers/staging/media/hantro/hantro_drv.c ++++ b/drivers/staging/media/hantro/hantro_drv.c +@@ -475,6 +475,7 @@ static const struct of_device_id of_hantro_match[] = { + { .compatible = "rockchip,rk3399-vpu", .data = &rk3399_vpu_variant, }, + { .compatible = "rockchip,rk3328-vpu", .data = &rk3328_vpu_variant, }, + { .compatible = "rockchip,rk3288-vpu", .data = &rk3288_vpu_variant, }, ++ { .compatible = "rockchip,rk3188-vpu", .data = &rk3188_vpu_variant, }, + #endif + #ifdef CONFIG_VIDEO_HANTRO_IMX8M + { .compatible = "nxp,imx8mq-vpu", .data = &imx8mq_vpu_variant, }, +diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h +index 7e35140a4f22..22b0ed01f673 100644 +--- a/drivers/staging/media/hantro/hantro_hw.h ++++ b/drivers/staging/media/hantro/hantro_hw.h +@@ -152,6 +152,7 @@ enum hantro_enc_fmt { + RK3288_VPU_ENC_FMT_UYVY422 = 3, + }; + ++extern const struct hantro_variant rk3188_vpu_variant; + extern const struct hantro_variant rk3399_vpu_variant; + extern const struct hantro_variant rk3328_vpu_variant; + extern const struct hantro_variant rk3288_vpu_variant; +diff --git a/drivers/staging/media/hantro/rk3288_vpu_hw.c b/drivers/staging/media/hantro/rk3288_vpu_hw.c +index 7b299ee3e93d..1ac00695a864 100644 +--- a/drivers/staging/media/hantro/rk3288_vpu_hw.c ++++ b/drivers/staging/media/hantro/rk3288_vpu_hw.c +@@ -13,6 +13,7 @@ + #include "hantro_g1_regs.h" + #include "hantro_h1_regs.h" + ++#define RK3188_ACLK_MAX_FREQ (300 * 1000 * 1000) + #define RK3288_ACLK_MAX_FREQ (400 * 1000 * 1000) + + /* +@@ -63,6 +64,52 @@ static const struct hantro_fmt rk3288_vpu_postproc_fmts[] = { + }, + }; + ++static const struct hantro_fmt rk3188_vpu_dec_fmts[] = { ++ { ++ .fourcc = V4L2_PIX_FMT_NV12, ++ .codec_mode = HANTRO_MODE_NONE, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_H264_SLICE, ++ .codec_mode = HANTRO_MODE_H264_DEC, ++ .max_depth = 2, ++ .frmsize = { ++ .min_width = 48, ++ .max_width = 1920, ++ .step_width = MB_DIM, ++ .min_height = 48, ++ .max_height = 1088, ++ .step_height = MB_DIM, ++ }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_MPEG2_SLICE, ++ .codec_mode = HANTRO_MODE_MPEG2_DEC, ++ .max_depth = 2, ++ .frmsize = { ++ .min_width = 48, ++ .max_width = 1920, ++ .step_width = MB_DIM, ++ .min_height = 48, ++ .max_height = 1088, ++ .step_height = MB_DIM, ++ }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_VP8_FRAME, ++ .codec_mode = HANTRO_MODE_VP8_DEC, ++ .max_depth = 2, ++ .frmsize = { ++ .min_width = 48, ++ .max_width = 1920, ++ .step_width = MB_DIM, ++ .min_height = 48, ++ .max_height = 1088, ++ .step_height = MB_DIM, ++ }, ++ }, ++}; ++ + static const struct hantro_fmt rk3288_vpu_dec_fmts[] = { + { + .fourcc = V4L2_PIX_FMT_NV12, +@@ -145,6 +192,14 @@ static irqreturn_t rk3288_vdpu_irq(int irq, void *dev_id) + return IRQ_HANDLED; + } + ++static int rk3188_vpu_hw_init(struct hantro_dev *vpu) ++{ ++ /* Bump ACLKs to max. possible freq. to improve performance. */ ++ clk_set_rate(vpu->clocks[0].clk, RK3188_ACLK_MAX_FREQ); ++ clk_set_rate(vpu->clocks[2].clk, RK3188_ACLK_MAX_FREQ); ++ return 0; ++} ++ + static int rk3288_vpu_hw_init(struct hantro_dev *vpu) + { + /* Bump ACLK to max. possible freq. to improve performance. */ +@@ -161,6 +216,15 @@ static void rk3288_vpu_enc_reset(struct hantro_ctx *ctx) + vepu_write(vpu, 0, H1_REG_AXI_CTRL); + } + ++ ++static void rk3188_vpu_dec_reset(struct hantro_ctx *ctx) ++{ ++ struct hantro_dev *vpu = ctx->dev; ++ ++ vdpu_write(vpu, G1_REG_INTERRUPT_DEC_IRQ_DIS, G1_REG_INTERRUPT); ++ vdpu_write(vpu, G1_REG_CONFIG_DEC_CLK_GATE_E, G1_REG_CONFIG); ++} ++ + static void rk3288_vpu_dec_reset(struct hantro_ctx *ctx) + { + struct hantro_dev *vpu = ctx->dev; +@@ -174,6 +238,33 @@ static void rk3288_vpu_dec_reset(struct hantro_ctx *ctx) + * Supported codec ops. + */ + ++static const struct hantro_codec_ops rk3188_vpu_codec_ops[] = { ++ [HANTRO_MODE_JPEG_ENC] = { ++ .run = hantro_h1_jpeg_enc_run, ++ .reset = rk3288_vpu_enc_reset, ++ .init = hantro_jpeg_enc_init, ++ .exit = hantro_jpeg_enc_exit, ++ }, ++ [HANTRO_MODE_H264_DEC] = { ++ .run = hantro_g1_h264_dec_run, ++ .reset = rk3188_vpu_dec_reset, ++ .init = hantro_h264_dec_init, ++ .exit = hantro_h264_dec_exit, ++ }, ++ [HANTRO_MODE_MPEG2_DEC] = { ++ .run = hantro_g1_mpeg2_dec_run, ++ .reset = rk3188_vpu_dec_reset, ++ .init = hantro_mpeg2_dec_init, ++ .exit = hantro_mpeg2_dec_exit, ++ }, ++ [HANTRO_MODE_VP8_DEC] = { ++ .run = hantro_g1_vp8_dec_run, ++ .reset = rk3188_vpu_dec_reset, ++ .init = hantro_vp8_dec_init, ++ .exit = hantro_vp8_dec_exit, ++ }, ++}; ++ + static const struct hantro_codec_ops rk3288_vpu_codec_ops[] = { + [HANTRO_MODE_JPEG_ENC] = { + .run = hantro_h1_jpeg_enc_run, +@@ -211,10 +302,35 @@ static const struct hantro_irq rk3288_irqs[] = { + { "vdpu", rk3288_vdpu_irq }, + }; + ++static const char * const rk3188_clk_names[] = { ++ "aclk_vdpu", "hclk_vdpu", ++ "aclk_vepu", "hclk_vepu", ++}; ++ + static const char * const rk3288_clk_names[] = { + "aclk", "hclk" + }; + ++const struct hantro_variant rk3188_vpu_variant = { ++ .enc_offset = 0x0, ++ .enc_fmts = rk3288_vpu_enc_fmts, ++ .num_enc_fmts = ARRAY_SIZE(rk3288_vpu_enc_fmts), ++ .dec_offset = 0x400, ++ .dec_fmts = rk3188_vpu_dec_fmts, ++ .num_dec_fmts = ARRAY_SIZE(rk3188_vpu_dec_fmts), ++ .postproc_fmts = rk3288_vpu_postproc_fmts, ++ .num_postproc_fmts = ARRAY_SIZE(rk3288_vpu_postproc_fmts), ++ .postproc_regs = &hantro_g1_postproc_regs, ++ .codec = HANTRO_JPEG_ENCODER | HANTRO_MPEG2_DECODER | ++ HANTRO_VP8_DECODER | HANTRO_H264_DECODER, ++ .codec_ops = rk3188_vpu_codec_ops, ++ .irqs = rk3288_irqs, ++ .num_irqs = ARRAY_SIZE(rk3288_irqs), ++ .init = rk3188_vpu_hw_init, ++ .clk_names = rk3188_clk_names, ++ .num_clocks = ARRAY_SIZE(rk3188_clk_names) ++}; ++ + const struct hantro_variant rk3288_vpu_variant = { + .enc_offset = 0x0, + .enc_fmts = rk3288_vpu_enc_fmts, + +From 134592088d9c703169c9daff5793e0321ecc245d Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Tue, 26 May 2020 14:12:35 +0200 +Subject: [PATCH] ARM: dts: rockchip: add vpu node for RK3188 + +Add VPU node to RK3188s dtsi. +--- + arch/arm/boot/dts/rk3188.dtsi | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi +index 2298a8d840ba..b6c1699345d0 100644 +--- a/arch/arm/boot/dts/rk3188.dtsi ++++ b/arch/arm/boot/dts/rk3188.dtsi +@@ -112,6 +112,19 @@ smp-sram@0 { + }; + }; + ++ vpu: video-codec@10104000 { ++ compatible = "rockchip,rk3188-vpu"; ++ reg = <0x10104000 0x800>; ++ interrupts = , ++ ; ++ interrupt-names = "vepu", "vdpu"; ++ clocks = <&cru ACLK_VDPU>, <&cru HCLK_VDPU>, ++ <&cru ACLK_VEPU>, <&cru HCLK_VEPU>; ++ clock-names = "aclk_vdpu", "hclk_vdpu", ++ "aclk_vepu", "hclk_vepu"; ++ power-domains = <&power RK3188_PD_VIDEO>; ++ }; ++ + vop0: vop@1010c000 { + compatible = "rockchip,rk3188-vop"; + reg = <0x1010c000 0x1000>; + +From 573413b3e49d1ca7676c976aa3e7d6bb65e497ed Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Tue, 26 May 2020 17:24:12 +0200 +Subject: [PATCH] media: hantro: add support for Rockchip RK3036 + +RK3036 shares the hantro VPU IP Block with RK3288. +HW differences are: +- supports decoding up to 1920x1088 only +- ACLK can be clocked at max. 300MHz +This makes adding another variant to the driver necessary here also. + +However RK3036 TRM does not mention that it has an encoder also. I verfied +this on my devices and it worked for JPEG encoding. Since the identification +register share the id with RK3288 and the fact that it has an interrupt for +video encoding, makes me think that the encoding IP is the same. + +This variant could also be used for RK312x, but has not been tested. +--- + drivers/staging/media/hantro/hantro_drv.c | 1 + + drivers/staging/media/hantro/hantro_hw.h | 1 + + drivers/staging/media/hantro/rk3288_vpu_hw.c | 27 ++++++++++++++++++++ + 3 files changed, 29 insertions(+) + +diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c +index ecc0938b7f35..ee59fad9a2f3 100644 +--- a/drivers/staging/media/hantro/hantro_drv.c ++++ b/drivers/staging/media/hantro/hantro_drv.c +@@ -476,6 +476,7 @@ static const struct of_device_id of_hantro_match[] = { + { .compatible = "rockchip,rk3328-vpu", .data = &rk3328_vpu_variant, }, + { .compatible = "rockchip,rk3288-vpu", .data = &rk3288_vpu_variant, }, + { .compatible = "rockchip,rk3188-vpu", .data = &rk3188_vpu_variant, }, ++ { .compatible = "rockchip,rk3036-vpu", .data = &rk3036_vpu_variant, }, + #endif + #ifdef CONFIG_VIDEO_HANTRO_IMX8M + { .compatible = "nxp,imx8mq-vpu", .data = &imx8mq_vpu_variant, }, +diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h +index 22b0ed01f673..ede7acec5e9f 100644 +--- a/drivers/staging/media/hantro/hantro_hw.h ++++ b/drivers/staging/media/hantro/hantro_hw.h +@@ -152,6 +152,7 @@ enum hantro_enc_fmt { + RK3288_VPU_ENC_FMT_UYVY422 = 3, + }; + ++extern const struct hantro_variant rk3036_vpu_variant; + extern const struct hantro_variant rk3188_vpu_variant; + extern const struct hantro_variant rk3399_vpu_variant; + extern const struct hantro_variant rk3328_vpu_variant; +diff --git a/drivers/staging/media/hantro/rk3288_vpu_hw.c b/drivers/staging/media/hantro/rk3288_vpu_hw.c +index 1ac00695a864..b5887fdae250 100644 +--- a/drivers/staging/media/hantro/rk3288_vpu_hw.c ++++ b/drivers/staging/media/hantro/rk3288_vpu_hw.c +@@ -192,6 +192,13 @@ static irqreturn_t rk3288_vdpu_irq(int irq, void *dev_id) + return IRQ_HANDLED; + } + ++static int rk3036_vpu_hw_init(struct hantro_dev *vpu) ++{ ++ /* Bump ACLK to max. possible freq. to improve performance. */ ++ clk_set_rate(vpu->clocks[0].clk, RK3188_ACLK_MAX_FREQ); ++ return 0; ++} ++ + static int rk3188_vpu_hw_init(struct hantro_dev *vpu) + { + /* Bump ACLKs to max. possible freq. to improve performance. */ +@@ -311,6 +318,26 @@ static const char * const rk3288_clk_names[] = { + "aclk", "hclk" + }; + ++const struct hantro_variant rk3036_vpu_variant = { ++ .enc_offset = 0x0, ++ .enc_fmts = rk3288_vpu_enc_fmts, ++ .num_enc_fmts = ARRAY_SIZE(rk3288_vpu_enc_fmts), ++ .dec_offset = 0x400, ++ .dec_fmts = rk3188_vpu_dec_fmts, ++ .num_dec_fmts = ARRAY_SIZE(rk3188_vpu_dec_fmts), ++ .postproc_fmts = rk3288_vpu_postproc_fmts, ++ .num_postproc_fmts = ARRAY_SIZE(rk3288_vpu_postproc_fmts), ++ .postproc_regs = &hantro_g1_postproc_regs, ++ .codec = HANTRO_JPEG_ENCODER | HANTRO_MPEG2_DECODER | ++ HANTRO_VP8_DECODER | HANTRO_H264_DECODER, ++ .codec_ops = rk3288_vpu_codec_ops, ++ .irqs = rk3288_irqs, ++ .num_irqs = ARRAY_SIZE(rk3288_irqs), ++ .init = rk3036_vpu_hw_init, ++ .clk_names = rk3288_clk_names, ++ .num_clocks = ARRAY_SIZE(rk3288_clk_names) ++}; ++ + const struct hantro_variant rk3188_vpu_variant = { + .enc_offset = 0x0, + .enc_fmts = rk3288_vpu_enc_fmts, + +From 387d5e35e99f03bb0caed01163ef393e15b30362 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Tue, 26 May 2020 17:42:55 +0200 +Subject: [PATCH] ARM: dts: rockchip: add vpu node for RK3036 + +This adds VPU node to RK3036. While at it also add the required mmu, +power-domain controller and qos node to make the VPU work on this SoC. +--- + .../bindings/media/rockchip-vpu.yaml | 1 + + arch/arm/boot/dts/rk3036.dtsi | 44 +++++++++++++++++++ + 2 files changed, 45 insertions(+) + +diff --git a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml +index d95274bf3b0f..15aeae3d1daf 100644 +--- a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml ++++ b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml +@@ -16,6 +16,7 @@ description: + properties: + compatible: + enum: ++ - rockchip,rk3036-vpu + - rockchip,rk3188-vpu + - rockchip,rk3228-vpu + - rockchip,rk3288-vpu +diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi +index 6be6d9d134fe..10f15cdb932c 100644 +--- a/arch/arm/boot/dts/rk3036.dtsi ++++ b/arch/arm/boot/dts/rk3036.dtsi +@@ -6,6 +6,7 @@ + #include + #include + #include ++#include + + / { + #address-cells = <1>; +@@ -134,6 +135,29 @@ gpu: gpu@10090000 { + status = "disabled"; + }; + ++ vpu: video-codec@10108000 { ++ compatible = "rockchip,rk3036-vpu"; ++ reg = <0x10108000 0x800>; ++ interrupts = , ++ ; ++ interrupt-names = "vepu", "vdpu"; ++ clocks = <&cru ACLK_VCODEC>, <&cru HCLK_VCODEC>; ++ clock-names = "aclk", "hclk"; ++ iommus = <&vpu_mmu>; ++ power-domains = <&power RK3036_PD_VPU>; ++ }; ++ ++ vpu_mmu: iommu@10108800 { ++ compatible = "rockchip,iommu"; ++ reg = <0x10108800 0x100>; ++ interrupts = ; ++ interrupt-names = "vpu_mmu"; ++ clocks = <&cru ACLK_VCODEC>, <&cru HCLK_VCODEC>; ++ clock-names = "aclk", "iface"; ++ power-domains = <&power RK3036_PD_VPU>; ++ #iommu-cells = <0>; ++ }; ++ + vop: vop@10118000 { + compatible = "rockchip,rk3036-vop"; + reg = <0x10118000 0x19c>; +@@ -166,6 +190,11 @@ vop_mmu: iommu@10118300 { + status = "disabled"; + }; + ++ qos_vpu: qos@1012e000 { ++ compatible = "syscon"; ++ reg = <0x1012e000 0x20>; ++ }; ++ + gic: interrupt-controller@10139000 { + compatible = "arm,gic-400"; + interrupt-controller; +@@ -329,6 +358,21 @@ reboot-mode { + mode-bootloader = ; + mode-loader = ; + }; ++ ++ power: power-controller { ++ compatible = "rockchip,rk3036-power-controller"; ++ #power-domain-cells = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ pd_vpu@RK3036_PD_VPU { ++ reg = ; ++ clocks = <&cru ACLK_VCODEC>, ++ <&cru HCLK_VCODEC>; ++ pm_qos = <&qos_vpu>; ++ }; ++ ++ }; + }; + + acodec: acodec-ana@20030000 { + +From 871a3ef06a4100a3d7ecc75d2751acf67269a07c Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Tue, 26 May 2020 17:54:22 +0200 +Subject: [PATCH] media: hantro: adapt Kconfig help text + +Since help text line would get very long if all supported SoCs are mentioned +I shortend it to "Rockchip SoCs" +--- + drivers/staging/media/hantro/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/staging/media/hantro/Kconfig b/drivers/staging/media/hantro/Kconfig +index 5b6cf9f62b1a..d33f1ddbc9c9 100644 +--- a/drivers/staging/media/hantro/Kconfig ++++ b/drivers/staging/media/hantro/Kconfig +@@ -30,4 +30,4 @@ config VIDEO_HANTRO_ROCKCHIP + depends on ARCH_ROCKCHIP || COMPILE_TEST + default y + help +- Enable support for RK3288, RK3328, and RK3399 SoCs. ++ Enable support for Rockchip SoCs. + +From 83c9c3f037c52e8c4ada8b5b5f1269ccfa6f6f14 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sat, 23 May 2020 14:22:54 +0200 +Subject: [PATCH] ARM: dts: rockchip: add vdec node for RK322x + +RK322x has the same VDEC IP block as RK3399 has and the driver in its +current state can be used as is. +Other than RK3399 its SCLKs have also to set to a fixed value to make it +work correctly. Rather than doing this in the driver it is done via +"assigned-clocks" in the vdec node. +--- + arch/arm/boot/dts/rk322x.dtsi | 42 +++++++++++++++++++++++++++++++++-- + 1 file changed, 40 insertions(+), 2 deletions(-) + +diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi +index 0586a89d24d3..eec601fb4cd0 100644 +--- a/arch/arm/boot/dts/rk322x.dtsi ++++ b/arch/arm/boot/dts/rk322x.dtsi +@@ -220,6 +220,15 @@ pd_vpu@RK3228_PD_VPU { + clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; + pm_qos = <&qos_vpu>; + }; ++ ++ pd_rkvdec@RK3228_PD_RKVDEC { ++ reg = ; ++ clocks = <&cru ACLK_RKVDEC>, ++ <&cru HCLK_RKVDEC>, ++ <&cru SCLK_VDEC_CABAC>, ++ <&cru SCLK_VDEC_CORE>; ++ pm_qos = <&qos_rkvdec_r>, <&qos_rkvdec_w>; ++ }; + }; + + u2phy0: usb2-phy@760 { +@@ -598,6 +607,25 @@ vpu_mmu: iommu@20020800 { + #iommu-cells = <0>; + }; + ++ vdec: video-codec@20030000 { ++ compatible = "rockchip,rk322x-vdec", "rockchip,rk3399-vdec"; ++ reg = <0x20030000 0x400>; ++ interrupts = ; ++ clocks = <&cru ACLK_RKVDEC>, <&cru HCLK_RKVDEC>, ++ <&cru SCLK_VDEC_CABAC>, <&cru SCLK_VDEC_CORE>; ++ clock-names = "axi", "ahb", "cabac", "core"; ++ assigned-clocks = <&cru ACLK_RKVDEC>, <&cru SCLK_VDEC_CABAC>, ++ <&cru SCLK_VDEC_CORE>; ++ assigned-clock-rates = <500000000>, <300000000>, <300000000>; ++ power-domains = <&power RK3228_PD_RKVDEC>; ++ resets = <&cru SRST_RKVDEC_H>, <&cru SRST_RKVDEC_A>, ++ <&cru SRST_RKVDEC_CORE>, <&cru SRST_RKVDEC_CABAC>, ++ <&cru SRST_RKVDEC_NOC_A>, <&cru SRST_RKVDEC_NOC_H>; ++ reset-names = "video_h", "video_a", "video_core", "video_cabac", ++ "niu_a", "niu_h"; ++ iommus = <&vdec_mmu>; ++ }; ++ + vdec_mmu: iommu@20030480 { + compatible = "rockchip,iommu"; + reg = <0x20030480 0x40>, <0x200304c0 0x40>; +@@ -605,8 +633,8 @@ vdec_mmu: iommu@20030480 { + interrupt-names = "vdec_mmu"; + clocks = <&cru ACLK_RKVDEC>, <&cru HCLK_RKVDEC>; + clock-names = "aclk", "iface"; +- iommu-cells = <0>; +- status = "disabled"; ++ power-domains = <&power RK3228_PD_RKVDEC>; ++ #iommu-cells = <0>; + }; + + vop: vop@20050000 { +@@ -838,6 +866,16 @@ qos_vpu: qos@31040000 { + reg = <0x31040000 0x20>; + }; + ++ qos_rkvdec_r: qos@31070000 { ++ compatible = "syscon"; ++ reg = <0x31070000 0x20>; ++ }; ++ ++ qos_rkvdec_w: qos@31070080 { ++ compatible = "syscon"; ++ reg = <0x31070080 0x20>; ++ }; ++ + gic: interrupt-controller@32010000 { + compatible = "arm,gic-400"; + interrupt-controller; diff --git a/patch/kernel/rk322x-current/01-linux-4000-rockchip-linux-wip.patch b/patch/kernel/rk322x-current/01-linux-4000-rockchip-linux-wip.patch new file mode 100644 index 000000000..2c2489b47 --- /dev/null +++ b/patch/kernel/rk322x-current/01-linux-4000-rockchip-linux-wip.patch @@ -0,0 +1,1692 @@ +From a49884fc5063fb0eb3db69568b45e3b8ef5ea094 Mon Sep 17 00:00:00 2001 +From: Finley Xiao +Date: Thu, 22 Jun 2017 20:22:25 +0800 +Subject: [PATCH] clk: rockchip: rk3228: fix some PLL_NUX_CLKs' gates + +Some PLL_NUX_CLKs' gates is actually behind muxs according to latest TRM, +so move the gates to composite clocks and amend their parent clocks. + +Change-Id: Ib6043caa61e9df0473f2d0bdc756850968bb2a55 +Signed-off-by: Finley Xiao +--- + drivers/clk/rockchip/clk-rk3228.c | 53 ++++++++----------------------- + 1 file changed, 14 insertions(+), 39 deletions(-) + +diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c +index dd414c8255e3..734126a2ad7e 100644 +--- a/drivers/clk/rockchip/clk-rk3228.c ++++ b/drivers/clk/rockchip/clk-rk3228.c +@@ -130,24 +130,22 @@ static const struct rockchip_cpuclk_reg_data rk3228_cpuclk_data = { + + PNAME(mux_pll_p) = { "clk_24m", "xin24m" }; + +-PNAME(mux_ddrphy_p) = { "dpll_ddr", "gpll_ddr", "apll_ddr" }; +-PNAME(mux_armclk_p) = { "apll_core", "gpll_core", "dpll_core" }; ++PNAME(mux_ddrphy_p) = { "dpll", "gpll", "apll" }; ++PNAME(mux_armclk_p) = { "apll", "gpll", "dpll" }; + PNAME(mux_usb480m_phy_p) = { "usb480m_phy0", "usb480m_phy1" }; + PNAME(mux_usb480m_p) = { "usb480m_phy", "xin24m" }; + PNAME(mux_hdmiphy_p) = { "hdmiphy_phy", "xin24m" }; +-PNAME(mux_aclk_cpu_src_p) = { "cpll_aclk_cpu", "gpll_aclk_cpu", "hdmiphy_aclk_cpu" }; + + PNAME(mux_pll_src_4plls_p) = { "cpll", "gpll", "hdmiphy" "usb480m" }; + PNAME(mux_pll_src_3plls_p) = { "cpll", "gpll", "hdmiphy" }; + PNAME(mux_pll_src_2plls_p) = { "cpll", "gpll" }; + PNAME(mux_sclk_hdmi_cec_p) = { "cpll", "gpll", "xin24m" }; +-PNAME(mux_aclk_peri_src_p) = { "cpll_peri", "gpll_peri", "hdmiphy_peri" }; + PNAME(mux_mmc_src_p) = { "cpll", "gpll", "xin24m", "usb480m" }; + PNAME(mux_pll_src_cpll_gpll_usb480m_p) = { "cpll", "gpll", "usb480m" }; + + PNAME(mux_sclk_rga_p) = { "gpll", "cpll", "sclk_rga_src" }; + +-PNAME(mux_sclk_vop_src_p) = { "gpll_vop", "cpll_vop" }; ++PNAME(mux_sclk_vop_src_p) = { "gpll", "cpll" }; + PNAME(mux_dclk_vop_p) = { "hdmiphy", "sclk_vop_pre" }; + + PNAME(mux_i2s0_p) = { "i2s0_src", "i2s0_frac", "ext_i2s", "xin12m" }; +@@ -216,27 +214,17 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + RK2928_CLKSEL_CON(4), 8, 5, DFLAGS), + + /* PD_DDR */ +- GATE(0, "apll_ddr", "apll", CLK_IGNORE_UNUSED, ++ COMPOSITE(0, "clk_ddrphy_src", mux_ddrphy_p, CLK_IGNORE_UNUSED, ++ RK2928_CLKSEL_CON(26), 8, 2, MFLAGS, 0, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, + RK2928_CLKGATE_CON(0), 2, GFLAGS), +- GATE(0, "dpll_ddr", "dpll", CLK_IGNORE_UNUSED, +- RK2928_CLKGATE_CON(0), 2, GFLAGS), +- GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED, +- RK2928_CLKGATE_CON(0), 2, GFLAGS), +- COMPOSITE(0, "ddrphy4x", mux_ddrphy_p, CLK_IGNORE_UNUSED, +- RK2928_CLKSEL_CON(26), 8, 2, MFLAGS, 0, 3, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, ++ GATE(0, "ddrphy4x", "clk_ddrphy_src", CLK_IGNORE_UNUSED, + RK2928_CLKGATE_CON(7), 1, GFLAGS), +- GATE(0, "ddrc", "ddrphy_pre", CLK_IGNORE_UNUSED, ++ FACTOR_GATE(0, "ddrc", "clk_ddrphy_src", CLK_IGNORE_UNUSED, 1, 4, + RK2928_CLKGATE_CON(8), 5, GFLAGS), +- FACTOR_GATE(0, "ddrphy", "ddrphy4x", CLK_IGNORE_UNUSED, 1, 4, ++ FACTOR_GATE(0, "ddrphy", "clk_ddrphy_src", CLK_IGNORE_UNUSED, 1, 4, + RK2928_CLKGATE_CON(7), 0, GFLAGS), + + /* PD_CORE */ +- GATE(0, "dpll_core", "dpll", CLK_IGNORE_UNUSED, +- RK2928_CLKGATE_CON(0), 6, GFLAGS), +- GATE(0, "apll_core", "apll", CLK_IGNORE_UNUSED, +- RK2928_CLKGATE_CON(0), 6, GFLAGS), +- GATE(0, "gpll_core", "gpll", CLK_IGNORE_UNUSED, +- RK2928_CLKGATE_CON(0), 6, GFLAGS), + COMPOSITE_NOMUX(0, "pclk_dbg", "armclk", CLK_IGNORE_UNUSED, + RK2928_CLKSEL_CON(1), 0, 4, DFLAGS | CLK_DIVIDER_READ_ONLY, + RK2928_CLKGATE_CON(4), 1, GFLAGS), +@@ -253,14 +241,9 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + RK2928_MISC_CON, 15, 1, MFLAGS), + + /* PD_BUS */ +- GATE(0, "hdmiphy_aclk_cpu", "hdmiphy", CLK_IGNORE_UNUSED, +- RK2928_CLKGATE_CON(0), 1, GFLAGS), +- GATE(0, "gpll_aclk_cpu", "gpll", CLK_IGNORE_UNUSED, +- RK2928_CLKGATE_CON(0), 1, GFLAGS), +- GATE(0, "cpll_aclk_cpu", "cpll", CLK_IGNORE_UNUSED, ++ COMPOSITE(0, "aclk_cpu_src", mux_pll_src_3plls_p, 0, ++ RK2928_CLKSEL_CON(0), 13, 2, MFLAGS, 8, 5, DFLAGS, + RK2928_CLKGATE_CON(0), 1, GFLAGS), +- COMPOSITE_NOGATE(0, "aclk_cpu_src", mux_aclk_cpu_src_p, 0, +- RK2928_CLKSEL_CON(0), 13, 2, MFLAGS, 8, 5, DFLAGS), + GATE(ACLK_CPU, "aclk_cpu", "aclk_cpu_src", 0, + RK2928_CLKGATE_CON(6), 0, GFLAGS), + COMPOSITE_NOMUX(HCLK_CPU, "hclk_cpu", "aclk_cpu_src", 0, +@@ -333,14 +316,9 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + RK2928_CLKGATE_CON(3), 8, GFLAGS), + + /* PD_PERI */ +- GATE(0, "cpll_peri", "cpll", CLK_IGNORE_UNUSED, ++ COMPOSITE(0, "aclk_peri_src", mux_pll_src_3plls_p, 0, ++ RK2928_CLKSEL_CON(10), 10, 2, MFLAGS, 0, 5, DFLAGS, + RK2928_CLKGATE_CON(2), 0, GFLAGS), +- GATE(0, "gpll_peri", "gpll", CLK_IGNORE_UNUSED, +- RK2928_CLKGATE_CON(2), 0, GFLAGS), +- GATE(0, "hdmiphy_peri", "hdmiphy", CLK_IGNORE_UNUSED, +- RK2928_CLKGATE_CON(2), 0, GFLAGS), +- COMPOSITE_NOGATE(0, "aclk_peri_src", mux_aclk_peri_src_p, 0, +- RK2928_CLKSEL_CON(10), 10, 2, MFLAGS, 0, 5, DFLAGS), + COMPOSITE_NOMUX(PCLK_PERI, "pclk_peri", "aclk_peri_src", 0, + RK2928_CLKSEL_CON(10), 12, 3, DFLAGS, + RK2928_CLKGATE_CON(5), 2, GFLAGS), +@@ -398,12 +376,9 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + * Clock-Architecture Diagram 2 + */ + +- GATE(0, "gpll_vop", "gpll", 0, +- RK2928_CLKGATE_CON(3), 1, GFLAGS), +- GATE(0, "cpll_vop", "cpll", 0, ++ COMPOSITE_NODIV(0, "sclk_vop_src", mux_sclk_vop_src_p, 0, ++ RK2928_CLKSEL_CON(27), 0, 1, MFLAGS, + RK2928_CLKGATE_CON(3), 1, GFLAGS), +- MUX(0, "sclk_vop_src", mux_sclk_vop_src_p, 0, +- RK2928_CLKSEL_CON(27), 0, 1, MFLAGS), + DIV(DCLK_HDMI_PHY, "dclk_hdmiphy", "sclk_vop_src", 0, + RK2928_CLKSEL_CON(29), 0, 3, DFLAGS), + DIV(0, "sclk_vop_pre", "sclk_vop_src", 0, + +From 368824e53d6be0914927df4281bbce6da58a03ff Mon Sep 17 00:00:00 2001 +From: Finley Xiao +Date: Sun, 18 Mar 2018 21:41:43 +0800 +Subject: [PATCH] clk: rockchip: rk3228: Fix sclk_wifi div_width + +Change-Id: I8e216249fbd588ce55660eba9911fc59aedc920d +Signed-off-by: Finley Xiao +--- + drivers/clk/rockchip/clk-rk3228.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c +index 734126a2ad7e..90e5638d4e7e 100644 +--- a/drivers/clk/rockchip/clk-rk3228.c ++++ b/drivers/clk/rockchip/clk-rk3228.c +@@ -353,7 +353,7 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + RK2928_CLKGATE_CON(10), 12, GFLAGS), + + COMPOSITE(SCLK_WIFI, "sclk_wifi", mux_pll_src_cpll_gpll_usb480m_p, 0, +- RK2928_CLKSEL_CON(23), 5, 2, MFLAGS, 0, 6, DFLAGS, ++ RK2928_CLKSEL_CON(23), 5, 2, MFLAGS, 0, 5, DFLAGS, + RK2928_CLKGATE_CON(2), 15, GFLAGS), + + COMPOSITE(SCLK_SDMMC, "sclk_sdmmc", mux_mmc_src_p, 0, + +From 06685aabce5c6147ca099bd1b1399f6a170f78e1 Mon Sep 17 00:00:00 2001 +From: Chen Lei +Date: Tue, 25 Dec 2018 18:29:04 +0800 +Subject: [PATCH] clk: rockchip: rk322x: fix wrong mmc phase shift for rk3228 + +mmc sample shift should be 1 for rk3228, or it will fail +if we enable mmc tuning for rk3228. + +Change-Id: I301c2a7d33de8d519d7c288aef03a82531016373 +Signed-off-by: Chen Lei +--- + drivers/clk/rockchip/clk-rk3228.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c +index 90e5638d4e7e..7fff74043766 100644 +--- a/drivers/clk/rockchip/clk-rk3228.c ++++ b/drivers/clk/rockchip/clk-rk3228.c +@@ -610,13 +610,13 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + + /* PD_MMC */ + MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "sclk_sdmmc", RK3228_SDMMC_CON0, 1), +- MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK3228_SDMMC_CON1, 0), ++ MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK3228_SDMMC_CON1, 1), + + MMC(SCLK_SDIO_DRV, "sdio_drv", "sclk_sdio", RK3228_SDIO_CON0, 1), +- MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "sclk_sdio", RK3228_SDIO_CON1, 0), ++ MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "sclk_sdio", RK3228_SDIO_CON1, 1), + + MMC(SCLK_EMMC_DRV, "emmc_drv", "sclk_emmc", RK3228_EMMC_CON0, 1), +- MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RK3228_EMMC_CON1, 0), ++ MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RK3228_EMMC_CON1, 1), + }; + + static const char *const rk3228_critical_clocks[] __initconst = { + +From a74448d0259e2fe4ad3d791d779ba7a85d31a08b Mon Sep 17 00:00:00 2001 +From: Finley Xiao +Date: Mon, 5 Feb 2018 10:04:15 +0800 +Subject: [PATCH] clk: rockchip: rk3228: Fix armclk parent + +Change-Id: I09830d96b37cca600f1782b9013b25e043467f97 +Signed-off-by: Finley Xiao +--- + drivers/clk/rockchip/clk-rk3228.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c +index 7fff74043766..00c5b8a1e295 100644 +--- a/drivers/clk/rockchip/clk-rk3228.c ++++ b/drivers/clk/rockchip/clk-rk3228.c +@@ -131,7 +131,7 @@ static const struct rockchip_cpuclk_reg_data rk3228_cpuclk_data = { + PNAME(mux_pll_p) = { "clk_24m", "xin24m" }; + + PNAME(mux_ddrphy_p) = { "dpll", "gpll", "apll" }; +-PNAME(mux_armclk_p) = { "apll", "gpll", "dpll" }; ++PNAME(mux_armclk_p) = { "apll_core", "gpll_core", "dpll_core" }; + PNAME(mux_usb480m_phy_p) = { "usb480m_phy0", "usb480m_phy1" }; + PNAME(mux_usb480m_p) = { "usb480m_phy", "xin24m" }; + PNAME(mux_hdmiphy_p) = { "hdmiphy_phy", "xin24m" }; +@@ -225,6 +225,12 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + RK2928_CLKGATE_CON(7), 0, GFLAGS), + + /* PD_CORE */ ++ GATE(0, "apll_core", "apll", CLK_IGNORE_UNUSED, ++ PX30_CLKGATE_CON(0), 6, GFLAGS), ++ GATE(0, "gpll_core", "gpll", CLK_IGNORE_UNUSED, ++ PX30_CLKGATE_CON(0), 6, GFLAGS), ++ GATE(0, "dpll_core", "dpll", CLK_IGNORE_UNUSED, ++ PX30_CLKGATE_CON(0), 6, GFLAGS), + COMPOSITE_NOMUX(0, "pclk_dbg", "armclk", CLK_IGNORE_UNUSED, + RK2928_CLKSEL_CON(1), 0, 4, DFLAGS | CLK_DIVIDER_READ_ONLY, + RK2928_CLKGATE_CON(4), 1, GFLAGS), + +From bdbce1840c0b73a5e5c01576fb394d1719736ee8 Mon Sep 17 00:00:00 2001 +From: Finley Xiao +Date: Sun, 18 Mar 2018 21:42:22 +0800 +Subject: [PATCH] clk: rockchip: rk3228: remove the flag ROCKCHIP_PLL_SYNC_RATE + for GPLL + +To slove the display shaking, when uboot logo display to kernel show. + +Change-Id: Ifc97f72df27b4e8dbcd34ab8ed65ac027fd424d1 +Signed-off-by: Finley Xiao +--- + drivers/clk/rockchip/clk-rk3228.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c +index 00c5b8a1e295..5e9c6986e541 100644 +--- a/drivers/clk/rockchip/clk-rk3228.c ++++ b/drivers/clk/rockchip/clk-rk3228.c +@@ -170,7 +170,7 @@ static struct rockchip_pll_clock rk3228_pll_clks[] __initdata = { + [cpll] = PLL(pll_rk3036, PLL_CPLL, "cpll", mux_pll_p, 0, RK2928_PLL_CON(6), + RK2928_MODE_CON, 8, 8, 0, NULL), + [gpll] = PLL(pll_rk3036, PLL_GPLL, "gpll", mux_pll_p, 0, RK2928_PLL_CON(9), +- RK2928_MODE_CON, 12, 9, ROCKCHIP_PLL_SYNC_RATE, rk3228_pll_rates), ++ RK2928_MODE_CON, 12, 9, 0, rk3228_pll_rates), + }; + + #define MFLAGS CLK_MUX_HIWORD_MASK + +From 0b7003eb4fe6803d6f6071758f069fd7a63f096a Mon Sep 17 00:00:00 2001 +From: Elaine Zhang +Date: Tue, 25 Dec 2018 14:58:30 +0800 +Subject: [PATCH] clk: rockchip: rk322x: fix up the gate con description error + +Change-Id: I439314c590a7144fab6e33d1fb4f325530669842 +Signed-off-by: Elaine Zhang +--- + drivers/clk/rockchip/clk-rk3228.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c +index 5e9c6986e541..448b202bf4f3 100644 +--- a/drivers/clk/rockchip/clk-rk3228.c ++++ b/drivers/clk/rockchip/clk-rk3228.c +@@ -226,11 +226,11 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + + /* PD_CORE */ + GATE(0, "apll_core", "apll", CLK_IGNORE_UNUSED, +- PX30_CLKGATE_CON(0), 6, GFLAGS), ++ RK2928_CLKGATE_CON(0), 6, GFLAGS), + GATE(0, "gpll_core", "gpll", CLK_IGNORE_UNUSED, +- PX30_CLKGATE_CON(0), 6, GFLAGS), ++ RK2928_CLKGATE_CON(0), 6, GFLAGS), + GATE(0, "dpll_core", "dpll", CLK_IGNORE_UNUSED, +- PX30_CLKGATE_CON(0), 6, GFLAGS), ++ RK2928_CLKGATE_CON(0), 6, GFLAGS), + COMPOSITE_NOMUX(0, "pclk_dbg", "armclk", CLK_IGNORE_UNUSED, + RK2928_CLKSEL_CON(1), 0, 4, DFLAGS | CLK_DIVIDER_READ_ONLY, + RK2928_CLKGATE_CON(4), 1, GFLAGS), + +From 8c78a060509051d135fceaaddd45aa8f3991298f Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sun, 16 Aug 2020 16:52:03 +0200 +Subject: [PATCH] clk: rockchip: add CLOCK_IGNORE_UNUSED to serval RK3228 clks + +Some clocks need the CLOCK_IGNORE_UNUSED flag in order to be prevented from being +disabled at boot time and to get respective devices working. +Has been taken from vendor kernel. +--- + drivers/clk/rockchip/clk-rk3228.c | 58 +++++++++++++++---------------- + 1 file changed, 29 insertions(+), 29 deletions(-) + +diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c +index 448b202bf4f3..e6654938d6bd 100644 +--- a/drivers/clk/rockchip/clk-rk3228.c ++++ b/drivers/clk/rockchip/clk-rk3228.c +@@ -510,12 +510,12 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + + /* PD_VOP */ + GATE(ACLK_RGA, "aclk_rga", "aclk_rga_pre", 0, RK2928_CLKGATE_CON(13), 0, GFLAGS), +- GATE(0, "aclk_rga_noc", "aclk_rga_pre", 0, RK2928_CLKGATE_CON(13), 11, GFLAGS), ++ GATE(0, "aclk_rga_noc", "aclk_rga_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(13), 11, GFLAGS), + GATE(ACLK_IEP, "aclk_iep", "aclk_iep_pre", 0, RK2928_CLKGATE_CON(13), 2, GFLAGS), +- GATE(0, "aclk_iep_noc", "aclk_iep_pre", 0, RK2928_CLKGATE_CON(13), 9, GFLAGS), ++ GATE(0, "aclk_iep_noc", "aclk_iep_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(13), 9, GFLAGS), + + GATE(ACLK_VOP, "aclk_vop", "aclk_vop_pre", 0, RK2928_CLKGATE_CON(13), 5, GFLAGS), +- GATE(0, "aclk_vop_noc", "aclk_vop_pre", 0, RK2928_CLKGATE_CON(13), 12, GFLAGS), ++ GATE(0, "aclk_vop_noc", "aclk_vop_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(13), 12, GFLAGS), + + GATE(ACLK_HDCP, "aclk_hdcp", "aclk_hdcp_pre", 0, RK2928_CLKGATE_CON(14), 10, GFLAGS), + GATE(0, "aclk_hdcp_noc", "aclk_hdcp_pre", 0, RK2928_CLKGATE_CON(13), 10, GFLAGS), +@@ -523,13 +523,13 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + GATE(HCLK_RGA, "hclk_rga", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 1, GFLAGS), + GATE(HCLK_IEP, "hclk_iep", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 3, GFLAGS), + GATE(HCLK_VOP, "hclk_vop", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 6, GFLAGS), +- GATE(0, "hclk_vio_ahb_arbi", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 7, GFLAGS), +- GATE(0, "hclk_vio_noc", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 8, GFLAGS), +- GATE(0, "hclk_vop_noc", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 13, GFLAGS), +- GATE(HCLK_VIO_H2P, "hclk_vio_h2p", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 7, GFLAGS), ++ GATE(0, "hclk_vio_ahb_arbi", "hclk_vio_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(13), 7, GFLAGS), ++ GATE(0, "hclk_vio_noc", "hclk_vio_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(13), 8, GFLAGS), ++ GATE(0, "hclk_vop_noc", "hclk_vio_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(13), 13, GFLAGS), ++ GATE(HCLK_VIO_H2P, "hclk_vio_h2p", "hclk_vio_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(14), 7, GFLAGS), + GATE(HCLK_HDCP_MMU, "hclk_hdcp_mmu", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 12, GFLAGS), + GATE(PCLK_HDMI_CTRL, "pclk_hdmi_ctrl", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 6, GFLAGS), +- GATE(PCLK_VIO_H2P, "pclk_vio_h2p", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 8, GFLAGS), ++ GATE(PCLK_VIO_H2P, "pclk_vio_h2p", "hclk_vio_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(14), 8, GFLAGS), + GATE(PCLK_HDCP, "pclk_hdcp", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 11, GFLAGS), + + /* PD_PERI */ +@@ -541,13 +541,13 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + GATE(HCLK_EMMC, "hclk_emmc", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 2, GFLAGS), + GATE(HCLK_NANDC, "hclk_nandc", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 3, GFLAGS), + GATE(HCLK_HOST0, "hclk_host0", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 6, GFLAGS), +- GATE(0, "hclk_host0_arb", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 7, GFLAGS), ++ GATE(0, "hclk_host0_arb", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(11), 7, GFLAGS), + GATE(HCLK_HOST1, "hclk_host1", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 8, GFLAGS), +- GATE(0, "hclk_host1_arb", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 9, GFLAGS), ++ GATE(0, "hclk_host1_arb", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(11), 9, GFLAGS), + GATE(HCLK_HOST2, "hclk_host2", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 10, GFLAGS), + GATE(HCLK_OTG, "hclk_otg", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 12, GFLAGS), +- GATE(0, "hclk_otg_pmu", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 13, GFLAGS), +- GATE(0, "hclk_host2_arb", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 14, GFLAGS), ++ GATE(0, "hclk_otg_pmu", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(11), 13, GFLAGS), ++ GATE(0, "hclk_host2_arb", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(11), 14, GFLAGS), + GATE(0, "hclk_peri_noc", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(12), 1, GFLAGS), + + GATE(PCLK_GMAC, "pclk_gmac", "pclk_peri", 0, RK2928_CLKGATE_CON(11), 5, GFLAGS), +@@ -555,15 +555,15 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + + /* PD_GPU */ + GATE(ACLK_GPU, "aclk_gpu", "aclk_gpu_pre", 0, RK2928_CLKGATE_CON(7), 14, GFLAGS), +- GATE(0, "aclk_gpu_noc", "aclk_gpu_pre", 0, RK2928_CLKGATE_CON(7), 15, GFLAGS), ++ GATE(0, "aclk_gpu_noc", "aclk_gpu_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(7), 15, GFLAGS), + + /* PD_BUS */ +- GATE(0, "sclk_initmem_mbist", "aclk_cpu", 0, RK2928_CLKGATE_CON(8), 1, GFLAGS), +- GATE(0, "aclk_initmem", "aclk_cpu", 0, RK2928_CLKGATE_CON(8), 0, GFLAGS), ++ GATE(0, "sclk_initmem_mbist", "aclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(8), 1, GFLAGS), ++ GATE(0, "aclk_initmem", "aclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(8), 0, GFLAGS), + GATE(ACLK_DMAC, "aclk_dmac_bus", "aclk_cpu", 0, RK2928_CLKGATE_CON(8), 2, GFLAGS), + GATE(0, "aclk_bus_noc", "aclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 1, GFLAGS), + +- GATE(0, "hclk_rom", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 3, GFLAGS), ++ GATE(0, "hclk_rom", "hclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(8), 3, GFLAGS), + GATE(HCLK_I2S0_8CH, "hclk_i2s0_8ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 7, GFLAGS), + GATE(HCLK_I2S1_8CH, "hclk_i2s1_8ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 8, GFLAGS), + GATE(HCLK_I2S2_2CH, "hclk_i2s2_2ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 9, GFLAGS), +@@ -572,9 +572,9 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + GATE(HCLK_M_CRYPTO, "hclk_crypto_mst", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 11, GFLAGS), + GATE(HCLK_S_CRYPTO, "hclk_crypto_slv", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 12, GFLAGS), + +- GATE(0, "pclk_ddrupctl", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(8), 4, GFLAGS), +- GATE(0, "pclk_ddrmon", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(8), 6, GFLAGS), +- GATE(0, "pclk_msch_noc", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(10), 2, GFLAGS), ++ GATE(0, "pclk_ddrupctl", "pclk_ddr_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(8), 4, GFLAGS), ++ GATE(0, "pclk_ddrmon", "pclk_ddr_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(8), 6, GFLAGS), ++ GATE(0, "pclk_msch_noc", "pclk_ddr_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 2, GFLAGS), + + GATE(PCLK_EFUSE_1024, "pclk_efuse_1024", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 13, GFLAGS), + GATE(PCLK_EFUSE_256, "pclk_efuse_256", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 14, GFLAGS), +@@ -583,7 +583,7 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + GATE(PCLK_I2C2, "pclk_i2c2", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 1, GFLAGS), + GATE(PCLK_I2C3, "pclk_i2c3", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 2, GFLAGS), + GATE(PCLK_TIMER, "pclk_timer0", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 4, GFLAGS), +- GATE(0, "pclk_stimer", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 5, GFLAGS), ++ GATE(0, "pclk_stimer", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 5, GFLAGS), + GATE(PCLK_SPI0, "pclk_spi0", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 6, GFLAGS), + GATE(PCLK_PWM, "pclk_rk_pwm", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 7, GFLAGS), + GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 8, GFLAGS), +@@ -597,22 +597,22 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + GATE(PCLK_GRF, "pclk_grf", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 0, GFLAGS), + GATE(0, "pclk_cru", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 1, GFLAGS), + GATE(0, "pclk_sgrf", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 2, GFLAGS), +- GATE(0, "pclk_sim", "pclk_cpu", 0, RK2928_CLKGATE_CON(10), 3, GFLAGS), ++ GATE(0, "pclk_sim", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 3, GFLAGS), + +- GATE(0, "pclk_ddrphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 3, GFLAGS), +- GATE(0, "pclk_acodecphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 5, GFLAGS), ++ GATE(0, "pclk_ddrphy", "pclk_phy_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 3, GFLAGS), ++ GATE(0, "pclk_acodecphy", "pclk_phy_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 5, GFLAGS), + GATE(PCLK_HDMI_PHY, "pclk_hdmiphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 7, GFLAGS), +- GATE(0, "pclk_vdacphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 8, GFLAGS), +- GATE(0, "pclk_phy_noc", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 9, GFLAGS), ++ GATE(0, "pclk_vdacphy", "pclk_phy_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 8, GFLAGS), ++ GATE(0, "pclk_phy_noc", "pclk_phy_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 9, GFLAGS), + + GATE(ACLK_VPU, "aclk_vpu", "aclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 0, GFLAGS), +- GATE(0, "aclk_vpu_noc", "aclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 4, GFLAGS), ++ GATE(0, "aclk_vpu_noc", "aclk_vpu_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(15), 4, GFLAGS), + GATE(ACLK_RKVDEC, "aclk_rkvdec", "aclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 2, GFLAGS), +- GATE(0, "aclk_rkvdec_noc", "aclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 6, GFLAGS), ++ GATE(0, "aclk_rkvdec_noc", "aclk_rkvdec_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(15), 6, GFLAGS), + GATE(HCLK_VPU, "hclk_vpu", "hclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 1, GFLAGS), +- GATE(0, "hclk_vpu_noc", "hclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 5, GFLAGS), ++ GATE(0, "hclk_vpu_noc", "hclk_vpu_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(15), 5, GFLAGS), + GATE(HCLK_RKVDEC, "hclk_rkvdec", "hclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 3, GFLAGS), +- GATE(0, "hclk_rkvdec_noc", "hclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 7, GFLAGS), ++ GATE(0, "hclk_rkvdec_noc", "hclk_rkvdec_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(15), 7, GFLAGS), + + /* PD_MMC */ + MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "sclk_sdmmc", RK3228_SDMMC_CON0, 1), + +From facbc2eed0bab25a67e65387c9ac05d504fb886e Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sun, 16 Aug 2020 17:07:35 +0200 +Subject: [PATCH] clk: rockchip add aclk_rkvdec and hclk_rkvdec to RK3228 + critical clocks + +To be prevented from being disabled at any time add aclk_rkvdec and hclk_rkvdec +to RK3228 critical clocks +--- + drivers/clk/rockchip/clk-rk3228.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c +index e6654938d6bd..595ad0301ca6 100644 +--- a/drivers/clk/rockchip/clk-rk3228.c ++++ b/drivers/clk/rockchip/clk-rk3228.c +@@ -656,8 +656,10 @@ static const char *const rk3228_critical_clocks[] __initconst = { + "pclk_phy_noc", + "aclk_vpu_noc", + "aclk_rkvdec_noc", ++ "aclk_rkvdec", + "hclk_vpu_noc", + "hclk_rkvdec_noc", ++ "hclk_rkvdec", + }; + + static void __init rk3228_clk_init(struct device_node *np) + +From 4a3f15e1bc2fb7cb7c093e2814dbc9f447e82bbc Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Fri, 24 Apr 2020 11:42:58 +0200 +Subject: [PATCH] soc: rockchip: Support powerdomains which don't need / + support to be switched on / off + +Taken from https://github.com/rockchip-linux/kernel/commit/5be2cb19cf8e678655b59ec70c6a5f66f08d9418 +--- + drivers/soc/rockchip/pm_domains.c | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c +index 727af107e6d3..3688e9e67872 100644 +--- a/drivers/soc/rockchip/pm_domains.c ++++ b/drivers/soc/rockchip/pm_domains.c +@@ -71,6 +71,7 @@ struct rockchip_pm_domain { + struct regmap **qos_regmap; + u32 *qos_save_regs[MAX_QOS_REGS_NUM]; + int num_clks; ++ bool is_ignore_pwr; + struct clk_bulk_data *clks; + }; + +@@ -353,6 +354,9 @@ static int rockchip_pd_power_on(struct generic_pm_domain *domain) + { + struct rockchip_pm_domain *pd = to_rockchip_pd(domain); + ++ if (pd->is_ignore_pwr) ++ return 0; ++ + return rockchip_pd_power(pd, true); + } + +@@ -360,6 +364,9 @@ static int rockchip_pd_power_off(struct generic_pm_domain *domain) + { + struct rockchip_pm_domain *pd = to_rockchip_pd(domain); + ++ if (pd->is_ignore_pwr) ++ return 0; ++ + return rockchip_pd_power(pd, false); + } + +@@ -439,6 +446,9 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, + pd->info = pd_info; + pd->pmu = pmu; + ++ if (!pd_info->pwr_mask) ++ pd->is_ignore_pwr = true; ++ + pd->num_clks = of_clk_get_parent_count(node); + if (pd->num_clks > 0) { + pd->clks = devm_kcalloc(pmu->dev, pd->num_clks, +@@ -589,6 +599,7 @@ static int rockchip_pm_add_subdomain(struct rockchip_pmu *pmu, + { + struct device_node *np; + struct generic_pm_domain *child_domain, *parent_domain; ++ struct rockchip_pm_domain *child_pd, *parent_pd; + int error; + + for_each_child_of_node(parent, np) { +@@ -629,6 +640,18 @@ static int rockchip_pm_add_subdomain(struct rockchip_pmu *pmu, + parent_domain->name, child_domain->name); + } + ++ /* ++ * If child_pd doesn't do idle request or power on/off, ++ * parent_pd may fail to do power on/off, so if parent_pd ++ * need to power on/off, child_pd can't ignore to do idle ++ * request and power on/off. ++ */ ++ child_pd = to_rockchip_pd(child_domain); ++ parent_pd = to_rockchip_pd(parent_domain); ++ if (!parent_pd->is_ignore_pwr) ++ child_pd->is_ignore_pwr = false; ++ ++ + rockchip_pm_add_subdomain(pmu, np); + } + + +From 02a2d327ebfce5e3b4ddd839c2cf3b9631c38b91 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Fri, 24 Apr 2020 13:01:07 +0200 +Subject: [PATCH] sound: soc: rockchip: use rouned rate for i2s + +--- + sound/soc/rockchip/rockchip_i2s.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c +index 61c984f10d8e..efca853eba6b 100644 +--- a/sound/soc/rockchip/rockchip_i2s.c ++++ b/sound/soc/rockchip/rockchip_i2s.c +@@ -279,10 +279,13 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, + if (i2s->is_master_mode) { + mclk_rate = clk_get_rate(i2s->mclk); + bclk_rate = 2 * 32 * params_rate(params); +- if (bclk_rate && mclk_rate % bclk_rate) ++ if (!bclk_rate) { ++ dev_err(i2s->dev, "invalid bclk_rate: %d\n", ++ bclk_rate); + return -EINVAL; ++ } + +- div_bclk = mclk_rate / bclk_rate; ++ div_bclk = DIV_ROUND_CLOSEST(mclk_rate, bclk_rate); + div_lrck = bclk_rate / params_rate(params); + regmap_update_bits(i2s->regmap, I2S_CKR, + I2S_CKR_MDIV_MASK, +@@ -312,6 +315,8 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, + val |= I2S_TXCR_VDW(32); + break; + default: ++ dev_err(i2s->dev, "invalid format: %d\n", ++ params_format(params)); + return -EINVAL; + } + + +From 824bce392cfdaaf0037f33637078e722a9f757b9 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Fri, 24 Apr 2020 09:08:44 +0200 +Subject: [PATCH] phy: rockchip: hdmi: readout hdmi phy flag for RK3228 HDMI + phys + +Some RK3228 HDMI phys only get a stable pll on frequencies higher 33,75 MHz. +This is defined in a flag in efuse of those devices. +--- + arch/arm/boot/dts/rk322x.dtsi | 6 +++ + drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 38 ++++++++++++++++++- + 2 files changed, 42 insertions(+), 2 deletions(-) + +diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi +index eec601fb4cd0..81dfdc8c864a 100644 +--- a/arch/arm/boot/dts/rk322x.dtsi ++++ b/arch/arm/boot/dts/rk322x.dtsi +@@ -340,6 +340,10 @@ efuse_id: id@7 { + cpu_leakage: cpu_leakage@17 { + reg = <0x17 0x1>; + }; ++ hdmi_phy_flag: hdmi-phy-flag@1d { ++ reg = <0x1d 0x1>; ++ bits = <1 1>; ++ }; + }; + + i2c0: i2c@11050000 { +@@ -559,6 +563,8 @@ hdmi_phy: hdmi-phy@12030000 { + clock-names = "sysclk", "refoclk", "refpclk"; + #clock-cells = <0>; + clock-output-names = "hdmiphy_phy"; ++ nvmem-cells = <&hdmi_phy_flag>; ++ nvmem-cell-names = "hdmi-phy-flag"; + #phy-cells = <0>; + status = "disabled"; + }; +diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c +index bb8bdf5e3301..0c7a97352714 100644 +--- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c +@@ -237,6 +237,9 @@ struct inno_hdmi_phy { + struct clk *refoclk; + struct clk *refpclk; + ++ /* phy_flag flag */ ++ bool phy_flag; ++ + /* platform data */ + const struct inno_hdmi_phy_drv_data *plat_data; + int chip_version; +@@ -347,6 +350,7 @@ static const struct pre_pll_config pre_pll_cfg_table[] = { + static const struct post_pll_config post_pll_cfg_table[] = { + {33750000, 1, 40, 8, 1}, + {33750000, 1, 80, 8, 2}, ++ {33750000, 1, 10, 2, 4}, + {74250000, 1, 40, 8, 1}, + {74250000, 18, 80, 8, 2}, + {148500000, 2, 40, 4, 3}, +@@ -497,8 +501,11 @@ static int inno_hdmi_phy_power_on(struct phy *phy) + return -EINVAL; + + for (; cfg->tmdsclock != 0; cfg++) +- if (tmdsclock <= cfg->tmdsclock && +- cfg->version & inno->chip_version) ++ if (((!inno->phy_flag || tmdsclock > 33750000) ++ && tmdsclock <= cfg->tmdsclock ++ && cfg->version & inno->chip_version) || ++ (inno->phy_flag && tmdsclock <= 33750000 ++ && cfg->version & 4)) + break; + + for (; phy_cfg->tmdsclock != 0; phy_cfg++) +@@ -909,6 +916,10 @@ static int inno_hdmi_phy_clk_register(struct inno_hdmi_phy *inno) + + static int inno_hdmi_phy_rk3228_init(struct inno_hdmi_phy *inno) + { ++ struct nvmem_cell *cell; ++ unsigned char *efuse_buf; ++ size_t len; ++ + /* + * Use phy internal register control + * rxsense/poweron/pllpd/pdataen signal. +@@ -923,7 +934,28 @@ static int inno_hdmi_phy_rk3228_init(struct inno_hdmi_phy *inno) + inno_update_bits(inno, 0xaa, RK3228_POST_PLL_CTRL_MANUAL, + RK3228_POST_PLL_CTRL_MANUAL); + ++ + inno->chip_version = 1; ++ inno->phy_flag = false; ++ ++ cell = nvmem_cell_get(inno->dev, "hdmi-phy-flag"); ++ if (IS_ERR(cell)) { ++ if (PTR_ERR(cell) == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ ++ return 0; ++ } ++ ++ efuse_buf = nvmem_cell_read(cell, &len); ++ nvmem_cell_put(cell); ++ ++ if (IS_ERR(efuse_buf)) ++ return 0; ++ if (len == 1) ++ inno->phy_flag = (efuse_buf[0] & BIT(1)) ? true : false; ++ kfree(efuse_buf); ++ ++ dev_info(inno->dev, "phy_flag is: %d\n", inno->phy_flag); + + return 0; + } +@@ -1023,6 +1055,8 @@ static int inno_hdmi_phy_rk3328_init(struct inno_hdmi_phy *inno) + + /* try to read the chip-version */ + inno->chip_version = 1; ++ inno->phy_flag = false; ++ + cell = nvmem_cell_get(inno->dev, "cpu-version"); + if (IS_ERR(cell)) { + if (PTR_ERR(cell) == -EPROBE_DEFER) + +From ac8834648e1e35703f6a0533b7c90b24d0d537da Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Tue, 26 May 2020 14:41:39 +0200 +Subject: [PATCH] usb: dwc2: QUIRKS: rockchip host only controller needs longer + msleep to initialize + +--- + drivers/usb/dwc2/core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c +index fec17a2d2447..eb55c64f63be 100644 +--- a/drivers/usb/dwc2/core.c ++++ b/drivers/usb/dwc2/core.c +@@ -663,7 +663,7 @@ void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg) + * platforms on their host-only dwc2. + */ + if (!dwc2_hw_is_otg(hsotg)) +- msleep(50); ++ msleep(200); + + break; + case USB_DR_MODE_PERIPHERAL: + +From 98c3cfe4ee409e64edcb9dff8341637588c9e166 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sun, 16 Aug 2020 17:35:43 +0200 +Subject: [PATCH] nvmem: rockchip-efuse: fix RK3188 efuse read + +In order to read from RK3188s efuse, the logic is slightly different from whats +done currently for RK3288 and also used for this SoC. +Logic, register mask and udelays have been taken from vendor kernel. +--- + drivers/nvmem/rockchip-efuse.c | 49 +++++++++++++++++++++++++++++++++- + 1 file changed, 48 insertions(+), 1 deletion(-) + +diff --git a/drivers/nvmem/rockchip-efuse.c b/drivers/nvmem/rockchip-efuse.c +index e4579de5d014..9afd71edf503 100644 +--- a/drivers/nvmem/rockchip-efuse.c ++++ b/drivers/nvmem/rockchip-efuse.c +@@ -17,6 +17,8 @@ + #include + #include + ++#define RK3188_A_MASK 0xff ++ + #define RK3288_A_SHIFT 6 + #define RK3288_A_MASK 0x3ff + #define RK3288_PGENB BIT(3) +@@ -52,6 +54,51 @@ struct rockchip_efuse_chip { + struct clk *clk; + }; + ++static int rockchip_rk3188_efuse_read(void *context, unsigned int offset, ++ void *val, size_t bytes) ++{ ++ struct rockchip_efuse_chip *efuse = context; ++ u8 *buf = val; ++ int ret; ++ ++ ret = clk_prepare_enable(efuse->clk); ++ if (ret < 0) { ++ dev_err(efuse->dev, "failed to prepare/enable efuse clk\n"); ++ return ret; ++ } ++ ++ writel(RK3288_CSB, efuse->base + REG_EFUSE_CTRL); ++ writel(RK3288_LOAD | RK3288_PGENB, efuse->base + REG_EFUSE_CTRL); ++ udelay(2); ++ ++ while (bytes--) { ++ writel(readl(efuse->base + REG_EFUSE_CTRL) & ++ (~(RK3188_A_MASK << RK3288_A_SHIFT)), ++ efuse->base + REG_EFUSE_CTRL); ++ writel(readl(efuse->base + REG_EFUSE_CTRL) | ++ ((offset++ & RK3188_A_MASK) << RK3288_A_SHIFT), ++ efuse->base + REG_EFUSE_CTRL); ++ udelay(2); ++ writel(readl(efuse->base + REG_EFUSE_CTRL) | ++ RK3288_STROBE, efuse->base + REG_EFUSE_CTRL); ++ udelay(2); ++ ++ *buf++ = readl(efuse->base + REG_EFUSE_DOUT); ++ writel(readl(efuse->base + REG_EFUSE_CTRL) & ++ (~RK3288_STROBE), efuse->base + REG_EFUSE_CTRL); ++ udelay(2); ++ } ++ ++ udelay(2); ++ /* Switch to standby mode */ ++ writel(RK3288_PGENB | RK3288_CSB, efuse->base + REG_EFUSE_CTRL); ++ udelay(1); ++ ++ clk_disable_unprepare(efuse->clk); ++ ++ return 0; ++} ++ + static int rockchip_rk3288_efuse_read(void *context, unsigned int offset, + void *val, size_t bytes) + { +@@ -222,7 +269,7 @@ static const struct of_device_id rockchip_efuse_match[] = { + }, + { + .compatible = "rockchip,rk3188-efuse", +- .data = (void *)&rockchip_rk3288_efuse_read, ++ .data = (void *)&rockchip_rk3188_efuse_read, + }, + { + .compatible = "rockchip,rk3228-efuse", + +From e95330563d2dfd9086ac3cadee0129b045c7a25d Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sun, 16 Aug 2020 17:43:08 +0200 +Subject: [PATCH] ARM: dts: rockchip: fix RK3188 efuse register width + +As with most Rockchip SoCs the RK3188s non-secure efuse contains 32 bytes of data. +This adapts the register width, so that we don't get repeated data when reading +out the values from it. +--- + arch/arm/boot/dts/rk3188.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi +index b6c1699345d0..9fab375231ec 100644 +--- a/arch/arm/boot/dts/rk3188.dtsi ++++ b/arch/arm/boot/dts/rk3188.dtsi +@@ -216,7 +216,7 @@ cru: clock-controller@20000000 { + + efuse: efuse@20010000 { + compatible = "rockchip,rk3188-efuse"; +- reg = <0x20010000 0x4000>; ++ reg = <0x20010000 0x20>; + #address-cells = <1>; + #size-cells = <1>; + clocks = <&cru PCLK_EFUSE>; + +From e12fc84e0782e332a2d309cc89f52119eee55de3 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sun, 16 Aug 2020 18:51:38 +0200 +Subject: [PATCH] ARM: dts: rockchip add operating-points, power-domain for + RK322Xs GPU + +This adds the operating-points table and the power-domain and the respective +qos registers for RK322xs GPU. +While at this it also adds the GPU to be a cooling cell. +--- + arch/arm/boot/dts/rk322x.dtsi | 39 ++++++++++++++++++++++++++++++++++- + 1 file changed, 38 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi +index 81dfdc8c864a..9e531d229ae1 100644 +--- a/arch/arm/boot/dts/rk322x.dtsi ++++ b/arch/arm/boot/dts/rk322x.dtsi +@@ -215,6 +215,12 @@ power: power-controller { + #address-cells = <1>; + #size-cells = <0>; + ++ pd_gpu@RK3228_PD_GPU { ++ reg = ; ++ clocks = <&cru ACLK_GPU>; ++ pm_qos = <&qos_gpu>; ++ }; ++ + pd_vpu@RK3228_PD_VPU { + reg = ; + clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; +@@ -533,6 +539,11 @@ map1 { + <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; ++ map2 { ++ trip = <&cpu_alert1>; ++ cooling-device = ++ <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; ++ }; + }; + }; + }; +@@ -587,7 +598,28 @@ gpu: gpu@20000000 { + clocks = <&cru ACLK_GPU>, <&cru ACLK_GPU>; + clock-names = "bus", "core"; + resets = <&cru SRST_GPU_A>; +- status = "disabled"; ++ operating-points-v2 = <&gpu_opp_table>; ++ power-domains = <&power RK3228_PD_GPU>; ++ #cooling-cells = <2>; /* min followed by max */ ++ }; ++ ++ gpu_opp_table: opp-table2 { ++ compatible = "operating-points-v2"; ++ ++ opp-200000000 { ++ opp-hz = /bits/ 64 <200000000>; ++ opp-microvolt = <1050000>; ++ }; ++ ++ opp-300000000 { ++ opp-hz = /bits/ 64 <300000000>; ++ opp-microvolt = <1050000>; ++ }; ++ ++ opp-500000000 { ++ opp-hz = /bits/ 64 <500000000>; ++ opp-microvolt = <1150000>; ++ }; + }; + + vpu: video-codec@20020000 { +@@ -872,6 +904,11 @@ qos_vpu: qos@31040000 { + reg = <0x31040000 0x20>; + }; + ++ qos_gpu: qos@31050000 { ++ compatible = "syscon"; ++ reg = <0x31050000 0x20>; ++ }; ++ + qos_rkvdec_r: qos@31070000 { + compatible = "syscon"; + reg = <0x31070000 0x20>; + +From 19b4b92aa56381148255f8d962649869f734b5f9 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sun, 16 Aug 2020 19:44:42 +0200 +Subject: [PATCH] ARM: dts: rockchip: add ethernet0 alias + +Add ethernet0 alias for gmac. This will, for example, be used +by u-boot to inject a "local-mac-address" in the devicetree. +--- + arch/arm/boot/dts/rk322x.dtsi | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi +index 9e531d229ae1..14eedffea4a3 100644 +--- a/arch/arm/boot/dts/rk322x.dtsi ++++ b/arch/arm/boot/dts/rk322x.dtsi +@@ -15,6 +15,7 @@ / { + interrupt-parent = <&gic>; + + aliases { ++ ethernet0 = &gmac; + serial0 = &uart0; + serial1 = &uart1; + serial2 = &uart2; + +From 7c1f6ab6b0c97b7aacaa39f842a9e8ef7bbea83e Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sun, 16 Aug 2020 20:00:01 +0200 +Subject: [PATCH] ARM: dts: rockchip: add hdmi simple-audio-card for RK322x + +Add "simple-audio-card" definition for hdmi-sound. While at +that also add the missing #sound-dai-cells for i2s, spdif and hdmi +nodes. +--- + arch/arm/boot/dts/rk322x.dtsi | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi +index 14eedffea4a3..7f15fc838c36 100644 +--- a/arch/arm/boot/dts/rk322x.dtsi ++++ b/arch/arm/boot/dts/rk322x.dtsi +@@ -124,6 +124,22 @@ arm-pmu { + interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>; + }; + ++ hdmi_sound: hdmi-sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,name = "hdmi-sound"; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,mclk-fs = <256>; ++ status = "disabled"; ++ ++ simple-audio-card,cpu { ++ sound-dai = <&i2s0>; ++ }; ++ ++ simple-audio-card,codec { ++ sound-dai = <&hdmi>; ++ }; ++ }; ++ + psci { + compatible = "arm,psci-1.0", "arm,psci-0.2"; + method = "smc"; +@@ -161,6 +177,7 @@ i2s1: i2s1@100b0000 { + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&i2s1_bus>; ++ #sound-dai-cells = <0>; + status = "disabled"; + }; + +@@ -172,6 +189,7 @@ i2s0: i2s0@100c0000 { + clocks = <&cru SCLK_I2S0>, <&cru HCLK_I2S0_8CH>; + dmas = <&pdma 11>, <&pdma 12>; + dma-names = "tx", "rx"; ++ #sound-dai-cells = <0>; + status = "disabled"; + }; + +@@ -185,6 +203,7 @@ spdif: spdif@100d0000 { + dma-names = "tx"; + pinctrl-names = "default"; + pinctrl-0 = <&spdif_tx>; ++ #sound-dai-cells = <0>; + status = "disabled"; + }; + +@@ -746,6 +765,7 @@ hdmi: hdmi@200a0000 { + phys = <&hdmi_phy>; + phy-names = "hdmi"; + rockchip,grf = <&grf>; ++ #sound-dai-cells = <0>; + status = "disabled"; + + ports { + +From 6fa1bf91b123f703a2fde726ad52af1539f365d0 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sun, 16 Aug 2020 21:16:11 +0200 +Subject: [PATCH] ARM: dts: rockchip: add uart1-1 pins for RK322x + +Add uart uart1-1 pins. +While at this also correct the uart2 default pinctrl, which is uart21_xfer. +--- + arch/arm/boot/dts/rk322x.dtsi | 19 ++++++++++++++++++- + 1 file changed, 18 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi +index 7f15fc838c36..693c6f18a889 100644 +--- a/arch/arm/boot/dts/rk322x.dtsi ++++ b/arch/arm/boot/dts/rk322x.dtsi +@@ -345,7 +345,7 @@ uart2: serial@11030000 { + clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>; + clock-names = "baudclk", "apb_pclk"; + pinctrl-names = "default"; +- pinctrl-0 = <&uart2_xfer>; ++ pinctrl-0 = <&uart21_xfer>; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; +@@ -1275,13 +1275,30 @@ uart1_xfer: uart1-xfer { + <1 RK_PB2 1 &pcfg_pull_none>; + }; + ++ uart11_xfer: uart11-xfer { ++ rockchip,pins = <3 RK_PB6 1 &pcfg_pull_up>, ++ <3 RK_PB5 1 &pcfg_pull_none>; ++ }; ++ + uart1_cts: uart1-cts { + rockchip,pins = <1 RK_PB0 1 &pcfg_pull_none>; + }; + ++ uart11_cts: uart11-cts { ++ rockchip,pins = <3 RK_PA7 1 &pcfg_pull_none>; ++ }; ++ + uart1_rts: uart1-rts { + rockchip,pins = <1 RK_PB3 1 &pcfg_pull_none>; + }; ++ ++ uart11_rts: uart11-rts { ++ rockchip,pins = <3 RK_PA6 1 &pcfg_pull_none>; ++ }; ++ ++ uart11_rts_gpio: uart11-rts-gpio { ++ rockchip,pins = <3 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; + }; + + uart2 { + +From 1c37c9a10362d2e049be1386bb1da7d4f488b1d8 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sun, 16 Aug 2020 21:58:56 +0200 +Subject: [PATCH] ARM: dts: rockchip: align mmc* node properties with driver + +Add resets, max-frequency and bus-width properties where required to emmc +,sdmmc and sdio nodes. While at that also add the sdmmc_pwr pinctrl which +is required to get the sd-card controller to work, if it was not/wrong +initialized by the bootloader (i.e. u-boot) +--- + arch/arm/boot/dts/rk322x.dtsi | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi +index 693c6f18a889..92e3eb1e7938 100644 +--- a/arch/arm/boot/dts/rk322x.dtsi ++++ b/arch/arm/boot/dts/rk322x.dtsi +@@ -787,9 +787,13 @@ sdmmc: mmc@30000000 { + clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>, + <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>; + clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; ++ bus-width = <4>; + fifo-depth = <0x100>; ++ max-frequency = <150000000>; + pinctrl-names = "default"; +- pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_bus4>; ++ pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_bus4 &sdmmc_pwr>; ++ resets = <&cru SRST_SDMMC>; ++ reset-names = "reset"; + status = "disabled"; + }; + +@@ -799,10 +803,14 @@ sdio: mmc@30010000 { + interrupts = ; + clocks = <&cru HCLK_SDIO>, <&cru SCLK_SDIO>, + <&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>; ++ bus-width = <4>; + clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; + fifo-depth = <0x100>; ++ max-frequency = <150000000>; + pinctrl-names = "default"; + pinctrl-0 = <&sdio_clk &sdio_cmd &sdio_bus4>; ++ resets = <&cru SRST_SDIO>; ++ reset-names = "reset"; + status = "disabled"; + }; + +@@ -810,14 +818,13 @@ emmc: mmc@30020000 { + compatible = "rockchip,rk3228-dw-mshc", "rockchip,rk3288-dw-mshc"; + reg = <0x30020000 0x4000>; + interrupts = ; +- clock-frequency = <37500000>; +- max-frequency = <37500000>; + clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>, + <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>; + clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; + bus-width = <8>; + rockchip,default-sample-phase = <158>; + fifo-depth = <0x100>; ++ max-frequency = <150000000>; + pinctrl-names = "default"; + pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; + resets = <&cru SRST_EMMC>; +@@ -1043,6 +1050,10 @@ sdmmc_bus4: sdmmc-bus4 { + <1 RK_PC4 1 &pcfg_pull_none_drv_12ma>, + <1 RK_PC5 1 &pcfg_pull_none_drv_12ma>; + }; ++ ++ sdmmc_pwr: sdmmc-pwr { ++ rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; + }; + + sdio { + +From 9a9db392c9d0fd23dd84c39f36290ab0bfbc2021 Mon Sep 17 00:00:00 2001 +From: Jeffy Chen +Date: Wed, 8 Jun 2016 14:05:42 +0800 +Subject: [PATCH] clk: rockchip: rk3036: add ACLK_VCODEC + +Change-Id: I36f6b23139345941656c127718cc4ff01c6d629f +Signed-off-by: Jeffy Chen +--- + drivers/clk/rockchip/clk-rk3036.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c +index 6a46f85ad837..3b285261ce39 100644 +--- a/drivers/clk/rockchip/clk-rk3036.c ++++ b/drivers/clk/rockchip/clk-rk3036.c +@@ -258,7 +258,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { + RK2928_CLKGATE_CON(1), 13, GFLAGS, + &rk3036_uart2_fracmux), + +- COMPOSITE(0, "aclk_vcodec", mux_pll_src_3plls_p, 0, ++ COMPOSITE(ACLK_VCODEC, "aclk_vcodec", mux_pll_src_3plls_p, 0, + RK2928_CLKSEL_CON(32), 14, 2, MFLAGS, 8, 5, DFLAGS, + RK2928_CLKGATE_CON(3), 11, GFLAGS), + FACTOR_GATE(HCLK_VCODEC, "hclk_vcodec", "aclk_vcodec", 0, 1, 4, + +From e1dd6aaa44b5ae46657f83bb066f50f5c9e0568a Mon Sep 17 00:00:00 2001 +From: Randy Li +Date: Fri, 20 Oct 2017 14:38:09 +0800 +Subject: [PATCH] clk: rockchip: rk3036: export the hevc core clock + +The clock hevc core will be used to drive the hevc decoder. + +Change-Id: Ic1298ce1edd07f86e5c243e3a2c9876481f4cba9 +Signed-off-by: Randy Li +--- + drivers/clk/rockchip/clk-rk3036.c | 2 +- + include/dt-bindings/clock/rk3036-cru.h | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c +index 3b285261ce39..a98ea978fc8a 100644 +--- a/drivers/clk/rockchip/clk-rk3036.c ++++ b/drivers/clk/rockchip/clk-rk3036.c +@@ -264,7 +264,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { + FACTOR_GATE(HCLK_VCODEC, "hclk_vcodec", "aclk_vcodec", 0, 1, 4, + RK2928_CLKGATE_CON(3), 12, GFLAGS), + +- COMPOSITE(0, "aclk_hvec", mux_pll_src_3plls_p, 0, ++ COMPOSITE(ACLK_HEVC, "aclk_hevc", mux_pll_src_3plls_p, 0, + RK2928_CLKSEL_CON(20), 0, 2, MFLAGS, 2, 5, DFLAGS, + RK2928_CLKGATE_CON(10), 6, GFLAGS), + +diff --git a/include/dt-bindings/clock/rk3036-cru.h b/include/dt-bindings/clock/rk3036-cru.h +index 35a5a01f9697..cd231f57278d 100644 +--- a/include/dt-bindings/clock/rk3036-cru.h ++++ b/include/dt-bindings/clock/rk3036-cru.h +@@ -55,6 +55,7 @@ + #define ACLK_VCODEC 208 + #define ACLK_CPU 209 + #define ACLK_PERI 210 ++#define ACLK_HEVC 211 + + /* pclk gates */ + #define PCLK_GPIO0 320 + +From e9752790e4c92f83924dc881cf1555977c512214 Mon Sep 17 00:00:00 2001 +From: Caesar Wang +Date: Mon, 13 Nov 2017 09:28:12 +0800 +Subject: [PATCH] clk: rockchip: export SCLK_I2S_PRE and SCLK_I2S_FRAC of i2s + on rk3036 + +Change-Id: I627c8c2582be2b27414e7b82e9d56dd560f68e64 +Signed-off-by: Caesar Wang +--- + drivers/clk/rockchip/clk-rk3036.c | 4 ++-- + include/dt-bindings/clock/rk3036-cru.h | 2 ++ + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c +index a98ea978fc8a..c67ee61ef0cd 100644 +--- a/drivers/clk/rockchip/clk-rk3036.c ++++ b/drivers/clk/rockchip/clk-rk3036.c +@@ -157,7 +157,7 @@ static struct rockchip_clk_branch rk3036_uart2_fracmux __initdata = + RK2928_CLKSEL_CON(15), 8, 2, MFLAGS); + + static struct rockchip_clk_branch rk3036_i2s_fracmux __initdata = +- MUX(0, "i2s_pre", mux_i2s_pre_p, CLK_SET_RATE_PARENT, ++ MUX(SCLK_I2S_PRE, "i2s_pre", mux_i2s_pre_p, CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(3), 8, 2, MFLAGS); + + static struct rockchip_clk_branch rk3036_spdif_fracmux __initdata = +@@ -306,7 +306,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { + COMPOSITE(0, "i2s_src", mux_pll_src_3plls_p, 0, + RK2928_CLKSEL_CON(3), 14, 2, MFLAGS, 0, 7, DFLAGS, + RK2928_CLKGATE_CON(0), 9, GFLAGS), +- COMPOSITE_FRACMUX(0, "i2s_frac", "i2s_src", CLK_SET_RATE_PARENT, ++ COMPOSITE_FRACMUX(SCLK_I2S_FRAC, "i2s_frac", "i2s_src", CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(7), 0, + RK2928_CLKGATE_CON(0), 10, GFLAGS, + &rk3036_i2s_fracmux), +diff --git a/include/dt-bindings/clock/rk3036-cru.h b/include/dt-bindings/clock/rk3036-cru.h +index cd231f57278d..4c7ff6141a67 100644 +--- a/include/dt-bindings/clock/rk3036-cru.h ++++ b/include/dt-bindings/clock/rk3036-cru.h +@@ -43,6 +43,8 @@ + #define SCLK_PVTM_CORE 123 + #define SCLK_PVTM_GPU 124 + #define SCLK_PVTM_VIDEO 125 ++#define SCLK_I2S_FRAC 126 ++#define SCLK_I2S_PRE 127 + #define SCLK_MAC 151 + #define SCLK_MACREF 152 + #define SCLK_MACPLL 153 + +From 1cfffef46d411629c71da2dea69c41b261355d5b Mon Sep 17 00:00:00 2001 +From: Caesar Wang +Date: Fri, 17 Nov 2017 14:49:16 +0800 +Subject: [PATCH] clk: rockchip: protect the armclk for rk3036 + +Some clocks may get disabled as a side effect of another clock +being disabled, because have no consumers. Says the dclk_hdmi's parent may +change from apll to gpll, but the apll's son clocks are very less. + +Change-Id: I4fb4e5fdf83a8f73979b50dbcf4f3e4543896fcf +Signed-off-by: Caesar Wang +--- + drivers/clk/rockchip/clk-rk3036.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c +index c67ee61ef0cd..ac5c1cfb3f54 100644 +--- a/drivers/clk/rockchip/clk-rk3036.c ++++ b/drivers/clk/rockchip/clk-rk3036.c +@@ -424,6 +424,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { + }; + + static const char *const rk3036_critical_clocks[] __initconst = { ++ "armclk", + "aclk_cpu", + "aclk_peri", + "hclk_peri", +@@ -467,14 +468,14 @@ static void __init rk3036_clk_init(struct device_node *np) + RK3036_GRF_SOC_STATUS0); + rockchip_clk_register_branches(ctx, rk3036_clk_branches, + ARRAY_SIZE(rk3036_clk_branches)); +- rockchip_clk_protect_critical(rk3036_critical_clocks, +- ARRAY_SIZE(rk3036_critical_clocks)); +- + rockchip_clk_register_armclk(ctx, ARMCLK, "armclk", + mux_armclk_p, ARRAY_SIZE(mux_armclk_p), + &rk3036_cpuclk_data, rk3036_cpuclk_rates, + ARRAY_SIZE(rk3036_cpuclk_rates)); + ++ rockchip_clk_protect_critical(rk3036_critical_clocks, ++ ARRAY_SIZE(rk3036_critical_clocks)); ++ + rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0), + ROCKCHIP_SOFTRST_HIWORD_MASK); + + +From 84f5c9e7a40b0e30b087aea7a618b18e2bb87fd5 Mon Sep 17 00:00:00 2001 +From: Finley Xiao +Date: Mon, 13 Nov 2017 15:32:25 +0800 +Subject: [PATCH] clk: rockchip: rk3036: leave apll for core, mac and lcdc only + +In order not to affect other clocks, remove the apll from the +parent list of other clocks and only core, mac and lcdc can +select apll as parent. + +Change-Id: I58b995f8ccf69c6564f74b5823f618a186030d70 +Signed-off-by: Finley Xiao +--- + drivers/clk/rockchip/clk-rk3036.c | 38 ++++++++++++++++--------------- + 1 file changed, 20 insertions(+), 18 deletions(-) + +diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c +index ac5c1cfb3f54..4ce2cf844123 100644 +--- a/drivers/clk/rockchip/clk-rk3036.c ++++ b/drivers/clk/rockchip/clk-rk3036.c +@@ -114,14 +114,16 @@ static const struct rockchip_cpuclk_reg_data rk3036_cpuclk_data = { + PNAME(mux_pll_p) = { "xin24m", "xin24m" }; + + PNAME(mux_armclk_p) = { "apll", "gpll_armclk" }; +-PNAME(mux_busclk_p) = { "apll", "dpll_cpu", "gpll_cpu" }; ++PNAME(mux_busclk_p) = { "dummy_apll", "dpll_cpu", "gpll_cpu" }; + PNAME(mux_ddrphy_p) = { "dpll_ddr", "gpll_ddr" }; +-PNAME(mux_pll_src_3plls_p) = { "apll", "dpll", "gpll" }; ++PNAME(mux_pll_src_apll_dpll_gpll_p) = { "apll", "dpll", "gpll" }; ++PNAME(mux_pll_src_dmyapll_dpll_gpll_p) = { "dummy_apll", "dpll", "gpll" }; ++ + PNAME(mux_timer_p) = { "xin24m", "pclk_peri_src" }; + +-PNAME(mux_pll_src_apll_dpll_gpll_usb480m_p) = { "apll", "dpll", "gpll", "usb480m" }; ++PNAME(mux_pll_src_dmyapll_dpll_gpll_usb480m_p) = { "dummy_apll", "dpll", "gpll", "usb480m" }; + +-PNAME(mux_mmc_src_p) = { "apll", "dpll", "gpll", "xin24m" }; ++PNAME(mux_mmc_src_p) = { "dummy_apll", "dpll", "gpll", "xin24m" }; + PNAME(mux_i2s_pre_p) = { "i2s_src", "i2s_frac", "ext_i2s", "xin12m" }; + PNAME(mux_i2s_clkout_p) = { "i2s_pre", "xin12m" }; + PNAME(mux_spdif_p) = { "spdif_src", "spdif_frac", "xin12m" }; +@@ -206,7 +208,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { + RK2928_CLKSEL_CON(1), 8, 2, DFLAGS | CLK_DIVIDER_READ_ONLY, + RK2928_CLKGATE_CON(0), 4, GFLAGS), + +- COMPOSITE(0, "aclk_peri_src", mux_pll_src_3plls_p, 0, ++ COMPOSITE(0, "aclk_peri_src", mux_pll_src_dmyapll_dpll_gpll_p, 0, + RK2928_CLKSEL_CON(10), 14, 2, MFLAGS, 0, 5, DFLAGS, + RK2928_CLKGATE_CON(2), 0, GFLAGS), + +@@ -234,7 +236,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { + RK2928_CLKSEL_CON(2), 7, 1, MFLAGS, + RK2928_CLKGATE_CON(2), 5, GFLAGS), + +- MUX(0, "uart_pll_clk", mux_pll_src_apll_dpll_gpll_usb480m_p, 0, ++ MUX(0, "uart_pll_clk", mux_pll_src_dmyapll_dpll_gpll_usb480m_p, 0, + RK2928_CLKSEL_CON(13), 10, 2, MFLAGS), + COMPOSITE_NOMUX(0, "uart0_src", "uart_pll_clk", 0, + RK2928_CLKSEL_CON(13), 0, 7, DFLAGS, +@@ -258,23 +260,23 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { + RK2928_CLKGATE_CON(1), 13, GFLAGS, + &rk3036_uart2_fracmux), + +- COMPOSITE(ACLK_VCODEC, "aclk_vcodec", mux_pll_src_3plls_p, 0, ++ COMPOSITE(ACLK_VCODEC, "aclk_vcodec", mux_pll_src_dmyapll_dpll_gpll_p, 0, + RK2928_CLKSEL_CON(32), 14, 2, MFLAGS, 8, 5, DFLAGS, + RK2928_CLKGATE_CON(3), 11, GFLAGS), + FACTOR_GATE(HCLK_VCODEC, "hclk_vcodec", "aclk_vcodec", 0, 1, 4, + RK2928_CLKGATE_CON(3), 12, GFLAGS), + +- COMPOSITE(ACLK_HEVC, "aclk_hevc", mux_pll_src_3plls_p, 0, ++ COMPOSITE(ACLK_HEVC, "aclk_hevc", mux_pll_src_dmyapll_dpll_gpll_p, 0, + RK2928_CLKSEL_CON(20), 0, 2, MFLAGS, 2, 5, DFLAGS, + RK2928_CLKGATE_CON(10), 6, GFLAGS), + +- COMPOSITE(0, "aclk_disp1_pre", mux_pll_src_3plls_p, 0, ++ COMPOSITE(0, "aclk_disp1_pre", mux_pll_src_dmyapll_dpll_gpll_p, 0, + RK2928_CLKSEL_CON(31), 14, 2, MFLAGS, 8, 5, DFLAGS, + RK2928_CLKGATE_CON(1), 4, GFLAGS), +- COMPOSITE(0, "hclk_disp_pre", mux_pll_src_3plls_p, 0, ++ COMPOSITE(0, "hclk_disp_pre", mux_pll_src_dmyapll_dpll_gpll_p, 0, + RK2928_CLKSEL_CON(30), 14, 2, MFLAGS, 8, 5, DFLAGS, + RK2928_CLKGATE_CON(0), 11, GFLAGS), +- COMPOSITE(SCLK_LCDC, "dclk_lcdc", mux_pll_src_3plls_p, 0, ++ COMPOSITE(SCLK_LCDC, "dclk_lcdc", mux_pll_src_apll_dpll_gpll_p, 0, + RK2928_CLKSEL_CON(28), 0, 2, MFLAGS, 8, 8, DFLAGS, + RK2928_CLKGATE_CON(3), 2, GFLAGS), + +@@ -303,7 +305,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { + MMC(SCLK_EMMC_DRV, "emmc_drv", "sclk_emmc", RK3036_EMMC_CON0, 1), + MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RK3036_EMMC_CON1, 0), + +- COMPOSITE(0, "i2s_src", mux_pll_src_3plls_p, 0, ++ COMPOSITE(0, "i2s_src", mux_pll_src_dmyapll_dpll_gpll_p, 0, + RK2928_CLKSEL_CON(3), 14, 2, MFLAGS, 0, 7, DFLAGS, + RK2928_CLKGATE_CON(0), 9, GFLAGS), + COMPOSITE_FRACMUX(SCLK_I2S_FRAC, "i2s_frac", "i2s_src", CLK_SET_RATE_PARENT, +@@ -316,7 +318,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { + GATE(SCLK_I2S, "sclk_i2s", "i2s_pre", CLK_SET_RATE_PARENT, + RK2928_CLKGATE_CON(0), 14, GFLAGS), + +- COMPOSITE(0, "spdif_src", mux_pll_src_3plls_p, 0, ++ COMPOSITE(0, "spdif_src", mux_pll_src_dmyapll_dpll_gpll_p, 0, + RK2928_CLKSEL_CON(5), 10, 2, MFLAGS, 0, 7, DFLAGS, + RK2928_CLKGATE_CON(2), 10, GFLAGS), + COMPOSITE_FRACMUX(0, "spdif_frac", "spdif_src", 0, +@@ -327,23 +329,23 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { + GATE(SCLK_OTGPHY0, "sclk_otgphy0", "xin12m", CLK_IGNORE_UNUSED, + RK2928_CLKGATE_CON(1), 5, GFLAGS), + +- COMPOSITE(SCLK_GPU, "sclk_gpu", mux_pll_src_3plls_p, 0, ++ COMPOSITE(SCLK_GPU, "sclk_gpu", mux_pll_src_dmyapll_dpll_gpll_p, 0, + RK2928_CLKSEL_CON(34), 8, 2, MFLAGS, 0, 5, DFLAGS, + RK2928_CLKGATE_CON(3), 13, GFLAGS), + +- COMPOSITE(SCLK_SPI, "sclk_spi", mux_pll_src_3plls_p, 0, ++ COMPOSITE(SCLK_SPI, "sclk_spi", mux_pll_src_dmyapll_dpll_gpll_p, 0, + RK2928_CLKSEL_CON(25), 8, 2, MFLAGS, 0, 7, DFLAGS, + RK2928_CLKGATE_CON(2), 9, GFLAGS), + +- COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_3plls_p, 0, ++ COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_dmyapll_dpll_gpll_p, 0, + RK2928_CLKSEL_CON(16), 8, 2, MFLAGS, 10, 5, DFLAGS, + RK2928_CLKGATE_CON(10), 4, GFLAGS), + +- COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_apll_dpll_gpll_usb480m_p, 0, ++ COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_dmyapll_dpll_gpll_usb480m_p, 0, + RK2928_CLKSEL_CON(16), 0, 2, MFLAGS, 2, 5, DFLAGS, + RK2928_CLKGATE_CON(10), 5, GFLAGS), + +- COMPOSITE_NOGATE(SCLK_MACPLL, "mac_pll_src", mux_pll_src_3plls_p, CLK_SET_RATE_NO_REPARENT, ++ COMPOSITE_NOGATE(SCLK_MACPLL, "mac_pll_src", mux_pll_src_apll_dpll_gpll_p, CLK_SET_RATE_NO_REPARENT, + RK2928_CLKSEL_CON(21), 0, 2, MFLAGS, 9, 5, DFLAGS), + MUX(SCLK_MACREF, "mac_clk_ref", mux_mac_p, CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(21), 3, 1, MFLAGS), + +From 30337bfc416283d487d91e82397c81f1cae745a9 Mon Sep 17 00:00:00 2001 +From: Randy Li +Date: Fri, 20 Apr 2018 10:43:46 +0800 +Subject: [PATCH] clk: rockchip: rk3036: export the sfc clocks + +The serial Flash controller on the rk3036 would request +two clock nodes. + +Change-Id: Iaa50c4a25602a68241b0b9b2f186e4c7e55bc3da +Signed-off-by: Randy Li +--- + drivers/clk/rockchip/clk-rk3036.c | 2 +- + include/dt-bindings/clock/rk3036-cru.h | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c +index 4ce2cf844123..0d1556ac185a 100644 +--- a/drivers/clk/rockchip/clk-rk3036.c ++++ b/drivers/clk/rockchip/clk-rk3036.c +@@ -404,7 +404,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { + GATE(HCLK_OTG0, "hclk_otg0", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 13, GFLAGS), + GATE(HCLK_OTG1, "hclk_otg1", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(7), 3, GFLAGS), + GATE(HCLK_I2S, "hclk_i2s", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 2, GFLAGS), +- GATE(0, "hclk_sfc", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(3), 14, GFLAGS), ++ GATE(HCLK_SFC, "hclk_sfc", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(3), 14, GFLAGS), + GATE(HCLK_MAC, "hclk_mac", "hclk_peri", 0, RK2928_CLKGATE_CON(3), 5, GFLAGS), + + /* pclk_peri gates */ +diff --git a/include/dt-bindings/clock/rk3036-cru.h b/include/dt-bindings/clock/rk3036-cru.h +index 4c7ff6141a67..72ba1952071d 100644 +--- a/include/dt-bindings/clock/rk3036-cru.h ++++ b/include/dt-bindings/clock/rk3036-cru.h +@@ -84,6 +84,7 @@ + #define HCLK_OTG0 449 + #define HCLK_OTG1 450 + #define HCLK_NANDC 453 ++#define HCLK_SFC 454 + #define HCLK_SDMMC 456 + #define HCLK_SDIO 457 + #define HCLK_EMMC 459 + +From 62768587c0db32f4180bd4cebbd9f8d8ad865901 Mon Sep 17 00:00:00 2001 +From: Elaine Zhang +Date: Mon, 1 Jun 2020 15:36:35 +0800 +Subject: [PATCH] clk: rockchip: rk3036: fix up the sclk_sfc parent error + +Change-Id: I0903161f34de8f309392bec6926348ffe37ba2f6 +Signed-off-by: Elaine Zhang +--- + drivers/clk/rockchip/clk-rk3036.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c +index 0d1556ac185a..693bee4009db 100644 +--- a/drivers/clk/rockchip/clk-rk3036.c ++++ b/drivers/clk/rockchip/clk-rk3036.c +@@ -122,6 +122,7 @@ PNAME(mux_pll_src_dmyapll_dpll_gpll_p) = { "dummy_apll", "dpll", "gpll" }; + PNAME(mux_timer_p) = { "xin24m", "pclk_peri_src" }; + + PNAME(mux_pll_src_dmyapll_dpll_gpll_usb480m_p) = { "dummy_apll", "dpll", "gpll", "usb480m" }; ++PNAME(mux_pll_src_dmyapll_dpll_gpll_xin24_p) = { "dummy_apll", "dpll", "gpll", "xin24m" }; + + PNAME(mux_mmc_src_p) = { "dummy_apll", "dpll", "gpll", "xin24m" }; + PNAME(mux_i2s_pre_p) = { "i2s_src", "i2s_frac", "ext_i2s", "xin12m" }; +@@ -341,7 +342,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { + RK2928_CLKSEL_CON(16), 8, 2, MFLAGS, 10, 5, DFLAGS, + RK2928_CLKGATE_CON(10), 4, GFLAGS), + +- COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_dmyapll_dpll_gpll_usb480m_p, 0, ++ COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_dmyapll_dpll_gpll_xin24_p, 0, + RK2928_CLKSEL_CON(16), 0, 2, MFLAGS, 2, 5, DFLAGS, + RK2928_CLKGATE_CON(10), 5, GFLAGS), + + +From cef2d7b595360c89a57fcf38d1dcf41759ceac95 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sun, 16 Aug 2020 22:41:29 +0200 +Subject: [PATCH] clk: rockchip: export PCLK_EFUSE for RK3036 + +Export PCLK_EFUSE for RK3036. +--- + drivers/clk/rockchip/clk-rk3036.c | 2 +- + include/dt-bindings/clock/rk3036-cru.h | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c +index 693bee4009db..06e92dd5ce25 100644 +--- a/drivers/clk/rockchip/clk-rk3036.c ++++ b/drivers/clk/rockchip/clk-rk3036.c +@@ -410,7 +410,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { + + /* pclk_peri gates */ + GATE(0, "pclk_peri_matrix", "pclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 1, GFLAGS), +- GATE(0, "pclk_efuse", "pclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 2, GFLAGS), ++ GATE(PCLK_EFUSE, "pclk_efuse", "pclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 2, GFLAGS), + GATE(PCLK_TIMER, "pclk_timer", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 7, GFLAGS), + GATE(PCLK_PWM, "pclk_pwm", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 10, GFLAGS), + GATE(PCLK_SPI, "pclk_spi", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 12, GFLAGS), +diff --git a/include/dt-bindings/clock/rk3036-cru.h b/include/dt-bindings/clock/rk3036-cru.h +index 72ba1952071d..febab04521a2 100644 +--- a/include/dt-bindings/clock/rk3036-cru.h ++++ b/include/dt-bindings/clock/rk3036-cru.h +@@ -79,6 +79,7 @@ + #define PCLK_DDRUPCTL 364 + #define PCLK_WDT 368 + #define PCLK_ACODEC 369 ++#define PCLK_EFUSE 370 + + /* hclk gates */ + #define HCLK_OTG0 449 + +From bf25b1441ad681e8b56ae6ec069165dc4fb6b445 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sun, 16 Aug 2020 22:43:41 +0200 +Subject: [PATCH] ARM: dts: rockchip: add RK3036 efuse node + +Add RK3036 efuse node to the devicetree and add the new compatible string +to bindings document. +--- + .../devicetree/bindings/nvmem/rockchip-efuse.yaml | 1 + + arch/arm/boot/dts/rk3036.dtsi | 7 +++++++ + 2 files changed, 8 insertions(+) + +diff --git a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.yaml b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.yaml +index 3ae00b0b23bc..c3fdabcb1e0a 100644 +--- a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.yaml ++++ b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.yaml +@@ -15,6 +15,7 @@ allOf: + properties: + compatible: + enum: ++ - rockchip,rk3036-efuse + - rockchip,rk3066a-efuse + - rockchip,rk3188-efuse + - rockchip,rk3228-efuse +diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi +index 10f15cdb932c..6700a17a6446 100644 +--- a/arch/arm/boot/dts/rk3036.dtsi ++++ b/arch/arm/boot/dts/rk3036.dtsi +@@ -873,4 +873,11 @@ spi_cs1:spi-cs1 { + }; + }; + }; ++ ++ efuse: efuse@20090000 { ++ compatible = "rockchip,rk3036-efuse", "rockchip,rk3288-efuse"; ++ reg = <0x20090000 0x20>; ++ clocks = <&cru PCLK_EFUSE>; ++ clock-names = "pclk_efuse"; ++ }; + }; + +From 490be97e9fdc5e4ea8afd5b41d2a9f2942f82b02 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sun, 16 Aug 2020 23:02:00 +0200 +Subject: [PATCH] ARM: dts: add opp-table for RK3188s GPU + +Add opp-table for RK3188s mali400 MP4 GPU +--- + arch/arm/boot/dts/rk3188.dtsi | 30 ++++++++++++++++++++++++++++++ + 1 file changed, 30 insertions(+) + +diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi +index 9fab375231ec..894fe6259ef2 100644 +--- a/arch/arm/boot/dts/rk3188.dtsi ++++ b/arch/arm/boot/dts/rk3188.dtsi +@@ -112,6 +112,35 @@ smp-sram@0 { + }; + }; + ++ gpu_opp_table: opp-table2 { ++ compatible = "operating-points-v2"; ++ ++ opp-133000000 { ++ opp-hz = /bits/ 64 <133000000>; ++ opp-microvolt = <975000>; ++ }; ++ opp-200000000 { ++ opp-hz = /bits/ 64 <200000000>; ++ opp-microvolt = <1000000>; ++ }; ++ opp-266000000 { ++ opp-hz = /bits/ 64 <266000000>; ++ opp-microvolt = <1025000>; ++ }; ++ opp-300000000 { ++ opp-hz = /bits/ 64 <300000000>; ++ opp-microvolt = <1050000>; ++ }; ++ opp-400000000 { ++ opp-hz = /bits/ 64 <400000000>; ++ opp-microvolt = <1100000>; ++ }; ++ opp-600000000 { ++ opp-hz = /bits/ 64 <600000000>; ++ opp-microvolt = <1250000>; ++ }; ++ }; ++ + vpu: video-codec@10104000 { + compatible = "rockchip,rk3188-vpu"; + reg = <0x10104000 0x800>; +@@ -672,6 +701,7 @@ &gpu { + "ppmmu2", + "pp3", + "ppmmu3"; ++ operating-points-v2 = <&gpu_opp_table>; + power-domains = <&power RK3188_PD_GPU>; + }; + + +From 313b1d3730fc3a9076a783e9e296a13fdae599ce Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sun, 16 Aug 2020 23:12:25 +0200 +Subject: [PATCH] ARM: dts: rk322x: add crypto node + +In order to add support for RK322x's crypto HW, the node +has been added t its dts. + +Signed-off-by: Alex Bee +--- + arch/arm/boot/dts/rk322x.dtsi | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi +index 92e3eb1e7938..be46697e125e 100644 +--- a/arch/arm/boot/dts/rk322x.dtsi ++++ b/arch/arm/boot/dts/rk322x.dtsi +@@ -167,6 +167,17 @@ display_subsystem: display-subsystem { + ports = <&vop_out>; + }; + ++ crypto: cypto-controller@100a0000 { ++ compatible = "rockchip,rk3288-crypto"; ++ reg = <0x100a0000 0x4000>; ++ interrupts = ; ++ clocks = <&cru HCLK_M_CRYPTO>, <&cru HCLK_S_CRYPTO>, ++ <&cru SCLK_CRYPTO>, <&cru ACLK_DMAC>; ++ clock-names = "aclk", "hclk", "sclk", "apb_pclk"; ++ resets = <&cru SRST_CRYPTO>; ++ reset-names = "crypto-rst"; ++ }; ++ + i2s1: i2s1@100b0000 { + compatible = "rockchip,rk3228-i2s", "rockchip,rk3066-i2s"; + reg = <0x100b0000 0x4000>; diff --git a/patch/kernel/rk322x-current/01-linux-9000-rockchip-linux-le-wip.patch b/patch/kernel/rk322x-current/01-linux-9000-rockchip-linux-le-wip.patch new file mode 100644 index 000000000..dad10c696 --- /dev/null +++ b/patch/kernel/rk322x-current/01-linux-9000-rockchip-linux-le-wip.patch @@ -0,0 +1,912 @@ +From 71fba6c19fa57e219657226d3d20528ebec86def Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sun, 16 Aug 2020 23:03:12 +0200 +Subject: [PATCH] WIP: ARM: dts: add RK322x box device trees + +--- + arch/arm/boot/dts/Makefile | 4 + + arch/arm/boot/dts/rk3228a-box-h96mini.dts | 115 +++++++++ + arch/arm/boot/dts/rk3228a-box.dts | 47 ++++ + arch/arm/boot/dts/rk3228a-box.dtsi | 12 + + arch/arm/boot/dts/rk3229-box-a95xr1.dts | 57 ++++ + arch/arm/boot/dts/rk3229-box.dts | 50 ++++ + arch/arm/boot/dts/rk3229-box.dtsi | 21 ++ + arch/arm/boot/dts/rk3229-cpu-opp.dtsi | 50 ++++ + arch/arm/boot/dts/rk322x-box-dcdc.dtsi | 164 ++++++++++++ + arch/arm/boot/dts/rk322x-box.dtsi | 301 ++++++++++++++++++++++ + 10 files changed, 821 insertions(+) + create mode 100644 arch/arm/boot/dts/rk3228a-box-h96mini.dts + create mode 100644 arch/arm/boot/dts/rk3228a-box.dts + create mode 100644 arch/arm/boot/dts/rk3228a-box.dtsi + create mode 100644 arch/arm/boot/dts/rk3229-box-a95xr1.dts + create mode 100644 arch/arm/boot/dts/rk3229-box.dts + create mode 100644 arch/arm/boot/dts/rk3229-box.dtsi + create mode 100644 arch/arm/boot/dts/rk3229-cpu-opp.dtsi + create mode 100644 arch/arm/boot/dts/rk322x-box-dcdc.dtsi + create mode 100644 arch/arm/boot/dts/rk322x-box.dtsi + +diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile +index e6a1cac0bfc7..1e633e4aa5a2 100644 +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -961,7 +961,11 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \ + rk3188-bqedison2qc.dtb \ + rk3188-px3-evb.dtb \ + rk3188-radxarock.dtb \ ++ rk3228a-box.dtb \ ++ rk3228a-box-h96mini.dtb \ + rk3228-evb.dtb \ ++ rk3229-box.dtb \ ++ rk3229-box-a95xr1.dtb \ + rk3229-evb.dtb \ + rk3229-xms6.dtb \ + rk3288-evb-act8846.dtb \ +diff --git a/arch/arm/boot/dts/rk3228a-box-h96mini.dts b/arch/arm/boot/dts/rk3228a-box-h96mini.dts +new file mode 100644 +index 000000000000..1041b6737d40 +--- /dev/null ++++ b/arch/arm/boot/dts/rk3228a-box-h96mini.dts +@@ -0,0 +1,115 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++/dts-v1/; ++#include ++#include ++#include "rk3228a-box.dtsi" ++ ++/ { ++ compatible = "eledvb,h96mini", "rockchip,rk3228a-box", "rockchip,rk3229"; ++ model = "Rockchip RK3228A Box H96 mini"; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led_green { ++ gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ }; ++ ++ led_red { ++ gpios = <&gpio0 RK_PB0 GPIO_ACTIVE_HIGH>; ++ default-state = "off"; ++ }; ++ }; ++ ++ openvfd { ++ compatible = "open,vfd"; ++ dev_name = "openvfd"; ++ openvfd_gpio_clk = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; ++ openvfd_gpio_dat = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>; ++ openvfd_display_type = <0x06000100>; ++ openvfd_dot_bits = [00 01 03 02 04 05 06]; ++ }; ++ ++}; ++ ++&emmc { ++ mmc-hs200-1_8v; ++ status = "okay"; ++}; ++ ++&gmac { ++ tx_delay = <0x26>; ++ rx_delay = <0x11>; ++}; ++ ++&ir_receiver { ++ status = "okay"; ++}; ++ ++&pinctrl { ++ wifi { ++ wifi_host_wake_l: wifi-host-wake-l { ++ rockchip,pins = <0 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ bt { ++ bt_host_wake_l: bt-host-wake-l { ++ rockchip,pins = <3 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ ++ bt_reg_on_h: bt-reg-on-h { ++ rockchip,pins = <2 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ ++ bt_wake_l: bt-wake-l { ++ rockchip,pins = <3 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++}; ++ ++&power_key { ++ status = "okay"; ++}; ++ ++&sdio { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ brcmf: wifi@1 { ++ compatible = "brcm,bcm4329-fmac"; ++ reg = <1>; ++ interrupt-parent = <&gpio0>; ++ interrupts = ; ++ interrupt-names = "host-wake"; ++ brcm,drive-strength = <5>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&wifi_host_wake_l>; ++ }; ++}; ++ ++&sdmmc { ++ disable-wp; ++ status = "okay"; ++}; ++ ++&uart1 { ++ status = "okay"; ++ ++ bluetooth { ++ compatible = "brcm,bcm4330-bt"; ++ host-wakeup-gpios = <&gpio3 RK_PD2 GPIO_ACTIVE_HIGH>; ++ device-wakeup-gpios = <&gpio3 RK_PD3 GPIO_ACTIVE_HIGH>; ++ shutdown-gpios = <&gpio2 RK_PD5 GPIO_ACTIVE_HIGH>; ++ max-speed = <4000000>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bt_reg_on_h &bt_host_wake_l &bt_wake_l>; ++ }; ++}; ++ ++&usb_otg { ++ dr_mode = "host"; ++}; +diff --git a/arch/arm/boot/dts/rk3228a-box.dts b/arch/arm/boot/dts/rk3228a-box.dts +new file mode 100644 +index 000000000000..e68ef44b95c9 +--- /dev/null ++++ b/arch/arm/boot/dts/rk3228a-box.dts +@@ -0,0 +1,47 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++/dts-v1/; ++#include "rk3228a-box.dtsi" ++ ++/ { ++ model = "Rockchip RK3228A Box"; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led_blue { ++ gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ }; ++ ++ led_red { ++ gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_HIGH>; ++ default-state = "off"; ++ }; ++ }; ++ ++}; ++ ++&emmc { ++ status = "okay"; ++}; ++ ++&ir_receiver { ++ status = "okay"; ++}; ++ ++&sdio { ++ status = "okay"; ++}; ++ ++&sdmmc { ++ status = "okay"; ++}; ++ ++&uart1 { ++ status = "okay"; ++}; ++ ++&usb_otg { ++ dr_mode = "host"; ++}; +diff --git a/arch/arm/boot/dts/rk3228a-box.dtsi b/arch/arm/boot/dts/rk3228a-box.dtsi +new file mode 100644 +index 000000000000..056945c6c9a7 +--- /dev/null ++++ b/arch/arm/boot/dts/rk3228a-box.dtsi +@@ -0,0 +1,12 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++/dts-v1/; ++ ++#include "rk322x-box-dcdc.dtsi" ++ ++/ { ++ ++ model = "Rockchip RK3228A Box"; ++ compatible = "rockchip,rk3228a-box", "rockchip,rk3229"; ++ ++}; +diff --git a/arch/arm/boot/dts/rk3229-box-a95xr1.dts b/arch/arm/boot/dts/rk3229-box-a95xr1.dts +new file mode 100644 +index 000000000000..b3695fb0b255 +--- /dev/null ++++ b/arch/arm/boot/dts/rk3229-box-a95xr1.dts +@@ -0,0 +1,57 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++/dts-v1/; ++#include ++#include ++#include "rk3229-box.dtsi" ++ ++/ { ++ model = "Rockchip RK3229 Box A95X-R1"; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led_blue { ++ gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ }; ++ ++ led_red { ++ gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_HIGH>; ++ default-state = "off"; ++ linux,default-trigger = "rc-feedback"; ++ }; ++ }; ++ ++}; ++ ++&emmc { ++ mmc-hs200-1_8v; ++ status = "okay"; ++}; ++ ++&gmac { ++ tx_delay = <0x26>; ++ rx_delay = <0x11>; ++}; ++ ++&ir_receiver { ++ status = "okay"; ++}; ++ ++&power_key { ++ status = "okay"; ++}; ++ ++&sdio { ++ status = "okay"; ++}; ++ ++&sdmmc { ++ disable-wp; ++ status = "okay"; ++}; ++ ++&usb_otg { ++ dr_mode = "host"; ++}; +diff --git a/arch/arm/boot/dts/rk3229-box.dts b/arch/arm/boot/dts/rk3229-box.dts +new file mode 100644 +index 000000000000..b63e61cda257 +--- /dev/null ++++ b/arch/arm/boot/dts/rk3229-box.dts +@@ -0,0 +1,50 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++/dts-v1/; ++#include "rk3229-box.dtsi" ++ ++/ { ++ model = "Rockchip RK3229 Box"; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led_green { ++ gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ }; ++ ++ led_red { ++ gpios = <&gpio0 RK_PB0 GPIO_ACTIVE_HIGH>; ++ default-state = "off"; ++ }; ++ }; ++}; ++ ++&emmc { ++ status = "okay"; ++}; ++ ++&ir_receiver { ++ status = "okay"; ++}; ++ ++&power_key { ++ status = "okay"; ++}; ++ ++&sdio { ++ status = "okay"; ++}; ++ ++&sdmmc { ++ status = "okay"; ++}; ++ ++&uart1 { ++ status = "okay"; ++}; ++ ++&usb_otg { ++ dr_mode = "host"; ++}; +diff --git a/arch/arm/boot/dts/rk3229-box.dtsi b/arch/arm/boot/dts/rk3229-box.dtsi +new file mode 100644 +index 000000000000..84f98fc53ebf +--- /dev/null ++++ b/arch/arm/boot/dts/rk3229-box.dtsi +@@ -0,0 +1,21 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++/dts-v1/; ++ ++#include "rk322x-box-dcdc.dtsi" ++#include "rk3229-cpu-opp.dtsi" ++ ++/ { ++ ++ model = "Rockchip RK3229 Box"; ++ compatible = "rockchip,rk3229-box", "rockchip,rk3229"; ++ ++}; ++ ++&cpu0_opp_table { ++ ++ opp-1464000000 { ++ status = "disabled"; ++ }; ++ ++}; +diff --git a/arch/arm/boot/dts/rk3229-cpu-opp.dtsi b/arch/arm/boot/dts/rk3229-cpu-opp.dtsi +new file mode 100644 +index 000000000000..c1c7613bab11 +--- /dev/null ++++ b/arch/arm/boot/dts/rk3229-cpu-opp.dtsi +@@ -0,0 +1,50 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd ++ */ ++ ++/ { ++ compatible = "rockchip,rk3229"; ++ ++ /delete-node/ opp-table0; ++ ++ cpu0_opp_table: opp_table0 { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ ++ opp-408000000 { ++ opp-hz = /bits/ 64 <408000000>; ++ opp-microvolt = <950000 950000 1400000>; ++ clock-latency-ns = <40000>; ++ opp-suspend; ++ }; ++ opp-600000000 { ++ opp-hz = /bits/ 64 <600000000>; ++ opp-microvolt = <975000 975000 1400000>; ++ }; ++ opp-816000000 { ++ opp-hz = /bits/ 64 <816000000>; ++ opp-microvolt = <1000000 1000000 1400000>; ++ }; ++ opp-1008000000 { ++ opp-hz = /bits/ 64 <1008000000>; ++ opp-microvolt = <1175000 1175000 1400000>; ++ }; ++ opp-1200000000 { ++ opp-hz = /bits/ 64 <1200000000>; ++ opp-microvolt = <1275000 1275000 1400000>; ++ }; ++ opp-1296000000 { ++ opp-hz = /bits/ 64 <1296000000>; ++ opp-microvolt = <1325000 1325000 1400000>; ++ }; ++ opp-1392000000 { ++ opp-hz = /bits/ 64 <1392000000>; ++ opp-microvolt = <1350000 1350000 1400000>; ++ }; ++ opp-1464000000 { ++ opp-hz = /bits/ 64 <1464000000>; ++ opp-microvolt = <1400000 1400000 1400000>; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/rk322x-box-dcdc.dtsi b/arch/arm/boot/dts/rk322x-box-dcdc.dtsi +new file mode 100644 +index 000000000000..b2e47c5b4693 +--- /dev/null ++++ b/arch/arm/boot/dts/rk322x-box-dcdc.dtsi +@@ -0,0 +1,164 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++/dts-v1/; ++ ++#include ++#include ++#include "rk322x-box.dtsi" ++ ++/ { ++ ++ vcc_host: vcc-host-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio3 RK_PC4 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&host_vbus_drv>; ++ regulator-name = "vcc_host"; ++ regulator-always-on; ++ regulator-boot-on; ++ vin-supply = <&vcc_sys>; ++ }; ++ ++ vccio_1v8: vccio-1v8-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vccio_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ vin-supply = <&vcc_sys>; ++ }; ++ ++ vccio_3v3: vccio-3v3-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vccio_3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ vin-supply = <&vcc_sys>; ++ }; ++ ++ ++ vcc_otg: vcc-otg-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio3 RK_PC6 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&otg_vbus_drv>; ++ regulator-name = "vcc_otg_vbus"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ regulator-always-on; ++ regulator-boot-on; ++ vin-supply = <&vcc_sys>; ++ }; ++ ++ vcc_phy: vcc-phy-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ regulator-name = "vcc_phy"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ vin-supply = <&vccio_1v8>; ++ }; ++ ++ vcc_sys: vcc-sys-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ }; ++ ++ vdd_arm: vdd-arm-regulator { ++ compatible = "pwm-regulator"; ++ pwms = <&pwm1 0 5000 1>; ++ pwm-supply = <&vcc_sys>; ++ regulator-name = "vdd_arm"; ++ regulator-min-microvolt = <950000>; ++ regulator-max-microvolt = <1400000>; ++ regulator-ramp-delay = <12500>; ++ regulator-settling-time-up-us = <250>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ vdd_log: vdd-log-regulator { ++ compatible = "pwm-regulator"; ++ pwms = <&pwm2 0 5000 1>; ++ pwm-supply = <&vcc_sys>; ++ regulator-name = "vdd_log"; ++ regulator-min-microvolt = <1000000>; ++ regulator-max-microvolt = <1300000>; ++ regulator-ramp-delay = <12500>; ++ regulator-settling-time-up-us = <250>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++}; ++ ++ ++&cpu0 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu1 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu2 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu3 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&io_domains { ++ vccio1-supply = <&vccio_3v3>; ++ vccio2-supply = <&vccio_1v8>; ++ vccio4-supply = <&vccio_3v3>; ++ status = "okay"; ++}; ++ ++&gmac { ++ phy-supply = <&vcc_phy>; ++}; ++ ++&gpu { ++ mali-supply = <&vdd_log>; ++}; ++ ++&pwm1 { ++ pinctrl-0 = <&pwm1_pin_pull_down>; ++ status = "okay"; ++}; ++ ++&pwm2 { ++ pinctrl-0 = <&pwm2_pin_pull_up>; ++ status = "okay"; ++}; ++ ++&u2phy0 { ++ u2phy0_host: host-port { ++ phy-supply = <&vcc_host>; ++ }; ++ ++ u2phy0_otg: otg-port { ++ phy-supply = <&vcc_otg>; ++ }; ++}; ++ ++&u2phy1 { ++ u2phy1_host: host-port { ++ phy-supply = <&vcc_host>; ++ }; ++ ++ u2phy1_otg: otg-port { ++ phy-supply = <&vcc_otg>; ++ }; ++}; +diff --git a/arch/arm/boot/dts/rk322x-box.dtsi b/arch/arm/boot/dts/rk322x-box.dtsi +new file mode 100644 +index 000000000000..02c9b3540f38 +--- /dev/null ++++ b/arch/arm/boot/dts/rk322x-box.dtsi +@@ -0,0 +1,299 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++/dts-v1/; ++ ++#include ++#include ++#include ++#include ++#include "rk322x.dtsi" ++ ++/ { ++ model = "Rockchip RK322x Box"; ++ compatible = "rockchip,rk3229"; ++ ++ chosen { ++ bootargs = "earlyprintk=uart8250,mmio32,0x11030000"; ++ }; ++ ++ gpio_keys { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ autorepeat; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwr_key>; ++ ++ power_key: power-key { ++ label = "GPIO Key Power"; ++ gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_LOW>; ++ linux,code = ; ++ debounce-interval = <100>; ++ wakeup-source; ++ status = "disabled"; ++ }; ++ }; ++ ++ ir_receiver: ir-receiver { ++ compatible = "gpio-ir-receiver"; ++ gpios = <&gpio1 RK_PB3 GPIO_ACTIVE_LOW>; ++ pinctrl-0 = <&ir_int>; ++ pinctrl-names = "default"; ++ status = "disabled"; ++ }; ++ ++ memory@60000000 { ++ device_type = "memory"; ++ reg = <0x60000000 0x40000000>; ++ }; ++ ++ reserved-memory { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ++ /* Not needed since u-boot 2020.07 ++ trust_reserved: trust@68400000 { ++ reg = <0x68400000 0xe00000>; ++ no-map; ++ };*/ ++ }; ++ ++ sdio_pwrseq: sdio-pwrseq { ++ compatible = "mmc-pwrseq-simple"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&wifi_enable_h>; ++ reset-gpios = <&gpio2 RK_PD2 GPIO_ACTIVE_LOW>; ++ }; ++ ++}; ++ ++&cpu_alert1 { ++ temperature = <105000>; ++}; ++ ++&cpu_crit { ++ temperature = <115000>; ++}; ++ ++&cpu_thermal { ++ cooling-maps { ++ /delete-node/ map0; ++ }; ++}; ++ ++&cpu0_opp_table { ++ ++ opp-408000000 { ++ opp-microvolt = <950000 950000 1275000>; ++ }; ++ ++ opp-600000000 { ++ opp-microvolt = <975000 975000 1275000>; ++ }; ++ ++ opp-816000000 { ++ opp-microvolt = <1000000 1000000 1275000>; ++ }; ++ ++ opp-1008000000 { ++ opp-microvolt = <1175000 1175000 1275000>; ++ }; ++ ++ opp-1200000000 { ++ opp-microvolt = <1275000 1275000 1275000>; ++ }; ++}; ++ ++&cru { ++ assigned-clocks = ++ <&cru PLL_GPLL>, <&cru ARMCLK>, ++ <&cru PLL_CPLL>, <&cru ACLK_PERI>, ++ <&cru HCLK_PERI>, <&cru PCLK_PERI>, ++ <&cru ACLK_CPU>, <&cru HCLK_CPU>, ++ <&cru PCLK_CPU>, <&cru ACLK_VOP>; ++ assigned-clock-rates = ++ <1200000000>, <816000000>, ++ <500000000>, <150000000>, ++ <150000000>, <75000000>, ++ <150000000>, <150000000>, ++ <75000000>, <400000000>; ++}; ++ ++&emmc { ++ cap-mmc-highspeed; ++ keep-power-in-suspend; ++ non-removable; ++}; ++ ++&gmac { ++ assigned-clocks = <&cru SCLK_MAC_SRC>; ++ assigned-clock-rates = <50000000>; ++ clock_in_out = "output"; ++ phy-handle = <&phy>; ++ phy-mode = "rmii"; ++ status = "okay"; ++ ++ mdio { ++ compatible = "snps,dwmac-mdio"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ phy: phy@0 { ++ compatible = "ethernet-phy-id1234.d400", ++ "ethernet-phy-ieee802.3-c22"; ++ reg = <0>; ++ clocks = <&cru SCLK_MAC_PHY>; ++ phy-is-integrated; ++ resets = <&cru SRST_MACPHY>; ++ }; ++ }; ++}; ++ ++&gpu { ++ assigned-clocks = <&cru ACLK_GPU>; ++ assigned-clock-rates = <300000000>; ++}; ++ ++&hdmi { ++ status = "okay"; ++}; ++ ++&hdmi_sound { ++ status = "okay"; ++}; ++ ++&hdmi_phy { ++ status = "okay"; ++}; ++ ++&i2s0 { ++ status = "okay"; ++}; ++ ++&pinctrl { ++ ++ ir { ++ ir_int: ir-int { ++ rockchip,pins = <1 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ keys { ++ pwr_key: pwr-key { ++ rockchip,pins = <3 RK_PC7 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ pwm1 { ++ pwm1_pin_pull_down: pwm1-pin-pull-down { ++ rockchip,pins = <0 RK_PD6 2 &pcfg_pull_down>; ++ }; ++ }; ++ ++ pwm2 { ++ pwm2_pin_pull_up: pwm2-pin-pull-up { ++ rockchip,pins = <1 RK_PB4 2 &pcfg_pull_up>; ++ }; ++ }; ++ ++ sdio-pwrseq { ++ wifi_enable_h: wifi-enable-h { ++ rockchip,pins = <2 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ usb { ++ host_vbus_drv: host-vbus-drv { ++ rockchip,pins = <3 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ ++ otg_vbus_drv: otg-vbus-drv { ++ rockchip,pins = <3 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++}; ++ ++&sdio { ++ mmc-pwrseq = <&sdio_pwrseq>; ++ cap-sd-highspeed; ++ cap-sdio-irq; ++ keep-power-in-suspend; ++ non-removable; ++ no-sd; ++}; ++ ++&sdmmc { ++ cap-sd-highspeed; ++ keep-power-in-suspend; ++ no-sdio; ++}; ++ ++&tsadc { ++ rockchip,grf = <&grf>; ++ rockchip,hw-tshut-mode = <0>; ++ rockchip,hw-tshut-polarity = <1>; ++ rockchip,hw-tshut-temp = <120000>; ++ status = "okay"; ++}; ++ ++&u2phy0 { ++ status = "okay"; ++}; ++ ++&u2phy1 { ++ status = "okay"; ++}; ++ ++&uart1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart11_xfer &uart11_rts &uart11_cts>; ++}; ++ ++&uart2 { ++ status = "okay"; ++}; ++ ++&usb_host0_ehci { ++ status = "okay"; ++}; ++ ++&usb_host0_ohci { ++ status = "okay"; ++}; ++ ++&usb_host1_ehci { ++ status = "okay"; ++}; ++ ++&usb_host1_ohci { ++ status = "okay"; ++}; ++ ++&usb_host2_ehci { ++ status = "okay"; ++}; ++ ++&usb_host2_ohci { ++ status = "okay"; ++}; ++ ++&usb_otg { ++ status = "okay"; ++}; ++ ++&vop { ++ assigned-clocks = <&cru DCLK_VOP>; ++ assigned-clock-parents = <&cru SCLK_HDMI_PHY>; ++ status = "okay"; ++}; ++ ++&vop_mmu { ++ status = "okay"; ++}; ++ ++&wdt { ++ status = "okay"; ++}; diff --git a/patch/kernel/rk322x-current/02-linux-0004-dtsi-adjust-nand-pinctrls.patch b/patch/kernel/rk322x-current/02-linux-0004-dtsi-adjust-nand-pinctrls.patch index f342f63b7..a6ea7e3d4 100644 --- a/patch/kernel/rk322x-current/02-linux-0004-dtsi-adjust-nand-pinctrls.patch +++ b/patch/kernel/rk322x-current/02-linux-0004-dtsi-adjust-nand-pinctrls.patch @@ -1,91 +1,92 @@ diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi -index b2fcf0e75..25051c03f 100644 +index be46697e1..b2a0246fb 100644 --- a/arch/arm/boot/dts/rk322x.dtsi +++ b/arch/arm/boot/dts/rk322x.dtsi -@@ -1149,51 +1149,71 @@ +@@ -843,6 +843,22 @@ + status = "disabled"; + }; - flash_cs0: flash-cs0 { - rockchip,pins = -- <2 RK_PA6 1 &pcfg_pull_none>; -+ <2 RK_PA6 RK_FUNC_1 &pcfg_pull_up>; - }; - - flash_cs1: flash-cs1 { - rockchip,pins = -- <0 RK_PC7 1 &pcfg_pull_none>; -+ <0 RK_PC7 RK_FUNC_1 &pcfg_pull_up>; -+ }; ++ nfc: nand-controller@ff4b0000 { ++ compatible = "rockchip,rk3228_nfc"; ++ reg = <0x30030000 0x4000>; ++ interrupts = ; ++ clocks = <&cru SCLK_NANDC>, <&cru HCLK_NANDC>; ++ clock-names = "nfc", "ahb"; ++ assigned-clocks = <&cru SCLK_NANDC>; ++ assigned-clock-rates = <150000000>; + -+ flash_cs2: flash-cs2 { -+ rockchip,pins = -+ <1 RK_PC6 RK_FUNC_1 &pcfg_pull_up>; -+ }; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&flash_cs0 &flash_rdy &flash_ale &flash_cle ++ &flash_wrn &flash_rdn &flash_bus8>; ++ status = "disabled"; + -+ flash_cs3: flash-cs3 { -+ rockchip,pins = -+ <1 RK_PC7 RK_FUNC_1 &pcfg_pull_up>; - }; - - flash_rdy: flash-rdy { - rockchip,pins = -- <2 RK_PA4 1 &pcfg_pull_none>; -+ <2 RK_PA4 RK_FUNC_1 &pcfg_pull_up>; - }; - - flash_ale: flash-ale { - rockchip,pins = -- <2 RK_PA0 1 &pcfg_pull_none>; -+ <2 RK_PA0 RK_FUNC_1 &pcfg_pull_down>; - }; - - flash_cle: flash-cle { - rockchip,pins = -- <2 RK_PA1 1 &pcfg_pull_none>; -+ <2 RK_PA1 RK_FUNC_1 &pcfg_pull_down>; - }; - - flash_wrn: flash-wrn { -- rockchip,pins = -- <2 RK_PA2 1 &pcfg_pull_none>; -+ rockchip,pins = -+ <2 RK_PA2 RK_FUNC_1 &pcfg_pull_up>; - }; - - flash_rdn: flash-rdn { - rockchip,pins = -- <2 RK_PA3 1 &pcfg_pull_none>; -+ <2 RK_PA3 RK_FUNC_1 &pcfg_pull_up>; - }; - - flash_bus8: flash-bus8 { -- rockchip,pins = <1 RK_PD0 1 &pcfg_pull_none>, -- <1 RK_PD1 1 &pcfg_pull_none>, -- <1 RK_PD2 1 &pcfg_pull_none>, -- <1 RK_PD3 1 &pcfg_pull_none>, -- <1 RK_PD4 1 &pcfg_pull_none>, -- <1 RK_PD5 1 &pcfg_pull_none>, -- <1 RK_PD6 1 &pcfg_pull_none>, -- <1 RK_PD7 1 &pcfg_pull_none>; -+ rockchip,pins = <1 RK_PD0 RK_FUNC_1 &pcfg_pull_up>, -+ <1 RK_PD1 RK_FUNC_1 &pcfg_pull_up>, -+ <1 RK_PD2 RK_FUNC_1 &pcfg_pull_up>, -+ <1 RK_PD3 RK_FUNC_1 &pcfg_pull_up>, -+ <1 RK_PD4 RK_FUNC_1 &pcfg_pull_up>, -+ <1 RK_PD5 RK_FUNC_1 &pcfg_pull_up>, -+ <1 RK_PD6 RK_FUNC_1 &pcfg_pull_up>, -+ <1 RK_PD7 RK_FUNC_1 &pcfg_pull_up>; - }; -+ -+ flash_dqs: flash-dqs { -+ rockchip,pins = <2 RK_PA7 RK_FUNC_1 &pcfg_pull_up>; -+ }; -+ -+ flash_wp: flash-wp { -+ rockchip,pins = <2 RK_PA5 RK_FUNC_1 &pcfg_pull_down>; -+ }; ++ }; + + usb_otg: usb@30040000 { + compatible = "rockchip,rk3228-usb", "rockchip,rk3066-usb", + "snps,dwc2"; +@@ -1105,6 +1121,65 @@ + }; }; ++ flash { ++ ++ flash_cs0: flash-cs0 { ++ rockchip,pins = <2 RK_PA6 1 &pcfg_pull_up>; ++ }; ++ ++ flash_cs1: flash-cs1 { ++ rockchip,pins = <0 RK_PC7 1 &pcfg_pull_up>; ++ }; ++ ++ flash_cs2: flash-cs2 { ++ rockchip,pins = <1 RK_PC6 1 &pcfg_pull_up>; ++ }; ++ ++ flash_cs3: flash-cs3 { ++ rockchip,pins = <1 RK_PC7 1 &pcfg_pull_up>; ++ }; ++ ++ flash_rdy: flash-rdy { ++ rockchip,pins = <2 RK_PA4 1 &pcfg_pull_up>; ++ }; ++ ++ flash_ale: flash-ale { ++ rockchip,pins = <2 RK_PA0 1 &pcfg_pull_down>; ++ }; ++ ++ flash_cle: flash-cle { ++ rockchip,pins = <2 RK_PA1 1 &pcfg_pull_down>; ++ }; ++ ++ flash_wrn: flash-wrn { ++ rockchip,pins = <2 RK_PA2 1 &pcfg_pull_up>; ++ }; ++ ++ flash_rdn: flash-rdn { ++ rockchip,pins = <2 RK_PA3 1 &pcfg_pull_up>; ++ }; ++ ++ flash_bus8: flash-bus8 { ++ rockchip,pins = <1 RK_PD0 1 &pcfg_pull_up>, ++ <1 RK_PD1 1 &pcfg_pull_up>, ++ <1 RK_PD2 1 &pcfg_pull_up>, ++ <1 RK_PD3 1 &pcfg_pull_up>, ++ <1 RK_PD4 1 &pcfg_pull_up>, ++ <1 RK_PD5 1 &pcfg_pull_up>, ++ <1 RK_PD6 1 &pcfg_pull_up>, ++ <1 RK_PD7 1 &pcfg_pull_up>; ++ }; ++ ++ flash_dqs: flash-dqs { ++ rockchip,pins = <2 RK_PA7 1 &pcfg_pull_up>; ++ }; ++ ++ flash_wp: flash-wp { ++ rockchip,pins = <2 RK_PA5 1 &pcfg_pull_down>; ++ }; ++ ++ }; + gmac { rgmii_pins: rgmii-pins { diff --git a/patch/kernel/rk322x-current/02-linux-0005-drm-plane-overlay.patch b/patch/kernel/rk322x-current/02-linux-0005-drm-plane-overlay.patch new file mode 100644 index 000000000..15319a894 --- /dev/null +++ b/patch/kernel/rk322x-current/02-linux-0005-drm-plane-overlay.patch @@ -0,0 +1,66 @@ +diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +index 73d24c6bbf05..d4ac6e161ef2 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c ++++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +@@ -614,6 +614,44 @@ static const struct vop_common rk3288_common = { + .dsp_background = VOP_REG(RK3288_DSP_BG, 0xffffffff, 0), + }; + ++static const struct vop_win_phy rk3228_win0_data = { ++ .scl = &rk3288_win_full_scl, ++ .data_formats = formats_win_full, ++ .nformats = ARRAY_SIZE(formats_win_full), ++ .enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0), ++ .format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1), ++ .rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12), ++ .act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0), ++ .dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0), ++ .dsp_st = VOP_REG(RK3288_WIN0_DSP_ST, 0x1fff1fff, 0), ++ .yrgb_mst = VOP_REG(RK3288_WIN0_YRGB_MST, 0xffffffff, 0), ++ .uv_mst = VOP_REG(RK3288_WIN0_CBR_MST, 0xffffffff, 0), ++ .yrgb_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 0), ++ .uv_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 16), ++ .src_alpha_ctl = VOP_REG(RK3288_WIN0_SRC_ALPHA_CTRL, 0xff, 0), ++ .dst_alpha_ctl = VOP_REG(RK3288_WIN0_DST_ALPHA_CTRL, 0xff, 0), ++ .channel = VOP_REG(RK3288_WIN0_CTRL2, 0xff, 0), ++}; ++ ++static const struct vop_win_phy rk3228_win1_data = { ++ .scl = &rk3288_win_full_scl, ++ .data_formats = formats_win_lite, ++ .nformats = ARRAY_SIZE(formats_win_lite), ++ .enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0), ++ .format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1), ++ .rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12), ++ .act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0), ++ .dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0), ++ .dsp_st = VOP_REG(RK3288_WIN0_DSP_ST, 0x1fff1fff, 0), ++ .yrgb_mst = VOP_REG(RK3288_WIN0_YRGB_MST, 0xffffffff, 0), ++ .uv_mst = VOP_REG(RK3288_WIN0_CBR_MST, 0xffffffff, 0), ++ .yrgb_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 0), ++ .uv_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 16), ++ .src_alpha_ctl = VOP_REG(RK3288_WIN0_SRC_ALPHA_CTRL, 0xff, 0), ++ .dst_alpha_ctl = VOP_REG(RK3288_WIN0_DST_ALPHA_CTRL, 0xff, 0), ++ .channel = VOP_REG(RK3288_WIN0_CTRL2, 0xff, 0), ++}; ++ + /* + * Note: rk3288 has a dedicated 'cursor' window, however, that window requires + * special support to get alpha blending working. For now, just use overlay +@@ -864,10 +902,10 @@ static const struct vop_data rk3399_vop_lit = { + }; + + static const struct vop_win_data rk3228_vop_win_data[] = { +- { .base = 0x00, .phy = &rk3288_win01_data, ++ { .base = 0x00, .phy = &rk3228_win0_data, + .type = DRM_PLANE_TYPE_PRIMARY }, +- { .base = 0x40, .phy = &rk3288_win01_data, +- .type = DRM_PLANE_TYPE_CURSOR }, ++ { .base = 0x40, .phy = &rk3228_win1_data, ++ .type = DRM_PLANE_TYPE_OVERLAY }, + }; + + static const struct vop_data rk3228_vop = { +-- +2.17.1 + diff --git a/patch/kernel/rk322x-current/board-rk322x-box.patch b/patch/kernel/rk322x-current/board-rk322x-box.patch index 2151c9d54..2b92f90c3 100644 --- a/patch/kernel/rk322x-current/board-rk322x-box.patch +++ b/patch/kernel/rk322x-current/board-rk322x-box.patch @@ -3,7 +3,7 @@ new file mode 100644 index 000000000..24590f864 --- /dev/null +++ b/arch/arm/boot/dts/rk322x-box.dts -@@ -0,0 +1,239 @@ +@@ -0,0 +1,235 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +/dts-v1/; @@ -53,10 +53,6 @@ index 000000000..24590f864 + rockchip,default-sample-phase = <180>; +}; + -+&nfc { -+ status = "okay"; -+}; -+ +&gmac { + tx_delay = <0x26>; + rx_delay = <0x11>; @@ -141,18 +137,18 @@ index 000000000..24590f864 + */ + sdmmc { + sdmmc_clk: sdmmc-clk { -+ rockchip,pins = <1 16 RK_FUNC_1 &pcfg_pull_down>; ++ rockchip,pins = <1 16 1 &pcfg_pull_down>; + }; + + sdmmc_cmd: sdmmc-cmd { -+ rockchip,pins = <1 15 RK_FUNC_1 &pcfg_pull_up>; ++ rockchip,pins = <1 15 1 &pcfg_pull_up>; + }; + + sdmmc_bus4: sdmmc-bus4 { -+ rockchip,pins = <1 18 RK_FUNC_1 &pcfg_pull_up>, -+ <1 19 RK_FUNC_1 &pcfg_pull_up>, -+ <1 20 RK_FUNC_1 &pcfg_pull_up>, -+ <1 21 RK_FUNC_1 &pcfg_pull_up>; ++ rockchip,pins = <1 18 1 &pcfg_pull_up>, ++ <1 19 1 &pcfg_pull_up>, ++ <1 20 1 &pcfg_pull_up>, ++ <1 21 1 &pcfg_pull_up>; + }; + }; + @@ -162,18 +158,18 @@ index 000000000..24590f864 + */ + sdio { + sdio_clk: sdio-clk { -+ rockchip,pins = <3 0 RK_FUNC_1 &pcfg_pull_down_2ma>; ++ rockchip,pins = <3 0 1 &pcfg_pull_down_2ma>; + }; + + sdio_cmd: sdio-cmd { -+ rockchip,pins = <3 1 RK_FUNC_1 &pcfg_pull_up_2ma>; ++ rockchip,pins = <3 1 1 &pcfg_pull_up_2ma>; + }; + + sdio_bus4: sdio-bus4 { -+ rockchip,pins = <3 2 RK_FUNC_1 &pcfg_pull_up_2ma>, -+ <3 3 RK_FUNC_1 &pcfg_pull_up_2ma>, -+ <3 4 RK_FUNC_1 &pcfg_pull_up_2ma>, -+ <3 5 RK_FUNC_1 &pcfg_pull_up_2ma>; ++ rockchip,pins = <3 2 1 &pcfg_pull_up_2ma>, ++ <3 3 1 &pcfg_pull_up_2ma>, ++ <3 4 1 &pcfg_pull_up_2ma>, ++ <3 5 1 &pcfg_pull_up_2ma>; + }; + }; + @@ -183,30 +179,30 @@ index 000000000..24590f864 + */ + emmc { + emmc_clk: emmc-clk { -+ rockchip,pins = <2 7 RK_FUNC_2 &pcfg_pull_up>; ++ rockchip,pins = <2 7 2 &pcfg_pull_up>; + }; + + emmc_cmd: emmc-cmd { -+ rockchip,pins = <1 22 RK_FUNC_2 &pcfg_pull_up>; ++ rockchip,pins = <1 22 2 &pcfg_pull_up>; + }; + + emmc_bus8: emmc-bus8 { -+ rockchip,pins = <1 24 RK_FUNC_2 &pcfg_pull_up>, -+ <1 25 RK_FUNC_2 &pcfg_pull_up>, -+ <1 26 RK_FUNC_2 &pcfg_pull_up>, -+ <1 27 RK_FUNC_2 &pcfg_pull_up>, -+ <1 28 RK_FUNC_2 &pcfg_pull_up>, -+ <1 29 RK_FUNC_2 &pcfg_pull_up>, -+ <1 30 RK_FUNC_2 &pcfg_pull_up>, -+ <1 31 RK_FUNC_2 &pcfg_pull_up>; ++ rockchip,pins = <1 24 2 &pcfg_pull_up>, ++ <1 25 2 &pcfg_pull_up>, ++ <1 26 2 &pcfg_pull_up>, ++ <1 27 2 &pcfg_pull_up>, ++ <1 28 2 &pcfg_pull_up>, ++ <1 29 2 &pcfg_pull_up>, ++ <1 30 2 &pcfg_pull_up>, ++ <1 31 2 &pcfg_pull_up>; + }; + + emmc_pwr: emmc-pwr { -+ rockchip,pins = <2 RK_PA5 RK_FUNC_2 &pcfg_pull_down>; ++ rockchip,pins = <2 RK_PA5 2 &pcfg_pull_down>; + }; + + emmc_rst: emmc-rst { -+ rockchip,pins = <1 RK_PC7 RK_FUNC_2 &pcfg_pull_up>; ++ rockchip,pins = <1 RK_PC7 2 &pcfg_pull_up>; + }; + + }; diff --git a/patch/kernel/rk322x-current/wifi-4003-fix-sha256_state-clashes.patch b/patch/kernel/rk322x-current/wifi-4003-fix-sha256_state-clashes.patch new file mode 100644 index 000000000..0dce511a1 --- /dev/null +++ b/patch/kernel/rk322x-current/wifi-4003-fix-sha256_state-clashes.patch @@ -0,0 +1,248 @@ +diff --git a/drivers/net/wireless/rtl8189es/include/rtw_security.h b/drivers/net/wireless/rtl8189es/include/rtw_security.h +index 5820a55..3e8e428 100644 +--- a/drivers/net/wireless/rtl8189es/include/rtw_security.h ++++ b/drivers/net/wireless/rtl8189es/include/rtw_security.h +@@ -238,7 +238,7 @@ struct security_priv + #endif /* DBG_SW_SEC_CNT */ + }; + +-struct sha256_state { ++struct rtl_sha256_state { + u64 length; + u32 state[8], curlen; + u8 buf[64]; +diff --git a/drivers/net/wireless/rtl8189es/core/rtw_security.c b/drivers/net/wireless/rtl8189es/core/rtw_security.c +index 8dac771..9b3a1f9 100644 +--- a/drivers/net/wireless/rtl8189es/core/rtw_security.c ++++ b/drivers/net/wireless/rtl8189es/core/rtw_security.c +@@ -2281,7 +2281,7 @@ BIP_exit: + + #ifndef PLATFORM_FREEBSD + /* compress 512-bits */ +-static int sha256_compress(struct sha256_state *md, unsigned char *buf) ++static int sha256_compress(struct rtl_sha256_state *md, unsigned char *buf) + { + u32 S[8], W[64], t0, t1; + u32 t; +@@ -2323,7 +2323,7 @@ static int sha256_compress(struct sha256_state *md, unsigned char *buf) + } + + /* Initialize the hash state */ +-static void sha256_init(struct sha256_state *md) ++static void sha256_init(struct rtl_sha256_state *md) + { + md->curlen = 0; + md->length = 0; +@@ -2344,7 +2344,7 @@ static void sha256_init(struct sha256_state *md) + @param inlen The length of the data (octets) + @return CRYPT_OK if successful + */ +-static int sha256_process(struct sha256_state *md, unsigned char *in, ++static int sha256_process(struct rtl_sha256_state *md, unsigned char *in, + unsigned long inlen) + { + unsigned long n; +@@ -2385,7 +2385,7 @@ static int sha256_process(struct sha256_state *md, unsigned char *in, + @param out [out] The destination of the hash (32 bytes) + @return CRYPT_OK if successful + */ +-static int sha256_done(struct sha256_state *md, unsigned char *out) ++static int sha256_done(struct rtl_sha256_state *md, unsigned char *out) + { + int i; + +@@ -2437,7 +2437,7 @@ static int sha256_done(struct sha256_state *md, unsigned char *out) + static int sha256_vector(size_t num_elem, u8 *addr[], size_t *len, + u8 *mac) + { +- struct sha256_state ctx; ++ struct rtl_sha256_state ctx; + size_t i; + + sha256_init(&ctx); +diff --git a/drivers/net/wireless/rtl8811cu/include/rtw_security.h b/drivers/net/wireless/rtl8811cu/include/rtw_security.h +index ac8432e..5f74fb7 100755 +--- a/drivers/net/wireless/rtl8811cu/include/rtw_security.h ++++ b/drivers/net/wireless/rtl8811cu/include/rtw_security.h +@@ -249,7 +249,7 @@ struct security_priv { + #define SEC_IS_BIP_KEY_INSTALLED(sec) _FALSE + #endif + +-struct sha256_state { ++struct rtl_sha256_state { + u64 length; + u32 state[8], curlen; + u8 buf[64]; +diff --git a/drivers/net/wireless/rtl8811cu/core/rtw_security.c b/drivers/net/wireless/rtl8811cu/core/rtw_security.c +index b537a26..f8c42f4 100755 +--- a/drivers/net/wireless/rtl8811cu/core/rtw_security.c ++++ b/drivers/net/wireless/rtl8811cu/core/rtw_security.c +@@ -2133,7 +2133,7 @@ BIP_exit: + #ifndef PLATFORM_FREEBSD + #if defined(CONFIG_TDLS) + /* compress 512-bits */ +-static int sha256_compress(struct sha256_state *md, unsigned char *buf) ++static int sha256_compress(struct rtl_sha256_state *md, unsigned char *buf) + { + u32 S[8], W[64], t0, t1; + u32 t; +@@ -2181,7 +2181,7 @@ static int sha256_compress(struct sha256_state *md, unsigned char *buf) + } + + /* Initialize the hash state */ +-static void sha256_init(struct sha256_state *md) ++static void sha256_init(struct rtl_sha256_state *md) + { + md->curlen = 0; + md->length = 0; +@@ -2202,7 +2202,7 @@ static void sha256_init(struct sha256_state *md) + @param inlen The length of the data (octets) + @return CRYPT_OK if successful + */ +-static int sha256_process(struct sha256_state *md, unsigned char *in, ++static int sha256_process(struct rtl_sha256_state *md, unsigned char *in, + unsigned long inlen) + { + unsigned long n; +@@ -2243,7 +2243,7 @@ static int sha256_process(struct sha256_state *md, unsigned char *in, + @param out [out] The destination of the hash (32 bytes) + @return CRYPT_OK if successful + */ +-static int sha256_done(struct sha256_state *md, unsigned char *out) ++static int sha256_done(struct rtl_sha256_state *md, unsigned char *out) + { + int i; + +@@ -2293,7 +2293,7 @@ static int sha256_done(struct sha256_state *md, unsigned char *out) + static int sha256_vector(size_t num_elem, u8 *addr[], size_t *len, + u8 *mac) + { +- struct sha256_state ctx; ++ struct rtl_sha256_state ctx; + size_t i; + + sha256_init(&ctx); +diff --git a/drivers/net/wireless/rtl8188eu/include/rtw_security.h b/drivers/net/wireless/rtl8188eu/include/rtw_security.h +index 0adc700..2a9cf9d 100644 +--- a/drivers/net/wireless/rtl8188eu/include/rtw_security.h ++++ b/drivers/net/wireless/rtl8188eu/include/rtw_security.h +@@ -249,7 +249,7 @@ struct security_priv { + #define SEC_IS_BIP_KEY_INSTALLED(sec) _FALSE + #endif + +-struct sha256_state { ++struct rtl_sha256_state { + u64 length; + u32 state[8], curlen; + u8 buf[64]; +diff --git a/drivers/net/wireless/rtl8188eu/core/rtw_security.c b/drivers/net/wireless/rtl8188eu/core/rtw_security.c +index 5807521..0b3eed2 100644 +--- a/drivers/net/wireless/rtl8188eu/core/rtw_security.c ++++ b/drivers/net/wireless/rtl8188eu/core/rtw_security.c +@@ -2133,7 +2133,7 @@ BIP_exit: + #ifndef PLATFORM_FREEBSD + #if defined(CONFIG_TDLS) + /* compress 512-bits */ +-static int sha256_compress(struct sha256_state *md, unsigned char *buf) ++static int sha256_compress(struct rtl_sha256_state *md, unsigned char *buf) + { + u32 S[8], W[64], t0, t1; + u32 t; +@@ -2181,7 +2181,7 @@ static int sha256_compress(struct sha256_state *md, unsigned char *buf) + } + + /* Initialize the hash state */ +-static void sha256_init(struct sha256_state *md) ++static void sha256_init(struct rtl_sha256_state *md) + { + md->curlen = 0; + md->length = 0; +@@ -2202,7 +2202,7 @@ static void sha256_init(struct sha256_state *md) + @param inlen The length of the data (octets) + @return CRYPT_OK if successful + */ +-static int sha256_process(struct sha256_state *md, unsigned char *in, ++static int sha256_process(struct rtl_sha256_state *md, unsigned char *in, + unsigned long inlen) + { + unsigned long n; +@@ -2243,7 +2243,7 @@ static int sha256_process(struct sha256_state *md, unsigned char *in, + @param out [out] The destination of the hash (32 bytes) + @return CRYPT_OK if successful + */ +-static int sha256_done(struct sha256_state *md, unsigned char *out) ++static int sha256_done(struct rtl_sha256_state *md, unsigned char *out) + { + int i; + +@@ -2293,7 +2293,7 @@ static int sha256_done(struct sha256_state *md, unsigned char *out) + static int sha256_vector(size_t num_elem, u8 *addr[], size_t *len, + u8 *mac) + { +- struct sha256_state ctx; ++ struct rtl_sha256_state ctx; + size_t i; + + sha256_init(&ctx); +diff --git a/drivers/net/wireless/rtl88x2bu/include/rtw_security.h b/drivers/net/wireless/rtl88x2bu/include/rtw_security.h +index ac8432e..5f74fb7 100644 +--- a/drivers/net/wireless/rtl88x2bu/include/rtw_security.h ++++ b/drivers/net/wireless/rtl88x2bu/include/rtw_security.h +@@ -249,7 +249,7 @@ struct security_priv { + #define SEC_IS_BIP_KEY_INSTALLED(sec) _FALSE + #endif + +-struct sha256_state { ++struct rtl_sha256_state { + u64 length; + u32 state[8], curlen; + u8 buf[64]; +diff --git a/drivers/net/wireless/rtl88x2bu/core/rtw_security.c b/drivers/net/wireless/rtl88x2bu/core/rtw_security.c +index b537a26..f8c42f4 100644 +--- a/drivers/net/wireless/rtl88x2bu/core/rtw_security.c ++++ b/drivers/net/wireless/rtl88x2bu/core/rtw_security.c +@@ -2133,7 +2133,7 @@ BIP_exit: + #ifndef PLATFORM_FREEBSD + #if defined(CONFIG_TDLS) + /* compress 512-bits */ +-static int sha256_compress(struct sha256_state *md, unsigned char *buf) ++static int sha256_compress(struct rtl_sha256_state *md, unsigned char *buf) + { + u32 S[8], W[64], t0, t1; + u32 t; +@@ -2181,7 +2181,7 @@ static int sha256_compress(struct sha256_state *md, unsigned char *buf) + } + + /* Initialize the hash state */ +-static void sha256_init(struct sha256_state *md) ++static void sha256_init(struct rtl_sha256_state *md) + { + md->curlen = 0; + md->length = 0; +@@ -2202,7 +2202,7 @@ static void sha256_init(struct sha256_state *md) + @param inlen The length of the data (octets) + @return CRYPT_OK if successful + */ +-static int sha256_process(struct sha256_state *md, unsigned char *in, ++static int sha256_process(struct rtl_sha256_state *md, unsigned char *in, + unsigned long inlen) + { + unsigned long n; +@@ -2243,7 +2243,7 @@ static int sha256_process(struct sha256_state *md, unsigned char *in, + @param out [out] The destination of the hash (32 bytes) + @return CRYPT_OK if successful + */ +-static int sha256_done(struct sha256_state *md, unsigned char *out) ++static int sha256_done(struct rtl_sha256_state *md, unsigned char *out) + { + int i; + +@@ -2293,7 +2293,7 @@ static int sha256_done(struct sha256_state *md, unsigned char *out) + static int sha256_vector(size_t num_elem, u8 *addr[], size_t *len, + u8 *mac) + { +- struct sha256_state ctx; ++ struct rtl_sha256_state ctx; + size_t i; + + sha256_init(&ctx); diff --git a/patch/kernel/rk322x-current/wifi-4004-fix-cfg80211-for-5.8.patch b/patch/kernel/rk322x-current/wifi-4004-fix-cfg80211-for-5.8.patch new file mode 100644 index 000000000..587d60460 --- /dev/null +++ b/patch/kernel/rk322x-current/wifi-4004-fix-cfg80211-for-5.8.patch @@ -0,0 +1,236 @@ +diff --git a/drivers/net/wireless/rtl8189es/os_dep/linux/ioctl_cfg80211.c b/drivers/net/wireless/rtl8189es/os_dep/linux/ioctl_cfg80211.c +index d77cc17..32cc240 100644 +--- a/drivers/net/wireless/rtl8189es/os_dep/linux/ioctl_cfg80211.c ++++ b/drivers/net/wireless/rtl8189es/os_dep/linux/ioctl_cfg80211.c +@@ -5567,6 +5567,33 @@ exit: + return ret; + } + ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)) ++ ++static void ++cfg80211_rtw_update_mgmt_frame_registrations(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ struct mgmt_frame_regs *upd) ++{ ++ struct net_device *ndev = wdev_to_ndev(wdev); ++ struct rtw_wdev_priv *pwdev_priv; ++ _adapter *adapter; ++ ++ if (ndev == NULL) ++ return; ++ ++ adapter = (_adapter *)rtw_netdev_priv(ndev); ++ pwdev_priv = adapter_wdev_data(adapter); ++ ++#ifdef CONFIG_DEBUG_CFG80211 ++ RTW_INFO(FUNC_ADPT_FMT" stypes:%x\n", FUNC_ADPT_ARG(adapter), ++ upd->interface_stypes); ++#endif ++ ++ /* not implemented, see bellow */ ++} ++ ++#else ++ + static void cfg80211_rtw_mgmt_frame_register(struct wiphy *wiphy, + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + struct wireless_dev *wdev, +@@ -5611,6 +5638,8 @@ exit: + return; + } + ++#endif ++ + #if defined(CONFIG_TDLS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0)) + static int cfg80211_rtw_tdls_mgmt(struct wiphy *wiphy, + struct net_device *ndev, +@@ -6505,7 +6534,11 @@ static struct cfg80211_ops rtw_cfg80211_ops = { + + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE) + .mgmt_tx = cfg80211_rtw_mgmt_tx, ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)) ++ .update_mgmt_frame_registrations = cfg80211_rtw_update_mgmt_frame_registrations, ++#else + .mgmt_frame_register = cfg80211_rtw_mgmt_frame_register, ++#endif + #elif (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,34) && LINUX_VERSION_CODE<=KERNEL_VERSION(2,6,35)) + .action = cfg80211_rtw_mgmt_tx, + #endif +diff --git a/drivers/net/wireless/rtl8811cu/os_dep/linux/ioctl_cfg80211.c b/drivers/net/wireless/rtl8811cu/os_dep/linux/ioctl_cfg80211.c +index c0df148..9bff924 100755 +--- a/drivers/net/wireless/rtl8811cu/os_dep/linux/ioctl_cfg80211.c ++++ b/drivers/net/wireless/rtl8811cu/os_dep/linux/ioctl_cfg80211.c +@@ -7143,6 +7143,33 @@ exit: + return ret; + } + ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)) ++ ++static void ++cfg80211_rtw_update_mgmt_frame_registrations(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ struct mgmt_frame_regs *upd) ++{ ++ struct net_device *ndev = wdev_to_ndev(wdev); ++ struct rtw_wdev_priv *pwdev_priv; ++ _adapter *adapter; ++ ++ if (ndev == NULL) ++ return; ++ ++ adapter = (_adapter *)rtw_netdev_priv(ndev); ++ pwdev_priv = adapter_wdev_data(adapter); ++ ++#ifdef CONFIG_DEBUG_CFG80211 ++ RTW_INFO(FUNC_ADPT_FMT" stypes:%x\n", FUNC_ADPT_ARG(adapter), ++ upd->interface_stypes); ++#endif ++ ++ /* not implemented, see bellow */ ++} ++ ++#else ++ + static void cfg80211_rtw_mgmt_frame_register(struct wiphy *wiphy, + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + struct wireless_dev *wdev, +@@ -7187,6 +7214,8 @@ exit: + return; + } + ++#endif ++ + #if defined(CONFIG_TDLS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)) + static int cfg80211_rtw_tdls_mgmt(struct wiphy *wiphy, + struct net_device *ndev, +@@ -9457,7 +9486,11 @@ static struct cfg80211_ops rtw_cfg80211_ops = { + + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE) + .mgmt_tx = cfg80211_rtw_mgmt_tx, ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)) ++ .update_mgmt_frame_registrations = cfg80211_rtw_update_mgmt_frame_registrations, ++#else + .mgmt_frame_register = cfg80211_rtw_mgmt_frame_register, ++#endif + #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) && LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) + .action = cfg80211_rtw_mgmt_tx, + #endif +diff --git a/drivers/net/wireless/rtl8188eu/os_dep/linux/ioctl_cfg80211.c b/drivers/net/wireless/rtl8188eu/os_dep/linux/ioctl_cfg80211.c +index 721723e..62fd530 100644 +--- a/drivers/net/wireless/rtl8188eu/os_dep/linux/ioctl_cfg80211.c ++++ b/drivers/net/wireless/rtl8188eu/os_dep/linux/ioctl_cfg80211.c +@@ -7470,6 +7470,33 @@ exit: + return ret; + } + ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)) ++ ++static void ++cfg80211_rtw_update_mgmt_frame_registrations(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ struct mgmt_frame_regs *upd) ++{ ++ struct net_device *ndev = wdev_to_ndev(wdev); ++ struct rtw_wdev_priv *pwdev_priv; ++ _adapter *adapter; ++ ++ if (ndev == NULL) ++ return; ++ ++ adapter = (_adapter *)rtw_netdev_priv(ndev); ++ pwdev_priv = adapter_wdev_data(adapter); ++ ++#ifdef CONFIG_DEBUG_CFG80211 ++ RTW_INFO(FUNC_ADPT_FMT" stypes:%x\n", FUNC_ADPT_ARG(adapter), ++ upd->interface_stypes); ++#endif ++ ++ /* not implemented, see bellow */ ++} ++ ++#else ++ + static void cfg80211_rtw_mgmt_frame_register(struct wiphy *wiphy, + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + struct wireless_dev *wdev, +@@ -7525,6 +7552,8 @@ exit: + return; + } + ++#endif ++ + #if defined(CONFIG_TDLS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)) + static int cfg80211_rtw_tdls_mgmt(struct wiphy *wiphy, + struct net_device *ndev, +@@ -9903,7 +9932,11 @@ static struct cfg80211_ops rtw_cfg80211_ops = { + + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE) + .mgmt_tx = cfg80211_rtw_mgmt_tx, ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)) ++ .update_mgmt_frame_registrations = cfg80211_rtw_update_mgmt_frame_registrations, ++#else + .mgmt_frame_register = cfg80211_rtw_mgmt_frame_register, ++#endif + #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) && LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) + .action = cfg80211_rtw_mgmt_tx, + #endif +diff --git a/drivers/net/wireless/rtl88x2bu/os_dep/linux/ioctl_cfg80211.c b/drivers/net/wireless/rtl88x2bu/os_dep/linux/ioctl_cfg80211.c +index 2fd4e28..b463e55 100755 +--- a/drivers/net/wireless/rtl88x2bu/os_dep/linux/ioctl_cfg80211.c ++++ b/drivers/net/wireless/rtl88x2bu/os_dep/linux/ioctl_cfg80211.c +@@ -7325,6 +7325,33 @@ exit: + return ret; + } + ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)) ++ ++static void ++cfg80211_rtw_update_mgmt_frame_registrations(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ struct mgmt_frame_regs *upd) ++{ ++ struct net_device *ndev = wdev_to_ndev(wdev); ++ struct rtw_wdev_priv *pwdev_priv; ++ _adapter *adapter; ++ ++ if (ndev == NULL) ++ return; ++ ++ adapter = (_adapter *)rtw_netdev_priv(ndev); ++ pwdev_priv = adapter_wdev_data(adapter); ++ ++#ifdef CONFIG_DEBUG_CFG80211 ++ RTW_INFO(FUNC_ADPT_FMT" stypes:%x\n", FUNC_ADPT_ARG(adapter), ++ upd->interface_stypes); ++#endif ++ ++ /* not implemented, see bellow */ ++} ++ ++#else ++ + static void cfg80211_rtw_mgmt_frame_register(struct wiphy *wiphy, + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + struct wireless_dev *wdev, +@@ -7369,6 +7396,8 @@ exit: + return; + } + ++#endif ++ + #if defined(CONFIG_TDLS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)) + static int cfg80211_rtw_tdls_mgmt(struct wiphy *wiphy, + struct net_device *ndev, +@@ -9652,7 +9681,11 @@ static struct cfg80211_ops rtw_cfg80211_ops = { + + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE) + .mgmt_tx = cfg80211_rtw_mgmt_tx, ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)) ++ .update_mgmt_frame_registrations = cfg80211_rtw_update_mgmt_frame_registrations, ++#else + .mgmt_frame_register = cfg80211_rtw_mgmt_frame_register, ++#endif + #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) && LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) + .action = cfg80211_rtw_mgmt_tx, + #endif diff --git a/patch/kernel/rk322x-dev/01-linux-0001-rockchip-from-5.9.patch b/patch/kernel/rk322x-dev/01-linux-0001-rockchip-from-5.9.patch new file mode 100644 index 000000000..d8845599b --- /dev/null +++ b/patch/kernel/rk322x-dev/01-linux-0001-rockchip-from-5.9.patch @@ -0,0 +1,3987 @@ +From df792eba98fd6a729c254623ea28968f642efd1e Mon Sep 17 00:00:00 2001 +From: Tobias Schramm +Date: Thu, 28 May 2020 19:25:50 +0200 +Subject: [PATCH] arm64: dts: rockchip: add fuel gauge to Pinebook Pro dts + +This commit adds cw2015 fuel gauge and battery to the Pinebook Pro dts. + +Signed-off-by: Tobias Schramm +Link: https://lore.kernel.org/r/20200528172550.2324722-2-t.schramm@manjaro.org +Signed-off-by: Heiko Stuebner +(cherry picked from commit c7c4d698cd2882c4d095aeed43bbad6fc990e998) +--- + .../boot/dts/rockchip/rk3399-pinebook-pro.dts | 25 +++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts +index cb0245d2226d..8f5b2df01560 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts +@@ -28,6 +28,13 @@ backlight: edp-backlight { + pwms = <&pwm0 0 740740 0>; + }; + ++ bat: battery { ++ compatible = "simple-battery"; ++ charge-full-design-microamp-hours = <9800000>; ++ voltage-max-design-microvolt = <4350000>; ++ voltage-min-design-microvolt = <3000000>; ++ }; ++ + edp_panel: edp-panel { + compatible = "boe,nv140fhmn49"; + backlight = <&backlight>; +@@ -741,6 +748,24 @@ usbc_dp: endpoint { + }; + }; + }; ++ ++ cw2015@62 { ++ compatible = "cellwise,cw2015"; ++ reg = <0x62>; ++ cellwise,battery-profile = /bits/ 8 < ++ 0x17 0x67 0x80 0x73 0x6E 0x6C 0x6B 0x63 ++ 0x77 0x51 0x5C 0x58 0x50 0x4C 0x48 0x36 ++ 0x15 0x0C 0x0C 0x19 0x5B 0x7D 0x6F 0x69 ++ 0x69 0x5B 0x0C 0x29 0x20 0x40 0x52 0x59 ++ 0x57 0x56 0x54 0x4F 0x3B 0x1F 0x7F 0x17 ++ 0x06 0x1A 0x30 0x5A 0x85 0x93 0x96 0x2D ++ 0x48 0x77 0x9C 0xB3 0x80 0x52 0x94 0xCB ++ 0x2F 0x00 0x64 0xA5 0xB5 0x11 0xF0 0x11 ++ >; ++ cellwise,monitor-interval-ms = <5000>; ++ monitored-battery = <&bat>; ++ power-supplies = <&mains_charger>, <&fusb0>; ++ }; + }; + + &i2s1 { + +From 279f038076d9ccc8a78c938eaf8008ff626ccb10 Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Sun, 14 Jun 2020 14:29:51 +0000 +Subject: [PATCH] arm64: dts: rockchip: set rockpro64 usbc dr_mode as host + +The usb-c port on the rockpro64 does not detect devices reliably when in otg mode. +Setting the mode to "host" allows the port to work reliably. +This aligns with the pinebook-pro configuration. + +Signed-off-by: Peter Geis +Link: https://lore.kernel.org/r/20200614142950.1120694-1-pgwipeout@gmail.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit 75152d66315521a48c4997305f4e01c5f139e160) +--- + arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi +index 6788ab28f89a..3456ee97c288 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi +@@ -795,7 +795,7 @@ &usbdrd3_0 { + + &usbdrd_dwc3_0 { + status = "okay"; +- dr_mode = "otg"; ++ dr_mode = "host"; + }; + + &usbdrd3_1 { + +From f739ccdaa19eac37af51d49e2d56e84b0bf62bfa Mon Sep 17 00:00:00 2001 +From: Johan Jonker +Date: Sun, 24 May 2020 18:06:36 +0200 +Subject: [PATCH] arm64: dts: rockchip: rename label and nodename pinctrl + subnodes that end with gpio + +A test with the command below gives for example this error: + +arch/arm64/boot/dts/rockchip/rk3326-odroid-go2.dt.yaml: +tsadc: tsadc-otp-gpio: +{'phandle': [[90]], 'rockchip,pins': [[0, 6, 0, 123]]} +is not of type 'array' + +'gpio' is a sort of reserved nodename and should not be used +for pinctrl in combination with 'rockchip,pins', so change +nodes that end with 'gpio' to end with 'pin' or 'pins'. + +make ARCH=arm64 dtbs_check +DT_SCHEMA_FILES=~/.local/lib/python3.5/site-packages/ +dtschema/schemas/gpio/gpio.yaml + +Signed-off-by: Johan Jonker +Link: https://lore.kernel.org/r/20200524160636.16547-2-jbx6244@gmail.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit 2bc65fef4fe424f5f8295175f1b42f8b94c6df01) +--- + arch/arm64/boot/dts/rockchip/px30.dtsi | 6 +- + arch/arm64/boot/dts/rockchip/rk3308.dtsi | 6 +- + arch/arm64/boot/dts/rockchip/rk3328-evb.dts | 2 +- + .../arm64/boot/dts/rockchip/rk3328-roc-cc.dts | 2 +- + .../arm64/boot/dts/rockchip/rk3328-rock64.dts | 2 +- + arch/arm64/boot/dts/rockchip/rk3328.dtsi | 24 +++--- + .../boot/dts/rockchip/rk3368-lion-haikou.dts | 2 +- + arch/arm64/boot/dts/rockchip/rk3368.dtsi | 6 +- + .../boot/dts/rockchip/rk3399-firefly.dts | 4 +- + .../boot/dts/rockchip/rk3399-gru-scarlet.dtsi | 2 +- + arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 4 +- + .../boot/dts/rockchip/rk3399-hugsun-x99.dts | 8 +- + .../boot/dts/rockchip/rk3399-leez-p710.dts | 8 +- + .../boot/dts/rockchip/rk3399-pinebook-pro.dts | 74 +++++++++---------- + .../boot/dts/rockchip/rk3399-roc-pc.dtsi | 8 +- + .../boot/dts/rockchip/rk3399-rock-pi-4.dts | 8 +- + .../boot/dts/rockchip/rk3399-rock960.dtsi | 4 +- + .../boot/dts/rockchip/rk3399-rockpro64.dtsi | 8 +- + .../boot/dts/rockchip/rk3399-sapphire.dtsi | 4 +- + arch/arm64/boot/dts/rockchip/rk3399.dtsi | 6 +- + 20 files changed, 94 insertions(+), 94 deletions(-) + +diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi +index a6b8427156d5..e9bb2b97ae55 100644 +--- a/arch/arm64/boot/dts/rockchip/px30.dtsi ++++ b/arch/arm64/boot/dts/rockchip/px30.dtsi +@@ -733,9 +733,9 @@ tsadc: tsadc@ff280000 { + rockchip,grf = <&grf>; + rockchip,hw-tshut-temp = <120000>; + pinctrl-names = "init", "default", "sleep"; +- pinctrl-0 = <&tsadc_otp_gpio>; ++ pinctrl-0 = <&tsadc_otp_pin>; + pinctrl-1 = <&tsadc_otp_out>; +- pinctrl-2 = <&tsadc_otp_gpio>; ++ pinctrl-2 = <&tsadc_otp_pin>; + #thermal-sensor-cells = <1>; + status = "disabled"; + }; +@@ -1373,7 +1373,7 @@ i2c3_xfer: i2c3-xfer { + }; + + tsadc { +- tsadc_otp_gpio: tsadc-otp-gpio { ++ tsadc_otp_pin: tsadc-otp-pin { + rockchip,pins = + <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3308.dtsi b/arch/arm64/boot/dts/rockchip/rk3308.dtsi +index ac7f694079d0..ba1c71568164 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3308.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3308.dtsi +@@ -1629,7 +1629,7 @@ spi2_mosi: spi2-mosi { + }; + + tsadc { +- tsadc_otp_gpio: tsadc-otp-gpio { ++ tsadc_otp_pin: tsadc-otp-pin { + rockchip,pins = + <0 RK_PB2 0 &pcfg_pull_none>; + }; +@@ -1657,7 +1657,7 @@ uart0_rts: uart0-rts { + <2 RK_PA3 1 &pcfg_pull_none>; + }; + +- uart0_rts_gpio: uart0-rts-gpio { ++ uart0_rts_pin: uart0-rts-pin { + rockchip,pins = + <2 RK_PA3 0 &pcfg_pull_none>; + }; +@@ -1730,7 +1730,7 @@ uart4_rts: uart4-rts { + <4 RK_PA7 1 &pcfg_pull_none>; + }; + +- uart4_rts_gpio: uart4-rts-gpio { ++ uart4_rts_pin: uart4-rts-pin { + rockchip,pins = + <4 RK_PA7 0 &pcfg_pull_none>; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3328-evb.dts b/arch/arm64/boot/dts/rockchip/rk3328-evb.dts +index ac29c2744d08..1969dab84138 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3328-evb.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3328-evb.dts +@@ -41,7 +41,7 @@ vcc_sd: sdmmc-regulator { + compatible = "regulator-fixed"; + gpio = <&gpio0 30 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; +- pinctrl-0 = <&sdmmc0m1_gpio>; ++ pinctrl-0 = <&sdmmc0m1_pin>; + regulator-name = "vcc_sd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; +diff --git a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts +index 34db48c274e5..b70ffb1c6a63 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts +@@ -34,7 +34,7 @@ vcc_sd: sdmmc-regulator { + compatible = "regulator-fixed"; + gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; +- pinctrl-0 = <&sdmmc0m1_gpio>; ++ pinctrl-0 = <&sdmmc0m1_pin>; + regulator-boot-on; + regulator-name = "vcc_sd"; + regulator-min-microvolt = <3300000>; +diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts +index 6e09c223ed57..86cfb5c50a94 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts +@@ -25,7 +25,7 @@ vcc_sd: sdmmc-regulator { + compatible = "regulator-fixed"; + gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; +- pinctrl-0 = <&sdmmc0m1_gpio>; ++ pinctrl-0 = <&sdmmc0m1_pin>; + regulator-name = "vcc_sd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; +diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +index d399883d4b75..72e655020560 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +@@ -552,9 +552,9 @@ tsadc: tsadc@ff250000 { + clocks = <&cru SCLK_TSADC>, <&cru PCLK_TSADC>; + clock-names = "tsadc", "apb_pclk"; + pinctrl-names = "init", "default", "sleep"; +- pinctrl-0 = <&otp_gpio>; ++ pinctrl-0 = <&otp_pin>; + pinctrl-1 = <&otp_out>; +- pinctrl-2 = <&otp_gpio>; ++ pinctrl-2 = <&otp_pin>; + resets = <&cru SRST_TSADC>; + reset-names = "tsadc-apb"; + rockchip,grf = <&grf>; +@@ -1154,7 +1154,7 @@ i2c3_xfer: i2c3-xfer { + rockchip,pins = <0 RK_PA5 2 &pcfg_pull_none>, + <0 RK_PA6 2 &pcfg_pull_none>; + }; +- i2c3_gpio: i2c3-gpio { ++ i2c3_pins: i2c3-pins { + rockchip,pins = + <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>, + <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; +@@ -1225,7 +1225,7 @@ pdmm0_fsync_sleep: pdmm0-fsync-sleep { + }; + + tsadc { +- otp_gpio: otp-gpio { ++ otp_pin: otp-pin { + rockchip,pins = <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + +@@ -1248,7 +1248,7 @@ uart0_rts: uart0-rts { + rockchip,pins = <1 RK_PB2 1 &pcfg_pull_none>; + }; + +- uart0_rts_gpio: uart0-rts-gpio { ++ uart0_rts_pin: uart0-rts-pin { + rockchip,pins = <1 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +@@ -1267,7 +1267,7 @@ uart1_rts: uart1-rts { + rockchip,pins = <3 RK_PA5 4 &pcfg_pull_none>; + }; + +- uart1_rts_gpio: uart1-rts-gpio { ++ uart1_rts_pin: uart1-rts-pin { + rockchip,pins = <3 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +@@ -1493,7 +1493,7 @@ sdmmc0m0_pwren: sdmmc0m0-pwren { + rockchip,pins = <2 RK_PA7 1 &pcfg_pull_up_4ma>; + }; + +- sdmmc0m0_gpio: sdmmc0m0-gpio { ++ sdmmc0m0_pin: sdmmc0m0-pin { + rockchip,pins = <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up_4ma>; + }; + }; +@@ -1503,7 +1503,7 @@ sdmmc0m1_pwren: sdmmc0m1-pwren { + rockchip,pins = <0 RK_PD6 3 &pcfg_pull_up_4ma>; + }; + +- sdmmc0m1_gpio: sdmmc0m1-gpio { ++ sdmmc0m1_pin: sdmmc0m1-pin { + rockchip,pins = <0 RK_PD6 RK_FUNC_GPIO &pcfg_pull_up_4ma>; + }; + }; +@@ -1536,7 +1536,7 @@ sdmmc0_bus4: sdmmc0-bus4 { + <1 RK_PA3 1 &pcfg_pull_up_8ma>; + }; + +- sdmmc0_gpio: sdmmc0-gpio { ++ sdmmc0_pins: sdmmc0-pins { + rockchip,pins = + <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up_4ma>, + <1 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up_4ma>, +@@ -1578,7 +1578,7 @@ sdmmc0ext_bus4: sdmmc0ext-bus4 { + <3 RK_PA7 3 &pcfg_pull_up_4ma>; + }; + +- sdmmc0ext_gpio: sdmmc0ext-gpio { ++ sdmmc0ext_pins: sdmmc0ext-pins { + rockchip,pins = + <3 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up_4ma>, + <3 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up_4ma>, +@@ -1623,7 +1623,7 @@ sdmmc1_bus4: sdmmc1-bus4 { + <1 RK_PC1 1 &pcfg_pull_up_8ma>; + }; + +- sdmmc1_gpio: sdmmc1-gpio { ++ sdmmc1_pins: sdmmc1-pins { + rockchip,pins = + <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up_4ma>, + <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up_4ma>, +@@ -1817,7 +1817,7 @@ tsadc_pin { + tsadc_int: tsadc-int { + rockchip,pins = <2 RK_PB5 2 &pcfg_pull_none>; + }; +- tsadc_gpio: tsadc-gpio { ++ tsadc_pin: tsadc-pin { + rockchip,pins = <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3368-lion-haikou.dts b/arch/arm64/boot/dts/rockchip/rk3368-lion-haikou.dts +index cbde279ae81d..dbd2caba322f 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3368-lion-haikou.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3368-lion-haikou.dts +@@ -125,7 +125,7 @@ led_sd_haikou: led-sd-gpio { + }; + + sdmmc { +- sdmmc_cd_gpio: sdmmc-cd-gpio { ++ sdmmc_cd_pin: sdmmc-cd-pin { + rockchip,pins = + <2 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3368.dtsi b/arch/arm64/boot/dts/rockchip/rk3368.dtsi +index 1ebb0eef42da..5d25a9d04051 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3368.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3368.dtsi +@@ -483,9 +483,9 @@ tsadc: tsadc@ff280000 { + resets = <&cru SRST_TSADC>; + reset-names = "tsadc-apb"; + pinctrl-names = "init", "default", "sleep"; +- pinctrl-0 = <&otp_gpio>; ++ pinctrl-0 = <&otp_pin>; + pinctrl-1 = <&otp_out>; +- pinctrl-2 = <&otp_gpio>; ++ pinctrl-2 = <&otp_pin>; + #thermal-sensor-cells = <1>; + rockchip,hw-tshut-temp = <95000>; + status = "disabled"; +@@ -1145,7 +1145,7 @@ spi2_tx: spi2-tx { + }; + + tsadc { +- otp_gpio: otp-gpio { ++ otp_pin: otp-pin { + rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts b/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts +index 20b5599f5e78..6db18808b9c5 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts +@@ -589,11 +589,11 @@ pcie_3g_drv: pcie-3g-drv { + }; + + pmic { +- vsel1_gpio: vsel1-gpio { ++ vsel1_pin: vsel1-pin { + rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_down>; + }; + +- vsel2_gpio: vsel2-gpio { ++ vsel2_pin: vsel2-pin { + rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru-scarlet.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru-scarlet.dtsi +index 4373ed732af7..60cd1c18cd4e 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-gru-scarlet.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399-gru-scarlet.dtsi +@@ -499,7 +499,7 @@ &i2s0_8ch_bus { + }; + + /* there is no external pull up, so need to set this pin pull up */ +-&sdmmc_cd_gpio { ++&sdmmc_cd_pin { + rockchip,pins = <1 RK_PB3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi +index 2f3997740068..32dcaf210085 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi +@@ -516,7 +516,7 @@ &sdmmc { + * configured as SDMMC and not JTAG. + */ + pinctrl-names = "default"; +- pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_cd_gpio ++ pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_cd_pin + &sdmmc_bus4>; + + bus-width = <4>; +@@ -767,7 +767,7 @@ sdmmc_cd: sdmmc-cd { + }; + + /* This is where we actually hook up CD; has external pull */ +- sdmmc_cd_gpio: sdmmc-cd-gpio { ++ sdmmc_cd_pin: sdmmc-cd-pin { + rockchip,pins = <4 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dts b/arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dts +index bf87fa32d3b1..341d074ed996 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dts +@@ -205,7 +205,7 @@ vdd_cpu_b: syr827@40 { + compatible = "silergy,syr827"; + reg = <0x40>; + regulator-compatible = "fan53555-reg"; +- pinctrl-0 = <&vsel1_gpio>; ++ pinctrl-0 = <&vsel1_pin>; + regulator-name = "vdd_cpu_b"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; +@@ -223,7 +223,7 @@ vdd_gpu: syr828@41 { + compatible = "silergy,syr828"; + reg = <0x41>; + regulator-compatible = "fan53555-reg"; +- pinctrl-0 = <&vsel2_gpio>; ++ pinctrl-0 = <&vsel2_pin>; + regulator-name = "vdd_gpu"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; +@@ -521,12 +521,12 @@ pmic_int_l: pmic-int-l { + <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + +- vsel1_gpio: vsel1-gpio { ++ vsel1_pin: vsel1-pin { + rockchip,pins = + <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>; + }; + +- vsel2_gpio: vsel2-gpio { ++ vsel2_pin: vsel2-pin { + rockchip,pins = + <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-leez-p710.dts b/arch/arm64/boot/dts/rockchip/rk3399-leez-p710.dts +index 73be38a53796..1fa80ac15464 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-leez-p710.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399-leez-p710.dts +@@ -341,7 +341,7 @@ vdd_cpu_b: regulator@40 { + reg = <0x40>; + fcs,suspend-voltage-selector = <1>; + pinctrl-names = "default"; +- pinctrl-0 = <&vsel1_gpio>; ++ pinctrl-0 = <&vsel1_pin>; + regulator-name = "vdd_cpu_b"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; +@@ -360,7 +360,7 @@ vdd_gpu: regulator@41 { + reg = <0x41>; + fcs,suspend-voltage-selector = <1>; + pinctrl-names = "default"; +- pinctrl-0 = <&vsel2_gpio>; ++ pinctrl-0 = <&vsel2_pin>; + regulator-name = "vdd_gpu"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; +@@ -447,11 +447,11 @@ pmic_int_l: pmic-int-l { + rockchip,pins = <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + +- vsel1_gpio: vsel1-gpio { ++ vsel1_pin: vsel1-pin { + rockchip,pins = <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>; + }; + +- vsel2_gpio: vsel2-gpio { ++ vsel2_pin: vsel2-pin { + rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts +index 8f5b2df01560..06d48338c836 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts +@@ -40,7 +40,7 @@ edp_panel: edp-panel { + backlight = <&backlight>; + enable-gpios = <&gpio1 RK_PA0 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; +- pinctrl-0 = <&panel_en_gpio>; ++ pinctrl-0 = <&panel_en_pin>; + power-supply = <&vcc3v3_panel>; + + ports { +@@ -67,7 +67,7 @@ panel_in_edp: endpoint@0 { + gpio-key-lid { + compatible = "gpio-keys"; + pinctrl-names = "default"; +- pinctrl-0 = <&lidbtn_gpio>; ++ pinctrl-0 = <&lidbtn_pin>; + + lid { + debounce-interval = <20>; +@@ -83,7 +83,7 @@ lid { + gpio-key-power { + compatible = "gpio-keys"; + pinctrl-names = "default"; +- pinctrl-0 = <&pwrbtn_gpio>; ++ pinctrl-0 = <&pwrbtn_pin>; + + power { + debounce-interval = <20>; +@@ -124,7 +124,7 @@ sdio_pwrseq: sdio-pwrseq { + clocks = <&rk808 1>; + clock-names = "ext_clock"; + pinctrl-names = "default"; +- pinctrl-0 = <&wifi_enable_h_gpio>; ++ pinctrl-0 = <&wifi_enable_h_pin>; + post-power-on-delay-ms = <100>; + power-off-delay-us = <500000>; + +@@ -136,7 +136,7 @@ sdio_pwrseq: sdio-pwrseq { + es8316-sound { + compatible = "simple-audio-card"; + pinctrl-names = "default"; +- pinctrl-0 = <&hp_det_gpio>; ++ pinctrl-0 = <&hp_det_pin>; + simple-audio-card,name = "rockchip,es8316-codec"; + simple-audio-card,format = "i2s"; + simple-audio-card,mclk-fs = <256>; +@@ -220,7 +220,7 @@ vcc5v0_usb: pa_5v: vcc5v0-usb-regulator { + enable-active-high; + gpio = <&gpio1 RK_PB5 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; +- pinctrl-0 = <&pwr_5v_gpio>; ++ pinctrl-0 = <&pwr_5v_pin>; + regulator-name = "vcc5v0_usb"; + regulator-always-on; + regulator-min-microvolt = <5000000>; +@@ -277,7 +277,7 @@ vcc3v0_sd: vcc3v0-sd { + enable-active-high; + gpio = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; +- pinctrl-0 = <&sdmmc0_pwr_h_gpio>; ++ pinctrl-0 = <&sdmmc0_pwr_h_pin>; + regulator-name = "vcc3v0_sd"; + regulator-always-on; + regulator-min-microvolt = <3000000>; +@@ -295,7 +295,7 @@ vcc3v3_panel: vcc3v3-panel { + enable-active-high; + gpio = <&gpio1 RK_PC6 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; +- pinctrl-0 = <&lcdvcc_en_gpio>; ++ pinctrl-0 = <&lcdvcc_en_pin>; + regulator-name = "vcc3v3_panel"; + regulator-always-on; + regulator-min-microvolt = <3300000>; +@@ -324,7 +324,7 @@ vcc5v0_otg: vcc5v0-otg { + enable-active-high; + gpio = <&gpio4 RK_PD2 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; +- pinctrl-0 = <&vcc5v0_host_en_gpio>; ++ pinctrl-0 = <&vcc5v0_host_en_pin>; + regulator-name = "vcc5v0_otg"; + regulator-always-on; + regulator-min-microvolt = <5000000>; +@@ -343,7 +343,7 @@ vbus_5vout: vbus_typec: vbus-5vout { + enable-active-high; + gpio = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; +- pinctrl-0 = <&vcc5v0_typec0_en_gpio>; ++ pinctrl-0 = <&vcc5v0_typec0_en_pin>; + regulator-name = "vbus_5vout"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; +@@ -375,7 +375,7 @@ mains_charger: dc-charger { + + /* Also triggered by USB charger */ + pinctrl-names = "default"; +- pinctrl-0 = <&dc_det_gpio>; ++ pinctrl-0 = <&dc_det_pin>; + }; + }; + +@@ -454,7 +454,7 @@ rk808: pmic@1b { + interrupt-parent = <&gpio3>; + interrupts = <10 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; +- pinctrl-0 = <&pmic_int_l_gpio>; ++ pinctrl-0 = <&pmic_int_l_pin>; + rockchip,system-power-controller; + wakeup-source; + +@@ -634,7 +634,7 @@ vdd_cpu_b: regulator@40 { + reg = <0x40>; + fcs,suspend-voltage-selector = <1>; + pinctrl-names = "default"; +- pinctrl-0 = <&vsel1_gpio>; ++ pinctrl-0 = <&vsel1_pin>; + regulator-name = "vdd_cpu_b"; + regulator-always-on; + regulator-boot-on; +@@ -653,7 +653,7 @@ vdd_gpu: regulator@41 { + reg = <0x41>; + fcs,suspend-voltage-selector = <1>; + pinctrl-names = "default"; +- pinctrl-0 = <&vsel2_gpio>; ++ pinctrl-0 = <&vsel2_pin>; + regulator-name = "vdd_gpu"; + regulator-always-on; + regulator-boot-on; +@@ -700,7 +700,7 @@ fusb0: fusb30x@22 { + interrupt-parent = <&gpio1>; + interrupts = ; + pinctrl-names = "default"; +- pinctrl-0 = <&fusb0_int_gpio>; ++ pinctrl-0 = <&fusb0_int_pin>; + vbus-supply = <&vbus_typec>; + + connector { +@@ -770,7 +770,7 @@ cw2015@62 { + + &i2s1 { + pinctrl-names = "default"; +- pinctrl-0 = <&i2s_8ch_mclk_gpio>, <&i2s1_2ch_bus>; ++ pinctrl-0 = <&i2s_8ch_mclk_pin>, <&i2s1_2ch_bus>; + rockchip,capture-channels = <8>; + rockchip,playback-channels = <8>; + status = "okay"; +@@ -802,49 +802,49 @@ &pcie0 { + + &pinctrl { + buttons { +- pwrbtn_gpio: pwrbtn-gpio { ++ pwrbtn_pin: pwrbtn-pin { + rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + +- lidbtn_gpio: lidbtn-gpio { ++ lidbtn_pin: lidbtn-pin { + rockchip,pins = <1 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + dc-charger { +- dc_det_gpio: dc-det-gpio { ++ dc_det_pin: dc-det-pin { + rockchip,pins = <4 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + es8316 { +- hp_det_gpio: hp-det-gpio { ++ hp_det_pin: hp-det-pin { + rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + fusb302x { +- fusb0_int_gpio: fusb0-int-gpio { ++ fusb0_int_pin: fusb0-int-pin { + rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + i2s1 { +- i2s_8ch_mclk_gpio: i2s-8ch-mclk-gpio { ++ i2s_8ch_mclk_pin: i2s-8ch-mclk-pin { + rockchip,pins = <4 RK_PA0 1 &pcfg_pull_none>; + }; + }; + + lcd-panel { +- lcdvcc_en_gpio: lcdvcc-en-gpio { ++ lcdvcc_en_pin: lcdvcc-en-pin { + rockchip,pins = <1 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + +- panel_en_gpio: panel-en-gpio { ++ panel_en_pin: panel-en-pin { + rockchip,pins = <1 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + +- lcd_panel_reset_gpio: lcd-panel-reset-gpio { ++ lcd_panel_reset_pin: lcd-panel-reset-pin { + rockchip,pins = <4 RK_PD6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +@@ -860,58 +860,58 @@ slp_led_pin: slp-led-pin { + }; + + pmic { +- pmic_int_l_gpio: pmic-int-l-gpio { ++ pmic_int_l_pin: pmic-int-l-pin { + rockchip,pins = <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + +- vsel1_gpio: vsel1-gpio { ++ vsel1_pin: vsel1-pin { + rockchip,pins = <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>; + }; + +- vsel2_gpio: vsel2-gpio { ++ vsel2_pin: vsel2-pin { + rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + sdcard { +- sdmmc0_pwr_h_gpio: sdmmc0-pwr-h-gpio { ++ sdmmc0_pwr_h_pin: sdmmc0-pwr-h-pin { + rockchip,pins = <0 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + }; + + sdio-pwrseq { +- wifi_enable_h_gpio: wifi-enable-h-gpio { ++ wifi_enable_h_pin: wifi-enable-h-pin { + rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + usb-typec { +- vcc5v0_typec0_en_gpio: vcc5v0-typec0-en-gpio { ++ vcc5v0_typec0_en_pin: vcc5v0-typec0-en-pin { + rockchip,pins = <1 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + usb2 { +- pwr_5v_gpio: pwr-5v-gpio { ++ pwr_5v_pin: pwr-5v-pin { + rockchip,pins = <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + +- vcc5v0_host_en_gpio: vcc5v0-host-en-gpio { ++ vcc5v0_host_en_pin: vcc5v0-host-en-pin { + rockchip,pins = <4 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + wireless-bluetooth { +- bt_wake_gpio: bt-wake-gpio { ++ bt_wake_pin: bt-wake-pin { + rockchip,pins = <2 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + +- bt_host_wake_gpio: bt-host-wake-gpio { ++ bt_host_wake_pin: bt-host-wake-pin { + rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + +- bt_reset_gpio: bt-reset-gpio { ++ bt_reset_pin: bt-reset-pin { + rockchip,pins = <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +@@ -1059,7 +1059,7 @@ bluetooth { + host-wakeup-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_HIGH>; + max-speed = <1500000>; + pinctrl-names = "default"; +- pinctrl-0 = <&bt_host_wake_gpio &bt_wake_gpio &bt_reset_gpio>; ++ pinctrl-0 = <&bt_host_wake_pin &bt_wake_pin &bt_reset_pin>; + shutdown-gpios = <&gpio0 RK_PB1 GPIO_ACTIVE_HIGH>; + vbat-supply = <&wifi_bat>; + vddio-supply = <&vcc_wl>; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi +index 9f225e9c3d54..59b89d6ccdef 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi +@@ -456,7 +456,7 @@ vdd_cpu_b: regulator@40 { + reg = <0x40>; + fcs,suspend-voltage-selector = <1>; + pinctrl-names = "default"; +- pinctrl-0 = <&vsel1_gpio>; ++ pinctrl-0 = <&vsel1_pin>; + regulator-name = "vdd_cpu_b"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; +@@ -475,7 +475,7 @@ vdd_gpu: regulator@41 { + reg = <0x41>; + fcs,suspend-voltage-selector = <1>; + pinctrl-names = "default"; +- pinctrl-0 = <&vsel2_gpio>; ++ pinctrl-0 = <&vsel2_pin>; + regulator-name = "vdd_gpu"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; +@@ -609,11 +609,11 @@ yellow_led_gpio: yellow_led-gpio { + }; + + pmic { +- vsel1_gpio: vsel1-gpio { ++ vsel1_pin: vsel1-pin { + rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_down>; + }; + +- vsel2_gpio: vsel2-gpio { ++ vsel2_pin: vsel2-pin { + rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts +index 3923ec01ef66..60f98a3e19d8 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts +@@ -390,7 +390,7 @@ vdd_cpu_b: regulator@40 { + reg = <0x40>; + fcs,suspend-voltage-selector = <1>; + pinctrl-names = "default"; +- pinctrl-0 = <&vsel1_gpio>; ++ pinctrl-0 = <&vsel1_pin>; + regulator-name = "vdd_cpu_b"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; +@@ -409,7 +409,7 @@ vdd_gpu: regulator@41 { + reg = <0x41>; + fcs,suspend-voltage-selector = <1>; + pinctrl-names = "default"; +- pinctrl-0 = <&vsel2_gpio>; ++ pinctrl-0 = <&vsel2_pin>; + regulator-name = "vdd_gpu"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; +@@ -532,11 +532,11 @@ pmic_int_l: pmic-int-l { + rockchip,pins = <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + +- vsel1_gpio: vsel1-gpio { ++ vsel1_pin: vsel1-pin { + rockchip,pins = <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>; + }; + +- vsel2_gpio: vsel2-gpio { ++ vsel2_pin: vsel2-pin { + rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi +index ba7c75c9f2a1..5e3ac589bc54 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi +@@ -470,12 +470,12 @@ pmic_int_l: pmic-int-l { + <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + +- vsel1_gpio: vsel1-gpio { ++ vsel1_pin: vsel1-pin { + rockchip,pins = + <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>; + }; + +- vsel2_gpio: vsel2-gpio { ++ vsel2_pin: vsel2-pin { + rockchip,pins = + <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi +index 3456ee97c288..c84cad16118a 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi +@@ -445,7 +445,7 @@ vdd_cpu_b: regulator@40 { + reg = <0x40>; + fcs,suspend-voltage-selector = <1>; + pinctrl-names = "default"; +- pinctrl-0 = <&vsel1_gpio>; ++ pinctrl-0 = <&vsel1_pin>; + regulator-name = "vdd_cpu_b"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; +@@ -464,7 +464,7 @@ vdd_gpu: regulator@41 { + reg = <0x41>; + fcs,suspend-voltage-selector = <1>; + pinctrl-names = "default"; +- pinctrl-0 = <&vsel2_gpio>; ++ pinctrl-0 = <&vsel2_pin>; + regulator-name = "vdd_gpu"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; +@@ -612,11 +612,11 @@ pmic_int_l: pmic-int-l { + rockchip,pins = <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + +- vsel1_gpio: vsel1-gpio { ++ vsel1_pin: vsel1-pin { + rockchip,pins = <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>; + }; + +- vsel2_gpio: vsel2-gpio { ++ vsel2_pin: vsel2-pin { + rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi +index 1bc1579674e5..701a567d7638 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi +@@ -481,11 +481,11 @@ pmic_int_l: pmic-int-l { + <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + +- vsel1_gpio: vsel1-gpio { ++ vsel1_pin: vsel1-pin { + rockchip,pins = <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>; + }; + +- vsel2_gpio: vsel2-gpio { ++ vsel2_pin: vsel2-pin { + rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi +index 2581e9cc7a1d..781b5c2cdb4d 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi +@@ -845,9 +845,9 @@ tsadc: tsadc@ff260000 { + rockchip,grf = <&grf>; + rockchip,hw-tshut-temp = <95000>; + pinctrl-names = "init", "default", "sleep"; +- pinctrl-0 = <&otp_gpio>; ++ pinctrl-0 = <&otp_pin>; + pinctrl-1 = <&otp_out>; +- pinctrl-2 = <&otp_gpio>; ++ pinctrl-2 = <&otp_pin>; + #thermal-sensor-cells = <1>; + status = "disabled"; + }; +@@ -2485,7 +2485,7 @@ test_clkout2: test-clkout2 { + }; + + tsadc { +- otp_gpio: otp-gpio { ++ otp_pin: otp-pin { + rockchip,pins = <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + +From b73a18f9f69f893cb7ae0155770d4eac8cc9874f Mon Sep 17 00:00:00 2001 +From: Johan Jonker +Date: Fri, 22 May 2020 17:46:57 +0200 +Subject: [PATCH] arm64: dts: rockchip: rename and label gpio-led subnodes part + 2 + +Current dts files with 'gpio-led' nodes were manually verified. +In order to automate this process leds-gpio.txt +has been converted to yaml. With this conversion a check +for pattern properties was added. In part 2 rename and label +gpio-led subnodes that passed the regex, but still don't have +the preferred form. Any pin subnode that ends with '-gpio' +in the pinctrl node generates a warning. + +Fix with help of the following rules: + +1: Add nodename in the preferred form. + +2: Always add a label that ends with '_led' to prevent conflicts + with other labels such as 'power' and 'mmc' + +3: If leds need pinctrl add a label that ends with '_led_pin' + also to prevent conflicts with other labels. + +patternProperties: + # The first form is preferred, but fall back to just 'led' + # anywhere in the node name to at least catch some child nodes. + "(^led-[0-9a-f]$|led)": + +make ARCH=arm64 dtbs_check +DT_SCHEMA_FILES=Documentation/devicetree/bindings/leds/ +leds-gpio.yaml + +make ARCH=arm64 dtbs_check +DT_SCHEMA_FILES=~/.local/lib/python3.5/site-packages/dtschema/ +schemas/gpio/gpio.yaml + +Signed-off-by: Johan Jonker +Link: https://lore.kernel.org/r/20200522154657.9472-1-jbx6244@gmail.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit 6dd5e12c0b9bba40b3947ac1a9fd2f992585b5c6) +--- + .../arm64/boot/dts/rockchip/rk3368-lion-haikou.dts | 6 +++--- + arch/arm64/boot/dts/rockchip/rk3368-lion.dtsi | 8 ++++---- + .../boot/dts/rockchip/rk3399-khadas-edge.dtsi | 10 +++++----- + arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi | 6 +++--- + .../arm64/boot/dts/rockchip/rk3399-puma-haikou.dts | 6 +++--- + arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi | 6 +++--- + arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi | 14 +++++++------- + arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi | 10 +++++----- + 8 files changed, 33 insertions(+), 33 deletions(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3368-lion-haikou.dts b/arch/arm64/boot/dts/rockchip/rk3368-lion-haikou.dts +index dbd2caba322f..7fcb1eacea8a 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3368-lion-haikou.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3368-lion-haikou.dts +@@ -25,9 +25,9 @@ eeprom: eeprom@50 { + }; + + leds { +- pinctrl-0 = <&led_pins_module>, <&led_sd_haikou>; ++ pinctrl-0 = <&module_led_pins>, <&sd_card_led_pin>; + +- sd-card-led { ++ sd_card_led: led-3 { + label = "sd_card_led"; + gpios = <&gpio0 RK_PD2 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "mmc0"; +@@ -118,7 +118,7 @@ haikou_pin_hog: haikou-pin-hog { + }; + + leds { +- led_sd_haikou: led-sd-gpio { ++ sd_card_led_pin: sd-card-led-pin { + rockchip,pins = + <0 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3368-lion.dtsi b/arch/arm64/boot/dts/rockchip/rk3368-lion.dtsi +index 216aafd90e7f..24d28be4736c 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3368-lion.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3368-lion.dtsi +@@ -76,16 +76,16 @@ i2c@1 { + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; +- pinctrl-0 = <&led_pins_module>; ++ pinctrl-0 = <&module_led_pins>; + +- module_led1 { ++ module_led1: led-1 { + label = "module_led1"; + gpios = <&gpio2 RK_PB5 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + panic-indicator; + }; + +- module_led2 { ++ module_led2: led-2 { + label = "module_led2"; + gpios = <&gpio3 RK_PA3 GPIO_ACTIVE_HIGH>; + default-state = "off"; +@@ -270,7 +270,7 @@ &i2c2 { + + &pinctrl { + leds { +- led_pins_module: led-module-gpio { ++ module_led_pins: module-led-pins { + rockchip,pins = + <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>, + <3 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-khadas-edge.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-khadas-edge.dtsi +index e87a04477440..e36837c04dc7 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-khadas-edge.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399-khadas-edge.dtsi +@@ -141,15 +141,15 @@ power { + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; +- pinctrl-0 = <&sys_led_gpio>, <&user_led_gpio>; ++ pinctrl-0 = <&sys_led_pin>, <&user_led_pin>; + +- sys-led { ++ sys_led: led-0 { + label = "sys_led"; + linux,default-trigger = "heartbeat"; + gpios = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>; + }; + +- user-led { ++ user_led: led-1 { + label = "user_led"; + default-state = "off"; + gpios = <&gpio4 RK_PD0 GPIO_ACTIVE_HIGH>; +@@ -586,11 +586,11 @@ pwrbtn: pwrbtn { + }; + + leds { +- sys_led_gpio: sys_led-gpio { ++ sys_led_pin: sys-led-pin { + rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + +- user_led_gpio: user_led-gpio { ++ user_led_pin: user-led-pin { + rockchip,pins = <4 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi +index 1d246c2caa3c..76a8b40a93c6 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi +@@ -117,9 +117,9 @@ power { + leds: gpio-leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; +- pinctrl-0 = <&leds_gpio>; ++ pinctrl-0 = <&status_led_pin>; + +- status { ++ status_led: led-0 { + gpios = <&gpio0 RK_PB5 GPIO_ACTIVE_HIGH>; + label = "status_led"; + linux,default-trigger = "heartbeat"; +@@ -520,7 +520,7 @@ fusb0_int: fusb0-int { + }; + + gpio-leds { +- leds_gpio: leds-gpio { ++ status_led_pin: status-led-pin { + rockchip,pins = <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts b/arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts +index d80d6b726820..a8d363568fd6 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts +@@ -15,9 +15,9 @@ chosen { + }; + + leds { +- pinctrl-0 = <&led_pin_module>, <&led_sd_haikou>; ++ pinctrl-0 = <&module_led_pin>, <&sd_card_led_pin>; + +- sd-card-led { ++ sd_card_led: led-1 { + label = "sd_card_led"; + gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "mmc0"; +@@ -179,7 +179,7 @@ haikou_pin_hog: haikou-pin-hog { + }; + + leds { +- led_sd_haikou: led-sd-gpio { ++ sd_card_led_pin: sd-card-led-pin { + rockchip,pins = + <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi +index 72c06abd27ea..4660416c8f38 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi +@@ -11,9 +11,9 @@ / { + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; +- pinctrl-0 = <&led_pin_module>; ++ pinctrl-0 = <&module_led_pin>; + +- module-led { ++ module_led: led-0 { + label = "module_led"; + gpios = <&gpio2 RK_PD1 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; +@@ -450,7 +450,7 @@ i2c8_xfer_a: i2c8-xfer { + }; + + leds { +- led_pin_module: led-module-gpio { ++ module_led_pin: module-led-pin { + rockchip,pins = + <2 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi +index 59b89d6ccdef..b85ec31cd283 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi +@@ -61,23 +61,23 @@ power { + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; +- pinctrl-0 = <&work_led_gpio>, <&diy_led_gpio>, <&yellow_led_gpio>; ++ pinctrl-0 = <&work_led_pin>, <&diy_led_pin>, <&yellow_led_pin>; + +- work-led { ++ work_led: led-0 { + label = "green:work"; + gpios = <&gpio2 RK_PD3 GPIO_ACTIVE_HIGH>; + default-state = "on"; + linux,default-trigger = "heartbeat"; + }; + +- diy-led { ++ diy_led: led-1 { + label = "red:diy"; + gpios = <&gpio0 RK_PB5 GPIO_ACTIVE_HIGH>; + default-state = "off"; + linux,default-trigger = "mmc1"; + }; + +- yellow-led { ++ yellow_led: led-2 { + label = "yellow:yellow-led"; + gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; + default-state = "off"; +@@ -595,15 +595,15 @@ lcd_panel_reset: lcd-panel-reset { + }; + + leds { +- diy_led_gpio: diy_led-gpio { ++ diy_led_pin: diy-led-pin { + rockchip,pins = <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + +- work_led_gpio: work_led-gpio { ++ work_led_pin: work-led-pin { + rockchip,pins = <2 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + +- yellow_led_gpio: yellow_led-gpio { ++ yellow_led_pin: yellow-led-pin { + rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi +index c84cad16118a..6e553ff47534 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi +@@ -39,15 +39,15 @@ power { + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; +- pinctrl-0 = <&work_led_gpio>, <&diy_led_gpio>; ++ pinctrl-0 = <&work_led_pin>, <&diy_led_pin>; + +- work-led { ++ work_led: led-0 { + label = "work"; + default-state = "on"; + gpios = <&gpio0 RK_PB3 GPIO_ACTIVE_HIGH>; + }; + +- diy-led { ++ diy_led: led-1 { + label = "diy"; + default-state = "off"; + gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; +@@ -588,11 +588,11 @@ fusb0_int: fusb0-int { + }; + + leds { +- work_led_gpio: work_led-gpio { ++ work_led_pin: work-led-pin { + rockchip,pins = <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + +- diy_led_gpio: diy_led-gpio { ++ diy_led_pin: diy-led-pin { + rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + +From c40071fd1c70da63fdd7cc308114b34623d7eb91 Mon Sep 17 00:00:00 2001 +From: Johan Jonker +Date: Sun, 24 May 2020 18:06:35 +0200 +Subject: [PATCH] ARM: dts: rockchip: rename label and nodename pinctrl + subnodes that end with gpio + +A test with the command below gives for example this error: + +arch/arm/boot/dts/rk3288-tinker.dt.yaml: tsadc: otp-gpio: +{'phandle': [[54]], 'rockchip,pins': [[0, 10, 0, 118]]} +is not of type 'array' + +'gpio' is a sort of reserved nodename and should not be used +for pinctrl in combination with 'rockchip,pins', so change +nodes that end with 'gpio' to end with 'pin' or 'pins'. + +make ARCH=arm dtbs_check +DT_SCHEMA_FILES=~/.local/lib/python3.5/site-packages/ +dtschema/schemas/gpio/gpio.yaml + +Signed-off-by: Johan Jonker +Link: https://lore.kernel.org/r/20200524160636.16547-1-jbx6244@gmail.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit fff987e7328951f7d6fb2d0545de8635ceafa89f) +--- + arch/arm/boot/dts/rk322x.dtsi | 6 +++--- + arch/arm/boot/dts/rk3288-veyron-jaq.dts | 2 +- + arch/arm/boot/dts/rk3288-veyron-jerry.dts | 2 +- + arch/arm/boot/dts/rk3288-veyron-mighty.dts | 6 +++--- + arch/arm/boot/dts/rk3288-veyron-minnie.dts | 2 +- + arch/arm/boot/dts/rk3288-veyron-pinky.dts | 6 +++--- + arch/arm/boot/dts/rk3288-veyron-sdmmc.dtsi | 2 +- + arch/arm/boot/dts/rk3288-veyron-speedy.dts | 2 +- + arch/arm/boot/dts/rk3288.dtsi | 6 +++--- + arch/arm/boot/dts/rv1108.dtsi | 12 ++++++------ + 10 files changed, 23 insertions(+), 23 deletions(-) + +diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi +index b0fd92befdeb..3236abb0aba9 100644 +--- a/arch/arm/boot/dts/rk322x.dtsi ++++ b/arch/arm/boot/dts/rk322x.dtsi +@@ -520,9 +520,9 @@ tsadc: tsadc@11150000 { + resets = <&cru SRST_TSADC>; + reset-names = "tsadc-apb"; + pinctrl-names = "init", "default", "sleep"; +- pinctrl-0 = <&otp_gpio>; ++ pinctrl-0 = <&otp_pin>; + pinctrl-1 = <&otp_out>; +- pinctrl-2 = <&otp_gpio>; ++ pinctrl-2 = <&otp_pin>; + #thermal-sensor-cells = <0>; + rockchip,hw-tshut-temp = <95000>; + status = "disabled"; +@@ -1111,7 +1111,7 @@ spdif_tx: spdif-tx { + }; + + tsadc { +- otp_gpio: otp-gpio { ++ otp_pin: otp-pin { + rockchip,pins = <0 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + +diff --git a/arch/arm/boot/dts/rk3288-veyron-jaq.dts b/arch/arm/boot/dts/rk3288-veyron-jaq.dts +index 171ba6185b6d..8efba9deae3c 100644 +--- a/arch/arm/boot/dts/rk3288-veyron-jaq.dts ++++ b/arch/arm/boot/dts/rk3288-veyron-jaq.dts +@@ -47,7 +47,7 @@ regulator-state-mem { + &sdmmc { + disable-wp; + pinctrl-names = "default"; +- pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd_disabled &sdmmc_cd_gpio ++ pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd_disabled &sdmmc_cd_pin + &sdmmc_bus4>; + }; + +diff --git a/arch/arm/boot/dts/rk3288-veyron-jerry.dts b/arch/arm/boot/dts/rk3288-veyron-jerry.dts +index 66f00d28801a..2c916c50dda5 100644 +--- a/arch/arm/boot/dts/rk3288-veyron-jerry.dts ++++ b/arch/arm/boot/dts/rk3288-veyron-jerry.dts +@@ -192,7 +192,7 @@ mwifiex: wifi@1 { + &sdmmc { + disable-wp; + pinctrl-names = "default"; +- pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd_disabled &sdmmc_cd_gpio ++ pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd_disabled &sdmmc_cd_pin + &sdmmc_bus4>; + }; + +diff --git a/arch/arm/boot/dts/rk3288-veyron-mighty.dts b/arch/arm/boot/dts/rk3288-veyron-mighty.dts +index 27fbc07476d2..fa695a88f236 100644 +--- a/arch/arm/boot/dts/rk3288-veyron-mighty.dts ++++ b/arch/arm/boot/dts/rk3288-veyron-mighty.dts +@@ -18,8 +18,8 @@ / { + }; + + &sdmmc { +- pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd_disabled &sdmmc_cd_gpio +- &sdmmc_wp_gpio &sdmmc_bus4>; ++ pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd_disabled &sdmmc_cd_pin ++ &sdmmc_wp_pin &sdmmc_bus4>; + wp-gpios = <&gpio7 10 GPIO_ACTIVE_HIGH>; + + /delete-property/ disable-wp; +@@ -27,7 +27,7 @@ &sdmmc { + + &pinctrl { + sdmmc { +- sdmmc_wp_gpio: sdmmc-wp-gpio { ++ sdmmc_wp_pin: sdmmc-wp-pin { + rockchip,pins = <7 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +diff --git a/arch/arm/boot/dts/rk3288-veyron-minnie.dts b/arch/arm/boot/dts/rk3288-veyron-minnie.dts +index 383fad1a88a1..f8b69e0a16a0 100644 +--- a/arch/arm/boot/dts/rk3288-veyron-minnie.dts ++++ b/arch/arm/boot/dts/rk3288-veyron-minnie.dts +@@ -114,7 +114,7 @@ regulator-state-mem { + &sdmmc { + disable-wp; + pinctrl-names = "default"; +- pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd_disabled &sdmmc_cd_gpio ++ pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd_disabled &sdmmc_cd_pin + &sdmmc_bus4>; + }; + +diff --git a/arch/arm/boot/dts/rk3288-veyron-pinky.dts b/arch/arm/boot/dts/rk3288-veyron-pinky.dts +index 71e6629cc208..4e9fdb0f722d 100644 +--- a/arch/arm/boot/dts/rk3288-veyron-pinky.dts ++++ b/arch/arm/boot/dts/rk3288-veyron-pinky.dts +@@ -105,7 +105,7 @@ emmc_reset: emmc-reset { + }; + + sdmmc { +- sdmmc_wp_gpio: sdmmc-wp-gpio { ++ sdmmc_wp_pin: sdmmc-wp-pin { + rockchip,pins = <7 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +@@ -126,8 +126,8 @@ regulator-state-mem { + + &sdmmc { + pinctrl-names = "default"; +- pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd_disabled &sdmmc_cd_gpio +- &sdmmc_wp_gpio &sdmmc_bus4>; ++ pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd_disabled &sdmmc_cd_pin ++ &sdmmc_wp_pin &sdmmc_bus4>; + wp-gpios = <&gpio7 RK_PB2 GPIO_ACTIVE_HIGH>; + }; + +diff --git a/arch/arm/boot/dts/rk3288-veyron-sdmmc.dtsi b/arch/arm/boot/dts/rk3288-veyron-sdmmc.dtsi +index fe950f9863e8..27fb06ce907e 100644 +--- a/arch/arm/boot/dts/rk3288-veyron-sdmmc.dtsi ++++ b/arch/arm/boot/dts/rk3288-veyron-sdmmc.dtsi +@@ -41,7 +41,7 @@ sdmmc_cd_disabled: sdmmc-cd-disabled { + }; + + /* This is where we actually hook up CD */ +- sdmmc_cd_gpio: sdmmc-cd-gpio { ++ sdmmc_cd_pin: sdmmc-cd-pin { + rockchip,pins = <7 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +diff --git a/arch/arm/boot/dts/rk3288-veyron-speedy.dts b/arch/arm/boot/dts/rk3288-veyron-speedy.dts +index e354c61a45e7..4a3ea934d03e 100644 +--- a/arch/arm/boot/dts/rk3288-veyron-speedy.dts ++++ b/arch/arm/boot/dts/rk3288-veyron-speedy.dts +@@ -54,7 +54,7 @@ &rk808 { + &sdmmc { + disable-wp; + pinctrl-names = "default"; +- pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd_disabled &sdmmc_cd_gpio ++ pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd_disabled &sdmmc_cd_pin + &sdmmc_bus4>; + }; + +diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi +index 2e1edd85f04a..84d59469035e 100644 +--- a/arch/arm/boot/dts/rk3288.dtsi ++++ b/arch/arm/boot/dts/rk3288.dtsi +@@ -574,9 +574,9 @@ tsadc: tsadc@ff280000 { + resets = <&cru SRST_TSADC>; + reset-names = "tsadc-apb"; + pinctrl-names = "init", "default", "sleep"; +- pinctrl-0 = <&otp_gpio>; ++ pinctrl-0 = <&otp_pin>; + pinctrl-1 = <&otp_out>; +- pinctrl-2 = <&otp_gpio>; ++ pinctrl-2 = <&otp_pin>; + #thermal-sensor-cells = <1>; + rockchip,grf = <&grf>; + rockchip,hw-tshut-temp = <95000>; +@@ -1929,7 +1929,7 @@ uart4_rts: uart4-rts { + }; + + tsadc { +- otp_gpio: otp-gpio { ++ otp_pin: otp-pin { + rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + +diff --git a/arch/arm/boot/dts/rv1108.dtsi b/arch/arm/boot/dts/rv1108.dtsi +index f9cfe2c80791..a5d130bd0547 100644 +--- a/arch/arm/boot/dts/rv1108.dtsi ++++ b/arch/arm/boot/dts/rv1108.dtsi +@@ -351,9 +351,9 @@ tsadc: tsadc@10370000 { + clocks = <&cru SCLK_TSADC>, <&cru PCLK_TSADC>; + clock-names = "tsadc", "apb_pclk"; + pinctrl-names = "init", "default", "sleep"; +- pinctrl-0 = <&otp_gpio>; ++ pinctrl-0 = <&otp_pin>; + pinctrl-1 = <&otp_out>; +- pinctrl-2 = <&otp_gpio>; ++ pinctrl-2 = <&otp_pin>; + resets = <&cru SRST_TSADC>; + reset-names = "tsadc-apb"; + rockchip,hw-tshut-temp = <120000>; +@@ -728,7 +728,7 @@ i2c2m1_xfer: i2c2m1-xfer { + <0 RK_PC6 3 &pcfg_pull_none>; + }; + +- i2c2m1_gpio: i2c2m1-gpio { ++ i2c2m1_pins: i2c2m1-pins { + rockchip,pins = <0 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>, + <0 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; + }; +@@ -740,7 +740,7 @@ i2c2m05v_xfer: i2c2m05v-xfer { + <1 RK_PD4 2 &pcfg_pull_none>; + }; + +- i2c2m05v_gpio: i2c2m05v-gpio { ++ i2c2m05v_pins: i2c2m05v-pins { + rockchip,pins = <1 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>, + <1 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>; + }; +@@ -867,7 +867,7 @@ otp_out: otp-out { + rockchip,pins = <0 RK_PB7 1 &pcfg_pull_none>; + }; + +- otp_gpio: otp-gpio { ++ otp_pin: otp-pin { + rockchip,pins = <0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +@@ -886,7 +886,7 @@ uart0_rts: uart0-rts { + rockchip,pins = <3 RK_PA3 1 &pcfg_pull_none>; + }; + +- uart0_rts_gpio: uart0-rts-gpio { ++ uart0_rts_pin: uart0-rts-pin { + rockchip,pins = <3 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + +From c07b527960a7909caa8adb15247362f2319f1653 Mon Sep 17 00:00:00 2001 +From: Abhishek Pandit-Subedi +Date: Fri, 12 Jun 2020 13:02:48 -0700 +Subject: [PATCH] ARM: dts: rockchip: Add marvell BT irq config + +Veyron Jaq and Mighty both use the Marvel 8897 WiFi+BT chip. Add wakeup +and pinctrl block to devicetree so the btmrvl driver can correctly +configure the wakeup interrupt. + +Signed-off-by: Abhishek Pandit-Subedi +Reviewed-by: Douglas Anderson +Link: https://lore.kernel.org/r/20200612130219.v2.1.I66864be898aa835ccb66b6cd5220d0b082338a81@changeid +Signed-off-by: Heiko Stuebner +(cherry picked from commit 6c2b99a2e7a073575b4ee91abf7d16470991c1f4) +--- + arch/arm/boot/dts/rk3288-veyron-jaq.dts | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/arch/arm/boot/dts/rk3288-veyron-jaq.dts b/arch/arm/boot/dts/rk3288-veyron-jaq.dts +index 8efba9deae3c..af77ab20586d 100644 +--- a/arch/arm/boot/dts/rk3288-veyron-jaq.dts ++++ b/arch/arm/boot/dts/rk3288-veyron-jaq.dts +@@ -44,6 +44,21 @@ regulator-state-mem { + }; + }; + ++&sdio0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ btmrvl: btmrvl@2 { ++ compatible = "marvell,sd8897-bt"; ++ reg = <2>; ++ interrupt-parent = <&gpio4>; ++ interrupts = ; ++ marvell,wakeup-pin = /bits/ 16 <13>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bt_host_wake_l>; ++ }; ++}; ++ + &sdmmc { + disable-wp; + pinctrl-names = "default"; + +From f0ee8fdc42d8bb5a2cb126df71302324fb23866b Mon Sep 17 00:00:00 2001 +From: Sugar Zhang +Date: Thu, 4 Jun 2020 09:36:38 +0800 +Subject: [PATCH] dmaengine: pl330: Make sure the debug is idle before doing + DMAGO + +According to the datasheet of pl330: + +Example 2-1 Using DMAGO with the debug instruction registers + +1. Create a program for the DMA channel +2. Store the program in a region of system memory +3. Poll the DBGSTATUS Register to ensure that the debug is idle +4. Write to the DBGINST0 Register +5. Write to the DBGINST1 Register +6. Write zero to the DBGCMD Register + +so, we should make sure the debug is idle before step 4/5/6, not +only step 6. if not, there maybe a risk that fail to write DBGINST0/1. + +Signed-off-by: Sugar Zhang +Link: https://lore.kernel.org/r/1591234598-78919-1-git-send-email-sugar.zhang@rock-chips.com +Signed-off-by: Vinod Koul +(cherry picked from commit d12ea5591eddf625b7707c018b72e46e8674c3c2) +--- + drivers/dma/pl330.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index 88b884cbb7c1..6a158eef6b8a 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -885,6 +885,12 @@ static inline void _execute_DBGINSN(struct pl330_thread *thrd, + void __iomem *regs = thrd->dmac->base; + u32 val; + ++ /* If timed out due to halted state-machine */ ++ if (_until_dmac_idle(thrd)) { ++ dev_err(thrd->dmac->ddma.dev, "DMAC halted!\n"); ++ return; ++ } ++ + val = (insn[0] << 16) | (insn[1] << 24); + if (!as_manager) { + val |= (1 << 0); +@@ -895,12 +901,6 @@ static inline void _execute_DBGINSN(struct pl330_thread *thrd, + val = le32_to_cpu(*((__le32 *)&insn[2])); + writel(val, regs + DBGINST1); + +- /* If timed out due to halted state-machine */ +- if (_until_dmac_idle(thrd)) { +- dev_err(thrd->dmac->ddma.dev, "DMAC halted!\n"); +- return; +- } +- + /* Get going */ + writel(0, regs + DBGCMD); + } + +From e5214dd97994bfdb32dcae94e03f18a794c43947 Mon Sep 17 00:00:00 2001 +From: Shunqian Zheng +Date: Fri, 3 Apr 2020 13:15:37 -0300 +Subject: [PATCH] arm64: dts: rockchip: add rx0 mipi-phy for rk3399 + +Designware MIPI D-PHY, used for ISP0 in rk3399. + +Verified with: +make ARCH=arm64 dtbs_check DT_SCHEMA_FILES=Documentation/devicetree/bindings/phy/rockchip-mipi-dphy-rx0.yaml + +Signed-off-by: Shunqian Zheng +Signed-off-by: Jacob Chen +Signed-off-by: Helen Koike +Link: https://lore.kernel.org/r/20200403161538.1375908-9-helen.koike@collabora.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit e4bfde13e323f9ee5f2f38aa5cac0676dd656f8e) +--- + arch/arm64/boot/dts/rockchip/rk3399.dtsi | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi +index 781b5c2cdb4d..f2ef0d8ba54b 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi +@@ -1397,6 +1397,17 @@ io_domains: io-domains { + status = "disabled"; + }; + ++ mipi_dphy_rx0: mipi-dphy-rx0 { ++ compatible = "rockchip,rk3399-mipi-dphy-rx0"; ++ clocks = <&cru SCLK_MIPIDPHY_REF>, ++ <&cru SCLK_DPHY_RX0_CFG>, ++ <&cru PCLK_VIO_GRF>; ++ clock-names = "dphy-ref", "dphy-cfg", "grf"; ++ power-domains = <&power RK3399_PD_VIO>; ++ #phy-cells = <0>; ++ status = "disabled"; ++ }; ++ + u2phy0: usb2-phy@e450 { + compatible = "rockchip,rk3399-usb2phy"; + reg = <0xe450 0x10>; + +From d2266424a494804c6709ea8231fc44e1ca376138 Mon Sep 17 00:00:00 2001 +From: Pierre-Louis Bossart +Date: Tue, 7 Jul 2020 14:06:10 -0500 +Subject: [PATCH] ASoC: codecs: es8316: fix 'defined but not used' warning + +Fix W=1 warning + +sound/soc/codecs/es8316.c:842:36: warning: 'es8316_acpi_match' defined +but not used [-Wunused-const-variable=] + 842 | static const struct acpi_device_id es8316_acpi_match[] = { + | ^~~~~~~~~~~~~~~~~ + +Signed-off-by: Pierre-Louis Bossart +Link: https://lore.kernel.org/r/20200707190612.97799-12-pierre-louis.bossart@linux.intel.com +Signed-off-by: Mark Brown +(cherry picked from commit 07ac670981fc5932ca3799ce7d96431d80afce0e) +--- + sound/soc/codecs/es8316.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c +index 36eef1fb3d18..70af35c5f727 100644 +--- a/sound/soc/codecs/es8316.c ++++ b/sound/soc/codecs/es8316.c +@@ -839,11 +839,13 @@ static const struct of_device_id es8316_of_match[] = { + }; + MODULE_DEVICE_TABLE(of, es8316_of_match); + ++#ifdef CONFIG_ACPI + static const struct acpi_device_id es8316_acpi_match[] = { + {"ESSX8316", 0}, + {}, + }; + MODULE_DEVICE_TABLE(acpi, es8316_acpi_match); ++#endif + + static struct i2c_driver es8316_i2c_driver = { + .driver = { + +From 2a38a809f8b033a5ddae29b81fb1209a897689f5 Mon Sep 17 00:00:00 2001 +From: Vinod Koul +Date: Wed, 8 Jul 2020 18:58:07 +0530 +Subject: [PATCH] phy: rockchip-typec: use correct format for structure + description + +We get warning with W=1 build: +drivers/phy/rockchip/phy-rockchip-typec.c:360: warning: cannot +understand function prototype: 'struct rockchip_usb3phy_port_cfg ' + +The 'struct rockchip_usb3phy_port_cfg ' is commented properly but uses +wrong format, so fix that up + +Link: https://lore.kernel.org/r/20200708132809.265967-4-vkoul@kernel.org +Signed-off-by: Vinod Koul +(cherry picked from commit 72fbf95f36218ec2a901e0eb7c3aa0bea6f1f396) +--- + drivers/phy/rockchip/phy-rockchip-typec.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c b/drivers/phy/rockchip/phy-rockchip-typec.c +index 24563160197f..70a31251b202 100644 +--- a/drivers/phy/rockchip/phy-rockchip-typec.c ++++ b/drivers/phy/rockchip/phy-rockchip-typec.c +@@ -347,7 +347,7 @@ struct usb3phy_reg { + }; + + /** +- * struct rockchip_usb3phy_port_cfg: usb3-phy port configuration. ++ * struct rockchip_usb3phy_port_cfg - usb3-phy port configuration. + * @reg: the base address for usb3-phy config. + * @typec_conn_dir: the register of type-c connector direction. + * @usb3tousb2_en: the register of type-c force usb2 to usb2 enable. + +From 4210b54dbec5ef3259494989feab48ffde364bb2 Mon Sep 17 00:00:00 2001 +From: Sugar Zhang +Date: Mon, 13 Jul 2020 18:26:00 +0800 +Subject: [PATCH] ASoC: rockchip: spdif: Handle clk by pm runtime + +This patch handle the clk by pm runtime mechanism to simplify +the clk management. + +Signed-off-by: Sugar Zhang +Link: https://lore.kernel.org/r/1594635960-67855-1-git-send-email-sugar.zhang@rock-chips.com +Signed-off-by: Mark Brown +(cherry picked from commit f50d67f9eff62f8078fe6e98ede3f4fb1defc361) +--- + sound/soc/rockchip/rockchip_spdif.c | 59 +++++++++-------------------- + 1 file changed, 17 insertions(+), 42 deletions(-) + +diff --git a/sound/soc/rockchip/rockchip_spdif.c b/sound/soc/rockchip/rockchip_spdif.c +index 6635145a26c4..674810851fbc 100644 +--- a/sound/soc/rockchip/rockchip_spdif.c ++++ b/sound/soc/rockchip/rockchip_spdif.c +@@ -306,44 +306,22 @@ static int rk_spdif_probe(struct platform_device *pdev) + return -ENOMEM; + + spdif->hclk = devm_clk_get(&pdev->dev, "hclk"); +- if (IS_ERR(spdif->hclk)) { +- dev_err(&pdev->dev, "Can't retrieve rk_spdif bus clock\n"); ++ if (IS_ERR(spdif->hclk)) + return PTR_ERR(spdif->hclk); +- } +- ret = clk_prepare_enable(spdif->hclk); +- if (ret) { +- dev_err(spdif->dev, "hclock enable failed %d\n", ret); +- return ret; +- } + + spdif->mclk = devm_clk_get(&pdev->dev, "mclk"); +- if (IS_ERR(spdif->mclk)) { +- dev_err(&pdev->dev, "Can't retrieve rk_spdif master clock\n"); +- ret = PTR_ERR(spdif->mclk); +- goto err_disable_hclk; +- } +- +- ret = clk_prepare_enable(spdif->mclk); +- if (ret) { +- dev_err(spdif->dev, "clock enable failed %d\n", ret); +- goto err_disable_clocks; +- } ++ if (IS_ERR(spdif->mclk)) ++ return PTR_ERR(spdif->mclk); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + regs = devm_ioremap_resource(&pdev->dev, res); +- if (IS_ERR(regs)) { +- ret = PTR_ERR(regs); +- goto err_disable_clocks; +- } ++ if (IS_ERR(regs)) ++ return PTR_ERR(regs); + + spdif->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "hclk", regs, + &rk_spdif_regmap_config); +- if (IS_ERR(spdif->regmap)) { +- dev_err(&pdev->dev, +- "Failed to initialise managed register map\n"); +- ret = PTR_ERR(spdif->regmap); +- goto err_disable_clocks; +- } ++ if (IS_ERR(spdif->regmap)) ++ return PTR_ERR(spdif->regmap); + + spdif->playback_dma_data.addr = res->start + SPDIF_SMPDR; + spdif->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; +@@ -352,47 +330,44 @@ static int rk_spdif_probe(struct platform_device *pdev) + spdif->dev = &pdev->dev; + dev_set_drvdata(&pdev->dev, spdif); + +- pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); +- pm_request_idle(&pdev->dev); ++ if (!pm_runtime_enabled(&pdev->dev)) { ++ ret = rk_spdif_runtime_resume(&pdev->dev); ++ if (ret) ++ goto err_pm_runtime; ++ } + + ret = devm_snd_soc_register_component(&pdev->dev, + &rk_spdif_component, + &rk_spdif_dai, 1); + if (ret) { + dev_err(&pdev->dev, "Could not register DAI\n"); +- goto err_pm_runtime; ++ goto err_pm_suspend; + } + + ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); + if (ret) { + dev_err(&pdev->dev, "Could not register PCM\n"); +- goto err_pm_runtime; ++ goto err_pm_suspend; + } + + return 0; + ++err_pm_suspend: ++ if (!pm_runtime_status_suspended(&pdev->dev)) ++ rk_spdif_runtime_suspend(&pdev->dev); + err_pm_runtime: + pm_runtime_disable(&pdev->dev); +-err_disable_clocks: +- clk_disable_unprepare(spdif->mclk); +-err_disable_hclk: +- clk_disable_unprepare(spdif->hclk); + + return ret; + } + + static int rk_spdif_remove(struct platform_device *pdev) + { +- struct rk_spdif_dev *spdif = dev_get_drvdata(&pdev->dev); +- + pm_runtime_disable(&pdev->dev); + if (!pm_runtime_status_suspended(&pdev->dev)) + rk_spdif_runtime_suspend(&pdev->dev); + +- clk_disable_unprepare(spdif->mclk); +- clk_disable_unprepare(spdif->hclk); +- + return 0; + } + + +From 6af0776af231629c2331f81faa2fdb311cf3ed44 Mon Sep 17 00:00:00 2001 +From: Katsuhiro Suzuki +Date: Tue, 14 Jul 2020 16:32:47 +0900 +Subject: [PATCH] ASoC: convert rk3328 codec binding to yaml + +This patch converts Rockchip rk3328 audio codec binding to DT schema. +And adds description about "mclk" clock and fixes some errors in +original example. + +Signed-off-by: Katsuhiro Suzuki +Reviewed-by: Rob Herring +Link: https://lore.kernel.org/r/20200714073247.172859-1-katsuhiro@katsuster.net +Signed-off-by: Mark Brown +(cherry picked from commit 3f6597ad2f9ed8ed89dbd2a9ec0b0c892774f9d2) +--- + .../bindings/sound/rockchip,rk3328-codec.txt | 28 -------- + .../bindings/sound/rockchip,rk3328-codec.yaml | 69 +++++++++++++++++++ + 2 files changed, 69 insertions(+), 28 deletions(-) + delete mode 100644 Documentation/devicetree/bindings/sound/rockchip,rk3328-codec.txt + create mode 100644 Documentation/devicetree/bindings/sound/rockchip,rk3328-codec.yaml + +diff --git a/Documentation/devicetree/bindings/sound/rockchip,rk3328-codec.txt b/Documentation/devicetree/bindings/sound/rockchip,rk3328-codec.txt +deleted file mode 100644 +index 1ecd75d2032a..000000000000 +--- a/Documentation/devicetree/bindings/sound/rockchip,rk3328-codec.txt ++++ /dev/null +@@ -1,28 +0,0 @@ +-* Rockchip Rk3328 internal codec +- +-Required properties: +- +-- compatible: "rockchip,rk3328-codec" +-- reg: physical base address of the controller and length of memory mapped +- region. +-- rockchip,grf: the phandle of the syscon node for GRF register. +-- clocks: a list of phandle + clock-specifer pairs, one for each entry in clock-names. +-- clock-names: should be "pclk". +-- spk-depop-time-ms: speak depop time msec. +- +-Optional properties: +- +-- mute-gpios: GPIO specifier for external line driver control (typically the +- dedicated GPIO_MUTE pin) +- +-Example for rk3328 internal codec: +- +-codec: codec@ff410000 { +- compatible = "rockchip,rk3328-codec"; +- reg = <0x0 0xff410000 0x0 0x1000>; +- rockchip,grf = <&grf>; +- clocks = <&cru PCLK_ACODEC>; +- clock-names = "pclk"; +- mute-gpios = <&grf_gpio 0 GPIO_ACTIVE_LOW>; +- spk-depop-time-ms = 100; +-}; +diff --git a/Documentation/devicetree/bindings/sound/rockchip,rk3328-codec.yaml b/Documentation/devicetree/bindings/sound/rockchip,rk3328-codec.yaml +new file mode 100644 +index 000000000000..5b85ad5e4834 +--- /dev/null ++++ b/Documentation/devicetree/bindings/sound/rockchip,rk3328-codec.yaml +@@ -0,0 +1,69 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/sound/rockchip,rk3328-codec.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Rockchip rk3328 internal codec ++ ++maintainers: ++ - Heiko Stuebner ++ ++properties: ++ compatible: ++ const: rockchip,rk3328-codec ++ ++ reg: ++ maxItems: 1 ++ ++ clocks: ++ items: ++ - description: clock for audio codec ++ - description: clock for I2S master clock ++ ++ clock-names: ++ items: ++ - const: pclk ++ - const: mclk ++ ++ rockchip,grf: ++ $ref: /schemas/types.yaml#/definitions/phandle ++ description: ++ The phandle of the syscon node for the GRF register. ++ ++ spk-depop-time-ms: ++ default: 200 ++ description: ++ Speaker depop time in msec. ++ ++ mute-gpios: ++ maxItems: 1 ++ description: ++ GPIO specifier for external line driver control (typically the ++ dedicated GPIO_MUTE pin) ++ ++ "#sound-dai-cells": ++ const: 0 ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ - clock-names ++ - rockchip,grf ++ - "#sound-dai-cells" ++ ++examples: ++ - | ++ #include ++ #include ++ codec: codec@ff410000 { ++ compatible = "rockchip,rk3328-codec"; ++ reg = <0xff410000 0x1000>; ++ clocks = <&cru PCLK_ACODECPHY>, <&cru SCLK_I2S1>; ++ clock-names = "pclk", "mclk"; ++ rockchip,grf = <&grf>; ++ mute-gpios = <&grf_gpio 0 GPIO_ACTIVE_LOW>; ++ spk-depop-time-ms = <100>; ++ #sound-dai-cells = <0>; ++ }; + +From 6917bb6287536dbdd26511d0ba6e6b82bc0f5d86 Mon Sep 17 00:00:00 2001 +From: Sugar Zhang +Date: Mon, 29 Jun 2020 22:05:42 +0800 +Subject: [PATCH] dmaengine: pl330: Remove the burst limit for quirk + 'NO-FLUSHP' + +There is no reason to limit the performance on the 'NO-FLUSHP' SoCs, +because 'FLUSHP' instruction is broken on these platforms, so remove +the limit to improve the efficiency. + +Signed-off-by: Sugar Zhang +Link: https://lore.kernel.org/r/1593439555-68130-2-git-send-email-sugar.zhang@rock-chips.com +Signed-off-by: Vinod Koul +(cherry picked from commit 05611a93b8ffa3fe7d2eb43dd6c11e37ead5908a) +--- + drivers/dma/pl330.c | 10 ++-------- + 1 file changed, 2 insertions(+), 8 deletions(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index 6a158eef6b8a..7686292bc1db 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -1183,9 +1183,6 @@ static inline int _ldst_peripheral(struct pl330_dmac *pl330, + { + int off = 0; + +- if (pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP) +- cond = BURST; +- + /* + * do FLUSHP at beginning to clear any stale dma requests before the + * first WFP. +@@ -2221,9 +2218,7 @@ static bool pl330_prep_slave_fifo(struct dma_pl330_chan *pch, + + static int fixup_burst_len(int max_burst_len, int quirks) + { +- if (quirks & PL330_QUIRK_BROKEN_NO_FLUSHP) +- return 1; +- else if (max_burst_len > PL330_MAX_BURST) ++ if (max_burst_len > PL330_MAX_BURST) + return PL330_MAX_BURST; + else if (max_burst_len < 1) + return 1; +@@ -3128,8 +3123,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) + pd->dst_addr_widths = PL330_DMA_BUSWIDTHS; + pd->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); + pd->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; +- pd->max_burst = ((pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP) ? +- 1 : PL330_MAX_BURST); ++ pd->max_burst = PL330_MAX_BURST; + + ret = dma_async_device_register(pd); + if (ret) { + +From cb00fa158b947abf47ce2f256139a849b3bc8f2e Mon Sep 17 00:00:00 2001 +From: Sugar Zhang +Date: Mon, 29 Jun 2020 22:05:43 +0800 +Subject: [PATCH] dmaengine: pl330: Improve transfer efficiency for the dregs + +Only the unaligned burst transfers have the dregs. +so, still use BURST transfer with a reduced size +for better performance. + +Signed-off-by: Sugar Zhang +Link: https://lore.kernel.org/r/1593439555-68130-3-git-send-email-sugar.zhang@rock-chips.com +Signed-off-by: Vinod Koul +(cherry picked from commit 3e7f0bd872087bf4653eeee9a83050f91baae907) +--- + drivers/dma/pl330.c | 32 +++++++++++++++++++++----------- + 1 file changed, 21 insertions(+), 11 deletions(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index 7686292bc1db..f1f0176c6c05 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -1228,8 +1228,9 @@ static int _bursts(struct pl330_dmac *pl330, unsigned dry_run, u8 buf[], + } + + /* +- * transfer dregs with single transfers to peripheral, or a reduced size burst +- * for mem-to-mem. ++ * only the unaligned burst transfers have the dregs. ++ * so, still transfer dregs with a reduced size burst ++ * for mem-to-mem, mem-to-dev or dev-to-mem. + */ + static int _dregs(struct pl330_dmac *pl330, unsigned int dry_run, u8 buf[], + const struct _xfer_spec *pxs, int transfer_length) +@@ -1240,22 +1241,31 @@ static int _dregs(struct pl330_dmac *pl330, unsigned int dry_run, u8 buf[], + if (transfer_length == 0) + return off; + ++ /* ++ * dregs_len = (total bytes - BURST_TO_BYTE(bursts, ccr)) / ++ * BRST_SIZE(ccr) ++ * the dregs len must be smaller than burst len, ++ * so, for higher efficiency, we can modify CCR ++ * to use a reduced size burst len for the dregs. ++ */ ++ dregs_ccr = pxs->ccr; ++ dregs_ccr &= ~((0xf << CC_SRCBRSTLEN_SHFT) | ++ (0xf << CC_DSTBRSTLEN_SHFT)); ++ dregs_ccr |= (((transfer_length - 1) & 0xf) << ++ CC_SRCBRSTLEN_SHFT); ++ dregs_ccr |= (((transfer_length - 1) & 0xf) << ++ CC_DSTBRSTLEN_SHFT); ++ + switch (pxs->desc->rqtype) { + case DMA_MEM_TO_DEV: + /* fall through */ + case DMA_DEV_TO_MEM: +- off += _ldst_peripheral(pl330, dry_run, &buf[off], pxs, +- transfer_length, SINGLE); ++ off += _emit_MOV(dry_run, &buf[off], CCR, dregs_ccr); ++ off += _ldst_peripheral(pl330, dry_run, &buf[off], pxs, 1, ++ BURST); + break; + + case DMA_MEM_TO_MEM: +- dregs_ccr = pxs->ccr; +- dregs_ccr &= ~((0xf << CC_SRCBRSTLEN_SHFT) | +- (0xf << CC_DSTBRSTLEN_SHFT)); +- dregs_ccr |= (((transfer_length - 1) & 0xf) << +- CC_SRCBRSTLEN_SHFT); +- dregs_ccr |= (((transfer_length - 1) & 0xf) << +- CC_DSTBRSTLEN_SHFT); + off += _emit_MOV(dry_run, &buf[off], CCR, dregs_ccr); + off += _ldst_memtomem(dry_run, &buf[off], pxs, 1); + break; + +From 73de2b83dab82d5b7ad55360f14b1aa35e55eb8f Mon Sep 17 00:00:00 2001 +From: Sugar Zhang +Date: Mon, 29 Jun 2020 22:05:45 +0800 +Subject: [PATCH] dmaengine: pl330: Add quirk 'arm,pl330-periph-burst' + +This patch adds the qurik to use burst transfers only +for pl330 controller, even for request with a length of 1. + +Although, the correct way should be: if the peripheral request +length is 1, the peripheral should use SINGLE request, and then +notify the dmac using SINGLE mode by src/dst_maxburst with 1. + +For example, on the Rockchip SoCs, all the peripherals can use +SINGLE or BURST request by setting GRF registers. it is possible +that if these peripheral drivers are used only for Rockchip SoCs. +Unfortunately, it's not, such as dw uart, which is used so widely, +and we can't set src/dst_maxburst according to the SoCs' specific +to compatible with all the other SoCs. + +So, for convenience, all the peripherals are set as BURST request +by default on the Rockchip SoCs. even for request with a length of 1. +the current pl330 driver will perform SINGLE transfer if the client's +maxburst is 1, which still should be working according to chapter 2.6.6 +of datasheet which describe how DMAC performs SINGLE transfers for +a BURST request. Unfortunately, it's broken on the Rockchip SoCs, +which support only matching transfers, such as BURST transfer for +BURST request, SINGLE transfer for SINGLE request. + +Finally, we add the quirk to specify pl330 to use burst transfers only. + +Signed-off-by: Sugar Zhang +Link: https://lore.kernel.org/r/1593439555-68130-5-git-send-email-sugar.zhang@rock-chips.com +Signed-off-by: Vinod Koul +(cherry picked from commit 5fb9e3a3423313fe6169d5069e471bfdab6e0b79) +--- + drivers/dma/pl330.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index f1f0176c6c05..3be8d462eab4 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -33,7 +33,8 @@ + #define PL330_MAX_PERI 32 + #define PL330_MAX_BURST 16 + +-#define PL330_QUIRK_BROKEN_NO_FLUSHP BIT(0) ++#define PL330_QUIRK_BROKEN_NO_FLUSHP BIT(0) ++#define PL330_QUIRK_PERIPH_BURST BIT(1) + + enum pl330_cachectrl { + CCTRL0, /* Noncacheable and nonbufferable */ +@@ -509,6 +510,10 @@ static struct pl330_of_quirks { + { + .quirk = "arm,pl330-broken-no-flushp", + .id = PL330_QUIRK_BROKEN_NO_FLUSHP, ++ }, ++ { ++ .quirk = "arm,pl330-periph-burst", ++ .id = PL330_QUIRK_PERIPH_BURST, + } + }; + +@@ -1206,6 +1211,9 @@ static int _bursts(struct pl330_dmac *pl330, unsigned dry_run, u8 buf[], + int off = 0; + enum pl330_cond cond = BRST_LEN(pxs->ccr) > 1 ? BURST : SINGLE; + ++ if (pl330->quirks & PL330_QUIRK_PERIPH_BURST) ++ cond = BURST; ++ + switch (pxs->desc->rqtype) { + case DMA_MEM_TO_DEV: + /* fall through */ + +From e02c5f202e532c3107f055ff4938852675c9effd Mon Sep 17 00:00:00 2001 +From: Lee Jones +Date: Tue, 14 Jul 2020 12:15:34 +0100 +Subject: [PATCH] dmaengine: pl330: Demote obvious misuse of kerneldoc to + standard comment block + +No 'struct' title is provided. Nor are any attribute descriptions. + +Fixes the following W=1 kernel build warning(s): + + drivers/dma/pl330.c:295: warning: cannot understand function prototype: 'struct pl330_reqcfg ' + +Signed-off-by: Lee Jones +Cc: Philipp Zabel +Cc: Jaswinder Singh +Link: https://lore.kernel.org/r/20200714111546.1755231-6-lee.jones@linaro.org +Signed-off-by: Vinod Koul +(cherry picked from commit f9e036df575d8efce6fd469acd9df3148c2adf6e) +--- + drivers/dma/pl330.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index 3be8d462eab4..2c508ee672b9 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -285,7 +285,7 @@ struct pl330_config { + u32 irq_ns; + }; + +-/** ++/* + * Request Configuration. + * The PL330 core does not modify this and uses the last + * working configuration if the request doesn't provide any. + +From 90e0dc93ec0461e912927d1667f31be40a277954 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto +Date: Thu, 9 Jul 2020 10:55:36 +0900 +Subject: [PATCH] ASoC: hdmi-codec: return -ENOTSUPP for digital_mute + +snd_soc_dai_digital_mute() will return -ENOTSUPP if driver doesn't +support mute. +In hdmi-codec case, hdmi_codec_digital_mute() will be used for it, +and each driver has .digital_mute() callback. +hdmi_codec_digital_mute() want to return -ENOTSUPP to follow it. + +Signed-off-by: Kuninori Morimoto +Link: https://lore.kernel.org/r/87fta1xxjc.wl-kuninori.morimoto.gx@renesas.com +Signed-off-by: Mark Brown +(cherry picked from commit e07e49c0d1e3693facf588142c4cbde45904b3f8) +--- + sound/soc/codecs/hdmi-codec.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c +index f005751da2cc..926ab447a96b 100644 +--- a/sound/soc/codecs/hdmi-codec.c ++++ b/sound/soc/codecs/hdmi-codec.c +@@ -566,7 +566,7 @@ static int hdmi_codec_digital_mute(struct snd_soc_dai *dai, int mute) + return hcp->hcd.ops->digital_mute(dai->dev->parent, + hcp->hcd.data, mute); + +- return 0; ++ return -ENOTSUPP; + } + + static const struct snd_soc_dai_ops hdmi_codec_i2s_dai_ops = { + +From f7c70c0be79698095f473dc90a266d98a4a5d12d Mon Sep 17 00:00:00 2001 +From: Johan Jonker +Date: Wed, 15 Jul 2020 09:09:54 +0200 +Subject: [PATCH] arm64: dts: rockchip: remove bus-width from mmc nodes in px30 + dts files + +'bus-width' has been added to px30.dtsi mmc nodes, so now it can be +removed from the dts files that include it. + +Signed-off-by: Johan Jonker +Link: https://lore.kernel.org/r/20200715070954.1992-1-jbx6244@gmail.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit e7e46a1f6b755248058db531b1cff3b0cc580650) +--- + arch/arm64/boot/dts/rockchip/px30-evb.dts | 3 --- + arch/arm64/boot/dts/rockchip/rk3326-odroid-go2.dts | 1 - + 2 files changed, 4 deletions(-) + +diff --git a/arch/arm64/boot/dts/rockchip/px30-evb.dts b/arch/arm64/boot/dts/rockchip/px30-evb.dts +index 0a680257d9c2..5fe905fae9a8 100644 +--- a/arch/arm64/boot/dts/rockchip/px30-evb.dts ++++ b/arch/arm64/boot/dts/rockchip/px30-evb.dts +@@ -145,7 +145,6 @@ &dsi_dphy { + }; + + &emmc { +- bus-width = <8>; + cap-mmc-highspeed; + mmc-hs200-1_8v; + non-removable; +@@ -499,7 +498,6 @@ &saradc { + }; + + &sdmmc { +- bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + card-detect-delay = <800>; +@@ -513,7 +511,6 @@ &sdmmc { + }; + + &sdio { +- bus-width = <4>; + cap-sd-highspeed; + keep-power-in-suspend; + non-removable; +diff --git a/arch/arm64/boot/dts/rockchip/rk3326-odroid-go2.dts b/arch/arm64/boot/dts/rockchip/rk3326-odroid-go2.dts +index b3a8f936578f..35bd6b904b9c 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3326-odroid-go2.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3326-odroid-go2.dts +@@ -445,7 +445,6 @@ &saradc { + }; + + &sdmmc { +- bus-width = <4>; + cap-sd-highspeed; + card-detect-delay = <200>; + cd-gpios = <&gpio0 RK_PA3 GPIO_ACTIVE_LOW>; /*[> CD GPIO <]*/ + +From 3abee17c54e34c806bacab0a257b88ea3d75ab80 Mon Sep 17 00:00:00 2001 +From: Sugar Zhang +Date: Mon, 29 Jun 2020 22:12:11 +0800 +Subject: [PATCH] arm64: dts: rockchip: Add 'arm,pl330-periph-burst' for dmac + +This patch Add the quirk to specify to use burst transfer +for better compatible and higher performance. + +Signed-off-by: Sugar Zhang + +Link: https://lore.kernel.org/r/1593439935-68540-1-git-send-email-sugar.zhang@rock-chips.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit 505af9184ec0a0222bb883486137fac32731e01d) +--- + arch/arm64/boot/dts/rockchip/px30.dtsi | 1 + + arch/arm64/boot/dts/rockchip/rk3308.dtsi | 2 ++ + arch/arm64/boot/dts/rockchip/rk3328.dtsi | 1 + + arch/arm64/boot/dts/rockchip/rk3368.dtsi | 2 ++ + arch/arm64/boot/dts/rockchip/rk3399.dtsi | 2 ++ + 5 files changed, 8 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi +index e9bb2b97ae55..2695ea8cda14 100644 +--- a/arch/arm64/boot/dts/rockchip/px30.dtsi ++++ b/arch/arm64/boot/dts/rockchip/px30.dtsi +@@ -714,6 +714,7 @@ dmac: dmac@ff240000 { + reg = <0x0 0xff240000 0x0 0x4000>; + interrupts = , + ; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMAC>; + clock-names = "apb_pclk"; + #dma-cells = <1>; +diff --git a/arch/arm64/boot/dts/rockchip/rk3308.dtsi b/arch/arm64/boot/dts/rockchip/rk3308.dtsi +index ba1c71568164..e8b754d415d8 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3308.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3308.dtsi +@@ -524,6 +524,7 @@ dmac0: dma-controller@ff2c0000 { + reg = <0x0 0xff2c0000 0x0 0x4000>; + interrupts = , + ; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMAC0>; + clock-names = "apb_pclk"; + #dma-cells = <1>; +@@ -534,6 +535,7 @@ dmac1: dma-controller@ff2d0000 { + reg = <0x0 0xff2d0000 0x0 0x4000>; + interrupts = , + ; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMAC1>; + clock-names = "apb_pclk"; + #dma-cells = <1>; +diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +index 72e655020560..bbdb19a3e85d 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +@@ -153,6 +153,7 @@ dmac: dmac@ff1f0000 { + reg = <0x0 0xff1f0000 0x0 0x4000>; + interrupts = , + ; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMAC>; + clock-names = "apb_pclk"; + #dma-cells = <1>; +diff --git a/arch/arm64/boot/dts/rockchip/rk3368.dtsi b/arch/arm64/boot/dts/rockchip/rk3368.dtsi +index 5d25a9d04051..3746f23dc3df 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3368.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3368.dtsi +@@ -149,6 +149,7 @@ dmac_peri: dma-controller@ff250000 { + ; + #dma-cells = <1>; + arm,pl330-broken-no-flushp; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMAC_PERI>; + clock-names = "apb_pclk"; + }; +@@ -160,6 +161,7 @@ dmac_bus: dma-controller@ff600000 { + ; + #dma-cells = <1>; + arm,pl330-broken-no-flushp; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMAC_BUS>; + clock-names = "apb_pclk"; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi +index f2ef0d8ba54b..ada724b12f01 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi +@@ -209,6 +209,7 @@ dmac_bus: dma-controller@ff6d0000 { + interrupts = , + ; + #dma-cells = <1>; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMAC0_PERILP>; + clock-names = "apb_pclk"; + }; +@@ -219,6 +220,7 @@ dmac_peri: dma-controller@ff6e0000 { + interrupts = , + ; + #dma-cells = <1>; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMAC1_PERILP>; + clock-names = "apb_pclk"; + }; + +From 932b4a4d3d1ea833e2ac81c122879e4671ee2429 Mon Sep 17 00:00:00 2001 +From: Sugar Zhang +Date: Mon, 29 Jun 2020 22:10:57 +0800 +Subject: [PATCH] ARM: dts: rockchip: Add 'arm,pl330-periph-burst' for dmac + +This patch Add the quirk to specify to use burst transfer +for better compatible and higher performance. + +Signed-off-by: Sugar Zhang + +Link: https://lore.kernel.org/r/1593439866-68459-1-git-send-email-sugar.zhang@rock-chips.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit fb082df317823463eaf09ac88de19fb3319e4f58) +--- + arch/arm/boot/dts/rk3036.dtsi | 1 + + arch/arm/boot/dts/rk322x.dtsi | 1 + + arch/arm/boot/dts/rk3288.dtsi | 3 +++ + arch/arm/boot/dts/rk3xxx.dtsi | 3 +++ + arch/arm/boot/dts/rv1108.dtsi | 1 + + 5 files changed, 9 insertions(+) + +diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi +index d9a0c9a29b68..093567022386 100644 +--- a/arch/arm/boot/dts/rk3036.dtsi ++++ b/arch/arm/boot/dts/rk3036.dtsi +@@ -67,6 +67,7 @@ pdma: pdma@20078000 { + ; + #dma-cells = <1>; + arm,pl330-broken-no-flushp; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMAC2>; + clock-names = "apb_pclk"; + }; +diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi +index 3236abb0aba9..48e6e8d44a1a 100644 +--- a/arch/arm/boot/dts/rk322x.dtsi ++++ b/arch/arm/boot/dts/rk322x.dtsi +@@ -107,6 +107,7 @@ pdma: pdma@110f0000 { + interrupts = , + ; + #dma-cells = <1>; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMAC>; + clock-names = "apb_pclk"; + }; +diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi +index 84d59469035e..9fa11b9f4522 100644 +--- a/arch/arm/boot/dts/rk3288.dtsi ++++ b/arch/arm/boot/dts/rk3288.dtsi +@@ -167,6 +167,7 @@ dmac_peri: dma-controller@ff250000 { + ; + #dma-cells = <1>; + arm,pl330-broken-no-flushp; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMAC2>; + clock-names = "apb_pclk"; + }; +@@ -178,6 +179,7 @@ dmac_bus_ns: dma-controller@ff600000 { + ; + #dma-cells = <1>; + arm,pl330-broken-no-flushp; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMAC1>; + clock-names = "apb_pclk"; + status = "disabled"; +@@ -190,6 +192,7 @@ dmac_bus_s: dma-controller@ffb20000 { + ; + #dma-cells = <1>; + arm,pl330-broken-no-flushp; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMAC1>; + clock-names = "apb_pclk"; + }; +diff --git a/arch/arm/boot/dts/rk3xxx.dtsi b/arch/arm/boot/dts/rk3xxx.dtsi +index d929b60517ab..859a7477909f 100644 +--- a/arch/arm/boot/dts/rk3xxx.dtsi ++++ b/arch/arm/boot/dts/rk3xxx.dtsi +@@ -45,6 +45,7 @@ dmac1_s: dma-controller@20018000 { + ; + #dma-cells = <1>; + arm,pl330-broken-no-flushp; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMA1>; + clock-names = "apb_pclk"; + }; +@@ -56,6 +57,7 @@ dmac1_ns: dma-controller@2001c000 { + ; + #dma-cells = <1>; + arm,pl330-broken-no-flushp; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMA1>; + clock-names = "apb_pclk"; + status = "disabled"; +@@ -68,6 +70,7 @@ dmac2: dma-controller@20078000 { + ; + #dma-cells = <1>; + arm,pl330-broken-no-flushp; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMA2>; + clock-names = "apb_pclk"; + }; +diff --git a/arch/arm/boot/dts/rv1108.dtsi b/arch/arm/boot/dts/rv1108.dtsi +index a5d130bd0547..a1a08cb9364e 100644 +--- a/arch/arm/boot/dts/rv1108.dtsi ++++ b/arch/arm/boot/dts/rv1108.dtsi +@@ -97,6 +97,7 @@ pdma: pdma@102a0000 { + interrupts = ; + #dma-cells = <1>; + arm,pl330-broken-no-flushp; ++ arm,pl330-periph-burst; + clocks = <&cru ACLK_DMAC>; + clock-names = "apb_pclk"; + }; + +From ea1abccee16e018a29011224d0e7b5392d818e70 Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Wed, 15 Jul 2020 14:04:12 +0530 +Subject: [PATCH] ARM: dts: rockchip: dalang-carrier: Move i2c nodes into SOM + +I2C nodes and associated slave devices defined in Carrier board +are specific to rk3399pro vmrac SOM. + +So, move them into SOM dtsi. + +Signed-off-by: Jagan Teki +Link: https://lore.kernel.org/r/20200715083418.112003-2-jagan@amarulasolutions.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit c2f343510d99ab53b46bdfeb184cb48f622e6943) +--- + .../dts/rockchip-radxa-dalang-carrier.dtsi | 32 ------------------- + .../dts/rockchip/rk3399pro-vmarc-som.dtsi | 29 +++++++++++++++++ + 2 files changed, 29 insertions(+), 32 deletions(-) + +diff --git a/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi b/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi +index df3712aedf8a..176b53b8e41a 100644 +--- a/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi ++++ b/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi +@@ -17,29 +17,6 @@ &gmac { + status = "okay"; + }; + +-&i2c1 { +- status = "okay"; +- i2c-scl-rising-time-ns = <140>; +- i2c-scl-falling-time-ns = <30>; +-}; +- +-&i2c2 { +- status = "okay"; +- clock-frequency = <400000>; +- +- hym8563: hym8563@51 { +- compatible = "haoyu,hym8563"; +- reg = <0x51>; +- #clock-cells = <0>; +- clock-frequency = <32768>; +- clock-output-names = "hym8563"; +- pinctrl-names = "default"; +- pinctrl-0 = <&hym8563_int>; +- interrupt-parent = <&gpio4>; +- interrupts = <30 IRQ_TYPE_LEVEL_LOW>; +- }; +-}; +- + &pwm0 { + status = "okay"; + }; +@@ -70,12 +47,3 @@ &uart0 { + &uart2 { + status = "okay"; + }; +- +-&pinctrl { +- hym8563 { +- hym8563_int: hym8563-int { +- rockchip,pins = +- <4 RK_PD6 0 &pcfg_pull_up>; +- }; +- }; +-}; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi b/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi +index 0a516334f15f..e11538171e67 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi +@@ -297,6 +297,29 @@ regulator-state-mem { + }; + }; + ++&i2c1 { ++ i2c-scl-falling-time-ns = <30>; ++ i2c-scl-rising-time-ns = <140>; ++ status = "okay"; ++}; ++ ++&i2c2 { ++ clock-frequency = <400000>; ++ status = "okay"; ++ ++ hym8563: hym8563@51 { ++ compatible = "haoyu,hym8563"; ++ reg = <0x51>; ++ #clock-cells = <0>; ++ clock-frequency = <32768>; ++ clock-output-names = "hym8563"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&hym8563_int>; ++ interrupt-parent = <&gpio4>; ++ interrupts = ; ++ }; ++}; ++ + &io_domains { + status = "okay"; + bt656-supply = <&vcca_1v8>; +@@ -324,6 +347,12 @@ &tsadc { + }; + + &pinctrl { ++ hym8563 { ++ hym8563_int: hym8563-int { ++ rockchip,pins = <4 RK_PD6 0 &pcfg_pull_up>; ++ }; ++ }; ++ + pmic { + pmic_int_l: pmic-int-l { + rockchip,pins = + +From 2e13dc44e6d147dad03cc7f4024ec9152f329fa9 Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Wed, 15 Jul 2020 14:04:13 +0530 +Subject: [PATCH] arm64: dts: rk3399pro: vmarc-som: Fix sorting nodes, + properties + +Fix node, properties sorting on RockPI N10 board dts(i) files. + +Signed-off-by: Jagan Teki +Link: https://lore.kernel.org/r/20200715083418.112003-3-jagan@amarulasolutions.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit 3047b384a74090f09b994298eb5c40986275233a) +--- + .../dts/rockchip/rk3399pro-rock-pi-n10.dts | 2 +- + .../dts/rockchip/rk3399pro-vmarc-som.dtsi | 35 +++++++++---------- + 2 files changed, 18 insertions(+), 19 deletions(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3399pro-rock-pi-n10.dts b/arch/arm64/boot/dts/rockchip/rk3399pro-rock-pi-n10.dts +index a1783e7f769a..539f4005386d 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399pro-rock-pi-n10.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399pro-rock-pi-n10.dts +@@ -8,8 +8,8 @@ + /dts-v1/; + #include "rk3399.dtsi" + #include "rk3399-opp.dtsi" +-#include "rk3399pro-vmarc-som.dtsi" + #include ++#include "rk3399pro-vmarc-som.dtsi" + + / { + model = "Radxa ROCK Pi N10"; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi b/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi +index e11538171e67..121a430d6a70 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi +@@ -76,8 +76,8 @@ &gmac { + + &i2c0 { + clock-frequency = <400000>; +- i2c-scl-rising-time-ns = <180>; + i2c-scl-falling-time-ns = <30>; ++ i2c-scl-rising-time-ns = <180>; + status = "okay"; + + rk809: pmic@20 { +@@ -323,8 +323,22 @@ hym8563: hym8563@51 { + &io_domains { + status = "okay"; + bt656-supply = <&vcca_1v8>; +- sdmmc-supply = <&vccio_sd>; + gpio1830-supply = <&vccio_3v0>; ++ sdmmc-supply = <&vccio_sd>; ++}; ++ ++&pinctrl { ++ hym8563 { ++ hym8563_int: hym8563-int { ++ rockchip,pins = <4 RK_PD6 0 &pcfg_pull_up>; ++ }; ++ }; ++ ++ pmic { ++ pmic_int_l: pmic-int-l { ++ rockchip,pins = <1 RK_PC2 0 &pcfg_pull_up>; ++ }; ++ }; + }; + + &pmu_io_domains { +@@ -341,22 +355,7 @@ &sdhci { + }; + + &tsadc { +- status = "okay"; + rockchip,hw-tshut-mode = <1>; + rockchip,hw-tshut-polarity = <1>; +-}; +- +-&pinctrl { +- hym8563 { +- hym8563_int: hym8563-int { +- rockchip,pins = <4 RK_PD6 0 &pcfg_pull_up>; +- }; +- }; +- +- pmic { +- pmic_int_l: pmic-int-l { +- rockchip,pins = +- <1 RK_PC2 0 &pcfg_pull_up>; +- }; +- }; ++ status = "okay"; + }; + +From 4617f4569e155d9512cdfa8defdea925cd30b9e4 Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Wed, 15 Jul 2020 14:04:14 +0530 +Subject: [PATCH] arm64: dts: rk3399pro: vmarc-som: Move supply regulators into + Carrier + +Supply regulators are common across different variants of vmarc SOM's +since the Type C power controller IC is part of the carrier board. + +So, move the supply regulators into carrier board dtsi. + +Signed-off-by: Jagan Teki +Link: https://lore.kernel.org/r/20200715083418.112003-4-jagan@amarulasolutions.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit 4a3ca113c0f3a2ce33e51fc6a48a121b2d707d4f) +--- + .../dts/rockchip-radxa-dalang-carrier.dtsi | 19 +++++++++++++++++++ + .../dts/rockchip/rk3399pro-vmarc-som.dtsi | 19 ------------------- + 2 files changed, 19 insertions(+), 19 deletions(-) + +diff --git a/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi b/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi +index 176b53b8e41a..00b200a62263 100644 +--- a/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi ++++ b/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi +@@ -11,6 +11,25 @@ / { + chosen { + stdout-path = "serial2:1500000n8"; + }; ++ ++ vcc12v_dcin: vcc12v-dcin-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc12v_dcin"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <12000000>; ++ regulator-max-microvolt = <12000000>; ++ }; ++ ++ vcc5v0_sys: vcc5v0-sys-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc5v0_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc12v_dcin>; ++ }; + }; + + &gmac { +diff --git a/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi b/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi +index 121a430d6a70..d8fa8127d9dc 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi +@@ -18,25 +18,6 @@ clkin_gmac: external-gmac-clock { + clock-output-names = "clkin_gmac"; + #clock-cells = <0>; + }; +- +- vcc12v_dcin: vcc12v-dcin-regulator { +- compatible = "regulator-fixed"; +- regulator-name = "vcc12v_dcin"; +- regulator-always-on; +- regulator-boot-on; +- regulator-min-microvolt = <12000000>; +- regulator-max-microvolt = <12000000>; +- }; +- +- vcc5v0_sys: vcc5v0-sys-regulator { +- compatible = "regulator-fixed"; +- regulator-name = "vcc5v0_sys"; +- regulator-always-on; +- regulator-boot-on; +- regulator-min-microvolt = <5000000>; +- regulator-max-microvolt = <5000000>; +- vin-supply = <&vcc12v_dcin>; +- }; + }; + + &cpu_l0 { + +From 772d02fccf2734a12aaaf22398aa70986a2868c7 Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Wed, 15 Jul 2020 14:04:15 +0530 +Subject: [PATCH] arm64: dts: rk3399pro: vmarc-som: Move common properties into + Carrier + +Some of gmac, sdmmc node properties are common across rk3288 and +rk3399pro SOM's so move them into Carrier dtsi. + +Chosen node is specific to rk3399pro configure SBC, so move it into +RockPI N10 dts. + +Signed-off-by: Jagan Teki +Link: https://lore.kernel.org/r/20200715083418.112003-5-jagan@amarulasolutions.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit a66bd94d0eac017e4846658750acaca2937555bb) +--- + .../dts/rockchip-radxa-dalang-carrier.dtsi | 18 ++++++++++++---- + .../dts/rockchip/rk3399pro-rock-pi-n10.dts | 4 ++++ + .../dts/rockchip/rk3399pro-vmarc-som.dtsi | 21 +++++-------------- + 3 files changed, 23 insertions(+), 20 deletions(-) + +diff --git a/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi b/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi +index 00b200a62263..450e5bb5af0b 100644 +--- a/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi ++++ b/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi +@@ -8,8 +8,11 @@ + #include + + / { +- chosen { +- stdout-path = "serial2:1500000n8"; ++ clkin_gmac: external-gmac-clock { ++ compatible = "fixed-clock"; ++ clock-frequency = <125000000>; ++ clock-output-names = "clkin_gmac"; ++ #clock-cells = <0>; + }; + + vcc12v_dcin: vcc12v-dcin-regulator { +@@ -33,6 +36,15 @@ vcc5v0_sys: vcc5v0-sys-regulator { + }; + + &gmac { ++ assigned-clock-parents = <&clkin_gmac>; ++ clock_in_out = "input"; ++ phy-mode = "rgmii"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&rgmii_pins>; ++ snps,reset-active-low; ++ snps,reset-delays-us = <0 10000 50000>; ++ tx_delay = <0x28>; ++ rx_delay = <0x11>; + status = "okay"; + }; + +@@ -48,10 +60,8 @@ &sdmmc { + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; +- cd-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>; + disable-wp; + vqmmc-supply = <&vccio_sd>; +- max-frequency = <150000000>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_bus4>; + status = "okay"; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399pro-rock-pi-n10.dts b/arch/arm64/boot/dts/rockchip/rk3399pro-rock-pi-n10.dts +index 539f4005386d..369de5dc0ebd 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399pro-rock-pi-n10.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399pro-rock-pi-n10.dts +@@ -15,4 +15,8 @@ / { + model = "Radxa ROCK Pi N10"; + compatible = "radxa,rockpi-n10", "vamrs,rk3399pro-vmarc-som", + "rockchip,rk3399pro"; ++ ++ chosen { ++ stdout-path = "serial2:1500000n8"; ++ }; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi b/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi +index d8fa8127d9dc..37ed95d5f7e9 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi +@@ -11,13 +11,6 @@ + + / { + compatible = "vamrs,rk3399pro-vmarc-som", "rockchip,rk3399pro"; +- +- clkin_gmac: external-gmac-clock { +- compatible = "fixed-clock"; +- clock-frequency = <125000000>; +- clock-output-names = "clkin_gmac"; +- #clock-cells = <0>; +- }; + }; + + &cpu_l0 { +@@ -42,17 +35,8 @@ &emmc_phy { + + &gmac { + assigned-clocks = <&cru SCLK_RMII_SRC>; +- assigned-clock-parents = <&clkin_gmac>; +- clock_in_out = "input"; + phy-supply = <&vcc_lan>; +- phy-mode = "rgmii"; +- pinctrl-names = "default"; +- pinctrl-0 = <&rgmii_pins>; + snps,reset-gpio = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; +- snps,reset-active-low; +- snps,reset-delays-us = <0 10000 50000>; +- tx_delay = <0x28>; +- rx_delay = <0x11>; + }; + + &i2c0 { +@@ -335,6 +319,11 @@ &sdhci { + status = "okay"; + }; + ++&sdmmc { ++ cd-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>; ++ max-frequency = <150000000>; ++}; ++ + &tsadc { + rockchip,hw-tshut-mode = <1>; + rockchip,hw-tshut-polarity = <1>; + +From 916191ead33a0ce0baec3a3cadb386c12d9a1b99 Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Wed, 15 Jul 2020 14:04:16 +0530 +Subject: [PATCH] dt-bindings: arm: rockchip: Add Rock Pi N8 binding + +Rock Pi N8 is a Rockchip RK3288 based SBC, which has +- VMARC RK3288 SOM (as per SMARC standard) from Vamrs. +- Compatible carrier board from Radxa. + +VMARC RK3288 SOM need to mount on top of dalang carrier +board for making Rock PI N8 SBC. + +Add dt-bindings for it. + +Signed-off-by: Jagan Teki +Reviewed-by: Rob Herring +Link: https://lore.kernel.org/r/20200715083418.112003-6-jagan@amarulasolutions.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit 09ee4794270f0010c6397163f033f883f5bff1aa) +--- + Documentation/devicetree/bindings/arm/rockchip.yaml | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/Documentation/devicetree/bindings/arm/rockchip.yaml b/Documentation/devicetree/bindings/arm/rockchip.yaml +index d4a4045092df..db2e35796795 100644 +--- a/Documentation/devicetree/bindings/arm/rockchip.yaml ++++ b/Documentation/devicetree/bindings/arm/rockchip.yaml +@@ -435,6 +435,12 @@ properties: + - const: radxa,rockpi4 + - const: rockchip,rk3399 + ++ - description: Radxa ROCK Pi N8 ++ items: ++ - const: radxa,rockpi-n8 ++ - const: vamrs,rk3288-vmarc-som ++ - const: rockchip,rk3288 ++ + - description: Radxa ROCK Pi N10 + items: + - const: radxa,rockpi-n10 + +From 2a5e46160a746adc9a7b9b952e2000060d6da48a Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Wed, 15 Jul 2020 14:04:17 +0530 +Subject: [PATCH] ARM: dts: rockchip: Add VMARC RK3288 SOM initial support + +VMARC RK3288 SOM is a standard SMARC SOM design with +Rockchip RK3288 SoC, which is designed by Vamrs. + +Specification: +- Rockchip RK3288 +- PMIC: RK808 +- eMMC: 16GB/32GB/64GB +- SD slot +- 2xUSB-2.0, 1xUSB3.0 +- USB-C for power supply +- Ethernet +- HDMI, MIPI-DSI/CSI, eDP + +Add initial support for VMARC RK3288 SOM, this would use +with associated carrier board. + +Signed-off-by: Jagan Teki +Link: https://lore.kernel.org/r/20200715083418.112003-7-jagan@amarulasolutions.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit b8c564d4fa76b1314a10585eea8e97b8c621a77a) +--- + arch/arm/boot/dts/rk3288-vmarc-som.dtsi | 270 ++++++++++++++++++++++++ + 1 file changed, 270 insertions(+) + create mode 100644 arch/arm/boot/dts/rk3288-vmarc-som.dtsi + +diff --git a/arch/arm/boot/dts/rk3288-vmarc-som.dtsi b/arch/arm/boot/dts/rk3288-vmarc-som.dtsi +new file mode 100644 +index 000000000000..cd61b6230f0d +--- /dev/null ++++ b/arch/arm/boot/dts/rk3288-vmarc-som.dtsi +@@ -0,0 +1,270 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd ++ * Copyright (c) 2019 Vamrs Limited ++ * Copyright (c) 2019 Amarula Solutions(India) ++ */ ++ ++#include ++#include ++ ++/ { ++ compatible = "vamrs,rk3288-vmarc-som", "rockchip,rk3288"; ++ ++ vccio_flash: vccio-flash-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vccio_flash"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ vin-supply = <&vcc_io>; ++ }; ++}; ++ ++&emmc { ++ bus-width = <8>; ++ cap-mmc-highspeed; ++ disable-wp; ++ non-removable; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_pwr &emmc_bus8>; ++ vmmc-supply = <&vcc_io>; ++ vqmmc-supply = <&vccio_flash>; ++ status = "okay"; ++}; ++ ++&gmac { ++ assigned-clocks = <&cru SCLK_MAC>; ++ phy-supply = <&vcc_io>; ++ snps,reset-gpio = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>; ++}; ++ ++&i2c0 { ++ clock-frequency = <400000>; ++ status = "okay"; ++ ++ rk808: pmic@1b { ++ compatible = "rockchip,rk808"; ++ reg = <0x1b>; ++ interrupt-parent = <&gpio0>; ++ interrupts = ; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_int &global_pwroff>; ++ rockchip,system-power-controller; ++ wakeup-source; ++ #clock-cells = <1>; ++ clock-output-names = "rk808-clkout1", "rk808-clkout2"; ++ ++ vcc1-supply = <&vcc5v0_sys>; ++ vcc2-supply = <&vcc5v0_sys>; ++ vcc3-supply = <&vcc5v0_sys>; ++ vcc4-supply = <&vcc5v0_sys>; ++ vcc6-supply = <&vcc5v0_sys>; ++ vcc7-supply = <&vcc5v0_sys>; ++ vcc8-supply = <&vcc_io>; ++ vcc9-supply = <&vcc_io>; ++ vcc10-supply = <&vcc5v0_sys>; ++ vcc11-supply = <&vcc5v0_sys>; ++ vcc12-supply = <&vcc_io>; ++ vddio-supply = <&vcc_io>; ++ ++ regulators { ++ vdd_cpu: DCDC_REG1 { ++ regulator-name = "vdd_arm"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <1400000>; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_gpu: DCDC_REG2 { ++ regulator-name = "vdd_gpu"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <1250000>; ++ regulator-ramp-delay = <6000>; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_ddr: DCDC_REG3 { ++ regulator-name = "vcc_ddr"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vcc_io: DCDC_REG4 { ++ regulator-name = "vcc_io"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vcc_tp: LDO_REG1 { ++ regulator-name = "vcc_tp"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcca_codec: LDO_REG2 { ++ regulator-name = "vcca_codec"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vdd_10: LDO_REG3 { ++ regulator-name = "vdd_10"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1000000>; ++ regulator-max-microvolt = <1000000>; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1000000>; ++ }; ++ }; ++ ++ vcc_wl: LDO_REG4 { ++ regulator-name = "vcc_wl"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vccio_sd: LDO_REG5 { ++ regulator-name = "vccio_sd"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vdd10_lcd: LDO_REG6 { ++ regulator-name = "vdd10_lcd"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1000000>; ++ regulator-max-microvolt = <1000000>; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_18: LDO_REG7 { ++ regulator-name = "vcc_18"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcc18_lcd: LDO_REG8 { ++ regulator-name = "vcc18_lcd"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_sd: SWITCH_REG1 { ++ regulator-name = "vcc_sd"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_lcd: SWITCH_REG2 { ++ regulator-name = "vcc_lcd"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&io_domains { ++ bb-supply = <&vcc_io>; ++ flash0-supply = <&vccio_flash>; ++ gpio1830-supply = <&vcc_18>; ++ gpio30-supply = <&vcc_io>; ++ sdcard-supply = <&vccio_sd>; ++ status = "okay"; ++}; ++ ++&pinctrl { ++ pcfg_pull_none_drv_8ma: pcfg-pull-none-drv-8ma { ++ drive-strength = <8>; ++ }; ++ ++ pcfg_pull_up_drv_8ma: pcfg-pull-up-drv-8ma { ++ bias-pull-up; ++ drive-strength = <8>; ++ }; ++ ++ pmic { ++ pmic_int: pmic-int { ++ rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ sdmmc { ++ sdmmc_bus4: sdmmc-bus4 { ++ rockchip,pins = ++ <6 RK_PC0 1 &pcfg_pull_up_drv_8ma>, ++ <6 RK_PC1 1 &pcfg_pull_up_drv_8ma>, ++ <6 RK_PC2 1 &pcfg_pull_up_drv_8ma>, ++ <6 RK_PC3 1 &pcfg_pull_up_drv_8ma>; ++ }; ++ ++ sdmmc_clk: sdmmc-clk { ++ rockchip,pins = <6 RK_PC4 1 &pcfg_pull_none_drv_8ma>; ++ }; ++ ++ sdmmc_cmd: sdmmc-cmd { ++ rockchip,pins = <6 RK_PC5 1 &pcfg_pull_up_drv_8ma>; ++ }; ++ }; ++}; + +From 10ff584a4e12d06e7f041b37f806bd6ffac91f94 Mon Sep 17 00:00:00 2001 +From: Michael Trimarchi +Date: Tue, 7 Jul 2020 12:12:14 +0200 +Subject: [PATCH] ARM: dts: rockchip: Fix VBUS on rk3288-vyasa + +Connect the voltage regulator of vbus to the otg connector. +Depending on the current mode this is enabled (in "host" mode") +or disabled (in "peripheral" mode). The regulator must be updated +if the controller is configured in "otg" mode and the status changes +between "host" and "peripheral". + +Signed-off-by: Michael Trimarchi +Link: https://lore.kernel.org/r/20200707101214.2301768-1-michael@amarulasolutions.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit 719646b76a41b8a482f8701825b635e9710ab329) +--- + arch/arm/boot/dts/rk3288-vyasa.dts | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/arch/arm/boot/dts/rk3288-vyasa.dts b/arch/arm/boot/dts/rk3288-vyasa.dts +index 385dd59393e1..1a20854a1317 100644 +--- a/arch/arm/boot/dts/rk3288-vyasa.dts ++++ b/arch/arm/boot/dts/rk3288-vyasa.dts +@@ -99,8 +99,6 @@ vusb1_5v: vusb1-5v { + pinctrl-0 = <&otg_vbus_drv>; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; +- regulator-always-on; +- regulator-boot-on; + vin-supply = <&vsus_5v>; + }; + +@@ -416,6 +414,7 @@ &usb_host1 { + }; + + &usb_otg { ++ vbus-supply = <&vusb1_5v>; + status = "okay"; + }; + + +From 8635890fdcf41e911c4e3dd5213f3ff891513cab Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Mon, 20 Jul 2020 16:28:46 +0530 +Subject: [PATCH] ARM: dts: rockchip: Add usb host0 ohci node for rk3288 + +rk3288 and rk3288w have a usb host0 ohci controller. + +Although rk3288 ohci doesn't actually work on hardware, but +rk3288w ohci can work well. + +So add usb host0 ohci node in rk3288 dtsi and boards +can then enable it if supported. + +Signed-off-by: Jagan Teki +Cc: William Wu +Link: https://lore.kernel.org/r/20200720105846.367776-1-jagan@amarulasolutions.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit 82540defdd9cfc491f564ffb8d01911966636bc7) +--- + arch/arm/boot/dts/rk3288.dtsi | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi +index 9fa11b9f4522..68d5a58cfe88 100644 +--- a/arch/arm/boot/dts/rk3288.dtsi ++++ b/arch/arm/boot/dts/rk3288.dtsi +@@ -616,7 +616,16 @@ usb_host0_ehci: usb@ff500000 { + status = "disabled"; + }; + +- /* NOTE: ohci@ff520000 doesn't actually work on hardware */ ++ /* NOTE: doesn't work on RK3288, but was fixed on RK3288W */ ++ usb_host0_ohci: usb@ff520000 { ++ compatible = "generic-ohci"; ++ reg = <0x0 0xff520000 0x0 0x100>; ++ interrupts = ; ++ clocks = <&cru HCLK_USBHOST0>; ++ phys = <&usbphy1>; ++ phy-names = "usb"; ++ status = "disabled"; ++ }; + + usb_host1: usb@ff540000 { + compatible = "rockchip,rk3288-usb", "rockchip,rk3066-usb", + +From cb343a78f51f82997bce9de813c1035f15010e38 Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Mon, 20 Jul 2020 16:32:28 +0530 +Subject: [PATCH] ARM: dts: rockchip: Add USB for RockPI N8/N10 + +Radxa dalang carrier board has 2x USB 2.0 and 1x USB 3.0 +ports. + +This patch adds support to enable all these USB ports for +N10 and N8 combinations SBCs. + +Note that the USB 3.0 port on RockPI N8 combination works +as USB 2.0 OTG since it is driven from RK3288. + +Signed-off-by: Jagan Teki +Link: https://lore.kernel.org/r/20200720110230.367985-1-jagan@amarulasolutions.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit 417b188a985d3557b0ecb5623b27bd9843f03aec) +--- + arch/arm/boot/dts/rk3288-vmarc-som.dtsi | 42 ++++++++++ + .../dts/rockchip-radxa-dalang-carrier.dtsi | 18 +++++ + .../dts/rockchip/rk3399pro-vmarc-som.dtsi | 78 +++++++++++++++++++ + 3 files changed, 138 insertions(+) + +diff --git a/arch/arm/boot/dts/rk3288-vmarc-som.dtsi b/arch/arm/boot/dts/rk3288-vmarc-som.dtsi +index cd61b6230f0d..78164d117248 100644 +--- a/arch/arm/boot/dts/rk3288-vmarc-som.dtsi ++++ b/arch/arm/boot/dts/rk3288-vmarc-som.dtsi +@@ -267,4 +267,46 @@ sdmmc_cmd: sdmmc-cmd { + rockchip,pins = <6 RK_PC5 1 &pcfg_pull_up_drv_8ma>; + }; + }; ++ ++ vbus_host { ++ usb1_en_oc: usb1-en-oc { ++ rockchip,pins = <0 RK_PC1 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ vbus_typec { ++ usb0_en_oc: usb0-en-oc { ++ rockchip,pins = <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++}; ++ ++&usbphy { ++ status = "okay"; ++}; ++ ++&usb_host0_ehci { ++ status = "okay"; ++}; ++ ++&usb_host0_ohci { ++ status = "okay"; ++}; ++ ++&usb_host1 { ++ status = "okay"; ++}; ++ ++&usb_otg { ++ status = "okay"; ++}; ++ ++&vbus_host { ++ enable-active-high; ++ gpio = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>; /* USB1_EN_OC# */ ++}; ++ ++&vbus_typec { ++ enable-active-high; ++ gpio = <&gpio0 RK_PB5 GPIO_ACTIVE_HIGH>; /* USB0_EN_OC# */ + }; +diff --git a/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi b/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi +index 450e5bb5af0b..d2b6ead148a2 100644 +--- a/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi ++++ b/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi +@@ -33,6 +33,24 @@ vcc5v0_sys: vcc5v0-sys-regulator { + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc12v_dcin>; + }; ++ ++ vbus_host: vbus-host { ++ compatible = "regulator-fixed"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usb1_en_oc>; ++ regulator-name = "vbus_host"; /* HOST-5V */ ++ regulator-always-on; ++ vin-supply = <&vcc5v0_sys>; ++ }; ++ ++ vbus_typec: vbus-typec { ++ compatible = "regulator-fixed"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usb0_en_oc>; ++ regulator-name = "vbus_typec"; ++ regulator-always-on; ++ vin-supply = <&vcc5v0_sys>; ++ }; + }; + + &gmac { +diff --git a/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi b/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi +index 37ed95d5f7e9..111d6cf9a4e6 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi +@@ -304,6 +304,18 @@ pmic_int_l: pmic-int-l { + rockchip,pins = <1 RK_PC2 0 &pcfg_pull_up>; + }; + }; ++ ++ vbus_host { ++ usb1_en_oc: usb1-en-oc { ++ rockchip,pins = <4 RK_PD1 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ vbus_typec { ++ usb0_en_oc: usb0-en-oc { ++ rockchip,pins = <4 RK_PD2 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; + }; + + &pmu_io_domains { +@@ -324,8 +336,74 @@ &sdmmc { + max-frequency = <150000000>; + }; + ++&tcphy0 { ++ status = "okay"; ++}; ++ + &tsadc { + rockchip,hw-tshut-mode = <1>; + rockchip,hw-tshut-polarity = <1>; + status = "okay"; + }; ++ ++&u2phy0 { ++ status = "okay"; ++ ++ u2phy0_otg: otg-port { ++ phy-supply = <&vbus_typec>; ++ status = "okay"; ++ }; ++ ++ u2phy0_host: host-port { ++ phy-supply = <&vbus_host>; ++ status = "okay"; ++ }; ++}; ++ ++ ++&u2phy1 { ++ status = "okay"; ++ ++ u2phy1_host: host-port { ++ phy-supply = <&vbus_host>; ++ status = "okay"; ++ }; ++}; ++ ++&usb_host0_ehci { ++ status = "okay"; ++}; ++ ++&usb_host0_ohci { ++ status = "okay"; ++}; ++ ++&usb_host1_ehci { ++ status = "okay"; ++}; ++ ++&usb_host1_ohci { ++ status = "okay"; ++}; ++ ++&usbdrd3_0 { ++ status = "okay"; ++}; ++ ++&usbdrd_dwc3_0 { ++ status = "okay"; ++}; ++ ++&vbus_host { ++ enable-active-high; ++ gpio = <&gpio4 RK_PD1 GPIO_ACTIVE_HIGH>; /* USB1_EN_OC# */ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usb1_en_oc>; ++}; ++ ++&vbus_typec { ++ enable-active-high; ++ gpio = <&gpio4 RK_PD2 GPIO_ACTIVE_HIGH>; /* USB0_EN_OC# */ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usb0_en_oc>; ++}; + +From 3137628a7366f1fc30748b59254d6b25c2c86efd Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Mon, 20 Jul 2020 16:32:29 +0530 +Subject: [PATCH] ARM: dts: rockchip: Add HDMI out for RockPI N8/N10 + +This patch adds support to enable HDMI out for +N10 and N8 combinations SBCs. + +Signed-off-by: Jagan Teki +Signed-off-by: Suniel Mahesh +Link: https://lore.kernel.org/r/20200720110230.367985-2-jagan@amarulasolutions.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit d0cb2f30e7c033f0a8bbe98ec73dbc1db4788942) +--- + arch/arm/boot/dts/rk3288-vmarc-som.dtsi | 10 ++++++++++ + .../dts/rockchip-radxa-dalang-carrier.dtsi | 20 +++++++++++++++++++ + .../dts/rockchip/rk3399pro-vmarc-som.dtsi | 12 +++++++++++ + 3 files changed, 42 insertions(+) + +diff --git a/arch/arm/boot/dts/rk3288-vmarc-som.dtsi b/arch/arm/boot/dts/rk3288-vmarc-som.dtsi +index 78164d117248..4a373f5aa600 100644 +--- a/arch/arm/boot/dts/rk3288-vmarc-som.dtsi ++++ b/arch/arm/boot/dts/rk3288-vmarc-som.dtsi +@@ -38,6 +38,12 @@ &gmac { + snps,reset-gpio = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>; + }; + ++&hdmi { ++ ddc-i2c-bus = <&i2c5>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&hdmi_cec_c0>; ++}; ++ + &i2c0 { + clock-frequency = <400000>; + status = "okay"; +@@ -225,6 +231,10 @@ regulator-state-mem { + }; + }; + ++&i2c5 { ++ status = "okay"; ++}; ++ + &io_domains { + bb-supply = <&vcc_io>; + flash0-supply = <&vccio_flash>; +diff --git a/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi b/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi +index d2b6ead148a2..26b53eac4706 100644 +--- a/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi ++++ b/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi +@@ -66,6 +66,10 @@ &gmac { + status = "okay"; + }; + ++&hdmi { ++ status = "okay"; ++}; ++ + &pwm0 { + status = "okay"; + }; +@@ -94,3 +98,19 @@ &uart0 { + &uart2 { + status = "okay"; + }; ++ ++&vopb { ++ status = "okay"; ++}; ++ ++&vopb_mmu { ++ status = "okay"; ++}; ++ ++&vopl { ++ status = "okay"; ++}; ++ ++&vopl_mmu { ++ status = "okay"; ++}; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi b/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi +index 111d6cf9a4e6..ebccc4a153a2 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi +@@ -39,6 +39,12 @@ &gmac { + snps,reset-gpio = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + }; + ++&hdmi { ++ ddc-i2c-bus = <&i2c3>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&hdmi_cec>; ++}; ++ + &i2c0 { + clock-frequency = <400000>; + i2c-scl-falling-time-ns = <30>; +@@ -285,6 +291,12 @@ hym8563: hym8563@51 { + }; + }; + ++&i2c3 { ++ i2c-scl-rising-time-ns = <450>; ++ i2c-scl-falling-time-ns = <15>; ++ status = "okay"; ++}; ++ + &io_domains { + status = "okay"; + bt656-supply = <&vcca_1v8>; + +From 0d5ba09fbbd6b8a5d9fc7df9d3f760842549c07f Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Mon, 20 Jul 2020 16:32:30 +0530 +Subject: [PATCH] arm64: dts: rockchip: Add PCIe for RockPI N10 + +This patch adds support to enable PCIe for RockPI N10. + +Signed-off-by: Jagan Teki +Link: https://lore.kernel.org/r/20200720110230.367985-3-jagan@amarulasolutions.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit 93ca8ac2e8fcea6feb02a40edd2334144b62fc6e) +--- + .../dts/rockchip/rk3399pro-vmarc-som.dtsi | 40 ++++++++++++++++++- + 1 file changed, 38 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi b/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi +index ebccc4a153a2..5d087be04af8 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi +@@ -11,6 +11,18 @@ + + / { + compatible = "vamrs,rk3399pro-vmarc-som", "rockchip,rk3399pro"; ++ ++ vcc3v3_pcie: vcc-pcie-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio4 RK_PD4 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pcie_pwr>; ++ regulator-name = "vcc3v3_pcie"; ++ regulator-always-on; ++ regulator-boot-on; ++ vin-supply = <&vcc5v0_sys>; ++ }; + }; + + &cpu_l0 { +@@ -142,7 +154,8 @@ vcca_0v9: LDO_REG1 { + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + regulator-state-mem { +- regulator-off-in-suspend; ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <900000>; + }; + }; + +@@ -177,7 +190,8 @@ vcca_1v8: LDO_REG4 { + regulator-min-microvolt = <1850000>; + regulator-max-microvolt = <1850000>; + regulator-state-mem { +- regulator-off-in-suspend; ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1850000>; + }; + }; + +@@ -304,6 +318,22 @@ &io_domains { + sdmmc-supply = <&vccio_sd>; + }; + ++&pcie_phy { ++ status = "okay"; ++}; ++ ++&pcie0 { ++ ep-gpios = <&gpio0 RK_PB4 GPIO_ACTIVE_HIGH>; ++ max-link-speed = <2>; ++ num-lanes = <4>; ++ pinctrl-0 = <&pcie_clkreqnb_cpm>; ++ pinctrl-names = "default"; ++ vpcie0v9-supply = <&vcca_0v9>; /* VCC_0V9_S0 */ ++ vpcie1v8-supply = <&vcca_1v8>; /* VCC_1V8_S0 */ ++ vpcie3v3-supply = <&vcc3v3_pcie>; ++ status = "okay"; ++}; ++ + &pinctrl { + hym8563 { + hym8563_int: hym8563-int { +@@ -311,6 +341,12 @@ hym8563_int: hym8563-int { + }; + }; + ++ pcie { ++ pcie_pwr: pcie-pwr { ++ rockchip,pins = <4 RK_PD4 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ + pmic { + pmic_int_l: pmic-int-l { + rockchip,pins = <1 RK_PC2 0 &pcfg_pull_up>; + +From ec258d2b9150088af58b6935bbf3c6c3618ea8f7 Mon Sep 17 00:00:00 2001 +From: Katsuhiro Suzuki +Date: Sat, 25 Jul 2020 00:59:33 +0900 +Subject: [PATCH] ASoC: convert Everest ES8316 binding to yaml + +This patch converts Everest Semiconductor ES8316 low power audio +CODEC binding to DT schema. + +Signed-off-by: Katsuhiro Suzuki +Reviewed-by: Rob Herring +Link: https://lore.kernel.org/r/20200724155933.1040501-1-katsuhiro@katsuster.net +Signed-off-by: Mark Brown +(cherry picked from commit 92e67a9c4f206dc9c859c405e67448a8be59ac5d) +--- + .../bindings/sound/everest,es8316.txt | 23 --------- + .../bindings/sound/everest,es8316.yaml | 50 +++++++++++++++++++ + 2 files changed, 50 insertions(+), 23 deletions(-) + delete mode 100644 Documentation/devicetree/bindings/sound/everest,es8316.txt + create mode 100644 Documentation/devicetree/bindings/sound/everest,es8316.yaml + +diff --git a/Documentation/devicetree/bindings/sound/everest,es8316.txt b/Documentation/devicetree/bindings/sound/everest,es8316.txt +deleted file mode 100644 +index 1bf03c5f2af4..000000000000 +--- a/Documentation/devicetree/bindings/sound/everest,es8316.txt ++++ /dev/null +@@ -1,23 +0,0 @@ +-Everest ES8316 audio CODEC +- +-This device supports both I2C and SPI. +- +-Required properties: +- +- - compatible : should be "everest,es8316" +- - reg : the I2C address of the device for I2C +- +-Optional properties: +- +- - clocks : a list of phandle, should contain entries for clock-names +- - clock-names : should include as follows: +- "mclk" : master clock (MCLK) of the device +- +-Example: +- +-es8316: codec@11 { +- compatible = "everest,es8316"; +- reg = <0x11>; +- clocks = <&clks 10>; +- clock-names = "mclk"; +-}; +diff --git a/Documentation/devicetree/bindings/sound/everest,es8316.yaml b/Documentation/devicetree/bindings/sound/everest,es8316.yaml +new file mode 100644 +index 000000000000..3b752bba748b +--- /dev/null ++++ b/Documentation/devicetree/bindings/sound/everest,es8316.yaml +@@ -0,0 +1,50 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/sound/everest,es8316.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Everest ES8316 audio CODEC ++ ++maintainers: ++ - Daniel Drake ++ - Katsuhiro Suzuki ++ ++properties: ++ compatible: ++ const: everest,es8316 ++ ++ reg: ++ maxItems: 1 ++ ++ clocks: ++ items: ++ - description: clock for master clock (MCLK) ++ ++ clock-names: ++ items: ++ - const: mclk ++ ++ "#sound-dai-cells": ++ const: 0 ++ ++required: ++ - compatible ++ - reg ++ - "#sound-dai-cells" ++ ++additionalProperties: false ++ ++examples: ++ - | ++ i2c0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ es8316: codec@11 { ++ compatible = "everest,es8316"; ++ reg = <0x11>; ++ clocks = <&clks 10>; ++ clock-names = "mclk"; ++ #sound-dai-cells = <0>; ++ }; ++ }; + +From f5b60a176251d6e0d1716bbe62a5697a80d38089 Mon Sep 17 00:00:00 2001 +From: Alper Nebi Yasak +Date: Tue, 21 Jul 2020 21:27:10 +0300 +Subject: [PATCH] ASoC: rk3399_gru_sound: Add DAPM pins, kcontrols for jack + detection + +PulseAudio (and perhaps other userspace utilities) can not detect any +jack for rk3399_gru_sound as the driver doesn't expose related Jack +kcontrols. + +This patch adds two DAPM pins to the headset jack, where the +snd_soc_card_jack_new() call automatically creates "Headphones Jack" and +"Headset Mic Jack" kcontrols from them. + +With an appropriate ALSA UCM config specifying JackControl fields for +the "Headphones" and "Headset" (mic) devices, PulseAudio can detect +plug/unplug events for both of them after this patch. + +Signed-off-by: Alper Nebi Yasak +Link: https://lore.kernel.org/r/20200721182709.6895-1-alpernebiyasak@gmail.com +Signed-off-by: Mark Brown +(cherry picked from commit d0508b4f16049a658d68a7c276ba08296c5a76bc) +--- + sound/soc/rockchip/rk3399_gru_sound.c | 17 ++++++++++++++++- + 1 file changed, 16 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/rockchip/rk3399_gru_sound.c b/sound/soc/rockchip/rk3399_gru_sound.c +index 9539b0d024fe..3e45179638ca 100644 +--- a/sound/soc/rockchip/rk3399_gru_sound.c ++++ b/sound/soc/rockchip/rk3399_gru_sound.c +@@ -32,6 +32,19 @@ static unsigned int dmic_wakeup_delay; + + static struct snd_soc_jack rockchip_sound_jack; + ++/* Headset jack detection DAPM pins */ ++static struct snd_soc_jack_pin rockchip_sound_jack_pins[] = { ++ { ++ .pin = "Headphones", ++ .mask = SND_JACK_HEADPHONE, ++ }, ++ { ++ .pin = "Headset Mic", ++ .mask = SND_JACK_MICROPHONE, ++ }, ++ ++}; ++ + static const struct snd_soc_dapm_widget rockchip_dapm_widgets[] = { + SND_SOC_DAPM_HP("Headphones", NULL), + SND_SOC_DAPM_SPK("Speakers", NULL), +@@ -176,7 +189,9 @@ static int rockchip_sound_da7219_init(struct snd_soc_pcm_runtime *rtd) + SND_JACK_HEADSET | SND_JACK_LINEOUT | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3, +- &rockchip_sound_jack, NULL, 0); ++ &rockchip_sound_jack, ++ rockchip_sound_jack_pins, ++ ARRAY_SIZE(rockchip_sound_jack_pins)); + + if (ret) { + dev_err(rtd->card->dev, "New Headset Jack failed! (%d)\n", ret); diff --git a/patch/kernel/rk322x-dev/01-linux-0002-rockchip-from-next.patch b/patch/kernel/rk322x-dev/01-linux-0002-rockchip-from-next.patch new file mode 100644 index 000000000..a20e585c6 --- /dev/null +++ b/patch/kernel/rk322x-dev/01-linux-0002-rockchip-from-next.patch @@ -0,0 +1,434 @@ +From 9d29c5e2f20a44575a5a0e483319682d62daa4b3 Mon Sep 17 00:00:00 2001 +From: Heiko Stuebner +Date: Wed, 29 Jan 2020 17:38:19 +0100 +Subject: [PATCH] clk: rockchip: convert rk3399 pll type to use + readl_relaxed_poll_timeout + +Instead of open coding the polling of the lock status, use the handy +readl_relaxed_poll_timeout for this. As the pll locking is normally +blazingly fast and we don't want to incur additional delays, we're +not doing any sleeps similar to for example the imx clk-pllv4 +and define a very safe but still short timeout of 1ms. + +Suggested-by: Stephen Boyd +Signed-off-by: Heiko Stuebner +Reviewed-by: Stephen Boyd +Link: https://lore.kernel.org/r/20200129163821.1547295-1-heiko@sntech.de +(cherry picked from commit bf4237a188f872e535de8cbfc7903c1387b83b01) +--- + drivers/clk/rockchip/clk-pll.c | 23 ++++++++++++----------- + 1 file changed, 12 insertions(+), 11 deletions(-) + +diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c +index 10560d963baf..28b04aad31ad 100644 +--- a/drivers/clk/rockchip/clk-pll.c ++++ b/drivers/clk/rockchip/clk-pll.c +@@ -589,19 +589,20 @@ static const struct clk_ops rockchip_rk3066_pll_clk_ops = { + static int rockchip_rk3399_pll_wait_lock(struct rockchip_clk_pll *pll) + { + u32 pllcon; +- int delay = 24000000; ++ int ret; + +- /* poll check the lock status in rk3399 xPLLCON2 */ +- while (delay > 0) { +- pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(2)); +- if (pllcon & RK3399_PLLCON2_LOCK_STATUS) +- return 0; ++ /* ++ * Lock time typical 250, max 500 input clock cycles @24MHz ++ * So define a very safe maximum of 1000us, meaning 24000 cycles. ++ */ ++ ret = readl_relaxed_poll_timeout(pll->reg_base + RK3399_PLLCON(2), ++ pllcon, ++ pllcon & RK3399_PLLCON2_LOCK_STATUS, ++ 0, 1000); ++ if (ret) ++ pr_err("%s: timeout waiting for pll to lock\n", __func__); + +- delay--; +- } +- +- pr_err("%s: timeout waiting for pll to lock\n", __func__); +- return -ETIMEDOUT; ++ return ret; + } + + static void rockchip_rk3399_pll_get_params(struct rockchip_clk_pll *pll, + +From afe54d66a661ce9d99250431f1371e46f9b6d8a5 Mon Sep 17 00:00:00 2001 +From: Heiko Stuebner +Date: Wed, 29 Jan 2020 17:38:20 +0100 +Subject: [PATCH] clk: rockchip: convert basic pll lock_wait to use + regmap_read_poll_timeout + +Instead of open coding the polling of the lock status, use the +handy regmap_read_poll_timeout for this. As the pll locking is +normally blazingly fast and we don't want to incur additional +delays, we're not doing any sleeps similar to for example the imx +clk-pllv4 and define a very safe but still short timeout of 1ms. + +Suggested-by: Stephen Boyd +Signed-off-by: Heiko Stuebner +Reviewed-by: Stephen Boyd +Link: https://lore.kernel.org/r/20200129163821.1547295-2-heiko@sntech.de +(cherry picked from commit 3507df1a4615113ae6509e0f14f6546f0d1c84b4) +--- + drivers/clk/rockchip/clk-pll.c | 21 ++++++--------------- + 1 file changed, 6 insertions(+), 15 deletions(-) + +diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c +index 28b04aad31ad..945f8b2cacc1 100644 +--- a/drivers/clk/rockchip/clk-pll.c ++++ b/drivers/clk/rockchip/clk-pll.c +@@ -86,23 +86,14 @@ static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll) + { + struct regmap *grf = pll->ctx->grf; + unsigned int val; +- int delay = 24000000, ret; +- +- while (delay > 0) { +- ret = regmap_read(grf, pll->lock_offset, &val); +- if (ret) { +- pr_err("%s: failed to read pll lock status: %d\n", +- __func__, ret); +- return ret; +- } ++ int ret; + +- if (val & BIT(pll->lock_shift)) +- return 0; +- delay--; +- } ++ ret = regmap_read_poll_timeout(grf, pll->lock_offset, val, ++ val & BIT(pll->lock_shift), 0, 1000); ++ if (ret) ++ pr_err("%s: timeout waiting for pll to lock\n", __func__); + +- pr_err("%s: timeout waiting for pll to lock\n", __func__); +- return -ETIMEDOUT; ++ return ret; + } + + /** + +From 9a37c781854b2cc475aced9045ba8c35b6838f3a Mon Sep 17 00:00:00 2001 +From: Heiko Stuebner +Date: Wed, 29 Jan 2020 17:38:21 +0100 +Subject: [PATCH] clk: rockchip: convert rk3036 pll type to use internal lock + status + +The rk3036 pll type exposes its lock status in both its pllcon registers +as well as the General Register Files. To remove one dependency convert +it to the "internal" lock status, similar to how rk3399 handles it. + +Signed-off-by: Heiko Stuebner +Reviewed-by: Stephen Boyd +Link: https://lore.kernel.org/r/20200129163821.1547295-3-heiko@sntech.de +(cherry picked from commit 7f6ffbb885d147557bdca471c37b7b1204005798) +--- + drivers/clk/rockchip/clk-pll.c | 26 +++++++++++++++++++++++--- + 1 file changed, 23 insertions(+), 3 deletions(-) + +diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c +index 945f8b2cacc1..4c6c9167ef50 100644 +--- a/drivers/clk/rockchip/clk-pll.c ++++ b/drivers/clk/rockchip/clk-pll.c +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + #include + #include + #include "clk.h" +@@ -109,12 +110,31 @@ static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll) + #define RK3036_PLLCON1_REFDIV_SHIFT 0 + #define RK3036_PLLCON1_POSTDIV2_MASK 0x7 + #define RK3036_PLLCON1_POSTDIV2_SHIFT 6 ++#define RK3036_PLLCON1_LOCK_STATUS BIT(10) + #define RK3036_PLLCON1_DSMPD_MASK 0x1 + #define RK3036_PLLCON1_DSMPD_SHIFT 12 ++#define RK3036_PLLCON1_PWRDOWN BIT(13) + #define RK3036_PLLCON2_FRAC_MASK 0xffffff + #define RK3036_PLLCON2_FRAC_SHIFT 0 + +-#define RK3036_PLLCON1_PWRDOWN (1 << 13) ++static int rockchip_rk3036_pll_wait_lock(struct rockchip_clk_pll *pll) ++{ ++ u32 pllcon; ++ int ret; ++ ++ /* ++ * Lock time typical 250, max 500 input clock cycles @24MHz ++ * So define a very safe maximum of 1000us, meaning 24000 cycles. ++ */ ++ ret = readl_relaxed_poll_timeout(pll->reg_base + RK3036_PLLCON(1), ++ pllcon, ++ pllcon & RK3036_PLLCON1_LOCK_STATUS, ++ 0, 1000); ++ if (ret) ++ pr_err("%s: timeout waiting for pll to lock\n", __func__); ++ ++ return ret; ++} + + static void rockchip_rk3036_pll_get_params(struct rockchip_clk_pll *pll, + struct rockchip_pll_rate_table *rate) +@@ -212,7 +232,7 @@ static int rockchip_rk3036_pll_set_params(struct rockchip_clk_pll *pll, + writel_relaxed(pllcon, pll->reg_base + RK3036_PLLCON(2)); + + /* wait for the pll to lock */ +- ret = rockchip_pll_wait_lock(pll); ++ ret = rockchip_rk3036_pll_wait_lock(pll); + if (ret) { + pr_warn("%s: pll update unsuccessful, trying to restore old params\n", + __func__); +@@ -251,7 +271,7 @@ static int rockchip_rk3036_pll_enable(struct clk_hw *hw) + + writel(HIWORD_UPDATE(0, RK3036_PLLCON1_PWRDOWN, 0), + pll->reg_base + RK3036_PLLCON(1)); +- rockchip_pll_wait_lock(pll); ++ rockchip_rk3036_pll_wait_lock(pll); + + return 0; + } + +From 4e8605e139b42a4b239339fc54016ef2d0704908 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Myl=C3=A8ne=20Josserand?= +Date: Tue, 2 Jun 2020 10:06:43 +0200 +Subject: [PATCH] clk: rockchip: Handle clock tree for rk3288w variant +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The revision rk3288w has a different clock tree about "hclk_vio" +clock, according to the BSP kernel code. + +This patch handles this difference by detecting which device-tree +we are using. If it is a "rockchip,rk3288-cru", let's register +the clock tree as it was before. If the device-tree node is +"rockchip,rk3288w-cru", we will apply the difference with this +version of this SoC. + +Noticed that this new device-tree compatible must be handled in +bootloader such as u-boot. + +Signed-off-by: Mylène Josserand +Link: https://lore.kernel.org/r/20200602080644.11333-2-mylene.josserand@collabora.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit 1627f683636df70fb25358b0a7b39a24e8fce5bf) +--- + drivers/clk/rockchip/clk-rk3288.c | 20 ++++++++++++++++++-- + 1 file changed, 18 insertions(+), 2 deletions(-) + +diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c +index cc2a177bbdbf..204976e2d0cb 100644 +--- a/drivers/clk/rockchip/clk-rk3288.c ++++ b/drivers/clk/rockchip/clk-rk3288.c +@@ -425,8 +425,6 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { + COMPOSITE(0, "aclk_vio0", mux_pll_src_cpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, + RK3288_CLKSEL_CON(31), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK3288_CLKGATE_CON(3), 0, GFLAGS), +- DIV(0, "hclk_vio", "aclk_vio0", 0, +- RK3288_CLKSEL_CON(28), 8, 5, DFLAGS), + COMPOSITE(0, "aclk_vio1", mux_pll_src_cpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, + RK3288_CLKSEL_CON(31), 14, 2, MFLAGS, 8, 5, DFLAGS, + RK3288_CLKGATE_CON(3), 2, GFLAGS), +@@ -819,6 +817,16 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { + INVERTER(0, "pclk_isp", "pclk_isp_in", RK3288_CLKSEL_CON(29), 3, IFLAGS), + }; + ++static struct rockchip_clk_branch rk3288w_hclkvio_branch[] __initdata = { ++ DIV(0, "hclk_vio", "aclk_vio1", 0, ++ RK3288_CLKSEL_CON(28), 8, 5, DFLAGS), ++}; ++ ++static struct rockchip_clk_branch rk3288_hclkvio_branch[] __initdata = { ++ DIV(0, "hclk_vio", "aclk_vio0", 0, ++ RK3288_CLKSEL_CON(28), 8, 5, DFLAGS), ++}; ++ + static const char *const rk3288_critical_clocks[] __initconst = { + "aclk_cpu", + "aclk_peri", +@@ -936,6 +944,14 @@ static void __init rk3288_clk_init(struct device_node *np) + RK3288_GRF_SOC_STATUS1); + rockchip_clk_register_branches(ctx, rk3288_clk_branches, + ARRAY_SIZE(rk3288_clk_branches)); ++ ++ if (of_device_is_compatible(np, "rockchip,rk3288w-cru")) ++ rockchip_clk_register_branches(ctx, rk3288w_hclkvio_branch, ++ ARRAY_SIZE(rk3288w_hclkvio_branch)); ++ else ++ rockchip_clk_register_branches(ctx, rk3288_hclkvio_branch, ++ ARRAY_SIZE(rk3288_hclkvio_branch)); ++ + rockchip_clk_protect_critical(rk3288_critical_clocks, + ARRAY_SIZE(rk3288_critical_clocks)); + + +From cac2ef41ac59ff839b73fea934e8ffd161d406f2 Mon Sep 17 00:00:00 2001 +From: Heiko Stuebner +Date: Fri, 3 Jul 2020 17:49:48 +0200 +Subject: [PATCH] clk: rockchip: use separate compatibles for rk3288w-cru + +Commit 1627f683636d ("clk: rockchip: Handle clock tree for rk3288w variant") +added the check for rk3288w-specific clock-tree changes but in turn would +require a double-compatible due to re-using the main rockchip,rk3288-cru +compatible as entry point. + +The binding change actually describes the compatibles as one or the other +so adapt the code accordingly and add a real second entry-point for the +clock controller. + +Signed-off-by: Heiko Stuebner +Reviewed-by: Ezequiel Garcia +Reviewed-by: Jagan Teki +Tested-by: Jagan Teki # rock-pi-n8 +Link: https://lore.kernel.org/r/20200703154948.260369-1-heiko@sntech.de +(cherry picked from commit 0a7f99aad259d223ce69c03e792c7e2bfcf8c2c6) +--- + drivers/clk/rockchip/clk-rk3288.c | 21 +++++++++++++++++++-- + 1 file changed, 19 insertions(+), 2 deletions(-) + +diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c +index 204976e2d0cb..93c794695c46 100644 +--- a/drivers/clk/rockchip/clk-rk3288.c ++++ b/drivers/clk/rockchip/clk-rk3288.c +@@ -15,6 +15,11 @@ + #define RK3288_GRF_SOC_CON(x) (0x244 + x * 4) + #define RK3288_GRF_SOC_STATUS1 0x284 + ++enum rk3288_variant { ++ RK3288_CRU, ++ RK3288W_CRU, ++}; ++ + enum rk3288_plls { + apll, dpll, cpll, gpll, npll, + }; +@@ -922,7 +927,8 @@ static struct syscore_ops rk3288_clk_syscore_ops = { + .resume = rk3288_clk_resume, + }; + +-static void __init rk3288_clk_init(struct device_node *np) ++static void __init rk3288_common_init(struct device_node *np, ++ enum rk3288_variant soc) + { + struct rockchip_clk_provider *ctx; + +@@ -945,7 +951,7 @@ static void __init rk3288_clk_init(struct device_node *np) + rockchip_clk_register_branches(ctx, rk3288_clk_branches, + ARRAY_SIZE(rk3288_clk_branches)); + +- if (of_device_is_compatible(np, "rockchip,rk3288w-cru")) ++ if (soc == RK3288W_CRU) + rockchip_clk_register_branches(ctx, rk3288w_hclkvio_branch, + ARRAY_SIZE(rk3288w_hclkvio_branch)); + else +@@ -970,4 +976,15 @@ static void __init rk3288_clk_init(struct device_node *np) + + rockchip_clk_of_add_provider(np, ctx); + } ++ ++static void __init rk3288_clk_init(struct device_node *np) ++{ ++ rk3288_common_init(np, RK3288_CRU); ++} + CLK_OF_DECLARE(rk3288_cru, "rockchip,rk3288-cru", rk3288_clk_init); ++ ++static void __init rk3288w_clk_init(struct device_node *np) ++{ ++ rk3288_common_init(np, RK3288W_CRU); ++} ++CLK_OF_DECLARE(rk3288w_cru, "rockchip,rk3288w-cru", rk3288w_clk_init); + +From b80ef30ce22bba6a4bdf9f0aaa9376b6fea24249 Mon Sep 17 00:00:00 2001 +From: Robin Murphy +Date: Thu, 18 Jun 2020 18:56:29 +0100 +Subject: [PATCH] clk: rockchip: Revert "fix wrong mmc sample phase shift for + rk3328" + +This reverts commit 82f4b67f018c88a7cc9337f0067ed3d6ec352648. + +According to a subsequent revert in the vendor kernel, the original +change was based on unclear documentation and was in fact incorrect. + +Emprically, my board's HS200 eMMC at 200MHZ apparently gets lucky with a +phase where this had no impact, but limiting max-frequency to 150MHz to +match the nominal capability of the I/O pins made it virtually unusable, +constantly throwing errors and retuning. With this revert, it starts +behaving perfectly at 150MHz too. + +Fixes: 82f4b67f018c ("clk: rockchip: fix wrong mmc sample phase shift for rk3328") +Signed-off-by: Robin Murphy +Reviewed-by: Shawn Lin +Link: https://lore.kernel.org/r/c80eb52e34c03f817586b6b7912fbd4e31be9079.1589475794.git.robin.murphy@arm.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit 465931e70881476a210d44705102ef8b6ee6cdb0) +--- + drivers/clk/rockchip/clk-rk3328.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/clk/rockchip/clk-rk3328.c b/drivers/clk/rockchip/clk-rk3328.c +index c186a1985bf4..2429b7c2a8b3 100644 +--- a/drivers/clk/rockchip/clk-rk3328.c ++++ b/drivers/clk/rockchip/clk-rk3328.c +@@ -808,22 +808,22 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = { + MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "clk_sdmmc", + RK3328_SDMMC_CON0, 1), + MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "clk_sdmmc", +- RK3328_SDMMC_CON1, 0), ++ RK3328_SDMMC_CON1, 1), + + MMC(SCLK_SDIO_DRV, "sdio_drv", "clk_sdio", + RK3328_SDIO_CON0, 1), + MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "clk_sdio", +- RK3328_SDIO_CON1, 0), ++ RK3328_SDIO_CON1, 1), + + MMC(SCLK_EMMC_DRV, "emmc_drv", "clk_emmc", + RK3328_EMMC_CON0, 1), + MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "clk_emmc", +- RK3328_EMMC_CON1, 0), ++ RK3328_EMMC_CON1, 1), + + MMC(SCLK_SDMMC_EXT_DRV, "sdmmc_ext_drv", "clk_sdmmc_ext", + RK3328_SDMMC_EXT_CON0, 1), + MMC(SCLK_SDMMC_EXT_SAMPLE, "sdmmc_ext_sample", "clk_sdmmc_ext", +- RK3328_SDMMC_EXT_CON1, 0), ++ RK3328_SDMMC_EXT_CON1, 1), + }; + + static const char *const rk3328_critical_clocks[] __initconst = { + +From 21710a18bfba0cf0993a1ef700f03f540d2648ed Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Wed, 22 Jul 2020 18:18:20 +0200 +Subject: [PATCH] clk: rockchip: add sclk_mac_lbtest to rk3188_critical_clocks + +Since the loopbacktest clock is not exported and is not touched in the +driver, it has to be added to rk3188_critical_clocks to be protected from +being disabled and in order to get the emac working. + +Signed-off-by: Alex Bee +Link: https://lore.kernel.org/r/20200722161820.5316-1-knaerzche@gmail.com +Signed-off-by: Heiko Stuebner +(cherry picked from commit ef990bcad58cf1d13c5a49191a2c2342eb8d6709) +--- + drivers/clk/rockchip/clk-rk3188.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c +index 77aebfb1d6d5..730020fcc7fe 100644 +--- a/drivers/clk/rockchip/clk-rk3188.c ++++ b/drivers/clk/rockchip/clk-rk3188.c +@@ -751,6 +751,7 @@ static const char *const rk3188_critical_clocks[] __initconst = { + "pclk_peri", + "hclk_cpubus", + "hclk_vio_bus", ++ "sclk_mac_lbtest", + }; + + static struct rockchip_clk_provider *__init rk3188_common_clk_init(struct device_node *np) diff --git a/patch/kernel/rk322x-dev/01-linux-0003-rockchip-fromlist.patch b/patch/kernel/rk322x-dev/01-linux-0003-rockchip-fromlist.patch new file mode 100644 index 000000000..1495e0bfe --- /dev/null +++ b/patch/kernel/rk322x-dev/01-linux-0003-rockchip-fromlist.patch @@ -0,0 +1,1956 @@ +From 01b6923a7d4b84609809a0695e58aeb7bd1376f1 Mon Sep 17 00:00:00 2001 +From: Yifeng Zhao +Date: Fri, 17 Jul 2020 17:24:17 +0800 +Subject: [PATCH] dt-bindings: mtd: Describe Rockchip RK3xxx NAND flash + controller + +Documentation support for Rockchip RK3xxx NAND flash controllers + +Signed-off-by: Yifeng Zhao +Reviewed-by: Rob Herring +--- + .../mtd/rockchip,nand-controller.yaml | 162 ++++++++++++++++++ + 1 file changed, 162 insertions(+) + create mode 100644 Documentation/devicetree/bindings/mtd/rockchip,nand-controller.yaml + +diff --git a/Documentation/devicetree/bindings/mtd/rockchip,nand-controller.yaml b/Documentation/devicetree/bindings/mtd/rockchip,nand-controller.yaml +new file mode 100644 +index 000000000000..b9d7a8c79402 +--- /dev/null ++++ b/Documentation/devicetree/bindings/mtd/rockchip,nand-controller.yaml +@@ -0,0 +1,162 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/mtd/rockchip,nand-controller.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Rockchip SoCs NAND FLASH Controller (NFC) ++ ++allOf: ++ - $ref: "nand-controller.yaml#" ++ ++maintainers: ++ - Heiko Stuebner ++ ++properties: ++ compatible: ++ oneOf: ++ - const: rockchip,px30-nfc ++ - const: rockchip,rk2928-nfc ++ - const: rockchip,rv1108-nfc ++ - items: ++ - const: rockchip,rk3036-nfc ++ - const: rockchip,rk2928-nfc ++ - items: ++ - const: rockchip,rk3308-nfc ++ - const: rockchip,rv1108-nfc ++ ++ reg: ++ maxItems: 1 ++ ++ interrupts: ++ maxItems: 1 ++ ++ clocks: ++ minItems: 1 ++ items: ++ - description: Bus Clock ++ - description: Module Clock ++ ++ clock-names: ++ minItems: 1 ++ items: ++ - const: ahb ++ - const: nfc ++ ++ assigned-clocks: ++ maxItems: 1 ++ ++ assigned-clock-rates: ++ maxItems: 1 ++ ++ power-domains: ++ maxItems: 1 ++ ++patternProperties: ++ "^nand@[0-7]$": ++ type: object ++ properties: ++ reg: ++ minimum: 0 ++ maximum: 7 ++ ++ nand-ecc-mode: ++ const: hw ++ ++ nand-ecc-step-size: ++ const: 1024 ++ ++ nand-ecc-strength: ++ enum: [16, 24, 40, 60, 70] ++ description: ++ The ECC configurations that can be supported are as follows. ++ NFC v600 ECC 16, 24, 40, 60 ++ RK2928, RK3066, RK3188 ++ ++ NFC v622 ECC 16, 24, 40, 60 ++ RK3036, RK3128 ++ ++ NFC v800 ECC 16 ++ RK3308, RV1108 ++ ++ NFC v900 ECC 16, 40, 60, 70 ++ RK3326, PX30 ++ ++ nand-bus-width: ++ const: 8 ++ ++ rockchip,boot-blks: ++ minimum: 2 ++ default: 16 ++ allOf: ++ - $ref: /schemas/types.yaml#/definitions/uint32 ++ description: ++ The NFC driver need this information to select ECC ++ algorithms supported by the boot ROM. ++ Only used in combination with 'nand-is-boot-medium'. ++ ++ rockchip,boot-ecc-strength: ++ enum: [16, 24, 40, 60, 70] ++ allOf: ++ - $ref: /schemas/types.yaml#/definitions/uint32 ++ description: ++ If specified it indicates that a different BCH/ECC setting is ++ supported by the boot ROM. ++ NFC v600 ECC 16, 24 ++ RK2928, RK3066, RK3188 ++ ++ NFC v622 ECC 16, 24, 40, 60 ++ RK3036, RK3128 ++ ++ NFC v800 ECC 16 ++ RK3308, RV1108 ++ ++ NFC v900 ECC 16, 70 ++ RK3326, PX30 ++ ++ Only used in combination with 'nand-is-boot-medium'. ++ ++required: ++ - compatible ++ - reg ++ - interrupts ++ - clocks ++ - clock-names ++ ++unevaluatedProperties: false ++ ++examples: ++ - | ++ #include ++ #include ++ nfc: nand-controller@ff4b0000 { ++ compatible = "rockchip,rk3308-nfc", ++ "rockchip,rv1108-nfc"; ++ reg = <0xff4b0000 0x4000>; ++ interrupts = ; ++ clocks = <&cru HCLK_NANDC>, <&cru SCLK_NANDC>; ++ clock-names = "ahb", "nfc"; ++ assigned-clocks = <&clks SCLK_NANDC>; ++ assigned-clock-rates = <150000000>; ++ ++ pinctrl-0 = <&flash_ale &flash_bus8 &flash_cle &flash_csn0 ++ &flash_rdn &flash_rdy &flash_wrn>; ++ pinctrl-names = "default"; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ nand@0 { ++ reg = <0>; ++ label = "rk-nand"; ++ nand-bus-width = <8>; ++ nand-ecc-mode = "hw"; ++ nand-ecc-step-size = <1024>; ++ nand-ecc-strength = <16>; ++ nand-is-boot-medium; ++ rockchip,boot-blks = <8>; ++ rockchip,boot-ecc-strength = <16>; ++ }; ++ }; ++ ++... + +From 8d00c3eb36f8fbccc159d6456bfd418a2841acff Mon Sep 17 00:00:00 2001 +From: Yifeng Zhao +Date: Fri, 17 Jul 2020 17:24:18 +0800 +Subject: [PATCH] mtd: rawnand: rockchip: NFC drivers for RK3308, RK2928 and + others + +This driver supports Rockchip NFC (NAND Flash Controller) found on RK3308, +RK2928, RKPX30, RV1108 and other SOCs. The driver has been tested using +8-bit NAND interface on the ARM based RK3308 platform. + +Support Rockchip SoCs and NFC versions: +- PX30 and RK3326(NFCv900). + ECC: 16/40/60/70 bits/1KB. + CLOCK: ahb and nfc. +- RK3308 and RV1108(NFCv800). + ECC: 16 bits/1KB. + CLOCK: ahb and nfc. +- RK3036 and RK3128(NFCv622). + ECC: 16/24/40/60 bits/1KB. + CLOCK: ahb and nfc. +- RK3066, RK3188 and RK2928(NFCv600). + ECC: 16/24/40/60 bits/1KB. + CLOCK: ahb. + +Supported features: +- Read full page data by DMA. +- Support HW ECC(one step is 1KB). +- Support 2 - 32K page size. +- Support 8 CS(depend on SoCs) + +Limitations: +- No support for the ecc step size is 512. +- Untested on some SoCs. +- No support for subpages. +- No support for the builtin randomizer. +- The original bad block mask is not supported. It is recommended to use + the BBT(bad block table). + +Signed-off-by: Yifeng Zhao +--- + drivers/mtd/nand/raw/Kconfig | 12 + + drivers/mtd/nand/raw/Makefile | 1 + + .../mtd/nand/raw/rockchip-nand-controller.c | 1422 +++++++++++++++++ + 3 files changed, 1435 insertions(+) + create mode 100644 drivers/mtd/nand/raw/rockchip-nand-controller.c + +diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig +index 113f61052269..6492855d4a55 100644 +--- a/drivers/mtd/nand/raw/Kconfig ++++ b/drivers/mtd/nand/raw/Kconfig +@@ -461,6 +461,18 @@ config MTD_NAND_ARASAN + Enables the driver for the Arasan NAND flash controller on + Zynq Ultrascale+ MPSoC. + ++config MTD_NAND_ROCKCHIP ++ tristate "Rockchip NAND controller" ++ depends on ARCH_ROCKCHIP && HAS_IOMEM ++ help ++ Enables support for NAND controller on Rockchip SoCs. ++ There are four different versions of NAND FLASH Controllers, ++ including: ++ NFC v600: RK2928, RK3066, RK3188 ++ NFC v622: RK3036, RK3128 ++ NFC v800: RK3308, RV1108 ++ NFC v900: PX30, RK3326 ++ + comment "Misc" + + config MTD_SM_COMMON +diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile +index 2930f5b9015d..960c9be25204 100644 +--- a/drivers/mtd/nand/raw/Makefile ++++ b/drivers/mtd/nand/raw/Makefile +@@ -58,6 +58,7 @@ obj-$(CONFIG_MTD_NAND_STM32_FMC2) += stm32_fmc2_nand.o + obj-$(CONFIG_MTD_NAND_MESON) += meson_nand.o + obj-$(CONFIG_MTD_NAND_CADENCE) += cadence-nand-controller.o + obj-$(CONFIG_MTD_NAND_ARASAN) += arasan-nand-controller.o ++obj-$(CONFIG_MTD_NAND_ROCKCHIP) += rockchip-nand-controller.o + + nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o + nand-objs += nand_onfi.o +diff --git a/drivers/mtd/nand/raw/rockchip-nand-controller.c b/drivers/mtd/nand/raw/rockchip-nand-controller.c +new file mode 100644 +index 000000000000..fec1360603e0 +--- /dev/null ++++ b/drivers/mtd/nand/raw/rockchip-nand-controller.c +@@ -0,0 +1,1422 @@ ++// SPDX-License-Identifier: GPL-2.0 OR MIT ++/* ++ * Rockchip NAND Flash controller driver. ++ * Copyright (C) 2020 Rockchip Inc. ++ * Author: Yifeng Zhao ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* ++ * NFC Page Data Layout: ++ * 1024 Bytes Data + 4Bytes sys data + 28Bytes~124Bytes ecc + ++ * 1024 Bytes Data + 4Bytes sys data + 28Bytes~124Bytes ecc + ++ * ...... ++ * NAND Page Data Layout: ++ * 1024 * n Data + m Bytes oob ++ * Original Bad Block Mask Location: ++ * First byte of oob(spare). ++ * nand_chip->oob_poi data layout: ++ * 4Bytes sys data + .... + 4Bytes sys data + ecc data. ++ */ ++ ++/* NAND controller register definition */ ++#define NFC_READ (0) ++#define NFC_WRITE (1) ++#define NFC_FMCTL (0x00) ++#define FMCTL_CE_SEL_M 0xFF ++#define FMCTL_CE_SEL(x) (1 << (x)) ++#define FMCTL_WP BIT(8) ++#define FMCTL_RDY BIT(9) ++#define NFC_FMWAIT (0x04) ++#define FLCTL_RST BIT(0) ++#define FLCTL_WR (1) /* 0: read, 1: write */ ++#define FLCTL_XFER_ST BIT(2) ++#define FLCTL_XFER_EN BIT(3) ++#define FLCTL_ACORRECT BIT(10) /* Auto correct error bits. */ ++#define FLCTL_XFER_READY BIT(20) ++#define FLCTL_XFER_SECTOR (22) ++#define FLCTL_TOG_FIX BIT(29) ++#define BCHCTL_BANK_M (7 << 5) ++#define BCHCTL_BANK (5) ++#define DMA_ST BIT(0) ++#define DMA_WR (1) /* 0: write, 1: read */ ++#define DMA_EN BIT(2) ++#define DMA_AHB_SIZE (3) /* 0: 1, 1: 2, 2: 4 */ ++#define DMA_BURST_SIZE (6) /* 0: 1, 3: 4, 5: 8, 7: 16 */ ++#define DMA_INC_NUM (9) /* 1 - 16 */ ++#define ECC_ERR_CNT(x, e) ((((x) >> (e).low) & (e).low_mask) \ ++ | (((x) >> (e).high) & (e).high_mask) << (e).low_bn) ++#define INT_DMA BIT(0) ++#define NFC_BANK (0x800) ++#define NFC_BANK_STEP (0x100) ++#define BANK_DATA (0x00) ++#define BANK_ADDR (0x04) ++#define BANK_CMD (0x08) ++#define NFC_SRAM0 (0x1000) ++#define NFC_SRAM1 (0x1400) ++#define NFC_SRAM_SIZE (0x400) ++#define NFC_TIMEOUT (500000) ++#define NFC_MAX_OOB_PER_STEP 128 ++#define NFC_MIN_OOB_PER_STEP 64 ++#define MAX_DATA_SIZE 0xFFFC ++#define MAX_ADDRESS_CYC 6 ++#define NFC_ECC_MAX_MODES 4 ++#define NFC_MAX_NSELS (8) /* Some Socs only have 1 or 2 CSs. */ ++#define NFC_SYS_DATA_SIZE (4) /* 4 bytes sys data in oob pre 1024 data.*/ ++#define RK_DEFAULT_CLOCK_RATE (150 * 1000 * 1000) /* 150 Mhz */ ++#define ACCTIMING(csrw, rwpw, rwcs) ((csrw) << 12 | (rwpw) << 5 | (rwcs)) ++ ++enum nfc_type { ++ NFC_V6, ++ NFC_V8, ++ NFC_V9, ++}; ++ ++/** ++ * struct rk_ecc_cnt_status: represent a ecc status data. ++ * @err_flag_bit: error flag bit index at register. ++ * @low: ecc count low bit index at register. ++ * @low_mask: mask bit. ++ * @low_bn: ecc count low bit number. ++ * @high: ecc count high bit index at register. ++ * @high_mask: mask bit ++ */ ++struct ecc_cnt_status { ++ u8 err_flag_bit; ++ u8 low; ++ u8 low_mask; ++ u8 low_bn; ++ u8 high; ++ u8 high_mask; ++}; ++ ++/* ++ * @type: nfc version ++ * @ecc_strengths: ecc strengths ++ * @ecc_cfgs: ecc config values ++ * @flctl_off: FLCTL register offset ++ * @bchctl_off: BCHCTL register offset ++ * @dma_data_buf_off: DMA_DATA_BUF register offset ++ * @dma_oob_buf_off: DMA_OOB_BUF register offset ++ * @dma_cfg_off: DMA_CFG register offset ++ * @dma_st_off: DMA_ST register offset ++ * @bch_st_off: BCG_ST register offset ++ * @randmz_off: RANDMZ register offset ++ * @int_en_off: interrupt enable register offset ++ * @int_clr_off: interrupt clean register offset ++ * @int_st_off: interrupt status register offset ++ * @oob0_off: oob0 register offset ++ * @oob1_off: oob1 register offset ++ * @ecc0: represent ECC0 status data ++ * @ecc1: represent ECC1 status data ++ */ ++struct nfc_cfg { ++ enum nfc_type type; ++ u8 ecc_strengths[NFC_ECC_MAX_MODES]; ++ u32 ecc_cfgs[NFC_ECC_MAX_MODES]; ++ u32 flctl_off; ++ u32 bchctl_off; ++ u32 dma_cfg_off; ++ u32 dma_data_buf_off; ++ u32 dma_oob_buf_off; ++ u32 dma_st_off; ++ u32 bch_st_off; ++ u32 randmz_off; ++ u32 int_en_off; ++ u32 int_clr_off; ++ u32 int_st_off; ++ u32 oob0_off; ++ u32 oob1_off; ++ struct ecc_cnt_status ecc0; ++ struct ecc_cnt_status ecc1; ++}; ++ ++struct rk_nfc_nand_chip { ++ struct list_head node; ++ struct nand_chip chip; ++ ++ u16 spare_per_sector; ++ u16 oob_buf_per_sector; ++ u16 boot_blks; ++ u16 boot_ecc; ++ u16 metadata_size; ++ ++ u8 nsels; ++ u8 sels[0]; ++ /* Nothing after this field. */ ++}; ++ ++struct rk_nfc_clk { ++ int nfc_rate; ++ struct clk *nfc_clk; ++ struct clk *ahb_clk; ++}; ++ ++struct rk_nfc { ++ struct nand_controller controller; ++ struct rk_nfc_clk clk; ++ ++ struct device *dev; ++ const struct nfc_cfg *cfg; ++ void __iomem *regs; ++ ++ int selected_bank; ++ int band_offset; ++ ++ struct completion done; ++ struct list_head chips; ++ ++ u8 *buffer; ++ u8 *page_buf; ++ u32 *oob_buf; ++ ++ unsigned long assigned_cs; ++}; ++ ++static inline struct rk_nfc_nand_chip *to_rknand(struct nand_chip *chip) ++{ ++ return container_of(chip, struct rk_nfc_nand_chip, chip); ++} ++ ++static inline u8 *data_ptr(struct nand_chip *chip, const u8 *p, int i) ++{ ++ return (u8 *)p + i * chip->ecc.size; ++} ++ ++static inline u8 *oob_ptr(struct nand_chip *chip, int i) ++{ ++ u8 *poi; ++ ++ poi = chip->oob_poi + i * NFC_SYS_DATA_SIZE; ++ ++ return poi; ++} ++ ++static inline u8 *oob_ecc_ptr(struct nand_chip *chip, int i) ++{ ++ struct rk_nfc_nand_chip *rknand = to_rknand(chip); ++ u8 *poi; ++ ++ poi = chip->oob_poi + rknand->metadata_size + ++ chip->ecc.bytes * i; ++ ++ return poi; ++} ++ ++static inline int rk_data_len(struct nand_chip *chip) ++{ ++ struct rk_nfc_nand_chip *rknand = to_rknand(chip); ++ ++ return chip->ecc.size + rknand->spare_per_sector; ++} ++ ++static inline u8 *rk_data_ptr(struct nand_chip *chip, int i) ++{ ++ struct rk_nfc *nfc = nand_get_controller_data(chip); ++ ++ return nfc->buffer + i * rk_data_len(chip); ++} ++ ++static inline u8 *rk_oob_ptr(struct nand_chip *chip, int i) ++{ ++ struct rk_nfc *nfc = nand_get_controller_data(chip); ++ ++ return nfc->buffer + i * rk_data_len(chip) + chip->ecc.size; ++} ++ ++static void rk_nfc_select_chip(struct nand_chip *chip, int cs) ++{ ++ struct rk_nfc *nfc = nand_get_controller_data(chip); ++ struct rk_nfc_nand_chip *rknand = to_rknand(chip); ++ u32 val; ++ ++ if (cs < 0) { ++ nfc->selected_bank = -1; ++ /* Deselect the currently selected target. */ ++ val = readl_relaxed(nfc->regs + NFC_FMCTL); ++ val &= ~FMCTL_CE_SEL_M; ++ writel(val, nfc->regs + NFC_FMCTL); ++ return; ++ } ++ ++ nfc->selected_bank = rknand->sels[cs]; ++ nfc->band_offset = NFC_BANK + nfc->selected_bank * NFC_BANK_STEP; ++ ++ val = readl_relaxed(nfc->regs + NFC_FMCTL); ++ val &= ~FMCTL_CE_SEL_M; ++ val |= FMCTL_CE_SEL(nfc->selected_bank); ++ ++ writel(val, nfc->regs + NFC_FMCTL); ++} ++ ++static inline int rk_nfc_wait_ioready(struct rk_nfc *nfc) ++{ ++ int rc; ++ u32 val; ++ ++ rc = readl_poll_timeout_atomic(nfc->regs + NFC_FMCTL, val, ++ val & FMCTL_RDY, 10, NFC_TIMEOUT); ++ ++ return rc; ++} ++ ++static inline u8 rk_nfc_read_byte(struct nand_chip *chip) ++{ ++ struct rk_nfc *nfc = nand_get_controller_data(chip); ++ ++ return readb_relaxed(nfc->regs + nfc->band_offset + BANK_DATA); ++} ++ ++static void rk_nfc_read_buf(struct nand_chip *chip, u8 *buf, int len) ++{ ++ int i; ++ ++ for (i = 0; i < len; i++) ++ buf[i] = rk_nfc_read_byte(chip); ++} ++ ++static void rk_nfc_write_byte(struct nand_chip *chip, u8 byte) ++{ ++ struct rk_nfc *nfc = nand_get_controller_data(chip); ++ ++ writeb(byte, nfc->regs + nfc->band_offset + BANK_DATA); ++} ++ ++static void rk_nfc_write_buf(struct nand_chip *chip, const u8 *buf, int len) ++{ ++ int i; ++ ++ for (i = 0; i < len; i++) ++ rk_nfc_write_byte(chip, buf[i]); ++} ++ ++static int rk_nfc_cmd(struct nand_chip *chip, ++ const struct nand_subop *subop) ++{ ++ struct rk_nfc *nfc = nand_get_controller_data(chip); ++ unsigned int i, j, remaining, start; ++ int reg_offset = nfc->band_offset; ++ void __iomem *data_reg; ++ u8 *inbuf = NULL; ++ const u8 *outbuf; ++ u32 cnt = 0; ++ int ret = 0; ++ ++ for (i = 0; i < subop->ninstrs; i++) { ++ const struct nand_op_instr *instr = &subop->instrs[i]; ++ ++ switch (instr->type) { ++ case NAND_OP_CMD_INSTR: ++ writeb(instr->ctx.cmd.opcode, ++ nfc->regs + reg_offset + BANK_CMD); ++ break; ++ ++ case NAND_OP_ADDR_INSTR: ++ remaining = nand_subop_get_num_addr_cyc(subop, i); ++ start = nand_subop_get_addr_start_off(subop, i); ++ ++ for (j = 0; j < 8 && j + start < remaining; j++) ++ writeb(instr->ctx.addr.addrs[j + start], ++ nfc->regs + reg_offset + BANK_ADDR); ++ break; ++ ++ case NAND_OP_DATA_IN_INSTR: ++ case NAND_OP_DATA_OUT_INSTR: ++ start = nand_subop_get_data_start_off(subop, i); ++ cnt = nand_subop_get_data_len(subop, i); ++ data_reg = nfc->regs + nfc->band_offset + BANK_DATA; ++ ++ if (instr->type == NAND_OP_DATA_OUT_INSTR) { ++ outbuf = instr->ctx.data.buf.out + start; ++ for (j = 0; j < cnt; j++) ++ writeb(outbuf[j], data_reg); ++ } else { ++ inbuf = instr->ctx.data.buf.in + start; ++ for (j = 0; j < cnt; j++) ++ inbuf[j] = readb_relaxed(data_reg); ++ } ++ break; ++ ++ case NAND_OP_WAITRDY_INSTR: ++ if (rk_nfc_wait_ioready(nfc) < 0) { ++ ret = -ETIMEDOUT; ++ dev_err(nfc->dev, "IO not ready\n"); ++ } ++ break; ++ } ++ } ++ ++ return ret; ++} ++ ++static const struct nand_op_parser rk_nfc_op_parser = NAND_OP_PARSER( ++ NAND_OP_PARSER_PATTERN( ++ rk_nfc_cmd, ++ NAND_OP_PARSER_PAT_CMD_ELEM(true), ++ NAND_OP_PARSER_PAT_ADDR_ELEM(true, MAX_ADDRESS_CYC), ++ NAND_OP_PARSER_PAT_CMD_ELEM(true), ++ NAND_OP_PARSER_PAT_WAITRDY_ELEM(true), ++ NAND_OP_PARSER_PAT_DATA_IN_ELEM(true, MAX_DATA_SIZE)), ++ NAND_OP_PARSER_PATTERN( ++ rk_nfc_cmd, ++ NAND_OP_PARSER_PAT_CMD_ELEM(true), ++ NAND_OP_PARSER_PAT_ADDR_ELEM(true, MAX_ADDRESS_CYC), ++ NAND_OP_PARSER_PAT_DATA_OUT_ELEM(true, MAX_DATA_SIZE), ++ NAND_OP_PARSER_PAT_CMD_ELEM(true), ++ NAND_OP_PARSER_PAT_WAITRDY_ELEM(true)), ++); ++ ++static int rk_nfc_exec_op(struct nand_chip *chip, ++ const struct nand_operation *op, ++ bool check_only) ++{ ++ rk_nfc_select_chip(chip, op->cs); ++ return nand_op_parser_exec_op(chip, &rk_nfc_op_parser, op, ++ check_only); ++} ++ ++static int rk_nfc_setup_data_interface(struct nand_chip *chip, int csline, ++ const struct nand_data_interface *conf) ++{ ++ struct rk_nfc *nfc = nand_get_controller_data(chip); ++ const struct nand_sdr_timings *timings; ++ u32 rate, tc2rw, trwpw, trw2c; ++ u32 temp; ++ ++ if (csline == NAND_DATA_IFACE_CHECK_ONLY) ++ return 0; ++ ++ if (!chip->parameters.onfi) ++ return 0; ++ ++ timings = nand_get_sdr_timings(conf); ++ if (IS_ERR(timings)) ++ return -EOPNOTSUPP; ++ ++ if (IS_ERR(nfc->clk.nfc_clk)) ++ rate = clk_get_rate(nfc->clk.ahb_clk); ++ else ++ rate = clk_get_rate(nfc->clk.nfc_clk); ++ ++ /* Turn clock rate into kHz. */ ++ rate /= 1000; ++ ++ tc2rw = 1; ++ trw2c = 1; ++ ++ trwpw = max(timings->tWC_min, timings->tRC_min) / 1000; ++ trwpw = DIV_ROUND_UP(trwpw * rate, 1000000); ++ ++ temp = timings->tREA_max / 1000; ++ temp = DIV_ROUND_UP(temp * rate, 1000000); ++ ++ if (trwpw < temp) ++ trwpw = temp; ++ ++ /* ++ * ACCON: access timing control register ++ * ------------------------------------- ++ * 31:18: reserved ++ * 17:12: csrw, clock cycles from the falling edge of CSn to the ++ falling edge of RDn or WRn ++ * 11:11: reserved ++ * 10:05: rwpw, the width of RDn or WRn in processor clock cycles ++ * 04:00: rwcs, clock cycles from the rising edge of RDn or WRn to the ++ rising edge of CSn ++ */ ++ temp = ACCTIMING(tc2rw, trwpw, trw2c); ++ writel(temp, nfc->regs + NFC_FMWAIT); ++ ++ return 0; ++} ++ ++static int rk_nfc_hw_ecc_setup(struct nand_chip *chip, ++ struct nand_ecc_ctrl *ecc, ++ uint32_t strength) ++{ ++ struct rk_nfc *nfc = nand_get_controller_data(chip); ++ u32 reg, i; ++ ++ for (i = 0; i < NFC_ECC_MAX_MODES; i++) { ++ if (ecc->strength == nfc->cfg->ecc_strengths[i]) { ++ reg = nfc->cfg->ecc_cfgs[i]; ++ break; ++ } ++ } ++ ++ if (i >= NFC_ECC_MAX_MODES) ++ return -EINVAL; ++ ++ writel(reg, nfc->regs + nfc->cfg->bchctl_off); ++ ++ return 0; ++} ++ ++static void rk_nfc_xfer_start(struct rk_nfc *nfc, u8 rw, u8 n_KB, ++ dma_addr_t dma_data, dma_addr_t dma_oob) ++{ ++ u32 dma_reg, fl_reg, bch_reg; ++ ++ dma_reg = DMA_ST | ((!rw) << DMA_WR) | DMA_EN | (2 << DMA_AHB_SIZE) | ++ (7 << DMA_BURST_SIZE) | (16 << DMA_INC_NUM); ++ ++ fl_reg = (rw << FLCTL_WR) | FLCTL_XFER_EN | FLCTL_ACORRECT | ++ (n_KB << FLCTL_XFER_SECTOR) | FLCTL_TOG_FIX; ++ ++ if (nfc->cfg->type == NFC_V6 || nfc->cfg->type == NFC_V8) { ++ bch_reg = readl_relaxed(nfc->regs + nfc->cfg->bchctl_off); ++ bch_reg = (bch_reg & (~BCHCTL_BANK_M)) | ++ (nfc->selected_bank << BCHCTL_BANK); ++ writel(bch_reg, nfc->regs + nfc->cfg->bchctl_off); ++ } ++ ++ writel(dma_reg, nfc->regs + nfc->cfg->dma_cfg_off); ++ writel((u32)dma_data, nfc->regs + nfc->cfg->dma_data_buf_off); ++ writel((u32)dma_oob, nfc->regs + nfc->cfg->dma_oob_buf_off); ++ writel(fl_reg, nfc->regs + nfc->cfg->flctl_off); ++ fl_reg |= FLCTL_XFER_ST; ++ writel(fl_reg, nfc->regs + nfc->cfg->flctl_off); ++} ++ ++static int rk_nfc_wait_for_xfer_done(struct rk_nfc *nfc) ++{ ++ void __iomem *ptr; ++ int ret = 0; ++ u32 reg; ++ ++ ptr = nfc->regs + nfc->cfg->flctl_off; ++ ++ ret = readl_poll_timeout_atomic(ptr, reg, ++ reg & FLCTL_XFER_READY, ++ 10, NFC_TIMEOUT); ++ ++ return ret; ++} ++ ++static int rk_nfc_write_page(struct mtd_info *mtd, struct nand_chip *chip, ++ const u8 *buf, int page, int raw) ++{ ++ struct rk_nfc *nfc = nand_get_controller_data(chip); ++ struct rk_nfc_nand_chip *rknand = to_rknand(chip); ++ struct nand_ecc_ctrl *ecc = &chip->ecc; ++ int oob_step = (ecc->bytes > 60) ? NFC_MAX_OOB_PER_STEP : ++ NFC_MIN_OOB_PER_STEP; ++ int pages_per_blk = mtd->erasesize / mtd->writesize; ++ int ret = 0, i, boot_rom_mode = 0; ++ dma_addr_t dma_data, dma_oob; ++ u32 reg; ++ u8 *oob; ++ ++ nand_prog_page_begin_op(chip, page, 0, NULL, 0); ++ ++ if (!raw) { ++ memcpy(nfc->page_buf, buf, mtd->writesize); ++ memset(nfc->oob_buf, 0xff, oob_step * ecc->steps); ++ ++ /* ++ * The first 8(some devices are 4 or 16) blocks are in use by ++ * the boot ROM and the first 32 bits of oob need to link ++ * to the next page address in the same block. ++ * Config the ECC algorithm supported by the boot ROM. ++ */ ++ if (page < pages_per_blk * rknand->boot_blks && ++ chip->options & NAND_IS_BOOT_MEDIUM) { ++ boot_rom_mode = 1; ++ if (rknand->boot_ecc != ecc->strength) ++ rk_nfc_hw_ecc_setup(chip, ecc, ++ rknand->boot_ecc); ++ } ++ ++ for (i = 0; i < ecc->steps; i++) { ++ if (!i) { ++ reg = 0xFFFFFFFF; ++ } else { ++ oob = chip->oob_poi + (i - 1) * NFC_SYS_DATA_SIZE; ++ reg = oob[0] | oob[1] << 8 | oob[2] << 16 | ++ oob[3] << 24; ++ } ++ if (!i && boot_rom_mode) ++ reg = (page & (pages_per_blk - 1)) * 4; ++ ++ if (nfc->cfg->type == NFC_V9) ++ nfc->oob_buf[i] = reg; ++ else ++ nfc->oob_buf[i * oob_step / 4] = reg; ++ } ++ ++ dma_data = dma_map_single(nfc->dev, (void *)nfc->page_buf, ++ mtd->writesize, DMA_TO_DEVICE); ++ dma_oob = dma_map_single(nfc->dev, nfc->oob_buf, ++ ecc->steps * oob_step, ++ DMA_TO_DEVICE); ++ ++ reinit_completion(&nfc->done); ++ writel(INT_DMA, nfc->regs + nfc->cfg->int_en_off); ++ ++ rk_nfc_xfer_start(nfc, NFC_WRITE, ecc->steps, dma_data, ++ dma_oob); ++ ret = wait_for_completion_timeout(&nfc->done, ++ msecs_to_jiffies(100)); ++ if (!ret) ++ dev_warn(nfc->dev, "write: wait dma done timeout.\n"); ++ /* ++ * Whether the DMA transfer is completed or not. The driver ++ * needs to check the NFC`s status register to see if the data ++ * transfer was completed. ++ */ ++ ret = rk_nfc_wait_for_xfer_done(nfc); ++ ++ dma_unmap_single(nfc->dev, dma_data, mtd->writesize, ++ DMA_TO_DEVICE); ++ dma_unmap_single(nfc->dev, dma_oob, ecc->steps * oob_step, ++ DMA_TO_DEVICE); ++ ++ if (boot_rom_mode && rknand->boot_ecc != ecc->strength) ++ rk_nfc_hw_ecc_setup(chip, ecc, ecc->strength); ++ ++ if (ret) { ++ ret = -EIO; ++ dev_err(nfc->dev, ++ "write: wait transfer done timeout.\n"); ++ } ++ } else { ++ rk_nfc_write_buf(chip, buf, mtd->writesize + mtd->oobsize); ++ } ++ ++ if (ret) ++ return ret; ++ ++ ret = nand_prog_page_end_op(chip); ++ ++ /* Deselect the currently selected target. */ ++ rk_nfc_select_chip(chip, -1); ++ ++ return ret; ++} ++ ++static int rk_nfc_write_page_raw(struct nand_chip *chip, const u8 *buf, ++ int oob_on, int page) ++{ ++ struct mtd_info *mtd = nand_to_mtd(chip); ++ struct rk_nfc *nfc = nand_get_controller_data(chip); ++ u32 i; ++ ++ memset(nfc->buffer, 0xff, mtd->writesize + mtd->oobsize); ++ ++ for (i = 0; i < chip->ecc.steps; i++) { ++ if (buf) ++ memcpy(rk_data_ptr(chip, i), data_ptr(chip, buf, i), ++ chip->ecc.size); ++ ++ if (!i) ++ memcpy(rk_oob_ptr(chip, i), ++ oob_ptr(chip, chip->ecc.steps - 1), ++ NFC_SYS_DATA_SIZE); ++ else ++ memcpy(rk_oob_ptr(chip, i), oob_ptr(chip, i - 1), ++ NFC_SYS_DATA_SIZE); ++ ++ memcpy(rk_oob_ptr(chip, i) + NFC_SYS_DATA_SIZE, ++ oob_ecc_ptr(chip, i), ++ chip->ecc.bytes); ++ } ++ ++ return rk_nfc_write_page(mtd, chip, nfc->buffer, page, 1); ++} ++ ++static int rk_nfc_write_oob_std(struct nand_chip *chip, int page) ++{ ++ return rk_nfc_write_page_raw(chip, NULL, 1, page); ++} ++ ++static int rk_nfc_read_page(struct mtd_info *mtd, struct nand_chip *chip, ++ u32 data_offs, u32 readlen, ++ u8 *buf, int page, int raw) ++{ ++ struct rk_nfc *nfc = nand_get_controller_data(chip); ++ struct rk_nfc_nand_chip *rknand = to_rknand(chip); ++ struct nand_ecc_ctrl *ecc = &chip->ecc; ++ int oob_step = (ecc->bytes > 60) ? NFC_MAX_OOB_PER_STEP : ++ NFC_MIN_OOB_PER_STEP; ++ int pages_per_blk = mtd->erasesize / mtd->writesize; ++ dma_addr_t dma_data, dma_oob; ++ int ret = 0, i, boot_rom_mode = 0; ++ int bitflips = 0, bch_st; ++ u8 *oob; ++ u32 tmp; ++ ++ nand_read_page_op(chip, page, 0, NULL, 0); ++ if (!raw) { ++ dma_data = dma_map_single(nfc->dev, nfc->page_buf, ++ mtd->writesize, ++ DMA_FROM_DEVICE); ++ dma_oob = dma_map_single(nfc->dev, nfc->oob_buf, ++ ecc->steps * oob_step, ++ DMA_FROM_DEVICE); ++ ++ /* ++ * The first 8(some devices are 4 or 16) blocks are in use by ++ * the boot ROM. ++ * Config the ECC algorithm supported by the boot ROM. ++ */ ++ if (page < pages_per_blk * rknand->boot_blks && ++ chip->options & NAND_IS_BOOT_MEDIUM) { ++ boot_rom_mode = 1; ++ if (rknand->boot_ecc != ecc->strength) ++ rk_nfc_hw_ecc_setup(chip, ecc, ++ rknand->boot_ecc); ++ } ++ ++ reinit_completion(&nfc->done); ++ writel(INT_DMA, nfc->regs + nfc->cfg->int_en_off); ++ rk_nfc_xfer_start(nfc, NFC_READ, ecc->steps, dma_data, ++ dma_oob); ++ ret = wait_for_completion_timeout(&nfc->done, ++ msecs_to_jiffies(100)); ++ if (!ret) ++ dev_warn(nfc->dev, "read: wait dma done timeout.\n"); ++ /* ++ * Whether the DMA transfer is completed or not. The driver ++ * needs to check the NFC`s status register to see if the data ++ * transfer was completed. ++ */ ++ ret = rk_nfc_wait_for_xfer_done(nfc); ++ dma_unmap_single(nfc->dev, dma_data, mtd->writesize, ++ DMA_FROM_DEVICE); ++ dma_unmap_single(nfc->dev, dma_oob, ecc->steps * oob_step, ++ DMA_FROM_DEVICE); ++ ++ if (ret) { ++ bitflips = -EIO; ++ dev_err(nfc->dev, ++ "read: wait transfer done timeout.\n"); ++ goto out; ++ } ++ ++ for (i = 1; i < ecc->steps; i++) { ++ oob = chip->oob_poi + (i - 1) * NFC_SYS_DATA_SIZE; ++ if (nfc->cfg->type == NFC_V9) ++ tmp = nfc->oob_buf[i]; ++ else ++ tmp = nfc->oob_buf[i * oob_step / 4]; ++ *oob++ = (u8)tmp; ++ *oob++ = (u8)(tmp >> 8); ++ *oob++ = (u8)(tmp >> 16); ++ *oob++ = (u8)(tmp >> 24); ++ } ++ ++ for (i = 0; i < ecc->steps / 2; i++) { ++ bch_st = readl_relaxed(nfc->regs + ++ nfc->cfg->bch_st_off + i * 4); ++ if (bch_st & BIT(nfc->cfg->ecc0.err_flag_bit) || ++ bch_st & BIT(nfc->cfg->ecc1.err_flag_bit)) { ++ mtd->ecc_stats.failed++; ++ bitflips = -1; ++ } else { ++ ret = ECC_ERR_CNT(bch_st, nfc->cfg->ecc0); ++ mtd->ecc_stats.corrected += ret; ++ bitflips = max_t(u32, bitflips, ret); ++ ++ ret = ECC_ERR_CNT(bch_st, nfc->cfg->ecc1); ++ mtd->ecc_stats.corrected += ret; ++ bitflips = max_t(u32, bitflips, ret); ++ } ++ } ++out: ++ memcpy(buf, nfc->page_buf, mtd->writesize); ++ ++ if (boot_rom_mode && rknand->boot_ecc != ecc->strength) ++ rk_nfc_hw_ecc_setup(chip, ecc, ecc->strength); ++ ++ if (bitflips < 0) ++ dev_err(nfc->dev, "read page: %x ecc error!\n", page); ++ } else { ++ rk_nfc_read_buf(chip, buf, mtd->writesize + mtd->oobsize); ++ } ++ /* Deselect the currently selected target. */ ++ rk_nfc_select_chip(chip, -1); ++ ++ return bitflips; ++} ++ ++static int rk_nfc_write_page_hwecc(struct nand_chip *chip, const u8 *buf, ++ int oob_on, int page) ++{ ++ return rk_nfc_write_page(nand_to_mtd(chip), chip, buf, page, 0); ++} ++ ++static int rk_nfc_read_page_hwecc(struct nand_chip *chip, u8 *p, int oob_on, ++ int pg) ++{ ++ struct mtd_info *mtd = nand_to_mtd(chip); ++ ++ return rk_nfc_read_page(mtd, chip, 0, mtd->writesize, p, pg, 0); ++} ++ ++static int rk_nfc_read_page_raw(struct nand_chip *chip, u8 *buf, int oob_on, ++ int page) ++{ ++ struct mtd_info *mtd = nand_to_mtd(chip); ++ struct rk_nfc *nfc = nand_get_controller_data(chip); ++ int i, ret; ++ ++ ret = rk_nfc_read_page(mtd, chip, 0, mtd->writesize, nfc->buffer, ++ page, 1); ++ if (ret < 0) ++ return ret; ++ ++ for (i = 0; i < chip->ecc.steps; i++) { ++ if (!i) ++ memcpy(oob_ptr(chip, chip->ecc.steps - 1), ++ rk_oob_ptr(chip, i), ++ NFC_SYS_DATA_SIZE); ++ else ++ memcpy(oob_ptr(chip, i - 1), rk_oob_ptr(chip, i), ++ NFC_SYS_DATA_SIZE); ++ ++ memcpy(oob_ecc_ptr(chip, i), ++ rk_oob_ptr(chip, i) + NFC_SYS_DATA_SIZE, ++ chip->ecc.bytes); ++ ++ if (buf) ++ memcpy(data_ptr(chip, buf, i), rk_data_ptr(chip, i), ++ chip->ecc.size); ++ } ++ ++ return ret; ++} ++ ++static int rk_nfc_read_oob_std(struct nand_chip *chip, int page) ++{ ++ return rk_nfc_read_page_raw(chip, NULL, 1, page); ++} ++ ++static inline void rk_nfc_hw_init(struct rk_nfc *nfc) ++{ ++ /* Disable flash wp. */ ++ writel(FMCTL_WP, nfc->regs + NFC_FMCTL); ++ /* Config default timing 40ns at 150 Mhz nfc clock. */ ++ writel(0x1081, nfc->regs + NFC_FMWAIT); ++ /* Disable randomizer and DMA. */ ++ writel(0, nfc->regs + nfc->cfg->randmz_off); ++ writel(0, nfc->regs + nfc->cfg->dma_cfg_off); ++ writel(FLCTL_RST, nfc->regs + nfc->cfg->flctl_off); ++} ++ ++static irqreturn_t rk_nfc_irq(int irq, void *id) ++{ ++ struct rk_nfc *nfc = id; ++ u32 sta, ien; ++ ++ sta = readl_relaxed(nfc->regs + nfc->cfg->int_st_off); ++ ien = readl_relaxed(nfc->regs + nfc->cfg->int_en_off); ++ ++ if (!(sta & ien)) ++ return IRQ_NONE; ++ ++ writel(sta, nfc->regs + nfc->cfg->int_clr_off); ++ writel(~sta & ien, nfc->regs + nfc->cfg->int_en_off); ++ ++ complete(&nfc->done); ++ ++ return IRQ_HANDLED; ++} ++ ++static int rk_nfc_enable_clk(struct device *dev, struct rk_nfc_clk *clk) ++{ ++ int ret; ++ ++ if (!IS_ERR(clk->nfc_clk)) { ++ ret = clk_prepare_enable(clk->nfc_clk); ++ if (ret) { ++ dev_err(dev, "failed to enable nfc clk\n"); ++ return ret; ++ } ++ } ++ ++ ret = clk_prepare_enable(clk->ahb_clk); ++ if (ret) { ++ dev_err(dev, "failed to enable ahb clk\n"); ++ if (!IS_ERR(clk->nfc_clk)) ++ clk_disable_unprepare(clk->nfc_clk); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static void rk_nfc_disable_clk(struct rk_nfc_clk *clk) ++{ ++ if (!IS_ERR(clk->nfc_clk)) ++ clk_disable_unprepare(clk->nfc_clk); ++ clk_disable_unprepare(clk->ahb_clk); ++} ++ ++static int rk_nfc_ooblayout_free(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oob_region) ++{ ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct rk_nfc_nand_chip *rknand = to_rknand(chip); ++ ++ if (section) ++ return -ERANGE; ++ ++ /* ++ * The beginning of the oob area stores the reserved data for the NFC, ++ * the size of the reserved data is NFC_SYS_DATA_SIZE bytes. ++ */ ++ oob_region->length = rknand->metadata_size - NFC_SYS_DATA_SIZE - 2; ++ oob_region->offset = NFC_SYS_DATA_SIZE + 2; ++ ++ return 0; ++} ++ ++static int rk_nfc_ooblayout_ecc(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oob_region) ++{ ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct rk_nfc_nand_chip *rknand = to_rknand(chip); ++ ++ if (section) ++ return -ERANGE; ++ ++ oob_region->offset = rknand->metadata_size; ++ oob_region->length = mtd->oobsize - oob_region->offset; ++ ++ return 0; ++} ++ ++static const struct mtd_ooblayout_ops rk_nfc_ooblayout_ops = { ++ .free = rk_nfc_ooblayout_free, ++ .ecc = rk_nfc_ooblayout_ecc, ++}; ++ ++static int rk_nfc_ecc_init(struct device *dev, struct mtd_info *mtd) ++{ ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct rk_nfc *nfc = nand_get_controller_data(chip); ++ struct nand_ecc_ctrl *ecc = &chip->ecc; ++ const u8 *strengths = nfc->cfg->ecc_strengths; ++ u8 max_strength, nfc_max_strength; ++ int i; ++ ++ nfc_max_strength = nfc->cfg->ecc_strengths[0]; ++ /* If optional dt settings not present. */ ++ if (!ecc->size || !ecc->strength || ++ ecc->strength > nfc_max_strength) { ++ /* Use datasheet requirements. */ ++ ecc->strength = chip->base.eccreq.strength; ++ ecc->size = chip->base.eccreq.step_size; ++ ++ /* Align ECC strength and ECC size. */ ++ if (chip->ecc.size < 1024) { ++ if (mtd->writesize > 512) { ++ chip->ecc.size = 1024; ++ chip->ecc.strength <<= 1; ++ } else { ++ dev_err(dev, "Unsupported ecc.size\n"); ++ return -EINVAL; ++ } ++ } else { ++ chip->ecc.size = 1024; ++ } ++ ++ ecc->steps = mtd->writesize / ecc->size; ++ ++ /* ++ * HW ECC always requests the number of ECC bytes per 1024 byte ++ * blocks. 4 Bytes is oob for sys data. ++ */ ++ max_strength = ((mtd->oobsize / ecc->steps) - 4) * 8 / ++ fls(8 * 1024); ++ if (max_strength > nfc_max_strength) ++ max_strength = nfc_max_strength; ++ ++ for (i = 0; i < 4; i++) { ++ if (max_strength >= strengths[i]) ++ break; ++ } ++ ++ if (i >= 4) { ++ dev_err(nfc->dev, "Unsupported ECC strength\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ ecc->strength = strengths[i]; ++ } ++ ecc->steps = mtd->writesize / ecc->size; ++ ecc->bytes = DIV_ROUND_UP(ecc->strength * fls(8 * 1024), 8); ++ /* HW ECC always work with even numbers of ECC bytes. */ ++ ecc->bytes = ALIGN(ecc->bytes, 2); ++ ++ rk_nfc_hw_ecc_setup(chip, ecc, ecc->strength); ++ ++ return 0; ++} ++ ++static int rk_nfc_attach_chip(struct nand_chip *chip) ++{ ++ struct mtd_info *mtd = nand_to_mtd(chip); ++ struct device *dev = mtd->dev.parent; ++ struct rk_nfc *nfc = nand_get_controller_data(chip); ++ struct rk_nfc_nand_chip *rknand = to_rknand(chip); ++ struct nand_ecc_ctrl *ecc = &chip->ecc; ++ int len; ++ int ret; ++ ++ if (chip->options & NAND_BUSWIDTH_16) { ++ dev_err(dev, "16 bits bus width not supported"); ++ return -EINVAL; ++ } ++ ++ if (ecc->mode != NAND_ECC_HW) ++ return 0; ++ ++ ret = rk_nfc_ecc_init(dev, mtd); ++ if (ret) ++ return ret; ++ rknand->spare_per_sector = ecc->bytes + NFC_SYS_DATA_SIZE; ++ rknand->metadata_size = NFC_SYS_DATA_SIZE * ecc->steps; ++ ++ if (rknand->metadata_size < NFC_SYS_DATA_SIZE + 2) { ++ dev_err(dev, ++ "Driver needs at least %d bytes of meta data\n", ++ NFC_SYS_DATA_SIZE + 2); ++ return -EIO; ++ } ++ /* Check buffer first, avoid duplicate alloc buffer. */ ++ if (nfc->buffer) ++ return 0; ++ ++ len = mtd->writesize + mtd->oobsize; ++ nfc->buffer = devm_kzalloc(dev, len, GFP_KERNEL | GFP_DMA); ++ if (!nfc->buffer) ++ return -ENOMEM; ++ ++ nfc->page_buf = nfc->buffer; ++ len = ecc->steps * NFC_MAX_OOB_PER_STEP; ++ nfc->oob_buf = devm_kzalloc(dev, len, GFP_KERNEL | GFP_DMA); ++ if (!nfc->oob_buf) { ++ nfc->buffer = NULL; ++ nfc->oob_buf = NULL; ++ return -ENOMEM; ++ } ++ ++ chip->ecc.write_page_raw = rk_nfc_write_page_raw; ++ chip->ecc.write_page = rk_nfc_write_page_hwecc; ++ chip->ecc.write_oob_raw = rk_nfc_write_oob_std; ++ chip->ecc.write_oob = rk_nfc_write_oob_std; ++ ++ chip->ecc.read_page_raw = rk_nfc_read_page_raw; ++ chip->ecc.read_page = rk_nfc_read_page_hwecc; ++ chip->ecc.read_oob_raw = rk_nfc_read_oob_std; ++ chip->ecc.read_oob = rk_nfc_read_oob_std; ++ ++ return 0; ++} ++ ++static const struct nand_controller_ops rk_nfc_controller_ops = { ++ .attach_chip = rk_nfc_attach_chip, ++ .exec_op = rk_nfc_exec_op, ++ .setup_data_interface = rk_nfc_setup_data_interface, ++}; ++ ++static int rk_nfc_nand_chip_init(struct device *dev, struct rk_nfc *nfc, ++ struct device_node *np) ++{ ++ struct rk_nfc_nand_chip *rknand; ++ struct nand_chip *chip; ++ struct mtd_info *mtd; ++ int nsels; ++ u32 tmp; ++ int ret; ++ int i; ++ ++ if (!of_get_property(np, "reg", &nsels)) ++ return -ENODEV; ++ nsels /= sizeof(u32); ++ if (!nsels || nsels > NFC_MAX_NSELS) { ++ dev_err(dev, "invalid reg property size %d\n", nsels); ++ return -EINVAL; ++ } ++ ++ rknand = devm_kzalloc(dev, sizeof(*rknand) + nsels * sizeof(u8), ++ GFP_KERNEL); ++ if (!rknand) ++ return -ENOMEM; ++ ++ rknand->nsels = nsels; ++ for (i = 0; i < nsels; i++) { ++ ret = of_property_read_u32_index(np, "reg", i, &tmp); ++ if (ret) { ++ dev_err(dev, "reg property failure : %d\n", ret); ++ return ret; ++ } ++ ++ if (tmp >= NFC_MAX_NSELS) { ++ dev_err(dev, "invalid CS: %u\n", tmp); ++ return -EINVAL; ++ } ++ ++ if (test_and_set_bit(tmp, &nfc->assigned_cs)) { ++ dev_err(dev, "CS %u already assigned\n", tmp); ++ return -EINVAL; ++ } ++ ++ rknand->sels[i] = tmp; ++ } ++ ++ chip = &rknand->chip; ++ chip->controller = &nfc->controller; ++ ++ nand_set_flash_node(chip, np); ++ ++ nand_set_controller_data(chip, nfc); ++ ++ chip->options |= NAND_USES_DMA | NAND_NO_SUBPAGE_WRITE; ++ chip->bbt_options = NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB; ++ ++ /* Set default mode in case dt entry is missing. */ ++ chip->ecc.mode = NAND_ECC_HW; ++ ++ mtd = nand_to_mtd(chip); ++ mtd->owner = THIS_MODULE; ++ mtd->dev.parent = dev; ++ ++ if (!mtd->name) { ++ dev_err(nfc->dev, "NAND label property is mandatory\n"); ++ return -EINVAL; ++ } ++ ++ mtd_set_ooblayout(mtd, &rk_nfc_ooblayout_ops); ++ rk_nfc_hw_init(nfc); ++ ret = nand_scan(chip, nsels); ++ if (ret) ++ return ret; ++ ++ if (chip->options & NAND_IS_BOOT_MEDIUM) { ++ ret = of_property_read_u32(np, "rockchip,boot-blks", &tmp); ++ rknand->boot_blks = ret ? 0 : tmp; ++ ++ ret = of_property_read_u32(np, "rockchip,boot-ecc-strength", ++ &tmp); ++ rknand->boot_ecc = ret ? chip->ecc.strength : tmp; ++ } ++ ++ ret = mtd_device_register(mtd, NULL, 0); ++ if (ret) { ++ dev_err(dev, "mtd parse partition error\n"); ++ nand_cleanup(chip); ++ return ret; ++ } ++ ++ list_add_tail(&rknand->node, &nfc->chips); ++ ++ return 0; ++} ++ ++static void rk_nfc_chips_cleanup(struct rk_nfc *nfc) ++{ ++ struct rk_nfc_nand_chip *rknand, *tmp; ++ struct nand_chip *chip; ++ int ret; ++ ++ list_for_each_entry_safe(rknand, tmp, &nfc->chips, node) { ++ chip = &rknand->chip; ++ ret = mtd_device_unregister(nand_to_mtd(chip)); ++ WARN_ON(ret); ++ nand_cleanup(chip); ++ list_del(&rknand->node); ++ } ++} ++ ++static int rk_nfc_nand_chips_init(struct device *dev, struct rk_nfc *nfc) ++{ ++ struct device_node *np = dev->of_node, *nand_np; ++ int nchips = of_get_child_count(np); ++ int ret; ++ ++ if (!nchips || nchips > NFC_MAX_NSELS) { ++ dev_err(nfc->dev, "Incorrect number of NAND chips (%d)\n", ++ nchips); ++ return -EINVAL; ++ } ++ ++ for_each_child_of_node(np, nand_np) { ++ ret = rk_nfc_nand_chip_init(dev, nfc, nand_np); ++ if (ret) { ++ of_node_put(nand_np); ++ rk_nfc_chips_cleanup(nfc); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++static struct nfc_cfg nfc_v6_cfg = { ++ .type = NFC_V6, ++ .ecc_strengths = {60, 40, 24, 16}, ++ .ecc_cfgs = { ++ 0x00040011, 0x00040001, 0x00000011, 0x00000001, ++ }, ++ .flctl_off = 0x08, ++ .bchctl_off = 0x0C, ++ .dma_cfg_off = 0x10, ++ .dma_data_buf_off = 0x14, ++ .dma_oob_buf_off = 0x18, ++ .dma_st_off = 0x1C, ++ .bch_st_off = 0x20, ++ .randmz_off = 0x150, ++ .int_en_off = 0x16C, ++ .int_clr_off = 0x170, ++ .int_st_off = 0x174, ++ .oob0_off = 0x200, ++ .oob1_off = 0x230, ++ .ecc0 = { ++ .err_flag_bit = 2, ++ .low = 3, ++ .low_mask = 0x1F, ++ .low_bn = 5, ++ .high = 27, ++ .high_mask = 0x1, ++ }, ++ .ecc1 = { ++ .err_flag_bit = 15, ++ .low = 16, ++ .low_mask = 0x1F, ++ .low_bn = 5, ++ .high = 29, ++ .high_mask = 0x1, ++ }, ++}; ++ ++static struct nfc_cfg nfc_v8_cfg = { ++ .type = NFC_V8, ++ .ecc_strengths = {16, 16, 16, 16}, ++ .ecc_cfgs = { ++ 0x00000001, 0x00000001, 0x00000001, 0x00000001, ++ }, ++ .flctl_off = 0x08, ++ .bchctl_off = 0x0C, ++ .dma_cfg_off = 0x10, ++ .dma_data_buf_off = 0x14, ++ .dma_oob_buf_off = 0x18, ++ .dma_st_off = 0x1C, ++ .bch_st_off = 0x20, ++ .randmz_off = 0x150, ++ .int_en_off = 0x16C, ++ .int_clr_off = 0x170, ++ .int_st_off = 0x174, ++ .oob0_off = 0x200, ++ .oob1_off = 0x230, ++ .ecc0 = { ++ .err_flag_bit = 2, ++ .low = 3, ++ .low_mask = 0x1F, ++ .low_bn = 5, ++ .high = 27, ++ .high_mask = 0x1, ++ }, ++ .ecc1 = { ++ .err_flag_bit = 15, ++ .low = 16, ++ .low_mask = 0x1F, ++ .low_bn = 5, ++ .high = 29, ++ .high_mask = 0x1, ++ }, ++}; ++ ++static struct nfc_cfg nfc_v9_cfg = { ++ .type = NFC_V9, ++ .ecc_strengths = {70, 60, 40, 16}, ++ .ecc_cfgs = { ++ 0x00000001, 0x06000001, 0x04000001, 0x02000001, ++ }, ++ .flctl_off = 0x10, ++ .bchctl_off = 0x20, ++ .dma_cfg_off = 0x30, ++ .dma_data_buf_off = 0x34, ++ .dma_oob_buf_off = 0x38, ++ .dma_st_off = 0x3C, ++ .bch_st_off = 0x150, ++ .randmz_off = 0x208, ++ .int_en_off = 0x120, ++ .int_clr_off = 0x124, ++ .int_st_off = 0x128, ++ .oob0_off = 0x200, ++ .oob1_off = 0x204, ++ .ecc0 = { ++ .err_flag_bit = 2, ++ .low = 3, ++ .low_mask = 0x7F, ++ .low_bn = 7, ++ .high = 0, ++ .high_mask = 0x0, ++ }, ++ .ecc1 = { ++ .err_flag_bit = 18, ++ .low = 19, ++ .low_mask = 0x7F, ++ .low_bn = 7, ++ .high = 0, ++ .high_mask = 0x0, ++ }, ++}; ++ ++static const struct of_device_id rk_nfc_id_table[] = { ++ {.compatible = "rockchip,px30-nfc", ++ .data = &nfc_v9_cfg }, ++ {.compatible = "rockchip,rk2928-nfc", ++ .data = &nfc_v6_cfg }, ++ {.compatible = "rockchip,rv1108-nfc", ++ .data = &nfc_v8_cfg }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, rk_nfc_id_table); ++ ++static int rk_nfc_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct rk_nfc *nfc; ++ int ret, irq; ++ ++ nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL); ++ if (!nfc) ++ return -ENOMEM; ++ ++ nand_controller_init(&nfc->controller); ++ INIT_LIST_HEAD(&nfc->chips); ++ nfc->controller.ops = &rk_nfc_controller_ops; ++ ++ nfc->cfg = of_device_get_match_data(dev); ++ nfc->dev = dev; ++ ++ init_completion(&nfc->done); ++ ++ nfc->regs = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(nfc->regs)) { ++ ret = PTR_ERR(nfc->regs); ++ goto release_nfc; ++ } ++ ++ nfc->clk.nfc_clk = devm_clk_get(dev, "nfc"); ++ if (IS_ERR(nfc->clk.nfc_clk)) { ++ dev_dbg(dev, "no nfc clk\n"); ++ /* Some earlier models, such as rk3066, have no nfc clk. */ ++ } ++ ++ nfc->clk.ahb_clk = devm_clk_get(dev, "ahb"); ++ if (IS_ERR(nfc->clk.ahb_clk)) { ++ dev_err(dev, "no ahb clk\n"); ++ ret = PTR_ERR(nfc->clk.ahb_clk); ++ goto release_nfc; ++ } ++ ++ ret = rk_nfc_enable_clk(dev, &nfc->clk); ++ if (ret) ++ goto release_nfc; ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ dev_err(dev, "no nfc irq resource\n"); ++ ret = -EINVAL; ++ goto clk_disable; ++ } ++ ++ writel(0, nfc->regs + nfc->cfg->int_en_off); ++ ret = devm_request_irq(dev, irq, rk_nfc_irq, 0x0, "rk-nand", nfc); ++ if (ret) { ++ dev_err(dev, "failed to request nfc irq\n"); ++ goto clk_disable; ++ } ++ ++ platform_set_drvdata(pdev, nfc); ++ ++ ret = rk_nfc_nand_chips_init(dev, nfc); ++ if (ret) { ++ dev_err(dev, "failed to init NAND chips\n"); ++ goto clk_disable; ++ } ++ return 0; ++ ++clk_disable: ++ rk_nfc_disable_clk(&nfc->clk); ++release_nfc: ++ return ret; ++} ++ ++static int rk_nfc_remove(struct platform_device *pdev) ++{ ++ struct rk_nfc *nfc = platform_get_drvdata(pdev); ++ ++ rk_nfc_chips_cleanup(nfc); ++ rk_nfc_disable_clk(&nfc->clk); ++ ++ return 0; ++} ++ ++static int __maybe_unused rk_nfc_suspend(struct device *dev) ++{ ++ struct rk_nfc *nfc = dev_get_drvdata(dev); ++ ++ rk_nfc_disable_clk(&nfc->clk); ++ ++ return 0; ++} ++ ++static int __maybe_unused rk_nfc_resume(struct device *dev) ++{ ++ struct rk_nfc *nfc = dev_get_drvdata(dev); ++ struct rk_nfc_nand_chip *rknand; ++ struct nand_chip *chip; ++ int ret; ++ u32 i; ++ ++ ret = rk_nfc_enable_clk(dev, &nfc->clk); ++ if (ret) ++ return ret; ++ ++ /* Reset NAND chip if VCC was powered off. */ ++ list_for_each_entry(rknand, &nfc->chips, node) { ++ chip = &rknand->chip; ++ for (i = 0; i < rknand->nsels; i++) ++ nand_reset(chip, i); ++ } ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops rk_nfc_pm_ops = { ++ SET_SYSTEM_SLEEP_PM_OPS(rk_nfc_suspend, rk_nfc_resume) ++}; ++ ++static struct platform_driver rk_nfc_driver = { ++ .probe = rk_nfc_probe, ++ .remove = rk_nfc_remove, ++ .driver = { ++ .name = "rockchip-nfc", ++ .of_match_table = rk_nfc_id_table, ++ .pm = &rk_nfc_pm_ops, ++ }, ++}; ++ ++module_platform_driver(rk_nfc_driver); ++ ++MODULE_LICENSE("Dual MIT/GPL"); ++MODULE_AUTHOR("Yifeng Zhao "); ++MODULE_DESCRIPTION("Rockchip Nand Flash Controller Driver"); ++MODULE_ALIAS("platform:rockchip-nand-controller"); + +From 9f9bc458898c407f25a6d38551713317161b0092 Mon Sep 17 00:00:00 2001 +From: Yifeng Zhao +Date: Fri, 17 Jul 2020 17:24:19 +0800 +Subject: [PATCH] MAINTAINERS: add maintainers to ROCKCHIP NFC + +Add maintainers to ROCKCHIP NFC. + +Signed-off-by: Yifeng Zhao +--- + MAINTAINERS | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/MAINTAINERS b/MAINTAINERS +index 4e2698cc7e23..db98a799f409 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -2344,12 +2344,12 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) + L: linux-rockchip@lists.infradead.org + S: Maintained + T: git git://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git ++F: Documentation/devicetree/bindings/*/*rockchip*.yaml + F: Documentation/devicetree/bindings/i2c/i2c-rk3x.yaml +-F: Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml +-F: Documentation/devicetree/bindings/spi/spi-rockchip.yaml + F: arch/arm/boot/dts/rk3* + F: arch/arm/boot/dts/rv1108* + F: arch/arm/mach-rockchip/ ++F: drivers/*/*/*/*rockchip* + F: drivers/*/*/*rockchip* + F: drivers/*/*rockchip* + F: drivers/clk/rockchip/ + +From 48604da8047dc2bb8009ee7af76655b41fb0c337 Mon Sep 17 00:00:00 2001 +From: Yifeng Zhao +Date: Fri, 17 Jul 2020 17:24:20 +0800 +Subject: [PATCH] arm64: dts: rockchip: Add NFC node for RK3308 SoC + +Add NAND FLASH Controller(NFC) node for RK3308 SoC. + +Signed-off-by: Yifeng Zhao +Signed-off-by: Yifeng Zhao +--- + arch/arm64/boot/dts/rockchip/rk3308.dtsi | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3308.dtsi b/arch/arm64/boot/dts/rockchip/rk3308.dtsi +index e8b754d415d8..e9d8610fccf5 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3308.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3308.dtsi +@@ -629,6 +629,21 @@ sdio: mmc@ff4a0000 { + status = "disabled"; + }; + ++ nfc: nand-controller@ff4b0000 { ++ compatible = "rockchip,rk3308-nfc", ++ "rockchip,rv1108-nfc"; ++ reg = <0x0 0xff4b0000 0x0 0x4000>; ++ interrupts = ; ++ clocks = <&cru HCLK_NANDC>, <&cru SCLK_NANDC>; ++ clock-names = "ahb", "nfc"; ++ assigned-clocks = <&cru SCLK_NANDC>; ++ assigned-clock-rates = <150000000>; ++ pinctrl-0 = <&flash_ale &flash_bus8 &flash_cle &flash_csn0 ++ &flash_rdn &flash_rdy &flash_wrn>; ++ pinctrl-names = "default"; ++ status = "disabled"; ++ }; ++ + cru: clock-controller@ff500000 { + compatible = "rockchip,rk3308-cru"; + reg = <0x0 0xff500000 0x0 0x1000>; + +From 046465fffd8f588097ed6f78bc3f193639bd5657 Mon Sep 17 00:00:00 2001 +From: Yifeng Zhao +Date: Fri, 17 Jul 2020 17:25:29 +0800 +Subject: [PATCH] arm64: dts: rockchip: Add NFC node for PX30 SoC + +Add NAND FLASH Controller(NFC) node for PX30 SoC. + +Signed-off-by: Yifeng Zhao +--- + arch/arm64/boot/dts/rockchip/px30.dtsi | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi +index 2695ea8cda14..6cd67e80d623 100644 +--- a/arch/arm64/boot/dts/rockchip/px30.dtsi ++++ b/arch/arm64/boot/dts/rockchip/px30.dtsi +@@ -973,6 +973,21 @@ emmc: mmc@ff390000 { + status = "disabled"; + }; + ++ nfc: nand-controller@ff3b0000 { ++ compatible = "rockchip,px30-nfc"; ++ reg = <0x0 0xff3b0000 0x0 0x4000>; ++ interrupts = ; ++ clocks = <&cru HCLK_NANDC>, <&cru SCLK_NANDC>; ++ clock-names = "ahb", "nfc"; ++ assigned-clocks = <&cru SCLK_NANDC>; ++ assigned-clock-rates = <150000000>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&flash_ale &flash_bus8 &flash_cle &flash_cs0 ++ &flash_rdn &flash_rdy &flash_wrn &flash_dqs>; ++ power-domains = <&power PX30_PD_MMC_NAND>; ++ status = "disabled"; ++ }; ++ + gpu: gpu@ff400000 { + compatible = "rockchip,px30-mali", "arm,mali-bifrost"; + reg = <0x0 0xff400000 0x0 0x4000>; + +From e67947a6ea98d31eda5e900909bc762714e97062 Mon Sep 17 00:00:00 2001 +From: Yifeng Zhao +Date: Fri, 17 Jul 2020 17:25:30 +0800 +Subject: [PATCH] arm: dts: rockchip: Add NFC node for RV1108 SoC + +Add NAND FLASH Controller(NFC) node for RV1108 SoC. + +Signed-off-by: Yifeng Zhao +--- + arch/arm/boot/dts/rv1108.dtsi | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/arch/arm/boot/dts/rv1108.dtsi b/arch/arm/boot/dts/rv1108.dtsi +index a1a08cb9364e..1696ea19488b 100644 +--- a/arch/arm/boot/dts/rv1108.dtsi ++++ b/arch/arm/boot/dts/rv1108.dtsi +@@ -452,6 +452,17 @@ cru: clock-controller@20200000 { + #reset-cells = <1>; + }; + ++ nfc: nand-controller@30100000 { ++ compatible = "rockchip,rv1108-nfc"; ++ reg = <0x30100000 0x1000>; ++ interrupts = ; ++ clocks = <&cru HCLK_NANDC>, <&cru SCLK_NANDC>; ++ clock-names = "ahb", "nfc"; ++ assigned-clocks = <&cru SCLK_NANDC>; ++ assigned-clock-rates = <150000000>; ++ status = "disabled"; ++ }; ++ + emmc: mmc@30110000 { + compatible = "rockchip,rv1108-dw-mshc", "rockchip,rk3288-dw-mshc"; + reg = <0x30110000 0x4000>; + +From 9f1eb721bf42f1470fe280b4f501526a8addd76e Mon Sep 17 00:00:00 2001 +From: Yifeng Zhao +Date: Fri, 17 Jul 2020 17:25:31 +0800 +Subject: [PATCH] arm: dts: rockchip: Add NFC node for RK2928 and other SoCs + +Add NAND FLASH Controller(NFC) node for RK2928, RK3066, RK3168 +and RK3188 SoCs. + +Signed-off-by: Yifeng Zhao +--- + arch/arm/boot/dts/rk3xxx.dtsi | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/arch/arm/boot/dts/rk3xxx.dtsi b/arch/arm/boot/dts/rk3xxx.dtsi +index 859a7477909f..97415180d5bb 100644 +--- a/arch/arm/boot/dts/rk3xxx.dtsi ++++ b/arch/arm/boot/dts/rk3xxx.dtsi +@@ -276,6 +276,15 @@ emmc: mmc@1021c000 { + status = "disabled"; + }; + ++ nfc: nand-controller@10500000 { ++ compatible = "rockchip,rk2928-nfc"; ++ reg = <0x10500000 0x4000>; ++ interrupts = ; ++ clocks = <&cru HCLK_NANDC0>; ++ clock-names = "ahb"; ++ status = "disabled"; ++ }; ++ + pmu: pmu@20004000 { + compatible = "rockchip,rk3066-pmu", "syscon", "simple-mfd"; + reg = <0x20004000 0x100>; + +From b299d8bd1f7b704e89fcb320b4d851cfc3a6f5e9 Mon Sep 17 00:00:00 2001 +From: Yifeng Zhao +Date: Fri, 17 Jul 2020 17:25:32 +0800 +Subject: [PATCH] arm: dts: rockchip: Add NFC node for RK3036 SoC + +Add NAND FLASH Controller(NFC) node for RK3036 SoC. + +Signed-off-by: Yifeng Zhao +--- + arch/arm/boot/dts/rk3036.dtsi | 52 +++++++++++++++++++++++++++++++++++ + 1 file changed, 52 insertions(+) + +diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi +index 093567022386..dda5a1f79aca 100644 +--- a/arch/arm/boot/dts/rk3036.dtsi ++++ b/arch/arm/boot/dts/rk3036.dtsi +@@ -292,6 +292,21 @@ i2s: i2s@10220000 { + status = "disabled"; + }; + ++ nfc: nand-controller@10500000 { ++ compatible = "rockchip,rk3036-nfc", ++ "rockchip,rk2928-nfc"; ++ reg = <0x10500000 0x4000>; ++ interrupts = ; ++ clocks = <&cru HCLK_NANDC>, <&cru SCLK_NANDC>; ++ clock-names = "ahb", "nfc"; ++ assigned-clocks = <&cru SCLK_NANDC>; ++ assigned-clock-rates = <150000000>; ++ pinctrl-0 = <&flash_ale &flash_bus8 &flash_cle &flash_csn0 ++ &flash_rdn &flash_rdy &flash_wrn>; ++ pinctrl-names = "default"; ++ status = "disabled"; ++ }; ++ + cru: clock-controller@20000000 { + compatible = "rockchip,rk3036-cru"; + reg = <0x20000000 0x1000>; +@@ -643,6 +658,43 @@ emmc_bus8: emmc-bus8 { + }; + }; + ++ nfc { ++ flash_ale: flash-ale { ++ rockchip,pins = <2 RK_PA0 1 &pcfg_pull_default>; ++ }; ++ ++ flash_bus8: flash-bus8 { ++ rockchip,pins = <1 RK_PD0 1 &pcfg_pull_default>, ++ <1 RK_PD1 1 &pcfg_pull_default>, ++ <1 RK_PD2 1 &pcfg_pull_default>, ++ <1 RK_PD3 1 &pcfg_pull_default>, ++ <1 RK_PD4 1 &pcfg_pull_default>, ++ <1 RK_PD5 1 &pcfg_pull_default>, ++ <1 RK_PD6 1 &pcfg_pull_default>, ++ <1 RK_PD7 1 &pcfg_pull_default>; ++ }; ++ ++ flash_cle: flash-cle { ++ rockchip,pins = <2 RK_PA1 1 &pcfg_pull_default>; ++ }; ++ ++ flash_csn0: flash-csn0 { ++ rockchip,pins = <2 RK_PA6 1 &pcfg_pull_default>; ++ }; ++ ++ flash_rdn: flash-rdn { ++ rockchip,pins = <2 RK_PA3 1 &pcfg_pull_default>; ++ }; ++ ++ flash_rdy: flash-rdy { ++ rockchip,pins = <2 RK_PA4 1 &pcfg_pull_default>; ++ }; ++ ++ flash_wrn: flash-wrn { ++ rockchip,pins = <2 RK_PA2 1 &pcfg_pull_default>; ++ }; ++ }; ++ + emac { + emac_xfer: emac-xfer { + rockchip,pins = <2 RK_PB2 1 &pcfg_pull_default>, /* crs_dvalid */ diff --git a/patch/kernel/rk322x-dev/01-linux-0011-v4l2-from-5.9.patch b/patch/kernel/rk322x-dev/01-linux-0011-v4l2-from-5.9.patch new file mode 100644 index 000000000..79efdfdb0 --- /dev/null +++ b/patch/kernel/rk322x-dev/01-linux-0011-v4l2-from-5.9.patch @@ -0,0 +1,1190 @@ +From 7ecb99ec97624da3354bc7702179e21309fb3a4e Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Wed, 1 Jul 2020 15:17:30 +0200 +Subject: [PATCH] v4l2-core: Print control name in VIDIOC_S/G_(EXT)_CTRL(S) + +While debugging, it's currently really hard to identify controls +by their ID. Print the control name making the print more helpful. + +With this change, the print changes from: + +video1: VIDIOC_S_EXT_CTRLS: which=0xf010000, count=5, error_idx=4, request_fd=45, id/size=0x990ce8/1048, id/size=0x990ce9/12, id/size=0x990cea/480, id/size=0x990ceb/896, id/size=0x990cec/400 + +video1: VIDIOC_S_EXT_CTRLS: which=0xf010000, count=5, error_idx=4, request_fd=42, name=H264 Sequence Parameter Set, id/size=0x990ce8/1048, name=H264 Picture Parameter Set, id/size=0x990ce9/12, name=H264 Scaling Matrix, id/size=0x990cea/480, name=H264 Slice Parameters, id/size=0x990ceb/896, name=H264 Decode Parameters, id/size=0x990cec/400 + +For instance, this is specially helpful when the ioctl fails. Consider +the following example: + +v4l2-ctrls: prepare_ext_ctrls: video1: pointer control id 0x990cec size too small, 400 bytes but 784 bytes needed +v4l2-ctrls: try_set_ext_ctrls: video1: video1: try_set_ext_ctrls_common failed (-14) +video1: VIDIOC_S_EXT_CTRLS: error -14: which=0xf010000, count=5, error_idx=5, request_fd=39, name=H264 Sequence Parameter Set, id/size=0x990ce8/1048, name=H264 Picture Parameter Set, id/size=0x990ce9/12, name=H264 Scaling Matrix, id/size=0x990cea/480, name=H264 Slice Parameters, id/size=0x990ceb/896, name=H264 Decode Parameters, id/size=0x990cec/400 + +Signed-off-by: Ezequiel Garcia +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +(cherry picked from commit a69a7a33268308ddcc9abf0f7d7cd61ec4300cbe) +--- + drivers/media/v4l2-core/v4l2-ioctl.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c +index 5e057f798a15..ccf947632a3b 100644 +--- a/drivers/media/v4l2-core/v4l2-ioctl.c ++++ b/drivers/media/v4l2-core/v4l2-ioctl.c +@@ -582,7 +582,10 @@ static void v4l_print_querymenu(const void *arg, bool write_only) + static void v4l_print_control(const void *arg, bool write_only) + { + const struct v4l2_control *p = arg; ++ const char *name = v4l2_ctrl_get_name(p->id); + ++ if (name) ++ pr_cont("name=%s, ", name); + pr_cont("id=0x%x, value=%d\n", p->id, p->value); + } + +@@ -594,12 +597,15 @@ static void v4l_print_ext_controls(const void *arg, bool write_only) + pr_cont("which=0x%x, count=%d, error_idx=%d, request_fd=%d", + p->which, p->count, p->error_idx, p->request_fd); + for (i = 0; i < p->count; i++) { ++ unsigned int id = p->controls[i].id; ++ const char *name = v4l2_ctrl_get_name(id); ++ ++ if (name) ++ pr_cont(", name=%s", name); + if (!p->controls[i].size) +- pr_cont(", id/val=0x%x/0x%x", +- p->controls[i].id, p->controls[i].value); ++ pr_cont(", id/val=0x%x/0x%x", id, p->controls[i].value); + else +- pr_cont(", id/size=0x%x/%u", +- p->controls[i].id, p->controls[i].size); ++ pr_cont(", id/size=0x%x/%u", id, p->controls[i].size); + } + pr_cont("\n"); + } + +From d524e0ef051dcccefbdff08e1023489922da198f Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Wed, 24 Jun 2020 21:28:00 +0200 +Subject: [PATCH] media: Add V4L2_TYPE_IS_CAPTURE helper + +It's all too easy to get confused by the V4L2_TYPE_IS_OUTPUT +macro, when it's used as !V4L2_TYPE_IS_OUTPUT. + +Reduce the risk of confusion with macro to explicitly +check for the CAPTURE queue type case. + +This change does not affect functionality, and it's +only intended to make the code more readable. + +Suggested-by: Nicolas Dufresne +Signed-off-by: Ezequiel Garcia +Signed-off-by: Hans Verkuil +[hverkuil-cisco@xs4all.nl: checkpatch: align with parenthesis] +Signed-off-by: Mauro Carvalho Chehab +(cherry picked from commit b3ab1c6058fad8cd5726f24e9ed9053e43bb2af4) +--- + drivers/media/common/videobuf2/videobuf2-v4l2.c | 4 ++-- + drivers/media/platform/exynos-gsc/gsc-core.c | 2 +- + drivers/media/platform/exynos-gsc/gsc-m2m.c | 2 +- + drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c | 2 +- + drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c | 7 +++---- + drivers/media/platform/rcar_jpu.c | 2 +- + drivers/media/platform/sti/hva/hva-v4l2.c | 2 +- + drivers/media/platform/ti-vpe/vpe.c | 2 +- + drivers/media/test-drivers/vicodec/vicodec-core.c | 6 +++--- + drivers/media/v4l2-core/v4l2-mem2mem.c | 6 +++--- + drivers/staging/media/hantro/hantro_v4l2.c | 2 +- + drivers/staging/media/rkvdec/rkvdec.c | 2 +- + include/uapi/linux/videodev2.h | 2 ++ + 13 files changed, 21 insertions(+), 20 deletions(-) + +diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c +index eb5d5db96552..fd32c2e64809 100644 +--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c ++++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c +@@ -94,7 +94,7 @@ static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b) + unsigned int bytesused; + unsigned int plane; + +- if (!V4L2_TYPE_IS_OUTPUT(b->type)) ++ if (V4L2_TYPE_IS_CAPTURE(b->type)) + return 0; + + if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) { +@@ -307,7 +307,7 @@ static int vb2_fill_vb2_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b + + /* Zero flags that we handle */ + vbuf->flags = b->flags & ~V4L2_BUFFER_MASK_FLAGS; +- if (!vb->vb2_queue->copy_timestamp || !V4L2_TYPE_IS_OUTPUT(b->type)) { ++ if (!vb->vb2_queue->copy_timestamp || V4L2_TYPE_IS_CAPTURE(b->type)) { + /* + * Non-COPY timestamps and non-OUTPUT queues will get + * their timestamp and timestamp source flags from the +diff --git a/drivers/media/platform/exynos-gsc/gsc-core.c b/drivers/media/platform/exynos-gsc/gsc-core.c +index f6650b45bc3d..9f41c2e7097a 100644 +--- a/drivers/media/platform/exynos-gsc/gsc-core.c ++++ b/drivers/media/platform/exynos-gsc/gsc-core.c +@@ -577,7 +577,7 @@ int gsc_try_selection(struct gsc_ctx *ctx, struct v4l2_selection *s) + v4l_bound_align_image(&tmp_w, min_w, max_w, mod_x, + &tmp_h, min_h, max_h, mod_y, 0); + +- if (!V4L2_TYPE_IS_OUTPUT(s->type) && ++ if (V4L2_TYPE_IS_CAPTURE(s->type) && + (ctx->gsc_ctrls.rotate->val == 90 || + ctx->gsc_ctrls.rotate->val == 270)) + gsc_check_crop_change(tmp_h, tmp_w, +diff --git a/drivers/media/platform/exynos-gsc/gsc-m2m.c b/drivers/media/platform/exynos-gsc/gsc-m2m.c +index e2c162635f72..27a3c92c73bc 100644 +--- a/drivers/media/platform/exynos-gsc/gsc-m2m.c ++++ b/drivers/media/platform/exynos-gsc/gsc-m2m.c +@@ -255,7 +255,7 @@ static int gsc_m2m_buf_prepare(struct vb2_buffer *vb) + if (IS_ERR(frame)) + return PTR_ERR(frame); + +- if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { ++ if (V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type)) { + for (i = 0; i < frame->fmt->num_planes; i++) + vb2_set_plane_payload(vb, i, frame->payload[i]); + } +diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c +index f82a81a3bdee..61fed1e35a00 100644 +--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c ++++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c +@@ -731,7 +731,7 @@ static void mtk_jpeg_stop_streaming(struct vb2_queue *q) + * subsampling. Update capture queue when the stream is off. + */ + if (ctx->state == MTK_JPEG_SOURCE_CHANGE && +- !V4L2_TYPE_IS_OUTPUT(q->type)) { ++ V4L2_TYPE_IS_CAPTURE(q->type)) { + struct mtk_jpeg_src_buf *src_buf; + + vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); +diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c b/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c +index 821f2cf325f0..a6ea22b57416 100644 +--- a/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c ++++ b/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c +@@ -193,7 +193,7 @@ static const struct mtk_mdp_fmt *mtk_mdp_try_fmt_mplane(struct mtk_mdp_ctx *ctx, + + pix_mp->field = V4L2_FIELD_NONE; + pix_mp->pixelformat = fmt->pixelformat; +- if (!V4L2_TYPE_IS_OUTPUT(f->type)) { ++ if (V4L2_TYPE_IS_CAPTURE(f->type)) { + pix_mp->colorspace = ctx->colorspace; + pix_mp->xfer_func = ctx->xfer_func; + pix_mp->ycbcr_enc = ctx->ycbcr_enc; +@@ -327,9 +327,8 @@ static int mtk_mdp_try_crop(struct mtk_mdp_ctx *ctx, u32 type, + mtk_mdp_bound_align_image(&new_w, min_w, max_w, align_w, + &new_h, min_h, max_h, align_h); + +- if (!V4L2_TYPE_IS_OUTPUT(type) && +- (ctx->ctrls.rotate->val == 90 || +- ctx->ctrls.rotate->val == 270)) ++ if (V4L2_TYPE_IS_CAPTURE(type) && ++ (ctx->ctrls.rotate->val == 90 || ctx->ctrls.rotate->val == 270)) + mtk_mdp_check_crop_change(new_h, new_w, + &r->width, &r->height); + else +diff --git a/drivers/media/platform/rcar_jpu.c b/drivers/media/platform/rcar_jpu.c +index 5250a14324e9..9b99ff368698 100644 +--- a/drivers/media/platform/rcar_jpu.c ++++ b/drivers/media/platform/rcar_jpu.c +@@ -1066,7 +1066,7 @@ static int jpu_buf_prepare(struct vb2_buffer *vb) + } + + /* decoder capture queue */ +- if (!ctx->encoder && !V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) ++ if (!ctx->encoder && V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type)) + vb2_set_plane_payload(vb, i, size); + } + +diff --git a/drivers/media/platform/sti/hva/hva-v4l2.c b/drivers/media/platform/sti/hva/hva-v4l2.c +index 197b99d8fd9c..bb34d6997d99 100644 +--- a/drivers/media/platform/sti/hva/hva-v4l2.c ++++ b/drivers/media/platform/sti/hva/hva-v4l2.c +@@ -1087,7 +1087,7 @@ static void hva_stop_streaming(struct vb2_queue *vq) + + if ((V4L2_TYPE_IS_OUTPUT(vq->type) && + vb2_is_streaming(&ctx->fh.m2m_ctx->cap_q_ctx.q)) || +- (!V4L2_TYPE_IS_OUTPUT(vq->type) && ++ (V4L2_TYPE_IS_CAPTURE(vq->type) && + vb2_is_streaming(&ctx->fh.m2m_ctx->out_q_ctx.q))) { + dev_dbg(dev, "%s %s out=%d cap=%d\n", + ctx->name, to_type_str(vq->type), +diff --git a/drivers/media/platform/ti-vpe/vpe.c b/drivers/media/platform/ti-vpe/vpe.c +index cff2fcd6d812..346f8212791c 100644 +--- a/drivers/media/platform/ti-vpe/vpe.c ++++ b/drivers/media/platform/ti-vpe/vpe.c +@@ -1576,7 +1576,7 @@ static int vpe_g_fmt(struct file *file, void *priv, struct v4l2_format *f) + + *f = q_data->format; + +- if (!V4L2_TYPE_IS_OUTPUT(f->type)) { ++ if (V4L2_TYPE_IS_CAPTURE(f->type)) { + struct vpe_q_data *s_q_data; + struct v4l2_pix_format_mplane *spix; + +diff --git a/drivers/media/test-drivers/vicodec/vicodec-core.c b/drivers/media/test-drivers/vicodec/vicodec-core.c +index e879290727ef..8941d73f6611 100644 +--- a/drivers/media/test-drivers/vicodec/vicodec-core.c ++++ b/drivers/media/test-drivers/vicodec/vicodec-core.c +@@ -1442,7 +1442,7 @@ static void vicodec_buf_queue(struct vb2_buffer *vb) + .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION, + }; + +- if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type) && ++ if (V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type) && + vb2_is_streaming(vb->vb2_queue) && + v4l2_m2m_dst_buf_is_last(ctx->fh.m2m_ctx)) { + unsigned int i; +@@ -1479,7 +1479,7 @@ static void vicodec_buf_queue(struct vb2_buffer *vb) + * in the compressed stream + */ + if (ctx->is_stateless || ctx->is_enc || +- !V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { ++ V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type)) { + v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); + return; + } +@@ -1574,7 +1574,7 @@ static int vicodec_start_streaming(struct vb2_queue *q, + state->gop_cnt = 0; + + if ((V4L2_TYPE_IS_OUTPUT(q->type) && !ctx->is_enc) || +- (!V4L2_TYPE_IS_OUTPUT(q->type) && ctx->is_enc)) ++ (V4L2_TYPE_IS_CAPTURE(q->type) && ctx->is_enc)) + return 0; + + if (info->id == V4L2_PIX_FMT_FWHT || +diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c +index 62ac9424c92a..95a8f2dc5341 100644 +--- a/drivers/media/v4l2-core/v4l2-mem2mem.c ++++ b/drivers/media/v4l2-core/v4l2-mem2mem.c +@@ -556,7 +556,7 @@ int v4l2_m2m_querybuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, + ret = vb2_querybuf(vq, buf); + + /* Adjust MMAP memory offsets for the CAPTURE queue */ +- if (buf->memory == V4L2_MEMORY_MMAP && !V4L2_TYPE_IS_OUTPUT(vq->type)) { ++ if (buf->memory == V4L2_MEMORY_MMAP && V4L2_TYPE_IS_CAPTURE(vq->type)) { + if (V4L2_TYPE_IS_MULTIPLANAR(vq->type)) { + for (i = 0; i < buf->length; ++i) + buf->m.planes[i].m.mem_offset +@@ -712,7 +712,7 @@ int v4l2_m2m_qbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, + int ret; + + vq = v4l2_m2m_get_vq(m2m_ctx, buf->type); +- if (!V4L2_TYPE_IS_OUTPUT(vq->type) && ++ if (V4L2_TYPE_IS_CAPTURE(vq->type) && + (buf->flags & V4L2_BUF_FLAG_REQUEST_FD)) { + dprintk("%s: requests cannot be used with capture buffers\n", + __func__); +@@ -729,7 +729,7 @@ int v4l2_m2m_qbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, + * buffer as DONE with LAST flag since it won't be queued on the + * device. + */ +- if (!V4L2_TYPE_IS_OUTPUT(vq->type) && ++ if (V4L2_TYPE_IS_CAPTURE(vq->type) && + vb2_is_streaming(vq) && !vb2_start_streaming_called(vq) && + (v4l2_m2m_has_stopped(m2m_ctx) || v4l2_m2m_dst_buf_is_last(m2m_ctx))) + v4l2_m2m_force_last_buf_done(m2m_ctx, vq); +diff --git a/drivers/staging/media/hantro/hantro_v4l2.c b/drivers/staging/media/hantro/hantro_v4l2.c +index f28a94e2fa93..63859e8a0923 100644 +--- a/drivers/staging/media/hantro/hantro_v4l2.c ++++ b/drivers/staging/media/hantro/hantro_v4l2.c +@@ -237,7 +237,7 @@ static int hantro_try_fmt(const struct hantro_ctx *ctx, + enum v4l2_buf_type type) + { + const struct hantro_fmt *fmt, *vpu_fmt; +- bool capture = !V4L2_TYPE_IS_OUTPUT(type); ++ bool capture = V4L2_TYPE_IS_CAPTURE(type); + bool coded; + + coded = capture == hantro_is_encoder_ctx(ctx); +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index 225eeca73356..fd68671f0286 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -489,7 +489,7 @@ static int rkvdec_start_streaming(struct vb2_queue *q, unsigned int count) + const struct rkvdec_coded_fmt_desc *desc; + int ret; + +- if (!V4L2_TYPE_IS_OUTPUT(q->type)) ++ if (V4L2_TYPE_IS_CAPTURE(q->type)) + return 0; + + desc = ctx->coded_fmt_desc; +diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h +index c3a1cf1c507f..6fe8822d2cb4 100644 +--- a/include/uapi/linux/videodev2.h ++++ b/include/uapi/linux/videodev2.h +@@ -171,6 +171,8 @@ enum v4l2_buf_type { + || (type) == V4L2_BUF_TYPE_SDR_OUTPUT \ + || (type) == V4L2_BUF_TYPE_META_OUTPUT) + ++#define V4L2_TYPE_IS_CAPTURE(type) (!V4L2_TYPE_IS_OUTPUT(type)) ++ + enum v4l2_tuner_type { + V4L2_TUNER_RADIO = 1, + V4L2_TUNER_ANALOG_TV = 2, + +From 728f96ea31862791706eb9390cb865e4fd8fa09d Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Wed, 1 Jul 2020 15:16:02 +0200 +Subject: [PATCH] hantro: h264: Remove unused macro definition + +The generic H264 reference list builder moved all +the users of this macro, but left the macro. + +Remove it. + +Signed-off-by: Ezequiel Garcia +Reviewed-by: Philipp Zabel +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +(cherry picked from commit 3ebf271b1dee6df816bd8f2135218640c478dedd) +--- + drivers/staging/media/hantro/hantro_h264.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/staging/media/hantro/hantro_h264.c b/drivers/staging/media/hantro/hantro_h264.c +index d561f125085a..dd935d7009bf 100644 +--- a/drivers/staging/media/hantro/hantro_h264.c ++++ b/drivers/staging/media/hantro/hantro_h264.c +@@ -22,8 +22,6 @@ + #define POC_BUFFER_SIZE 34 + #define SCALING_LIST_SIZE (6 * 16 + 2 * 64) + +-#define HANTRO_CMP(a, b) ((a) < (b) ? -1 : 1) +- + /* Data structure describing auxiliary buffer format. */ + struct hantro_h264_dec_priv_tbl { + u32 cabac_table[CABAC_INIT_BUFFER_SIZE]; + +From ad6f6337541843af2f943f603636f64a6a55e215 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Wed, 1 Jul 2020 15:16:03 +0200 +Subject: [PATCH] hantro: h264: Rename scaling list handling function + +Commit e17f08e31666 ("media: hantro: Do not reorder +H264 scaling list") removed the scaling list reordering, +which was wrong and not needed. + +However, the name of the function stayed, which is +confusing for anyone reading the code. Rename +from "reorder" to "assemble" which is cleaner. + +This is just a cosmetic cleanup. + +Signed-off-by: Ezequiel Garcia +Reviewed-by: Philipp Zabel +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +(cherry picked from commit 4df3a47e3422a9de1f3ce1a4ba8a0447a73e7567) +--- + drivers/staging/media/hantro/hantro_h264.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/staging/media/hantro/hantro_h264.c b/drivers/staging/media/hantro/hantro_h264.c +index dd935d7009bf..194d05848077 100644 +--- a/drivers/staging/media/hantro/hantro_h264.c ++++ b/drivers/staging/media/hantro/hantro_h264.c +@@ -193,7 +193,7 @@ static const u32 h264_cabac_table[] = { + }; + + static void +-reorder_scaling_list(struct hantro_ctx *ctx) ++assemble_scaling_list(struct hantro_ctx *ctx) + { + const struct hantro_h264_dec_ctrls *ctrls = &ctx->h264_dec.ctrls; + const struct v4l2_ctrl_h264_scaling_matrix *scaling = ctrls->scaling; +@@ -235,7 +235,7 @@ static void prepare_table(struct hantro_ctx *ctx) + tbl->poc[32] = dec_param->top_field_order_cnt; + tbl->poc[33] = dec_param->bottom_field_order_cnt; + +- reorder_scaling_list(ctx); ++ assemble_scaling_list(ctx); + } + + static bool dpb_entry_match(const struct v4l2_h264_dpb_entry *a, + +From 63c05ac390a6fb9d4930804931732630dd0e20ac Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Wed, 1 Jul 2020 15:16:04 +0200 +Subject: [PATCH] hantro: Rework how encoder and decoder are identified + +So far we've been using the .buf_finish hook to distinguish +decoder from encoder. This is unnecessarily obfuscated. + +Moreover, we want to move the buf_finish, so use a cleaner +scheme to distinguish the driver decoder/encoder type. + +Signed-off-by: Ezequiel Garcia +Reviewed-by: Philipp Zabel +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +(cherry picked from commit 21f0315b7b3ee6ca909d81a963744671fb27bf71) +--- + drivers/staging/media/hantro/hantro.h | 6 ++--- + drivers/staging/media/hantro/hantro_drv.c | 9 +++---- + drivers/staging/media/hantro/hantro_v4l2.c | 28 +++++++++++----------- + 3 files changed, 20 insertions(+), 23 deletions(-) + +diff --git a/drivers/staging/media/hantro/hantro.h b/drivers/staging/media/hantro/hantro.h +index 3005207fc6fb..2284e23d8500 100644 +--- a/drivers/staging/media/hantro/hantro.h ++++ b/drivers/staging/media/hantro/hantro.h +@@ -199,6 +199,7 @@ struct hantro_dev { + * + * @dev: VPU driver data to which the context belongs. + * @fh: V4L2 file handler. ++ * @is_encoder: Decoder or encoder context? + * + * @sequence_cap: Sequence counter for capture queue + * @sequence_out: Sequence counter for output queue +@@ -223,6 +224,7 @@ struct hantro_dev { + struct hantro_ctx { + struct hantro_dev *dev; + struct v4l2_fh fh; ++ bool is_encoder; + + u32 sequence_cap; + u32 sequence_out; +@@ -399,8 +401,6 @@ static inline void hantro_reg_write_s(struct hantro_dev *vpu, + vdpu_write(vpu, vdpu_read_mask(vpu, reg, val), reg->base); + } + +-bool hantro_is_encoder_ctx(const struct hantro_ctx *ctx); +- + void *hantro_get_ctrl(struct hantro_ctx *ctx, u32 id); + dma_addr_t hantro_get_ref(struct hantro_ctx *ctx, u64 ts); + +@@ -420,7 +420,7 @@ static inline bool + hantro_needs_postproc(const struct hantro_ctx *ctx, + const struct hantro_fmt *fmt) + { +- return !hantro_is_encoder_ctx(ctx) && fmt->fourcc != V4L2_PIX_FMT_NV12; ++ return !ctx->is_encoder && fmt->fourcc != V4L2_PIX_FMT_NV12; + } + + static inline dma_addr_t +diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c +index 0db8ad455160..9145d02e5d3c 100644 +--- a/drivers/staging/media/hantro/hantro_drv.c ++++ b/drivers/staging/media/hantro/hantro_drv.c +@@ -195,11 +195,6 @@ static void device_run(void *priv) + hantro_job_finish(ctx->dev, ctx, 0, VB2_BUF_STATE_ERROR); + } + +-bool hantro_is_encoder_ctx(const struct hantro_ctx *ctx) +-{ +- return ctx->buf_finish == hantro_enc_buf_finish; +-} +- + static struct v4l2_m2m_ops vpu_m2m_ops = { + .device_run = device_run, + }; +@@ -240,7 +235,7 @@ queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq) + * + * For the DMA destination buffer, we use a bounce buffer. + */ +- if (hantro_is_encoder_ctx(ctx)) { ++ if (ctx->is_encoder) { + dst_vq->mem_ops = &vb2_vmalloc_memops; + } else { + dst_vq->bidirectional = true; +@@ -420,8 +415,10 @@ static int hantro_open(struct file *filp) + if (func->id == MEDIA_ENT_F_PROC_VIDEO_ENCODER) { + allowed_codecs = vpu->variant->codec & HANTRO_ENCODERS; + ctx->buf_finish = hantro_enc_buf_finish; ++ ctx->is_encoder = true; + } else if (func->id == MEDIA_ENT_F_PROC_VIDEO_DECODER) { + allowed_codecs = vpu->variant->codec & HANTRO_DECODERS; ++ ctx->is_encoder = false; + } else { + ret = -ENODEV; + goto err_ctx_free; +diff --git a/drivers/staging/media/hantro/hantro_v4l2.c b/drivers/staging/media/hantro/hantro_v4l2.c +index 63859e8a0923..b668a82d40ad 100644 +--- a/drivers/staging/media/hantro/hantro_v4l2.c ++++ b/drivers/staging/media/hantro/hantro_v4l2.c +@@ -40,7 +40,7 @@ hantro_get_formats(const struct hantro_ctx *ctx, unsigned int *num_fmts) + { + const struct hantro_fmt *formats; + +- if (hantro_is_encoder_ctx(ctx)) { ++ if (ctx->is_encoder) { + formats = ctx->dev->variant->enc_fmts; + *num_fmts = ctx->dev->variant->num_enc_fmts; + } else { +@@ -55,7 +55,7 @@ static const struct hantro_fmt * + hantro_get_postproc_formats(const struct hantro_ctx *ctx, + unsigned int *num_fmts) + { +- if (hantro_is_encoder_ctx(ctx)) { ++ if (ctx->is_encoder) { + *num_fmts = 0; + return NULL; + } +@@ -158,7 +158,7 @@ static int vidioc_enum_fmt(struct file *file, void *priv, + * not MODE_NONE. + * - on the output side we want to filter out all MODE_NONE formats. + */ +- skip_mode_none = capture == hantro_is_encoder_ctx(ctx); ++ skip_mode_none = capture == ctx->is_encoder; + + formats = hantro_get_formats(ctx, &num_fmts); + for (i = 0; i < num_fmts; i++) { +@@ -240,7 +240,7 @@ static int hantro_try_fmt(const struct hantro_ctx *ctx, + bool capture = V4L2_TYPE_IS_CAPTURE(type); + bool coded; + +- coded = capture == hantro_is_encoder_ctx(ctx); ++ coded = capture == ctx->is_encoder; + + vpu_debug(4, "trying format %c%c%c%c\n", + (pix_mp->pixelformat & 0x7f), +@@ -257,7 +257,7 @@ static int hantro_try_fmt(const struct hantro_ctx *ctx, + if (coded) { + pix_mp->num_planes = 1; + vpu_fmt = fmt; +- } else if (hantro_is_encoder_ctx(ctx)) { ++ } else if (ctx->is_encoder) { + vpu_fmt = ctx->vpu_dst_fmt; + } else { + vpu_fmt = ctx->vpu_src_fmt; +@@ -330,7 +330,7 @@ hantro_reset_encoded_fmt(struct hantro_ctx *ctx) + + vpu_fmt = hantro_get_default_fmt(ctx, true); + +- if (hantro_is_encoder_ctx(ctx)) { ++ if (ctx->is_encoder) { + ctx->vpu_dst_fmt = vpu_fmt; + fmt = &ctx->dst_fmt; + } else { +@@ -341,7 +341,7 @@ hantro_reset_encoded_fmt(struct hantro_ctx *ctx) + hantro_reset_fmt(fmt, vpu_fmt); + fmt->width = vpu_fmt->frmsize.min_width; + fmt->height = vpu_fmt->frmsize.min_height; +- if (hantro_is_encoder_ctx(ctx)) ++ if (ctx->is_encoder) + hantro_set_fmt_cap(ctx, fmt); + else + hantro_set_fmt_out(ctx, fmt); +@@ -355,7 +355,7 @@ hantro_reset_raw_fmt(struct hantro_ctx *ctx) + + raw_vpu_fmt = hantro_get_default_fmt(ctx, false); + +- if (hantro_is_encoder_ctx(ctx)) { ++ if (ctx->is_encoder) { + ctx->vpu_src_fmt = raw_vpu_fmt; + raw_fmt = &ctx->src_fmt; + encoded_fmt = &ctx->dst_fmt; +@@ -368,7 +368,7 @@ hantro_reset_raw_fmt(struct hantro_ctx *ctx) + hantro_reset_fmt(raw_fmt, raw_vpu_fmt); + raw_fmt->width = encoded_fmt->width; + raw_fmt->width = encoded_fmt->width; +- if (hantro_is_encoder_ctx(ctx)) ++ if (ctx->is_encoder) + hantro_set_fmt_out(ctx, raw_fmt); + else + hantro_set_fmt_cap(ctx, raw_fmt); +@@ -409,7 +409,7 @@ static int hantro_set_fmt_out(struct hantro_ctx *ctx, + if (ret) + return ret; + +- if (!hantro_is_encoder_ctx(ctx)) { ++ if (!ctx->is_encoder) { + struct vb2_queue *peer_vq; + + /* +@@ -450,7 +450,7 @@ static int hantro_set_fmt_out(struct hantro_ctx *ctx, + * Note that hantro_reset_raw_fmt() also propagates size + * changes to the raw format. + */ +- if (!hantro_is_encoder_ctx(ctx)) ++ if (!ctx->is_encoder) + hantro_reset_raw_fmt(ctx); + + /* Colorimetry information are always propagated. */ +@@ -479,7 +479,7 @@ static int hantro_set_fmt_cap(struct hantro_ctx *ctx, + if (vb2_is_busy(vq)) + return -EBUSY; + +- if (hantro_is_encoder_ctx(ctx)) { ++ if (ctx->is_encoder) { + struct vb2_queue *peer_vq; + + /* +@@ -512,7 +512,7 @@ static int hantro_set_fmt_cap(struct hantro_ctx *ctx, + * Note that hantro_reset_raw_fmt() also propagates size + * changes to the raw format. + */ +- if (hantro_is_encoder_ctx(ctx)) ++ if (ctx->is_encoder) + hantro_reset_raw_fmt(ctx); + + /* Colorimetry information are always propagated. */ +@@ -655,7 +655,7 @@ static bool hantro_vq_is_coded(struct vb2_queue *q) + { + struct hantro_ctx *ctx = vb2_get_drv_priv(q); + +- return hantro_is_encoder_ctx(ctx) != V4L2_TYPE_IS_OUTPUT(q->type); ++ return ctx->is_encoder != V4L2_TYPE_IS_OUTPUT(q->type); + } + + static int hantro_start_streaming(struct vb2_queue *q, unsigned int count) + +From 9067e59021400f6924e6fe593585bb6a561ef251 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Wed, 1 Jul 2020 15:16:05 +0200 +Subject: [PATCH] hantro: Move hantro_enc_buf_finish to JPEG codec_ops.done + +hantro_enc_buf_finish is used only for JPEG, and so should +be moved to JPEG codec_ops.done. + +This cleanup is also taking care of addressing +a subtle issue: checking the non-NULL bounce buffer +using ctx->jpeg_enc, which is a member of a union is +confusing and error-prone. + +Note that the issue is currently innocuous because an +encoder context only supports JPEG. + +The codec_ops.done has an argument that codec-specific code +shouldn't need, so drop that as well. + +Signed-off-by: Ezequiel Garcia +Reviewed-by: Philipp Zabel +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +(cherry picked from commit e765dba11ec26d7ea42974ec4d470b5ce00be3de) +--- + drivers/staging/media/hantro/hantro.h | 7 ---- + drivers/staging/media/hantro/hantro_drv.c | 37 ++----------------- + .../staging/media/hantro/hantro_h1_jpeg_enc.c | 17 +++++++++ + drivers/staging/media/hantro/hantro_hw.h | 3 +- + drivers/staging/media/hantro/rk3288_vpu_hw.c | 1 + + 5 files changed, 24 insertions(+), 41 deletions(-) + +diff --git a/drivers/staging/media/hantro/hantro.h b/drivers/staging/media/hantro/hantro.h +index 2284e23d8500..65f9f7ea7dcf 100644 +--- a/drivers/staging/media/hantro/hantro.h ++++ b/drivers/staging/media/hantro/hantro.h +@@ -212,9 +212,6 @@ struct hantro_dev { + * @ctrl_handler: Control handler used to register controls. + * @jpeg_quality: User-specified JPEG compression quality. + * +- * @buf_finish: Buffer finish. This depends on encoder or decoder +- * context, and it's called right before +- * calling v4l2_m2m_job_finish. + * @codec_ops: Set of operations related to codec mode. + * @postproc: Post-processing context. + * @jpeg_enc: JPEG-encoding context. +@@ -237,10 +234,6 @@ struct hantro_ctx { + struct v4l2_ctrl_handler ctrl_handler; + int jpeg_quality; + +- int (*buf_finish)(struct hantro_ctx *ctx, +- struct vb2_buffer *buf, +- unsigned int bytesused); +- + const struct hantro_codec_ops *codec_ops; + struct hantro_postproc_ctx postproc; + +diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c +index 9145d02e5d3c..88b5c5989d83 100644 +--- a/drivers/staging/media/hantro/hantro_drv.c ++++ b/drivers/staging/media/hantro/hantro_drv.c +@@ -56,37 +56,12 @@ dma_addr_t hantro_get_ref(struct hantro_ctx *ctx, u64 ts) + return hantro_get_dec_buf_addr(ctx, buf); + } + +-static int +-hantro_enc_buf_finish(struct hantro_ctx *ctx, struct vb2_buffer *buf, +- unsigned int bytesused) +-{ +- size_t avail_size; +- +- avail_size = vb2_plane_size(buf, 0) - ctx->vpu_dst_fmt->header_size; +- if (bytesused > avail_size) +- return -EINVAL; +- /* +- * The bounce buffer is only for the JPEG encoder. +- * TODO: Rework the JPEG encoder to eliminate the need +- * for a bounce buffer. +- */ +- if (ctx->jpeg_enc.bounce_buffer.cpu) { +- memcpy(vb2_plane_vaddr(buf, 0) + +- ctx->vpu_dst_fmt->header_size, +- ctx->jpeg_enc.bounce_buffer.cpu, bytesused); +- } +- buf->planes[0].bytesused = +- ctx->vpu_dst_fmt->header_size + bytesused; +- return 0; +-} +- + static void hantro_job_finish(struct hantro_dev *vpu, + struct hantro_ctx *ctx, + unsigned int bytesused, + enum vb2_buffer_state result) + { + struct vb2_v4l2_buffer *src, *dst; +- int ret; + + pm_runtime_mark_last_busy(vpu->dev); + pm_runtime_put_autosuspend(vpu->dev); +@@ -103,12 +78,6 @@ static void hantro_job_finish(struct hantro_dev *vpu, + src->sequence = ctx->sequence_out++; + dst->sequence = ctx->sequence_cap++; + +- if (ctx->buf_finish) { +- ret = ctx->buf_finish(ctx, &dst->vb2_buf, bytesused); +- if (ret) +- result = VB2_BUF_STATE_ERROR; +- } +- + v4l2_m2m_buf_done_and_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx, + result); + } +@@ -124,8 +93,11 @@ void hantro_irq_done(struct hantro_dev *vpu, unsigned int bytesused, + * the timeout expired. The watchdog is running, + * and will take care of finishing the job. + */ +- if (cancel_delayed_work(&vpu->watchdog_work)) ++ if (cancel_delayed_work(&vpu->watchdog_work)) { ++ if (result == VB2_BUF_STATE_DONE && ctx->codec_ops->done) ++ ctx->codec_ops->done(ctx); + hantro_job_finish(vpu, ctx, bytesused, result); ++ } + } + + void hantro_watchdog(struct work_struct *work) +@@ -414,7 +386,6 @@ static int hantro_open(struct file *filp) + ctx->dev = vpu; + if (func->id == MEDIA_ENT_F_PROC_VIDEO_ENCODER) { + allowed_codecs = vpu->variant->codec & HANTRO_ENCODERS; +- ctx->buf_finish = hantro_enc_buf_finish; + ctx->is_encoder = true; + } else if (func->id == MEDIA_ENT_F_PROC_VIDEO_DECODER) { + allowed_codecs = vpu->variant->codec & HANTRO_DECODERS; +diff --git a/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c b/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c +index b22418436823..b88dc4ed06db 100644 +--- a/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c ++++ b/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c +@@ -137,3 +137,20 @@ void hantro_h1_jpeg_enc_run(struct hantro_ctx *ctx) + + vepu_write(vpu, reg, H1_REG_ENC_CTRL); + } ++ ++void hantro_jpeg_enc_done(struct hantro_ctx *ctx) ++{ ++ struct hantro_dev *vpu = ctx->dev; ++ u32 bytesused = vepu_read(vpu, H1_REG_STR_BUF_LIMIT) / 8; ++ struct vb2_v4l2_buffer *dst_buf = hantro_get_dst_buf(ctx); ++ ++ /* ++ * TODO: Rework the JPEG encoder to eliminate the need ++ * for a bounce buffer. ++ */ ++ memcpy(vb2_plane_vaddr(&dst_buf->vb2_buf, 0) + ++ ctx->vpu_dst_fmt->header_size, ++ ctx->jpeg_enc.bounce_buffer.cpu, bytesused); ++ vb2_set_plane_payload(&dst_buf->vb2_buf, 0, ++ ctx->vpu_dst_fmt->header_size + bytesused); ++} +diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h +index 4053d8710e04..2d6323cd6732 100644 +--- a/drivers/staging/media/hantro/hantro_hw.h ++++ b/drivers/staging/media/hantro/hantro_hw.h +@@ -138,7 +138,7 @@ struct hantro_codec_ops { + int (*init)(struct hantro_ctx *ctx); + void (*exit)(struct hantro_ctx *ctx); + void (*run)(struct hantro_ctx *ctx); +- void (*done)(struct hantro_ctx *ctx, enum vb2_buffer_state); ++ void (*done)(struct hantro_ctx *ctx); + void (*reset)(struct hantro_ctx *ctx); + }; + +@@ -172,6 +172,7 @@ void hantro_h1_jpeg_enc_run(struct hantro_ctx *ctx); + void rk3399_vpu_jpeg_enc_run(struct hantro_ctx *ctx); + int hantro_jpeg_enc_init(struct hantro_ctx *ctx); + void hantro_jpeg_enc_exit(struct hantro_ctx *ctx); ++void hantro_jpeg_enc_done(struct hantro_ctx *ctx); + + dma_addr_t hantro_h264_get_ref_buf(struct hantro_ctx *ctx, + unsigned int dpb_idx); +diff --git a/drivers/staging/media/hantro/rk3288_vpu_hw.c b/drivers/staging/media/hantro/rk3288_vpu_hw.c +index 2f914b37b9e5..b1cf2abb972f 100644 +--- a/drivers/staging/media/hantro/rk3288_vpu_hw.c ++++ b/drivers/staging/media/hantro/rk3288_vpu_hw.c +@@ -180,6 +180,7 @@ static const struct hantro_codec_ops rk3288_vpu_codec_ops[] = { + .run = hantro_h1_jpeg_enc_run, + .reset = rk3288_vpu_enc_reset, + .init = hantro_jpeg_enc_init, ++ .done = hantro_jpeg_enc_done, + .exit = hantro_jpeg_enc_exit, + }, + [HANTRO_MODE_H264_DEC] = { + +From 7d3bf1fa2170bacf99bd02ccd7dc0f5fdc1fbc45 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Wed, 1 Jul 2020 15:16:06 +0200 +Subject: [PATCH] hantro: Remove unused bytesused argument + +The driver doesn't need the bytesused argument. + +For decoders, the plane bytesused is known and therefore, +buf_prepare is used to set it. For encoders, it's +handled by the codec_ops.done hook. + +Signed-off-by: Ezequiel Garcia +Reviewed-by: Philipp Zabel +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +(cherry picked from commit b72a6342dd240ce8e15b7acf1c38c67a0c56092b) +--- + drivers/staging/media/hantro/hantro_drv.c | 9 ++++----- + drivers/staging/media/hantro/hantro_hw.h | 2 +- + drivers/staging/media/hantro/imx8m_vpu_hw.c | 2 +- + drivers/staging/media/hantro/rk3288_vpu_hw.c | 7 +++---- + drivers/staging/media/hantro/rk3399_vpu_hw.c | 7 +++---- + 5 files changed, 12 insertions(+), 15 deletions(-) + +diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c +index 88b5c5989d83..34367b169011 100644 +--- a/drivers/staging/media/hantro/hantro_drv.c ++++ b/drivers/staging/media/hantro/hantro_drv.c +@@ -58,7 +58,6 @@ dma_addr_t hantro_get_ref(struct hantro_ctx *ctx, u64 ts) + + static void hantro_job_finish(struct hantro_dev *vpu, + struct hantro_ctx *ctx, +- unsigned int bytesused, + enum vb2_buffer_state result) + { + struct vb2_v4l2_buffer *src, *dst; +@@ -82,7 +81,7 @@ static void hantro_job_finish(struct hantro_dev *vpu, + result); + } + +-void hantro_irq_done(struct hantro_dev *vpu, unsigned int bytesused, ++void hantro_irq_done(struct hantro_dev *vpu, + enum vb2_buffer_state result) + { + struct hantro_ctx *ctx = +@@ -96,7 +95,7 @@ void hantro_irq_done(struct hantro_dev *vpu, unsigned int bytesused, + if (cancel_delayed_work(&vpu->watchdog_work)) { + if (result == VB2_BUF_STATE_DONE && ctx->codec_ops->done) + ctx->codec_ops->done(ctx); +- hantro_job_finish(vpu, ctx, bytesused, result); ++ hantro_job_finish(vpu, ctx, result); + } + } + +@@ -111,7 +110,7 @@ void hantro_watchdog(struct work_struct *work) + if (ctx) { + vpu_err("frame processing timed out!\n"); + ctx->codec_ops->reset(ctx); +- hantro_job_finish(vpu, ctx, 0, VB2_BUF_STATE_ERROR); ++ hantro_job_finish(vpu, ctx, VB2_BUF_STATE_ERROR); + } + } + +@@ -164,7 +163,7 @@ static void device_run(void *priv) + return; + + err_cancel_job: +- hantro_job_finish(ctx->dev, ctx, 0, VB2_BUF_STATE_ERROR); ++ hantro_job_finish(ctx->dev, ctx, VB2_BUF_STATE_ERROR); + } + + static struct v4l2_m2m_ops vpu_m2m_ops = { +diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h +index 2d6323cd6732..f066de6b592d 100644 +--- a/drivers/staging/media/hantro/hantro_hw.h ++++ b/drivers/staging/media/hantro/hantro_hw.h +@@ -163,7 +163,7 @@ extern const u32 hantro_vp8_dec_mc_filter[8][6]; + + void hantro_watchdog(struct work_struct *work); + void hantro_run(struct hantro_ctx *ctx); +-void hantro_irq_done(struct hantro_dev *vpu, unsigned int bytesused, ++void hantro_irq_done(struct hantro_dev *vpu, + enum vb2_buffer_state result); + void hantro_start_prepare_run(struct hantro_ctx *ctx); + void hantro_end_prepare_run(struct hantro_ctx *ctx); +diff --git a/drivers/staging/media/hantro/imx8m_vpu_hw.c b/drivers/staging/media/hantro/imx8m_vpu_hw.c +index cb2420c5526e..c222de075ef4 100644 +--- a/drivers/staging/media/hantro/imx8m_vpu_hw.c ++++ b/drivers/staging/media/hantro/imx8m_vpu_hw.c +@@ -143,7 +143,7 @@ static irqreturn_t imx8m_vpu_g1_irq(int irq, void *dev_id) + vdpu_write(vpu, 0, G1_REG_INTERRUPT); + vdpu_write(vpu, G1_REG_CONFIG_DEC_CLK_GATE_E, G1_REG_CONFIG); + +- hantro_irq_done(vpu, 0, state); ++ hantro_irq_done(vpu, state); + + return IRQ_HANDLED; + } +diff --git a/drivers/staging/media/hantro/rk3288_vpu_hw.c b/drivers/staging/media/hantro/rk3288_vpu_hw.c +index b1cf2abb972f..7b299ee3e93d 100644 +--- a/drivers/staging/media/hantro/rk3288_vpu_hw.c ++++ b/drivers/staging/media/hantro/rk3288_vpu_hw.c +@@ -113,17 +113,16 @@ static irqreturn_t rk3288_vepu_irq(int irq, void *dev_id) + { + struct hantro_dev *vpu = dev_id; + enum vb2_buffer_state state; +- u32 status, bytesused; ++ u32 status; + + status = vepu_read(vpu, H1_REG_INTERRUPT); +- bytesused = vepu_read(vpu, H1_REG_STR_BUF_LIMIT) / 8; + state = (status & H1_REG_INTERRUPT_FRAME_RDY) ? + VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR; + + vepu_write(vpu, 0, H1_REG_INTERRUPT); + vepu_write(vpu, 0, H1_REG_AXI_CTRL); + +- hantro_irq_done(vpu, bytesused, state); ++ hantro_irq_done(vpu, state); + + return IRQ_HANDLED; + } +@@ -141,7 +140,7 @@ static irqreturn_t rk3288_vdpu_irq(int irq, void *dev_id) + vdpu_write(vpu, 0, G1_REG_INTERRUPT); + vdpu_write(vpu, G1_REG_CONFIG_DEC_CLK_GATE_E, G1_REG_CONFIG); + +- hantro_irq_done(vpu, 0, state); ++ hantro_irq_done(vpu, state); + + return IRQ_HANDLED; + } +diff --git a/drivers/staging/media/hantro/rk3399_vpu_hw.c b/drivers/staging/media/hantro/rk3399_vpu_hw.c +index 9ac1f2cb6a16..7a7962cf771e 100644 +--- a/drivers/staging/media/hantro/rk3399_vpu_hw.c ++++ b/drivers/staging/media/hantro/rk3399_vpu_hw.c +@@ -92,17 +92,16 @@ static irqreturn_t rk3399_vepu_irq(int irq, void *dev_id) + { + struct hantro_dev *vpu = dev_id; + enum vb2_buffer_state state; +- u32 status, bytesused; ++ u32 status; + + status = vepu_read(vpu, VEPU_REG_INTERRUPT); +- bytesused = vepu_read(vpu, VEPU_REG_STR_BUF_LIMIT) / 8; + state = (status & VEPU_REG_INTERRUPT_FRAME_READY) ? + VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR; + + vepu_write(vpu, 0, VEPU_REG_INTERRUPT); + vepu_write(vpu, 0, VEPU_REG_AXI_CTRL); + +- hantro_irq_done(vpu, bytesused, state); ++ hantro_irq_done(vpu, state); + + return IRQ_HANDLED; + } +@@ -120,7 +119,7 @@ static irqreturn_t rk3399_vdpu_irq(int irq, void *dev_id) + vdpu_write(vpu, 0, VDPU_REG_INTERRUPT); + vdpu_write(vpu, 0, VDPU_REG_AXI_CTRL); + +- hantro_irq_done(vpu, 0, state); ++ hantro_irq_done(vpu, state); + + return IRQ_HANDLED; + } + +From 7e6a3bfc6d6ac30204d5ad0fc6496f1c263f809b Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Wed, 1 Jul 2020 15:16:07 +0200 +Subject: [PATCH] hantro: Make sure we don't use post-processor on an encoder + +Commit 986eee3a5234 ("media: hantro: Prevent encoders from using +post-processing") fixed hantro_needs_postproc condition, +but missed one case. Encoders don't have any post-processor +hardware block, so also can't be disabled. + +Fix it. + +Fixes: 986eee3a5234 ("media: hantro: Prevent encoders from using post-processing") +Signed-off-by: Ezequiel Garcia +Reviewed-by: Philipp Zabel +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +(cherry picked from commit 46d7aaebbe441d5381e35d8e16df784690e65ef3) +--- + drivers/staging/media/hantro/hantro_drv.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c +index 34367b169011..d32b6b1ab70b 100644 +--- a/drivers/staging/media/hantro/hantro_drv.c ++++ b/drivers/staging/media/hantro/hantro_drv.c +@@ -122,10 +122,12 @@ void hantro_start_prepare_run(struct hantro_ctx *ctx) + v4l2_ctrl_request_setup(src_buf->vb2_buf.req_obj.req, + &ctx->ctrl_handler); + +- if (hantro_needs_postproc(ctx, ctx->vpu_dst_fmt)) +- hantro_postproc_enable(ctx); +- else +- hantro_postproc_disable(ctx); ++ if (!ctx->is_encoder) { ++ if (hantro_needs_postproc(ctx, ctx->vpu_dst_fmt)) ++ hantro_postproc_enable(ctx); ++ else ++ hantro_postproc_disable(ctx); ++ } + } + + void hantro_end_prepare_run(struct hantro_ctx *ctx) + +From 1f833bbde61660aabc0320b314bab5a2f7e42d10 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Thu, 9 Jul 2020 18:36:34 +0200 +Subject: [PATCH] rkvdec: h264: Refuse to decode unsupported bitstream + +The hardware only supports 4:2:2, 4:2:0 or 4:0:0 (monochrome), +8-bit or 10-bit depth content. + +Verify that the SPS refers to a supported bitstream, and refuse +unsupported bitstreams by failing at TRY_EXT_CTRLS time. + +The driver is currently broken on 10-bit and 4:2:2 +so disallow those as well. + +Signed-off-by: Ezequiel Garcia +Reviewed-by: Jonas Karlman +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +(cherry picked from commit 9363aa33f6a9acfd16f98c749f17f6c65d184670) +--- + drivers/staging/media/rkvdec/rkvdec.c | 27 +++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index fd68671f0286..c8151328fb70 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -27,6 +27,32 @@ + #include "rkvdec.h" + #include "rkvdec-regs.h" + ++static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_SPS) { ++ const struct v4l2_ctrl_h264_sps *sps = ctrl->p_new.p_h264_sps; ++ /* ++ * TODO: The hardware supports 10-bit and 4:2:2 profiles, ++ * but it's currently broken in the driver. ++ * Reject them for now, until it's fixed. ++ */ ++ if (sps->chroma_format_idc > 1) ++ /* Only 4:0:0 and 4:2:0 are supported */ ++ return -EINVAL; ++ if (sps->bit_depth_luma_minus8 != sps->bit_depth_chroma_minus8) ++ /* Luma and chroma bit depth mismatch */ ++ return -EINVAL; ++ if (sps->bit_depth_luma_minus8 != 0) ++ /* Only 8-bit is supported */ ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static const struct v4l2_ctrl_ops rkvdec_ctrl_ops = { ++ .try_ctrl = rkvdec_try_ctrl, ++}; ++ + static const struct rkvdec_ctrl_desc rkvdec_h264_ctrl_descs[] = { + { + .per_request = true, +@@ -42,6 +68,7 @@ static const struct rkvdec_ctrl_desc rkvdec_h264_ctrl_descs[] = { + .per_request = true, + .mandatory = true, + .cfg.id = V4L2_CID_MPEG_VIDEO_H264_SPS, ++ .cfg.ops = &rkvdec_ctrl_ops, + }, + { + .per_request = true, + +From c09155eb49e230da5fa16f188677120f967bbb36 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Thu, 9 Jul 2020 18:36:35 +0200 +Subject: [PATCH] hantro: h264: Refuse to decode unsupported bitstream + +The hardware only supports 4:2:0 or 4:0:0 (monochrome), +8-bit depth content. + +Verify that the SPS refers to a supported bitstream, and refuse +unsupported bitstreams by failing at TRY_EXT_CTRLS time. + +Given the JPEG compression level control is the only one +that needs setting, a specific ops is provided. + +Signed-off-by: Ezequiel Garcia +Reviewed-by: Philipp Zabel +Reviewed-by: Jonas Karlman +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +(cherry picked from commit d70cca7323442026e20c474314518c446cb4766f) +--- + drivers/staging/media/hantro/hantro_drv.c | 29 ++++++++++++++++++++--- + 1 file changed, 26 insertions(+), 3 deletions(-) + +diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c +index d32b6b1ab70b..34797507f214 100644 +--- a/drivers/staging/media/hantro/hantro_drv.c ++++ b/drivers/staging/media/hantro/hantro_drv.c +@@ -229,7 +229,25 @@ queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq) + return vb2_queue_init(dst_vq); + } + +-static int hantro_s_ctrl(struct v4l2_ctrl *ctrl) ++static int hantro_try_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_SPS) { ++ const struct v4l2_ctrl_h264_sps *sps = ctrl->p_new.p_h264_sps; ++ ++ if (sps->chroma_format_idc > 1) ++ /* Only 4:0:0 and 4:2:0 are supported */ ++ return -EINVAL; ++ if (sps->bit_depth_luma_minus8 != sps->bit_depth_chroma_minus8) ++ /* Luma and chroma bit depth mismatch */ ++ return -EINVAL; ++ if (sps->bit_depth_luma_minus8 != 0) ++ /* Only 8-bit is supported */ ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int hantro_jpeg_s_ctrl(struct v4l2_ctrl *ctrl) + { + struct hantro_ctx *ctx; + +@@ -250,7 +268,11 @@ static int hantro_s_ctrl(struct v4l2_ctrl *ctrl) + } + + static const struct v4l2_ctrl_ops hantro_ctrl_ops = { +- .s_ctrl = hantro_s_ctrl, ++ .try_ctrl = hantro_try_ctrl, ++}; ++ ++static const struct v4l2_ctrl_ops hantro_jpeg_ctrl_ops = { ++ .s_ctrl = hantro_jpeg_s_ctrl, + }; + + static const struct hantro_ctrl controls[] = { +@@ -262,7 +284,7 @@ static const struct hantro_ctrl controls[] = { + .max = 100, + .step = 1, + .def = 50, +- .ops = &hantro_ctrl_ops, ++ .ops = &hantro_jpeg_ctrl_ops, + }, + }, { + .codec = HANTRO_MPEG2_DECODER, +@@ -293,6 +315,7 @@ static const struct hantro_ctrl controls[] = { + .codec = HANTRO_H264_DECODER, + .cfg = { + .id = V4L2_CID_MPEG_VIDEO_H264_SPS, ++ .ops = &hantro_ctrl_ops, + }, + }, { + .codec = HANTRO_H264_DECODER, diff --git a/patch/kernel/rk322x-dev/01-linux-0012-v4l2-from-next-from-list.patch b/patch/kernel/rk322x-dev/01-linux-0012-v4l2-from-next-from-list.patch new file mode 100644 index 000000000..c06b7447b --- /dev/null +++ b/patch/kernel/rk322x-dev/01-linux-0012-v4l2-from-next-from-list.patch @@ -0,0 +1,7852 @@ +From 337af64a63b5d8d5a60ad8302cca0bfa4d0cc4ad Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Fri, 17 Jul 2020 16:53:16 +0200 +Subject: [PATCH] media: i2c: Use the new get_mbus_config pad op + +Move the existing users of the g_mbus_config video operation to use the +newly introduced get_mbus_config pad operations. + +All the ported drivers report a static media bus configuration and do no +support s_mbus_config so the operation implementation has not changed. + +Bridge drivers needs to call the new pad operation and will receive an +-ENOICTLCMD when calling the old g_mbus_config video operation + +Signed-off-by: Jacopo Mondi +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/i2c/adv7180.c | 7 ++++--- + drivers/media/i2c/ml86v7667.c | 7 ++++--- + drivers/media/i2c/mt9m001.c | 7 ++++--- + drivers/media/i2c/mt9m111.c | 7 ++++--- + drivers/media/i2c/ov9640.c | 7 ++++--- + drivers/media/i2c/tc358743.c | 7 ++++--- + drivers/media/i2c/tvp5150.c | 7 ++++--- + 7 files changed, 28 insertions(+), 21 deletions(-) + +diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c +index 00159daa6fcd..e8744efe3cf0 100644 +--- a/drivers/media/i2c/adv7180.c ++++ b/drivers/media/i2c/adv7180.c +@@ -760,8 +760,9 @@ static int adv7180_init_cfg(struct v4l2_subdev *sd, + return adv7180_set_pad_format(sd, cfg, &fmt); + } + +-static int adv7180_g_mbus_config(struct v4l2_subdev *sd, +- struct v4l2_mbus_config *cfg) ++static int adv7180_get_mbus_config(struct v4l2_subdev *sd, ++ unsigned int pad, ++ struct v4l2_mbus_config *cfg) + { + struct adv7180_state *state = to_state(sd); + +@@ -852,7 +853,6 @@ static const struct v4l2_subdev_video_ops adv7180_video_ops = { + .querystd = adv7180_querystd, + .g_input_status = adv7180_g_input_status, + .s_routing = adv7180_s_routing, +- .g_mbus_config = adv7180_g_mbus_config, + .g_pixelaspect = adv7180_g_pixelaspect, + .g_tvnorms = adv7180_g_tvnorms, + .s_stream = adv7180_s_stream, +@@ -869,6 +869,7 @@ static const struct v4l2_subdev_pad_ops adv7180_pad_ops = { + .enum_mbus_code = adv7180_enum_mbus_code, + .set_fmt = adv7180_set_pad_format, + .get_fmt = adv7180_get_pad_format, ++ .get_mbus_config = adv7180_get_mbus_config, + }; + + static const struct v4l2_subdev_sensor_ops adv7180_sensor_ops = { +diff --git a/drivers/media/i2c/ml86v7667.c b/drivers/media/i2c/ml86v7667.c +index c444bd6a0658..ff212335326a 100644 +--- a/drivers/media/i2c/ml86v7667.c ++++ b/drivers/media/i2c/ml86v7667.c +@@ -219,8 +219,9 @@ static int ml86v7667_fill_fmt(struct v4l2_subdev *sd, + return 0; + } + +-static int ml86v7667_g_mbus_config(struct v4l2_subdev *sd, +- struct v4l2_mbus_config *cfg) ++static int ml86v7667_get_mbus_config(struct v4l2_subdev *sd, ++ unsigned int pad, ++ struct v4l2_mbus_config *cfg) + { + cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING | + V4L2_MBUS_DATA_ACTIVE_HIGH; +@@ -291,13 +292,13 @@ static const struct v4l2_subdev_video_ops ml86v7667_subdev_video_ops = { + .s_std = ml86v7667_s_std, + .querystd = ml86v7667_querystd, + .g_input_status = ml86v7667_g_input_status, +- .g_mbus_config = ml86v7667_g_mbus_config, + }; + + static const struct v4l2_subdev_pad_ops ml86v7667_subdev_pad_ops = { + .enum_mbus_code = ml86v7667_enum_mbus_code, + .get_fmt = ml86v7667_fill_fmt, + .set_fmt = ml86v7667_fill_fmt, ++ .get_mbus_config = ml86v7667_get_mbus_config, + }; + + static const struct v4l2_subdev_core_ops ml86v7667_subdev_core_ops = { +diff --git a/drivers/media/i2c/mt9m001.c b/drivers/media/i2c/mt9m001.c +index 210ea76adb53..3b0ba8ed5233 100644 +--- a/drivers/media/i2c/mt9m001.c ++++ b/drivers/media/i2c/mt9m001.c +@@ -689,8 +689,9 @@ static int mt9m001_enum_mbus_code(struct v4l2_subdev *sd, + return 0; + } + +-static int mt9m001_g_mbus_config(struct v4l2_subdev *sd, +- struct v4l2_mbus_config *cfg) ++static int mt9m001_get_mbus_config(struct v4l2_subdev *sd, ++ unsigned int pad, ++ struct v4l2_mbus_config *cfg) + { + /* MT9M001 has all capture_format parameters fixed */ + cfg->flags = V4L2_MBUS_PCLK_SAMPLE_FALLING | +@@ -703,7 +704,6 @@ static int mt9m001_g_mbus_config(struct v4l2_subdev *sd, + + static const struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = { + .s_stream = mt9m001_s_stream, +- .g_mbus_config = mt9m001_g_mbus_config, + }; + + static const struct v4l2_subdev_sensor_ops mt9m001_subdev_sensor_ops = { +@@ -717,6 +717,7 @@ static const struct v4l2_subdev_pad_ops mt9m001_subdev_pad_ops = { + .set_selection = mt9m001_set_selection, + .get_fmt = mt9m001_get_fmt, + .set_fmt = mt9m001_set_fmt, ++ .get_mbus_config = mt9m001_get_mbus_config, + }; + + static const struct v4l2_subdev_ops mt9m001_subdev_ops = { +diff --git a/drivers/media/i2c/mt9m111.c b/drivers/media/i2c/mt9m111.c +index 17e8253f5748..69697386ffcd 100644 +--- a/drivers/media/i2c/mt9m111.c ++++ b/drivers/media/i2c/mt9m111.c +@@ -1137,8 +1137,9 @@ static int mt9m111_init_cfg(struct v4l2_subdev *sd, + return 0; + } + +-static int mt9m111_g_mbus_config(struct v4l2_subdev *sd, +- struct v4l2_mbus_config *cfg) ++static int mt9m111_get_mbus_config(struct v4l2_subdev *sd, ++ unsigned int pad, ++ struct v4l2_mbus_config *cfg) + { + struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev); + +@@ -1155,7 +1156,6 @@ static int mt9m111_g_mbus_config(struct v4l2_subdev *sd, + } + + static const struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = { +- .g_mbus_config = mt9m111_g_mbus_config, + .s_stream = mt9m111_s_stream, + .g_frame_interval = mt9m111_g_frame_interval, + .s_frame_interval = mt9m111_s_frame_interval, +@@ -1168,6 +1168,7 @@ static const struct v4l2_subdev_pad_ops mt9m111_subdev_pad_ops = { + .set_selection = mt9m111_set_selection, + .get_fmt = mt9m111_get_fmt, + .set_fmt = mt9m111_set_fmt, ++ .get_mbus_config = mt9m111_get_mbus_config, + }; + + static const struct v4l2_subdev_ops mt9m111_subdev_ops = { +diff --git a/drivers/media/i2c/ov9640.c b/drivers/media/i2c/ov9640.c +index 482609665305..0ef5af026d09 100644 +--- a/drivers/media/i2c/ov9640.c ++++ b/drivers/media/i2c/ov9640.c +@@ -648,8 +648,9 @@ static const struct v4l2_subdev_core_ops ov9640_core_ops = { + }; + + /* Request bus settings on camera side */ +-static int ov9640_g_mbus_config(struct v4l2_subdev *sd, +- struct v4l2_mbus_config *cfg) ++static int ov9640_get_mbus_config(struct v4l2_subdev *sd, ++ unsigned int pad, ++ struct v4l2_mbus_config *cfg) + { + cfg->flags = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER | + V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_HIGH | +@@ -661,13 +662,13 @@ static int ov9640_g_mbus_config(struct v4l2_subdev *sd, + + static const struct v4l2_subdev_video_ops ov9640_video_ops = { + .s_stream = ov9640_s_stream, +- .g_mbus_config = ov9640_g_mbus_config, + }; + + static const struct v4l2_subdev_pad_ops ov9640_pad_ops = { + .enum_mbus_code = ov9640_enum_mbus_code, + .get_selection = ov9640_get_selection, + .set_fmt = ov9640_set_fmt, ++ .get_mbus_config = ov9640_get_mbus_config, + }; + + static const struct v4l2_subdev_ops ov9640_subdev_ops = { +diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c +index dbbab75f135e..a03dcab5ce61 100644 +--- a/drivers/media/i2c/tc358743.c ++++ b/drivers/media/i2c/tc358743.c +@@ -1602,8 +1602,9 @@ static int tc358743_dv_timings_cap(struct v4l2_subdev *sd, + return 0; + } + +-static int tc358743_g_mbus_config(struct v4l2_subdev *sd, +- struct v4l2_mbus_config *cfg) ++static int tc358743_get_mbus_config(struct v4l2_subdev *sd, ++ unsigned int pad, ++ struct v4l2_mbus_config *cfg) + { + struct tc358743_state *state = to_state(sd); + +@@ -1836,7 +1837,6 @@ static const struct v4l2_subdev_video_ops tc358743_video_ops = { + .s_dv_timings = tc358743_s_dv_timings, + .g_dv_timings = tc358743_g_dv_timings, + .query_dv_timings = tc358743_query_dv_timings, +- .g_mbus_config = tc358743_g_mbus_config, + .s_stream = tc358743_s_stream, + }; + +@@ -1848,6 +1848,7 @@ static const struct v4l2_subdev_pad_ops tc358743_pad_ops = { + .set_edid = tc358743_s_edid, + .enum_dv_timings = tc358743_enum_dv_timings, + .dv_timings_cap = tc358743_dv_timings_cap, ++ .get_mbus_config = tc358743_get_mbus_config, + }; + + static const struct v4l2_subdev_ops tc358743_ops = { +diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c +index 9df575238952..1c2050944b92 100644 +--- a/drivers/media/i2c/tvp5150.c ++++ b/drivers/media/i2c/tvp5150.c +@@ -1191,8 +1191,9 @@ static int tvp5150_get_selection(struct v4l2_subdev *sd, + } + } + +-static int tvp5150_g_mbus_config(struct v4l2_subdev *sd, +- struct v4l2_mbus_config *cfg) ++static int tvp5150_get_mbus_config(struct v4l2_subdev *sd, ++ unsigned int pad, ++ struct v4l2_mbus_config *cfg) + { + struct tvp5150 *decoder = to_tvp5150(sd); + +@@ -1721,7 +1722,6 @@ static const struct v4l2_subdev_video_ops tvp5150_video_ops = { + .querystd = tvp5150_querystd, + .s_stream = tvp5150_s_stream, + .s_routing = tvp5150_s_routing, +- .g_mbus_config = tvp5150_g_mbus_config, + }; + + static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = { +@@ -1739,6 +1739,7 @@ static const struct v4l2_subdev_pad_ops tvp5150_pad_ops = { + .get_fmt = tvp5150_fill_fmt, + .get_selection = tvp5150_get_selection, + .set_selection = tvp5150_set_selection, ++ .get_mbus_config = tvp5150_get_mbus_config, + }; + + static const struct v4l2_subdev_ops tvp5150_ops = { + +From 4cc9a9a8b16549358ea377485df8fe21ea9e1bff Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Tue, 21 Jul 2020 09:53:17 +0200 +Subject: [PATCH] media: i2c: ov6650: Use new [get|set]_mbus_config ops + +Use the new get_mbus_config and set_mbus_config pad operations in place +of the video operations currently in use. + +Compared to other drivers where the same conversion has been performed, +ov6650 proved to be a bit more tricky, as the existing g_mbus_config +implementation did not report the currently applied configuration but +the set of all possible configuration options. + +Adapt the driver to support the semantic of the two newly introduced +operations: +- get_mbus_config reports the current media bus configuration +- set_mbus_config applies only changes explicitly requested and updates + the provided cfg parameter to report what has actually been applied to + the hardware. + +Compile-tested only. + +Signed-off-by: Jacopo Mondi +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/i2c/ov6650.c | 53 ++++++++++++++++++++++++++------------ + 1 file changed, 37 insertions(+), 16 deletions(-) + +diff --git a/drivers/media/i2c/ov6650.c b/drivers/media/i2c/ov6650.c +index 91906b94f978..48493af81198 100644 +--- a/drivers/media/i2c/ov6650.c ++++ b/drivers/media/i2c/ov6650.c +@@ -921,55 +921,74 @@ static const struct v4l2_subdev_core_ops ov6650_core_ops = { + }; + + /* Request bus settings on camera side */ +-static int ov6650_g_mbus_config(struct v4l2_subdev *sd, +- struct v4l2_mbus_config *cfg) ++static int ov6650_get_mbus_config(struct v4l2_subdev *sd, ++ unsigned int pad, ++ struct v4l2_mbus_config *cfg) + { ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ u8 comj, comf; ++ int ret; ++ ++ ret = ov6650_reg_read(client, REG_COMJ, &comj); ++ if (ret) ++ return ret; + +- cfg->flags = V4L2_MBUS_MASTER | +- V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING | +- V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_LOW | +- V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_LOW | +- V4L2_MBUS_DATA_ACTIVE_HIGH; ++ ret = ov6650_reg_read(client, REG_COMF, &comf); ++ if (ret) ++ return ret; ++ ++ cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_DATA_ACTIVE_HIGH ++ | ((comj & COMJ_VSYNC_HIGH) ? V4L2_MBUS_VSYNC_ACTIVE_HIGH ++ : V4L2_MBUS_VSYNC_ACTIVE_LOW) ++ | ((comf & COMF_HREF_LOW) ? V4L2_MBUS_HSYNC_ACTIVE_LOW ++ : V4L2_MBUS_HSYNC_ACTIVE_HIGH) ++ | ((comj & COMJ_PCLK_RISING) ? V4L2_MBUS_PCLK_SAMPLE_RISING ++ : V4L2_MBUS_PCLK_SAMPLE_FALLING); + cfg->type = V4L2_MBUS_PARALLEL; + + return 0; + } + + /* Alter bus settings on camera side */ +-static int ov6650_s_mbus_config(struct v4l2_subdev *sd, +- const struct v4l2_mbus_config *cfg) ++static int ov6650_set_mbus_config(struct v4l2_subdev *sd, ++ unsigned int pad, ++ struct v4l2_mbus_config *cfg) + { + struct i2c_client *client = v4l2_get_subdevdata(sd); +- int ret; ++ int ret = 0; + + if (cfg->flags & V4L2_MBUS_PCLK_SAMPLE_RISING) + ret = ov6650_reg_rmw(client, REG_COMJ, COMJ_PCLK_RISING, 0); +- else ++ else if (cfg->flags & V4L2_MBUS_PCLK_SAMPLE_FALLING) + ret = ov6650_reg_rmw(client, REG_COMJ, 0, COMJ_PCLK_RISING); + if (ret) + return ret; + + if (cfg->flags & V4L2_MBUS_HSYNC_ACTIVE_LOW) + ret = ov6650_reg_rmw(client, REG_COMF, COMF_HREF_LOW, 0); +- else ++ else if (cfg->flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) + ret = ov6650_reg_rmw(client, REG_COMF, 0, COMF_HREF_LOW); + if (ret) + return ret; + + if (cfg->flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) + ret = ov6650_reg_rmw(client, REG_COMJ, COMJ_VSYNC_HIGH, 0); +- else ++ else if (cfg->flags & V4L2_MBUS_VSYNC_ACTIVE_LOW) + ret = ov6650_reg_rmw(client, REG_COMJ, 0, COMJ_VSYNC_HIGH); ++ if (ret) ++ return ret; + +- return ret; ++ /* ++ * Update the configuration to report what is actually applied to ++ * the hardware. ++ */ ++ return ov6650_get_mbus_config(sd, pad, cfg); + } + + static const struct v4l2_subdev_video_ops ov6650_video_ops = { + .s_stream = ov6650_s_stream, + .g_frame_interval = ov6650_g_frame_interval, + .s_frame_interval = ov6650_s_frame_interval, +- .g_mbus_config = ov6650_g_mbus_config, +- .s_mbus_config = ov6650_s_mbus_config, + }; + + static const struct v4l2_subdev_pad_ops ov6650_pad_ops = { +@@ -978,6 +997,8 @@ static const struct v4l2_subdev_pad_ops ov6650_pad_ops = { + .set_selection = ov6650_set_selection, + .get_fmt = ov6650_get_fmt, + .set_fmt = ov6650_set_fmt, ++ .get_mbus_config = ov6650_get_mbus_config, ++ .set_mbus_config = ov6650_set_mbus_config, + }; + + static const struct v4l2_subdev_ops ov6650_subdev_ops = { + +From 9b55924aa37a4ba85f84b8c4e382efffdf2b73df Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Fri, 17 Jul 2020 16:53:18 +0200 +Subject: [PATCH] media: pxa_camera: Use the new set_mbus_config op + +Move the PXA camera driver to use the new set_mbus_config pad operation. +For this platform the change is not only cosmetic, as the pxa driver is +currently the only driver in mainline to make use of the g_mbus_config +and s_mbus_config video operations. + +The existing driver semantic is the following: +- Collect all supported mbus config flags from the remote end +- Match them with the supported PXA mbus configuration flags +- If the remote subdevice allows multiple options for for VSYNC, HSYNC + and PCLK polarity, use platform data requested settings + +The semantic of the new get_mbus_config and set_mbus_config differs from +the corresponding video ops, particularly in the fact get_mbus_config +reports the current mbus configuration and not the set of supported +configuration options, with set_mbus_config always reporting the actual +mbus configuration applied to the remote subdevice. + +Adapt the driver to perform the following +- Set the remote subdevice mbus configuration according to the PXA + platform data preferences. +- If the applied configuration differs from the requested one (i.e. the + remote subdevice does not allow changing one setting) make sure that + - The remote end does not claim for DATA_ACTIVE_LOW, which seems not + supported by the platform + - The bus mastering roles match + +While at there remove a few checks performed on the media bus +configuration at get_format() time as they do not belong there. + +Compile-tested only. + +Signed-off-by: Jacopo Mondi +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/platform/pxa_camera.c | 189 ++++++++-------------------- + 1 file changed, 51 insertions(+), 138 deletions(-) + +diff --git a/drivers/media/platform/pxa_camera.c b/drivers/media/platform/pxa_camera.c +index 3c5fe737d36f..3a2cd28178da 100644 +--- a/drivers/media/platform/pxa_camera.c ++++ b/drivers/media/platform/pxa_camera.c +@@ -605,42 +605,6 @@ static const struct pxa_mbus_pixelfmt *pxa_mbus_get_fmtdesc( + return pxa_mbus_find_fmtdesc(code, mbus_fmt, ARRAY_SIZE(mbus_fmt)); + } + +-static unsigned int pxa_mbus_config_compatible(const struct v4l2_mbus_config *cfg, +- unsigned int flags) +-{ +- unsigned long common_flags; +- bool hsync = true, vsync = true, pclk, data, mode; +- bool mipi_lanes, mipi_clock; +- +- common_flags = cfg->flags & flags; +- +- switch (cfg->type) { +- case V4L2_MBUS_PARALLEL: +- hsync = common_flags & (V4L2_MBUS_HSYNC_ACTIVE_HIGH | +- V4L2_MBUS_HSYNC_ACTIVE_LOW); +- vsync = common_flags & (V4L2_MBUS_VSYNC_ACTIVE_HIGH | +- V4L2_MBUS_VSYNC_ACTIVE_LOW); +- /* fall through */ +- case V4L2_MBUS_BT656: +- pclk = common_flags & (V4L2_MBUS_PCLK_SAMPLE_RISING | +- V4L2_MBUS_PCLK_SAMPLE_FALLING); +- data = common_flags & (V4L2_MBUS_DATA_ACTIVE_HIGH | +- V4L2_MBUS_DATA_ACTIVE_LOW); +- mode = common_flags & (V4L2_MBUS_MASTER | V4L2_MBUS_SLAVE); +- return (!hsync || !vsync || !pclk || !data || !mode) ? +- 0 : common_flags; +- case V4L2_MBUS_CSI2_DPHY: +- mipi_lanes = common_flags & V4L2_MBUS_CSI2_LANES; +- mipi_clock = common_flags & (V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK | +- V4L2_MBUS_CSI2_CONTINUOUS_CLOCK); +- return (!mipi_lanes || !mipi_clock) ? 0 : common_flags; +- default: +- WARN_ON(1); +- return -EINVAL; +- } +- return 0; +-} +- + /** + * struct pxa_camera_format_xlate - match between host and sensor formats + * @code: code of a sensor provided format +@@ -1231,31 +1195,6 @@ static irqreturn_t pxa_camera_irq(int irq, void *data) + return IRQ_HANDLED; + } + +-static int test_platform_param(struct pxa_camera_dev *pcdev, +- unsigned char buswidth, unsigned long *flags) +-{ +- /* +- * Platform specified synchronization and pixel clock polarities are +- * only a recommendation and are only used during probing. The PXA270 +- * quick capture interface supports both. +- */ +- *flags = (pcdev->platform_flags & PXA_CAMERA_MASTER ? +- V4L2_MBUS_MASTER : V4L2_MBUS_SLAVE) | +- V4L2_MBUS_HSYNC_ACTIVE_HIGH | +- V4L2_MBUS_HSYNC_ACTIVE_LOW | +- V4L2_MBUS_VSYNC_ACTIVE_HIGH | +- V4L2_MBUS_VSYNC_ACTIVE_LOW | +- V4L2_MBUS_DATA_ACTIVE_HIGH | +- V4L2_MBUS_PCLK_SAMPLE_RISING | +- V4L2_MBUS_PCLK_SAMPLE_FALLING; +- +- /* If requested data width is supported by the platform, use it */ +- if ((1 << (buswidth - 1)) & pcdev->width_flags) +- return 0; +- +- return -EINVAL; +-} +- + static void pxa_camera_setup_cicr(struct pxa_camera_dev *pcdev, + unsigned long flags, __u32 pixfmt) + { +@@ -1598,99 +1537,78 @@ static int pxa_camera_init_videobuf2(struct pxa_camera_dev *pcdev) + */ + static int pxa_camera_set_bus_param(struct pxa_camera_dev *pcdev) + { ++ unsigned int bus_width = pcdev->current_fmt->host_fmt->bits_per_sample; + struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,}; + u32 pixfmt = pcdev->current_fmt->host_fmt->fourcc; +- unsigned long bus_flags, common_flags; ++ int mbus_config; + int ret; + +- ret = test_platform_param(pcdev, +- pcdev->current_fmt->host_fmt->bits_per_sample, +- &bus_flags); +- if (ret < 0) +- return ret; +- +- ret = sensor_call(pcdev, video, g_mbus_config, &cfg); +- if (!ret) { +- common_flags = pxa_mbus_config_compatible(&cfg, +- bus_flags); +- if (!common_flags) { +- dev_warn(pcdev_to_dev(pcdev), +- "Flags incompatible: camera 0x%x, host 0x%lx\n", +- cfg.flags, bus_flags); +- return -EINVAL; +- } +- } else if (ret != -ENOIOCTLCMD) { +- return ret; +- } else { +- common_flags = bus_flags; ++ if (!((1 << (bus_width - 1)) & pcdev->width_flags)) { ++ dev_err(pcdev_to_dev(pcdev), "Unsupported bus width %u", ++ bus_width); ++ return -EINVAL; + } + + pcdev->channels = 1; + + /* Make choices, based on platform preferences */ +- if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) && +- (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) { +- if (pcdev->platform_flags & PXA_CAMERA_HSP) +- common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH; +- else +- common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW; +- } ++ mbus_config = 0; ++ if (pcdev->platform_flags & PXA_CAMERA_MASTER) ++ mbus_config |= V4L2_MBUS_MASTER; ++ else ++ mbus_config |= V4L2_MBUS_SLAVE; + +- if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) && +- (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) { +- if (pcdev->platform_flags & PXA_CAMERA_VSP) +- common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH; +- else +- common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW; +- } ++ if (pcdev->platform_flags & PXA_CAMERA_HSP) ++ mbus_config |= V4L2_MBUS_HSYNC_ACTIVE_HIGH; ++ else ++ mbus_config |= V4L2_MBUS_HSYNC_ACTIVE_LOW; + +- if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) && +- (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) { +- if (pcdev->platform_flags & PXA_CAMERA_PCP) +- common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING; +- else +- common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING; +- } ++ if (pcdev->platform_flags & PXA_CAMERA_VSP) ++ mbus_config |= V4L2_MBUS_VSYNC_ACTIVE_HIGH; ++ else ++ mbus_config |= V4L2_MBUS_VSYNC_ACTIVE_LOW; + +- cfg.flags = common_flags; +- ret = sensor_call(pcdev, video, s_mbus_config, &cfg); ++ if (pcdev->platform_flags & PXA_CAMERA_PCP) ++ mbus_config |= V4L2_MBUS_PCLK_SAMPLE_RISING; ++ else ++ mbus_config |= V4L2_MBUS_PCLK_SAMPLE_FALLING; ++ mbus_config |= V4L2_MBUS_DATA_ACTIVE_HIGH; ++ ++ cfg.flags = mbus_config; ++ ret = sensor_call(pcdev, pad, set_mbus_config, 0, &cfg); + if (ret < 0 && ret != -ENOIOCTLCMD) { +- dev_dbg(pcdev_to_dev(pcdev), +- "camera s_mbus_config(0x%lx) returned %d\n", +- common_flags, ret); ++ dev_err(pcdev_to_dev(pcdev), ++ "Failed to call set_mbus_config: %d\n", ret); + return ret; + } + +- pxa_camera_setup_cicr(pcdev, common_flags, pixfmt); +- +- return 0; +-} +- +-static int pxa_camera_try_bus_param(struct pxa_camera_dev *pcdev, +- unsigned char buswidth) +-{ +- struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,}; +- unsigned long bus_flags, common_flags; +- int ret = test_platform_param(pcdev, buswidth, &bus_flags); +- +- if (ret < 0) +- return ret; ++ /* ++ * If the requested media bus configuration has not been fully applied ++ * make sure it is supported by the platform. ++ * ++ * PXA does not support V4L2_MBUS_DATA_ACTIVE_LOW and the bus mastering ++ * roles should match. ++ */ ++ if (cfg.flags != mbus_config) { ++ unsigned int pxa_mbus_role = mbus_config & (V4L2_MBUS_MASTER | ++ V4L2_MBUS_SLAVE); ++ if (pxa_mbus_role != (cfg.flags & (V4L2_MBUS_MASTER | ++ V4L2_MBUS_SLAVE))) { ++ dev_err(pcdev_to_dev(pcdev), ++ "Unsupported mbus configuration: bus mastering\n"); ++ return -EINVAL; ++ } + +- ret = sensor_call(pcdev, video, g_mbus_config, &cfg); +- if (!ret) { +- common_flags = pxa_mbus_config_compatible(&cfg, +- bus_flags); +- if (!common_flags) { +- dev_warn(pcdev_to_dev(pcdev), +- "Flags incompatible: camera 0x%x, host 0x%lx\n", +- cfg.flags, bus_flags); ++ if (cfg.flags & V4L2_MBUS_DATA_ACTIVE_LOW) { ++ dev_err(pcdev_to_dev(pcdev), ++ "Unsupported mbus configuration: DATA_ACTIVE_LOW\n"); + return -EINVAL; + } +- } else if (ret == -ENOIOCTLCMD) { +- ret = 0; + } + +- return ret; ++ pxa_camera_setup_cicr(pcdev, cfg.flags, pixfmt); ++ ++ return 0; + } + + static const struct pxa_mbus_pixelfmt pxa_camera_formats[] = { +@@ -1738,11 +1656,6 @@ static int pxa_camera_get_formats(struct v4l2_device *v4l2_dev, + return 0; + } + +- /* This also checks support for the requested bits-per-sample */ +- ret = pxa_camera_try_bus_param(pcdev, fmt->bits_per_sample); +- if (ret < 0) +- return 0; +- + switch (code.code) { + case MEDIA_BUS_FMT_UYVY8_2X8: + formats++; + +From 562b1d8a78c8367d9809491277a6c60441565aa4 Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Fri, 17 Jul 2020 16:53:19 +0200 +Subject: [PATCH] media: v4l2-subdev: Remove [s|g]_mbus_config video ops + +With all sensor and platform drivers now converted to use the new +get_mbus_config and set_mbus_config pad operations, remove the +deprecated video operations g_mbus_config and s_mbus_config. + +Signed-off-by: Jacopo Mondi +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + include/media/v4l2-subdev.h | 10 ---------- + 1 file changed, 10 deletions(-) + +diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h +index f7fe78a6f65a..90098fb1d770 100644 +--- a/include/media/v4l2-subdev.h ++++ b/include/media/v4l2-subdev.h +@@ -402,12 +402,6 @@ struct v4l2_mbus_frame_desc { + * + * @query_dv_timings: callback for VIDIOC_QUERY_DV_TIMINGS() ioctl handler code. + * +- * @g_mbus_config: get supported mediabus configurations +- * +- * @s_mbus_config: set a certain mediabus configuration. This operation is added +- * for compatibility with soc-camera drivers and should not be used by new +- * software. +- * + * @s_rx_buffer: set a host allocated memory buffer for the subdev. The subdev + * can adjust @size to a lower value and must not write more data to the + * buffer starting at @data than the original value of @size. +@@ -435,10 +429,6 @@ struct v4l2_subdev_video_ops { + struct v4l2_dv_timings *timings); + int (*query_dv_timings)(struct v4l2_subdev *sd, + struct v4l2_dv_timings *timings); +- int (*g_mbus_config)(struct v4l2_subdev *sd, +- struct v4l2_mbus_config *cfg); +- int (*s_mbus_config)(struct v4l2_subdev *sd, +- const struct v4l2_mbus_config *cfg); + int (*s_rx_buffer)(struct v4l2_subdev *sd, void *buf, + unsigned int *size); + }; + +From 1ea27db9eaddf1eb44e533e4baa49b5b3a50900f Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Fri, 17 Jul 2020 16:53:20 +0200 +Subject: [PATCH] media: v4l2- mediabus: Add usage note for V4L2_MBUS_* + +With the removal of the legacy g_mbus_config and s_mbus_config video +operations, the sole users of V4L2_MBUS_* flags are now the newly +introduced get_mbus_config and set_mbus_config pad operations. + +As the semantic of the new operations differs from the semantic of +the legacy ones, add a usage note in the v4l2-mediabus.h header to +specify how to use the flags. + +Also add a TODO note to record that we intend to replace the existing +flags with fields, to prevent users from mixing conflicting values +in a single operation call. + +Signed-off-by: Jacopo Mondi +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + include/media/v4l2-mediabus.h | 33 +++++++++++++++++++++++++++++---- + 1 file changed, 29 insertions(+), 4 deletions(-) + +diff --git a/include/media/v4l2-mediabus.h b/include/media/v4l2-mediabus.h +index 45f88f0248c4..59b1de197114 100644 +--- a/include/media/v4l2-mediabus.h ++++ b/include/media/v4l2-mediabus.h +@@ -11,9 +11,34 @@ + #include + #include + ++/* ++ * How to use the V4L2_MBUS_* flags: ++ * Flags are defined for each of the possible states and values of a media ++ * bus configuration parameter. One and only one bit of each group of flags ++ * shall be set by the users of the v4l2_subdev_pad_ops.get_mbus_config and ++ * v4l2_subdev_pad_ops.set_mbus_config operations to ensure that no ++ * conflicting settings are specified when reporting and setting the media bus ++ * configuration with the two operations respectively. For example, it is ++ * invalid to set or clear both the V4L2_MBUS_HSYNC_ACTIVE_HIGH and the ++ * V4L2_MBUS_HSYNC_ACTIVE_LOW flag at the same time. Instead either flag ++ * V4L2_MBUS_HSYNC_ACTIVE_HIGH or flag V4L2_MBUS_HSYNC_ACTIVE_LOW shall be ++ * set. The same is true for the V4L2_MBUS_CSI2_1/2/3/4_LANE flags group: only ++ * one of these four bits shall be set. ++ * ++ * TODO: replace the existing V4L2_MBUS_* flags with structures of fields ++ * to avoid conflicting settings. ++ * ++ * In example: ++ * #define V4L2_MBUS_HSYNC_ACTIVE_HIGH BIT(2) ++ * #define V4L2_MBUS_HSYNC_ACTIVE_LOW BIT(3) ++ * will be replaced by a field whose value reports the intended active state of ++ * the signal: ++ * unsigned int v4l2_mbus_hsync_active : 1; ++ */ ++ + /* Parallel flags */ + /* +- * Can the client run in master or in slave mode. By "Master mode" an operation ++ * The client runs in master or in slave mode. By "Master mode" an operation + * mode is meant, when the client (e.g., a camera sensor) is producing + * horizontal and vertical synchronisation. In "Slave mode" the host is + * providing these signals to the slave. +@@ -45,17 +70,17 @@ + #define V4L2_MBUS_DATA_ENABLE_LOW BIT(15) + + /* Serial flags */ +-/* How many lanes the client can use */ ++/* CSI-2 D-PHY number of data lanes. */ + #define V4L2_MBUS_CSI2_1_LANE BIT(0) + #define V4L2_MBUS_CSI2_2_LANE BIT(1) + #define V4L2_MBUS_CSI2_3_LANE BIT(2) + #define V4L2_MBUS_CSI2_4_LANE BIT(3) +-/* On which channels it can send video data */ ++/* CSI-2 Virtual Channel identifiers. */ + #define V4L2_MBUS_CSI2_CHANNEL_0 BIT(4) + #define V4L2_MBUS_CSI2_CHANNEL_1 BIT(5) + #define V4L2_MBUS_CSI2_CHANNEL_2 BIT(6) + #define V4L2_MBUS_CSI2_CHANNEL_3 BIT(7) +-/* Does it support only continuous or also non-continuous clock mode */ ++/* Clock non-continuous mode support. */ + #define V4L2_MBUS_CSI2_CONTINUOUS_CLOCK BIT(8) + #define V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK BIT(9) + + +From 9aae063d84435edfb0212c7613f887105dd58009 Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Fri, 17 Jul 2020 16:53:21 +0200 +Subject: [PATCH] media: staging: media: imx: Update TODO entry + +Update the TODO entry that mentioned a potential use case for the now +removed g_mbus_config video operation. + +Signed-off-by: Jacopo Mondi +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/staging/media/imx/TODO | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/staging/media/imx/TODO b/drivers/staging/media/imx/TODO +index a371cdedcdb0..9cfc1c1e78dc 100644 +--- a/drivers/staging/media/imx/TODO ++++ b/drivers/staging/media/imx/TODO +@@ -10,6 +10,10 @@ + driver uses the parsed DT bus config method until this issue is + resolved. + ++ 2020-06: g_mbus has been removed in favour of the get_mbus_config pad ++ operation which should be used to avoid parsing the remote endpoint ++ configuration. ++ + - This media driver supports inheriting V4L2 controls to the + video capture devices, from the subdevices in the capture device's + pipeline. The controls for each capture device are updated in the + +From 33a781840365c6b8a2b86b1c6cb4aaa86941a5d6 Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Fri, 17 Jul 2020 16:53:22 +0200 +Subject: [PATCH] media: i2c: adv748x: Adjust TXA data lanes number +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When outputting SD-Core output through the TXA MIPI CSI-2 interface, +the number of enabled data lanes should be reduced in order to guarantee +that the two video formats produced by the SD-Core (480i and 576i) +generate a MIPI CSI-2 link clock frequency compatible with the MIPI D-PHY +specifications. + +Limit the number of enabled data lanes to 2, which is guaranteed to +support 480i and 576i formats. + +Cache the number of enabled data lanes to be able to report it through +the new get_mbus_config operation. + +Reviewed-by: Kieran Bingham +Reviewed-by: Laurent Pinchart +Reviewed-by: Niklas Söderlund +Signed-off-by: Jacopo Mondi +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/i2c/adv748x/adv748x-core.c | 31 ++++++++++++++++++------ + drivers/media/i2c/adv748x/adv748x.h | 1 + + 2 files changed, 25 insertions(+), 7 deletions(-) + +diff --git a/drivers/media/i2c/adv748x/adv748x-core.c b/drivers/media/i2c/adv748x/adv748x-core.c +index 23e02ff27b17..1fe7f97c6d52 100644 +--- a/drivers/media/i2c/adv748x/adv748x-core.c ++++ b/drivers/media/i2c/adv748x/adv748x-core.c +@@ -241,10 +241,10 @@ static int adv748x_power_up_tx(struct adv748x_csi2 *tx) + int ret = 0; + + /* Enable n-lane MIPI */ +- adv748x_write_check(state, page, 0x00, 0x80 | tx->num_lanes, &ret); ++ adv748x_write_check(state, page, 0x00, 0x80 | tx->active_lanes, &ret); + + /* Set Auto DPHY Timing */ +- adv748x_write_check(state, page, 0x00, 0xa0 | tx->num_lanes, &ret); ++ adv748x_write_check(state, page, 0x00, 0xa0 | tx->active_lanes, &ret); + + /* ADI Required Write */ + if (tx->src == &state->hdmi.sd) { +@@ -270,7 +270,7 @@ static int adv748x_power_up_tx(struct adv748x_csi2 *tx) + usleep_range(2000, 2500); + + /* Power-up CSI-TX */ +- adv748x_write_check(state, page, 0x00, 0x20 | tx->num_lanes, &ret); ++ adv748x_write_check(state, page, 0x00, 0x20 | tx->active_lanes, &ret); + usleep_range(1000, 1500); + + /* ADI Required Writes */ +@@ -292,7 +292,7 @@ static int adv748x_power_down_tx(struct adv748x_csi2 *tx) + adv748x_write_check(state, page, 0x1e, 0x00, &ret); + + /* Enable n-lane MIPI */ +- adv748x_write_check(state, page, 0x00, 0x80 | tx->num_lanes, &ret); ++ adv748x_write_check(state, page, 0x00, 0x80 | tx->active_lanes, &ret); + + /* i2c_mipi_pll_en - 1'b1 */ + adv748x_write_check(state, page, 0xda, 0x01, &ret); +@@ -357,14 +357,29 @@ static int adv748x_link_setup(struct media_entity *entity, + if (state->afe.tx) { + /* AFE Requires TXA enabled, even when output to TXB */ + io10 |= ADV748X_IO_10_CSI4_EN; +- if (is_txa(tx)) ++ if (is_txa(tx)) { ++ /* ++ * Output from the SD-core (480i and 576i) from the TXA ++ * interface requires reducing the number of enabled ++ * data lanes in order to guarantee a valid link ++ * frequency. ++ */ ++ tx->active_lanes = min(tx->num_lanes, 2U); + io10 |= ADV748X_IO_10_CSI4_IN_SEL_AFE; +- else ++ } else { ++ /* TXB has a single data lane, no need to adjust. */ + io10 |= ADV748X_IO_10_CSI1_EN; ++ } + } + +- if (state->hdmi.tx) ++ if (state->hdmi.tx) { ++ /* ++ * Restore the number of active lanes, in case we have gone ++ * through an AFE->TXA streaming sessions. ++ */ ++ tx->active_lanes = tx->num_lanes; + io10 |= ADV748X_IO_10_CSI4_EN; ++ } + + return io_clrset(state, ADV748X_IO_10, io10_mask, io10); + } +@@ -596,6 +611,7 @@ static int adv748x_parse_csi2_lanes(struct adv748x_state *state, + } + + state->txa.num_lanes = num_lanes; ++ state->txa.active_lanes = num_lanes; + adv_dbg(state, "TXA: using %u lanes\n", state->txa.num_lanes); + } + +@@ -607,6 +623,7 @@ static int adv748x_parse_csi2_lanes(struct adv748x_state *state, + } + + state->txb.num_lanes = num_lanes; ++ state->txb.active_lanes = num_lanes; + adv_dbg(state, "TXB: using %u lanes\n", state->txb.num_lanes); + } + +diff --git a/drivers/media/i2c/adv748x/adv748x.h b/drivers/media/i2c/adv748x/adv748x.h +index fccb388ce179..1061f425ece5 100644 +--- a/drivers/media/i2c/adv748x/adv748x.h ++++ b/drivers/media/i2c/adv748x/adv748x.h +@@ -79,6 +79,7 @@ struct adv748x_csi2 { + unsigned int page; + unsigned int port; + unsigned int num_lanes; ++ unsigned int active_lanes; + + struct media_pad pads[ADV748X_CSI2_NR_PADS]; + struct v4l2_ctrl_handler ctrl_hdl; + +From 5ccfd4f056cc53beef915bd24985449b7d20affc Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Fri, 17 Jul 2020 16:53:23 +0200 +Subject: [PATCH] media: i2c: adv748x: Implement get_mbus_config +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Implement the newly introduced get_mbus_config operation to report the +number of currently used data lanes on the MIPI CSI-2 interface. + +Reviewed-by: Kieran Bingham +Reviewed-by: Niklas Söderlund +Signed-off-by: Jacopo Mondi +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/i2c/adv748x/adv748x-csi2.c | 31 ++++++++++++++++++++++++ + 1 file changed, 31 insertions(+) + +diff --git a/drivers/media/i2c/adv748x/adv748x-csi2.c b/drivers/media/i2c/adv748x/adv748x-csi2.c +index 2091cda50935..99bb63d05eef 100644 +--- a/drivers/media/i2c/adv748x/adv748x-csi2.c ++++ b/drivers/media/i2c/adv748x/adv748x-csi2.c +@@ -214,9 +214,40 @@ static int adv748x_csi2_set_format(struct v4l2_subdev *sd, + return ret; + } + ++static int adv748x_csi2_get_mbus_config(struct v4l2_subdev *sd, unsigned int pad, ++ struct v4l2_mbus_config *config) ++{ ++ struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd); ++ ++ if (pad != ADV748X_CSI2_SOURCE) ++ return -EINVAL; ++ ++ config->type = V4L2_MBUS_CSI2_DPHY; ++ switch (tx->active_lanes) { ++ case 1: ++ config->flags = V4L2_MBUS_CSI2_1_LANE; ++ break; ++ ++ case 2: ++ config->flags = V4L2_MBUS_CSI2_2_LANE; ++ break; ++ ++ case 3: ++ config->flags = V4L2_MBUS_CSI2_3_LANE; ++ break; ++ ++ case 4: ++ config->flags = V4L2_MBUS_CSI2_4_LANE; ++ break; ++ } ++ ++ return 0; ++} ++ + static const struct v4l2_subdev_pad_ops adv748x_csi2_pad_ops = { + .get_fmt = adv748x_csi2_get_format, + .set_fmt = adv748x_csi2_set_format, ++ .get_mbus_config = adv748x_csi2_get_mbus_config, + }; + + /* ----------------------------------------------------------------------------- + +From a7053f425fb6140bdf72c009cab1730e9d3094af Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Fri, 17 Jul 2020 16:53:24 +0200 +Subject: [PATCH] media: rcar-csi2: Negotiate data lanes number +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use the newly introduced get_mbus_config() subdevice pad operation to +retrieve the remote subdevice MIPI CSI-2 bus configuration and configure +the number of active data lanes accordingly. + +In order to be able to call the remote subdevice operation cache the +index of the remote pad connected to the single CSI-2 input port. + +Reviewed-by: Niklas Söderlund +Signed-off-by: Jacopo Mondi +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/platform/rcar-vin/rcar-csi2.c | 75 +++++++++++++++++++-- + 1 file changed, 68 insertions(+), 7 deletions(-) + +diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c +index 151e6a90c5fb..fe99ae00e690 100644 +--- a/drivers/media/platform/rcar-vin/rcar-csi2.c ++++ b/drivers/media/platform/rcar-vin/rcar-csi2.c +@@ -363,6 +363,7 @@ struct rcar_csi2 { + struct v4l2_async_notifier notifier; + struct v4l2_async_subdev asd; + struct v4l2_subdev *remote; ++ unsigned int remote_pad; + + struct v4l2_mbus_framefmt mf; + +@@ -408,13 +409,14 @@ static void rcsi2_exit_standby(struct rcar_csi2 *priv) + reset_control_deassert(priv->rstc); + } + +-static int rcsi2_wait_phy_start(struct rcar_csi2 *priv) ++static int rcsi2_wait_phy_start(struct rcar_csi2 *priv, ++ unsigned int lanes) + { + unsigned int timeout; + + /* Wait for the clock and data lanes to enter LP-11 state. */ + for (timeout = 0; timeout <= 20; timeout++) { +- const u32 lane_mask = (1 << priv->lanes) - 1; ++ const u32 lane_mask = (1 << lanes) - 1; + + if ((rcsi2_read(priv, PHCLM_REG) & PHCLM_STOPSTATECKL) && + (rcsi2_read(priv, PHDLM_REG) & lane_mask) == lane_mask) +@@ -446,7 +448,8 @@ static int rcsi2_set_phypll(struct rcar_csi2 *priv, unsigned int mbps) + return 0; + } + +-static int rcsi2_calc_mbps(struct rcar_csi2 *priv, unsigned int bpp) ++static int rcsi2_calc_mbps(struct rcar_csi2 *priv, unsigned int bpp, ++ unsigned int lanes) + { + struct v4l2_subdev *source; + struct v4l2_ctrl *ctrl; +@@ -471,15 +474,64 @@ static int rcsi2_calc_mbps(struct rcar_csi2 *priv, unsigned int bpp) + * bps = link_freq * 2 + */ + mbps = v4l2_ctrl_g_ctrl_int64(ctrl) * bpp; +- do_div(mbps, priv->lanes * 1000000); ++ do_div(mbps, lanes * 1000000); + + return mbps; + } + ++static int rcsi2_get_active_lanes(struct rcar_csi2 *priv, ++ unsigned int *lanes) ++{ ++ struct v4l2_mbus_config mbus_config = { 0 }; ++ unsigned int num_lanes = UINT_MAX; ++ int ret; ++ ++ *lanes = priv->lanes; ++ ++ ret = v4l2_subdev_call(priv->remote, pad, get_mbus_config, ++ priv->remote_pad, &mbus_config); ++ if (ret == -ENOIOCTLCMD) { ++ dev_dbg(priv->dev, "No remote mbus configuration available\n"); ++ return 0; ++ } ++ ++ if (ret) { ++ dev_err(priv->dev, "Failed to get remote mbus configuration\n"); ++ return ret; ++ } ++ ++ if (mbus_config.type != V4L2_MBUS_CSI2_DPHY) { ++ dev_err(priv->dev, "Unsupported media bus type %u\n", ++ mbus_config.type); ++ return -EINVAL; ++ } ++ ++ if (mbus_config.flags & V4L2_MBUS_CSI2_1_LANE) ++ num_lanes = 1; ++ else if (mbus_config.flags & V4L2_MBUS_CSI2_2_LANE) ++ num_lanes = 2; ++ else if (mbus_config.flags & V4L2_MBUS_CSI2_3_LANE) ++ num_lanes = 3; ++ else if (mbus_config.flags & V4L2_MBUS_CSI2_4_LANE) ++ num_lanes = 4; ++ ++ if (num_lanes > priv->lanes) { ++ dev_err(priv->dev, ++ "Unsupported mbus config: too many data lanes %u\n", ++ num_lanes); ++ return -EINVAL; ++ } ++ ++ *lanes = num_lanes; ++ ++ return 0; ++} ++ + static int rcsi2_start_receiver(struct rcar_csi2 *priv) + { + const struct rcar_csi2_format *format; + u32 phycnt, vcdt = 0, vcdt2 = 0, fld = 0; ++ unsigned int lanes; + unsigned int i; + int mbps, ret; + +@@ -521,10 +573,18 @@ static int rcsi2_start_receiver(struct rcar_csi2 *priv) + fld |= FLD_FLD_NUM(1); + } + ++ /* ++ * Get the number of active data lanes inspecting the remote mbus ++ * configuration. ++ */ ++ ret = rcsi2_get_active_lanes(priv, &lanes); ++ if (ret) ++ return ret; ++ + phycnt = PHYCNT_ENABLECLK; +- phycnt |= (1 << priv->lanes) - 1; ++ phycnt |= (1 << lanes) - 1; + +- mbps = rcsi2_calc_mbps(priv, format->bpp); ++ mbps = rcsi2_calc_mbps(priv, format->bpp, lanes); + if (mbps < 0) + return mbps; + +@@ -571,7 +631,7 @@ static int rcsi2_start_receiver(struct rcar_csi2 *priv) + rcsi2_write(priv, PHYCNT_REG, phycnt | PHYCNT_SHUTDOWNZ); + rcsi2_write(priv, PHYCNT_REG, phycnt | PHYCNT_SHUTDOWNZ | PHYCNT_RSTZ); + +- ret = rcsi2_wait_phy_start(priv); ++ ret = rcsi2_wait_phy_start(priv, lanes); + if (ret) + return ret; + +@@ -748,6 +808,7 @@ static int rcsi2_notify_bound(struct v4l2_async_notifier *notifier, + } + + priv->remote = subdev; ++ priv->remote_pad = pad; + + dev_dbg(priv->dev, "Bound %s pad: %d\n", subdev->name, pad); + + +From ed9092fbdad008ed58e0bd8079b6d6484839d811 Mon Sep 17 00:00:00 2001 +From: Dinghao Liu +Date: Sun, 28 Jun 2020 07:55:23 +0200 +Subject: [PATCH] media: venus: core: Fix runtime PM imbalance in venus_probe + +pm_runtime_get_sync() increments the runtime PM usage counter even +when it returns an error code. Thus a pairing decrement is needed on +the error handling path to keep the counter balanced. For other error +paths after this call, things are the same. + +Fix this by adding pm_runtime_put_noidle() after 'err_runtime_disable' +label. But in this case, the error path after pm_runtime_put_sync() +will decrease PM usage counter twice. Thus add an extra +pm_runtime_get_noresume() in this path to balance PM counter. + +Signed-off-by: Dinghao Liu +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/platform/qcom/venus/core.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c +index 203c6538044f..b0b932bf8c02 100644 +--- a/drivers/media/platform/qcom/venus/core.c ++++ b/drivers/media/platform/qcom/venus/core.c +@@ -287,8 +287,10 @@ static int venus_probe(struct platform_device *pdev) + goto err_core_deinit; + + ret = pm_runtime_put_sync(dev); +- if (ret) ++ if (ret) { ++ pm_runtime_get_noresume(dev); + goto err_dev_unregister; ++ } + + return 0; + +@@ -299,6 +301,7 @@ static int venus_probe(struct platform_device *pdev) + err_venus_shutdown: + venus_shutdown(core); + err_runtime_disable: ++ pm_runtime_put_noidle(dev); + pm_runtime_set_suspended(dev); + pm_runtime_disable(dev); + hfi_destroy(core); + +From 757449d0037dd11f6b783bc31b27c76c5fa636c8 Mon Sep 17 00:00:00 2001 +From: Rajendra Nayak +Date: Wed, 29 Jul 2020 09:16:42 +0200 +Subject: [PATCH] media: venus: core: Fix error handling in probe + +Post a successful pm_ops->core_get, an error in probe +should exit by doing a pm_ops->core_put which seems +to be missing. So fix it. + +Signed-off-by: Rajendra Nayak +Reviewed-by: Bjorn Andersson +Signed-off-by: Stanimir Varbanov +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/platform/qcom/venus/core.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c +index b0b932bf8c02..321ad77cb6cf 100644 +--- a/drivers/media/platform/qcom/venus/core.c ++++ b/drivers/media/platform/qcom/venus/core.c +@@ -224,13 +224,15 @@ static int venus_probe(struct platform_device *pdev) + + ret = dma_set_mask_and_coherent(dev, core->res->dma_mask); + if (ret) +- return ret; ++ goto err_core_put; + + if (!dev->dma_parms) { + dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms), + GFP_KERNEL); +- if (!dev->dma_parms) +- return -ENOMEM; ++ if (!dev->dma_parms) { ++ ret = -ENOMEM; ++ goto err_core_put; ++ } + } + dma_set_max_seg_size(dev, DMA_BIT_MASK(32)); + +@@ -242,11 +244,11 @@ static int venus_probe(struct platform_device *pdev) + IRQF_TRIGGER_HIGH | IRQF_ONESHOT, + "venus", core); + if (ret) +- return ret; ++ goto err_core_put; + + ret = hfi_create(core, &venus_core_ops); + if (ret) +- return ret; ++ goto err_core_put; + + pm_runtime_enable(dev); + +@@ -305,6 +307,9 @@ static int venus_probe(struct platform_device *pdev) + pm_runtime_set_suspended(dev); + pm_runtime_disable(dev); + hfi_destroy(core); ++err_core_put: ++ if (core->pm_ops->core_put) ++ core->pm_ops->core_put(dev); + return ret; + } + + +From 207ffb881dd2058c1a86022671817cef37a9d273 Mon Sep 17 00:00:00 2001 +From: Rajendra Nayak +Date: Wed, 29 Jul 2020 09:16:43 +0200 +Subject: [PATCH] media: venus: core: Add support for opp tables/perf voting + +Add support to add OPP tables and perf voting on the OPP powerdomain. +This is needed so venus votes on the corresponding performance state +for the OPP powerdomain along with setting the core clock rate. + +Signed-off-by: Rajendra Nayak +Reviewed-by: Matthias Kaehlcke +Reviewed-by: Bjorn Andersson +Signed-off-by: Stanimir Varbanov +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/platform/qcom/venus/core.c | 2 + + drivers/media/platform/qcom/venus/core.h | 5 + + .../media/platform/qcom/venus/pm_helpers.c | 92 +++++++++++++++++-- + 3 files changed, 92 insertions(+), 7 deletions(-) + +diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c +index 321ad77cb6cf..5fd70f8cf857 100644 +--- a/drivers/media/platform/qcom/venus/core.c ++++ b/drivers/media/platform/qcom/venus/core.c +@@ -528,6 +528,7 @@ static const struct venus_resources sdm845_res_v2 = { + .vcodec_clks_num = 2, + .vcodec_pmdomains = { "venus", "vcodec0", "vcodec1" }, + .vcodec_pmdomains_num = 3, ++ .opp_pmdomain = (const char *[]) { "cx", NULL }, + .vcodec_num = 2, + .max_load = 3110400, /* 4096x2160@90 */ + .hfi_version = HFI_VERSION_4XX, +@@ -573,6 +574,7 @@ static const struct venus_resources sc7180_res = { + .vcodec_clks_num = 2, + .vcodec_pmdomains = { "venus", "vcodec0" }, + .vcodec_pmdomains_num = 2, ++ .opp_pmdomain = (const char *[]) { "cx", NULL }, + .vcodec_num = 1, + .hfi_version = HFI_VERSION_4XX, + .vmem_id = VIDC_RESOURCE_NONE, +diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h +index 7118612673c9..b0cc544ad39f 100644 +--- a/drivers/media/platform/qcom/venus/core.h ++++ b/drivers/media/platform/qcom/venus/core.h +@@ -62,6 +62,7 @@ struct venus_resources { + unsigned int vcodec_clks_num; + const char * const vcodec_pmdomains[VIDC_PMDOMAINS_NUM_MAX]; + unsigned int vcodec_pmdomains_num; ++ const char **opp_pmdomain; + unsigned int vcodec_num; + enum hfi_version hfi_version; + u32 max_load; +@@ -145,8 +146,12 @@ struct venus_core { + struct clk *vcodec1_clks[VIDC_VCODEC_CLKS_NUM_MAX]; + struct icc_path *video_path; + struct icc_path *cpucfg_path; ++ struct opp_table *opp_table; ++ bool has_opp_table; + struct device_link *pd_dl_venus; + struct device *pmdomains[VIDC_PMDOMAINS_NUM_MAX]; ++ struct device_link *opp_dl_venus; ++ struct device *opp_pmdomain; + struct video_device *vdev_dec; + struct video_device *vdev_enc; + struct v4l2_device v4l2_dev; +diff --git a/drivers/media/platform/qcom/venus/pm_helpers.c b/drivers/media/platform/qcom/venus/pm_helpers.c +index 531e7a41658f..3127af8985cf 100644 +--- a/drivers/media/platform/qcom/venus/pm_helpers.c ++++ b/drivers/media/platform/qcom/venus/pm_helpers.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -66,10 +67,9 @@ static void core_clks_disable(struct venus_core *core) + + static int core_clks_set_rate(struct venus_core *core, unsigned long freq) + { +- struct clk *clk = core->clks[0]; + int ret; + +- ret = clk_set_rate(clk, freq); ++ ret = dev_pm_opp_set_rate(core->dev, freq); + if (ret) + return ret; + +@@ -744,13 +744,16 @@ static int venc_power_v4(struct device *dev, int on) + + static int vcodec_domains_get(struct device *dev) + { ++ int ret; ++ struct opp_table *opp_table; ++ struct device **opp_virt_dev; + struct venus_core *core = dev_get_drvdata(dev); + const struct venus_resources *res = core->res; + struct device *pd; + unsigned int i; + + if (!res->vcodec_pmdomains_num) +- return -ENODEV; ++ goto skip_pmdomains; + + for (i = 0; i < res->vcodec_pmdomains_num; i++) { + pd = dev_pm_domain_attach_by_name(dev, +@@ -767,7 +770,41 @@ static int vcodec_domains_get(struct device *dev) + if (!core->pd_dl_venus) + return -ENODEV; + ++skip_pmdomains: ++ if (!core->has_opp_table) ++ return 0; ++ ++ /* Attach the power domain for setting performance state */ ++ opp_table = dev_pm_opp_attach_genpd(dev, res->opp_pmdomain, &opp_virt_dev); ++ if (IS_ERR(opp_table)) { ++ ret = PTR_ERR(opp_table); ++ goto opp_attach_err; ++ } ++ ++ core->opp_pmdomain = *opp_virt_dev; ++ core->opp_dl_venus = device_link_add(dev, core->opp_pmdomain, ++ DL_FLAG_RPM_ACTIVE | ++ DL_FLAG_PM_RUNTIME | ++ DL_FLAG_STATELESS); ++ if (!core->opp_dl_venus) { ++ ret = -ENODEV; ++ goto opp_dl_add_err; ++ } ++ + return 0; ++ ++opp_dl_add_err: ++ dev_pm_domain_detach(core->opp_pmdomain, true); ++opp_attach_err: ++ if (core->pd_dl_venus) { ++ device_link_del(core->pd_dl_venus); ++ for (i = 0; i < res->vcodec_pmdomains_num; i++) { ++ if (IS_ERR_OR_NULL(core->pmdomains[i])) ++ continue; ++ dev_pm_domain_detach(core->pmdomains[i], true); ++ } ++ } ++ return ret; + } + + static void vcodec_domains_put(struct device *dev) +@@ -777,7 +814,7 @@ static void vcodec_domains_put(struct device *dev) + unsigned int i; + + if (!res->vcodec_pmdomains_num) +- return; ++ goto skip_pmdomains; + + if (core->pd_dl_venus) + device_link_del(core->pd_dl_venus); +@@ -787,6 +824,15 @@ static void vcodec_domains_put(struct device *dev) + continue; + dev_pm_domain_detach(core->pmdomains[i], true); + } ++ ++skip_pmdomains: ++ if (!core->has_opp_table) ++ return; ++ ++ if (core->opp_dl_venus) ++ device_link_del(core->opp_dl_venus); ++ ++ dev_pm_domain_detach(core->opp_pmdomain, true); + } + + static int core_get_v4(struct device *dev) +@@ -815,19 +861,46 @@ static int core_get_v4(struct device *dev) + if (legacy_binding) + return 0; + ++ core->opp_table = dev_pm_opp_set_clkname(dev, "core"); ++ if (IS_ERR(core->opp_table)) ++ return PTR_ERR(core->opp_table); ++ ++ if (core->res->opp_pmdomain) { ++ ret = dev_pm_opp_of_add_table(dev); ++ if (!ret) { ++ core->has_opp_table = true; ++ } else if (ret != -ENODEV) { ++ dev_err(dev, "invalid OPP table in device tree\n"); ++ dev_pm_opp_put_clkname(core->opp_table); ++ return ret; ++ } ++ } ++ + ret = vcodec_domains_get(dev); +- if (ret) ++ if (ret) { ++ if (core->has_opp_table) ++ dev_pm_opp_of_remove_table(dev); ++ dev_pm_opp_put_clkname(core->opp_table); + return ret; ++ } + + return 0; + } + + static void core_put_v4(struct device *dev) + { ++ struct venus_core *core = dev_get_drvdata(dev); ++ + if (legacy_binding) + return; + + vcodec_domains_put(dev); ++ ++ if (core->has_opp_table) ++ dev_pm_opp_of_remove_table(dev); ++ if (core->opp_table) ++ dev_pm_opp_put_clkname(core->opp_table); ++ + } + + static int core_power_v4(struct device *dev, int on) +@@ -835,10 +908,15 @@ static int core_power_v4(struct device *dev, int on) + struct venus_core *core = dev_get_drvdata(dev); + int ret = 0; + +- if (on == POWER_ON) ++ if (on == POWER_ON) { + ret = core_clks_enable(core); +- else ++ } else { ++ /* Drop the performance state vote */ ++ if (core->opp_pmdomain) ++ dev_pm_opp_set_rate(dev, 0); ++ + core_clks_disable(core); ++ } + + return ret; + } + +From 3bf1ba10b6ac9cfff7ecd329c38dc31213e88ce1 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Mon, 27 Jul 2020 14:05:37 -0300 +Subject: [PATCH] hantro: h264: Get the correct fallback reference buffer + +If the bitstream and the application are incorrectly configuring +the reference pictures, the hardware will need to fallback +to using some other reference picture. + +When the post-processor is enabled, the fallback buffer +should be a shadow buffer (postproc.dec_q), and not a +CAPTURE queue buffer, since the latter is post-processed +and not really the output of the decoder core. + +Fixes: 8c2d66b036c77 ("media: hantro: Support color conversion via post-processing") +Signed-off-by: Ezequiel Garcia +--- + drivers/staging/media/hantro/hantro_h264.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/staging/media/hantro/hantro_h264.c b/drivers/staging/media/hantro/hantro_h264.c +index 194d05848077..6dcd47bd9ed3 100644 +--- a/drivers/staging/media/hantro/hantro_h264.c ++++ b/drivers/staging/media/hantro/hantro_h264.c +@@ -325,7 +325,7 @@ dma_addr_t hantro_h264_get_ref_buf(struct hantro_ctx *ctx, + */ + dst_buf = hantro_get_dst_buf(ctx); + buf = &dst_buf->vb2_buf; +- dma_addr = vb2_dma_contig_plane_dma_addr(buf, 0); ++ dma_addr = hantro_get_dec_buf_addr(ctx, buf); + } + + return dma_addr; + +From 28bebe4b9396ef9d2e4ae2a179abdb840ceddb03 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Mon, 27 Jul 2020 14:05:38 -0300 +Subject: [PATCH] hantro: postproc: Fix motion vector space allocation + +When the post-processor is enabled, the driver allocates +"shadow buffers" which are used for the decoder core, +and exposes the post-processed buffers to userspace. + +For this reason, extra motion vector space has to +be allocated on the shadow buffers, which the driver +wasn't doing. Fix it. + +This fix should address artifacts on high profile bitstreams. + +Fixes: 8c2d66b036c77 ("media: hantro: Support color conversion via post-processing") +Signed-off-by: Ezequiel Garcia +--- + drivers/staging/media/hantro/hantro_postproc.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/staging/media/hantro/hantro_postproc.c b/drivers/staging/media/hantro/hantro_postproc.c +index 44062ffceaea..6d2a8f2a8f0b 100644 +--- a/drivers/staging/media/hantro/hantro_postproc.c ++++ b/drivers/staging/media/hantro/hantro_postproc.c +@@ -118,7 +118,9 @@ int hantro_postproc_alloc(struct hantro_ctx *ctx) + unsigned int num_buffers = cap_queue->num_buffers; + unsigned int i, buf_size; + +- buf_size = ctx->dst_fmt.plane_fmt[0].sizeimage; ++ buf_size = ctx->dst_fmt.plane_fmt[0].sizeimage + ++ hantro_h264_mv_size(ctx->dst_fmt.width, ++ ctx->dst_fmt.height); + + for (i = 0; i < num_buffers; ++i) { + struct hantro_aux_buf *priv = &ctx->postproc.dec_q[i]; + +From be1ec3a445d13ab0bac45fd84edb30a11a2c0b8c Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Fri, 14 Aug 2020 10:36:16 -0300 +Subject: [PATCH] media: uapi: h264: Update reference lists + +When dealing with with interlaced frames, reference lists must tell if +each particular reference is meant for top or bottom field. This info +is currently not provided at all in the H264 related controls. + +Make reference lists hold a structure which will also hold an +enumerator type along index into DPB array. The enumerator must +be used to specify if reference is for top or bottom field. + +Currently the only user of these lists is Cedrus which is just compile +fixed here. Actual usage of will come in a following commit. + +Signed-off-by: Jernej Skrabec +Signed-off-by: Ezequiel Garcia +--- + .../media/v4l/ext-ctrls-codec.rst | 44 ++++++++++++++++++- + .../staging/media/sunxi/cedrus/cedrus_h264.c | 6 +-- + include/media/h264-ctrls.h | 23 +++++++--- + 3 files changed, 62 insertions(+), 11 deletions(-) + +diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +index d0d506a444b1..b9b2617c3bda 100644 +--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst ++++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +@@ -1843,10 +1843,10 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + * - __u32 + - ``slice_group_change_cycle`` + - +- * - __u8 ++ * - struct :c:type:`v4l2_h264_reference` + - ``ref_pic_list0[32]`` + - Reference picture list after applying the per-slice modifications +- * - __u8 ++ * - struct :c:type:`v4l2_h264_reference` + - ``ref_pic_list1[32]`` + - Reference picture list after applying the per-slice modifications + * - __u32 +@@ -1926,6 +1926,46 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + - ``chroma_offset[32][2]`` + - + ++``Picture Reference`` ++ ++.. c:type:: v4l2_h264_reference ++ ++.. cssclass:: longtable ++ ++.. flat-table:: struct v4l2_h264_reference ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - enum :c:type:`v4l2_h264_field_reference` ++ - ``reference`` ++ - Specifies how the picture is referenced. ++ * - __u8 ++ - ``index`` ++ - Index into the :c:type:`v4l2_ctrl_h264_decode_params`.dpb array. ++ ++.. c:type:: v4l2_h264_field_reference ++ ++.. cssclass:: longtable ++ ++.. flat-table:: ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - ``V4L2_H264_TOP_FIELD_REF`` ++ - 0x1 ++ - The top field in field pair is used for ++ short-term reference. ++ * - ``V4L2_H264_BOTTOM_FIELD_REF`` ++ - 0x2 ++ - The bottom field in field pair is used for ++ short-term reference. ++ * - ``V4L2_H264_FRAME_REF`` ++ - 0x3 ++ - The frame (or the top/bottom fields, if it's a field pair) ++ is used for short-term reference. ++ + ``V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS (struct)`` + Specifies the decode parameters (as extracted from the bitstream) + for the associated H264 slice data. This includes the necessary +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +index 54ee2aa423e2..cce527bbdf86 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +@@ -166,8 +166,8 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx, + + static void _cedrus_write_ref_list(struct cedrus_ctx *ctx, + struct cedrus_run *run, +- const u8 *ref_list, u8 num_ref, +- enum cedrus_h264_sram_off sram) ++ const struct v4l2_h264_reference *ref_list, ++ u8 num_ref, enum cedrus_h264_sram_off sram) + { + const struct v4l2_ctrl_h264_decode_params *decode = run->h264.decode_params; + struct vb2_queue *cap_q; +@@ -188,7 +188,7 @@ static void _cedrus_write_ref_list(struct cedrus_ctx *ctx, + int buf_idx; + u8 dpb_idx; + +- dpb_idx = ref_list[i]; ++ dpb_idx = ref_list[i].index; + dpb = &decode->dpb[dpb_idx]; + + if (!(dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)) +diff --git a/include/media/h264-ctrls.h b/include/media/h264-ctrls.h +index 080fd1293c42..5f635e8d25e2 100644 +--- a/include/media/h264-ctrls.h ++++ b/include/media/h264-ctrls.h +@@ -19,6 +19,8 @@ + */ + #define V4L2_H264_NUM_DPB_ENTRIES 16 + ++#define V4L2_H264_REF_LIST_LEN (2 * V4L2_H264_NUM_DPB_ENTRIES) ++ + /* Our pixel format isn't stable at the moment */ + #define V4L2_PIX_FMT_H264_SLICE v4l2_fourcc('S', '2', '6', '4') /* H264 parsed slices */ + +@@ -140,6 +142,19 @@ struct v4l2_h264_pred_weight_table { + #define V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED 0x04 + #define V4L2_H264_SLICE_FLAG_SP_FOR_SWITCH 0x08 + ++enum v4l2_h264_field_reference { ++ V4L2_H264_TOP_FIELD_REF = 0x1, ++ V4L2_H264_BOTTOM_FIELD_REF = 0x2, ++ V4L2_H264_FRAME_REF = 0x3, ++}; ++ ++struct v4l2_h264_reference { ++ enum v4l2_h264_field_reference fields; ++ ++ /* Index into v4l2_ctrl_h264_decode_params.dpb[] */ ++ __u8 index; ++}; ++ + struct v4l2_ctrl_h264_slice_params { + /* Size in bytes, including header */ + __u32 size; +@@ -178,12 +193,8 @@ struct v4l2_ctrl_h264_slice_params { + __u8 num_ref_idx_l1_active_minus1; + __u32 slice_group_change_cycle; + +- /* +- * Entries on each list are indices into +- * v4l2_ctrl_h264_decode_params.dpb[]. +- */ +- __u8 ref_pic_list0[32]; +- __u8 ref_pic_list1[32]; ++ struct v4l2_h264_reference ref_pic_list0[V4L2_H264_REF_LIST_LEN]; ++ struct v4l2_h264_reference ref_pic_list1[V4L2_H264_REF_LIST_LEN]; + + __u32 flags; + }; + +From 9e30508e5834c1a37aa07836bf7fc78f96559f82 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Fri, 14 Aug 2020 10:36:17 -0300 +Subject: [PATCH] media: uapi: h264: Further clarify scaling lists order + +Commit 0b0393d59eb4a ("media: uapi: h264: clarify +expected scaling_list_4x4/8x8 order") improved the +documentation on H264 scaling lists order. + +This commit improves the documentation by clarifying +that the lists themselves are expected in raster scan order. + +Signed-off-by: Ezequiel Garcia +--- + Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +index b9b2617c3bda..694037ce888a 100644 +--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst ++++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +@@ -1725,12 +1725,14 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + - ``scaling_list_4x4[6][16]`` + - Scaling matrix after applying the inverse scanning process. + Expected list order is Intra Y, Intra Cb, Intra Cr, Inter Y, +- Inter Cb, Inter Cr. ++ Inter Cb, Inter Cr. The values on each scaling list are ++ expected in raster scan order. + * - __u8 + - ``scaling_list_8x8[6][64]`` + - Scaling matrix after applying the inverse scanning process. + Expected list order is Intra Y, Inter Y, Intra Cb, Inter Cb, +- Intra Cr, Inter Cr. ++ Intra Cr, Inter Cr. The values on each scaling list are ++ expected in raster scan order. + + ``V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS (struct)`` + Specifies the slice parameters (as extracted from the bitstream) + +From da0e200cf7bd3c42b97c8fa8e941a756ffdbfb26 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Fri, 14 Aug 2020 10:36:18 -0300 +Subject: [PATCH] media: uapi: h264: Split prediction weight parameters + +The prediction weight parameters are only required under +certain conditions, which depend on slice header parameters. + +As specified in section 7.3.3 Slice header syntax, the prediction +weight table is present if: + +((weighted_pred_flag && (slice_type == P || slice_type == SP)) || \ +(weighted_bipred_idc == 1 && slice_type == B)) + +Given its size, it makes sense to move this table to its control, +so applications can avoid passing it if the slice doesn't specify it. + +Before this change struct v4l2_ctrl_h264_slice_params was 960 bytes. +With this change, it's 188 bytes and struct v4l2_ctrl_h264_pred_weight +is 772 bytes. + +Signed-off-by: Ezequiel Garcia +--- + .../media/v4l/ext-ctrls-codec.rst | 19 ++++++++++++------- + drivers/media/v4l2-core/v4l2-ctrls.c | 8 ++++++++ + drivers/staging/media/sunxi/cedrus/cedrus.c | 7 +++++++ + drivers/staging/media/sunxi/cedrus/cedrus.h | 1 + + .../staging/media/sunxi/cedrus/cedrus_dec.c | 2 ++ + .../staging/media/sunxi/cedrus/cedrus_h264.c | 12 +++--------- + include/media/h264-ctrls.h | 12 ++++++++++-- + include/media/v4l2-ctrls.h | 2 ++ + 8 files changed, 45 insertions(+), 18 deletions(-) + +diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +index 694037ce888a..ddf9c6af7d0a 100644 +--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst ++++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +@@ -1879,18 +1879,23 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + - 0x00000008 + - + +-``Prediction Weight Table`` ++``V4L2_CID_MPEG_VIDEO_H264_PRED_WEIGHTS (struct)`` ++ Prediction weight table defined according to :ref:`h264`, ++ section 7.4.3.2 "Prediction Weight Table Semantics". ++ The prediction weight table must be passed by applications ++ under the conditions explained in section 7.3.3 "Slice header ++ syntax". + +- The bitstream parameters are defined according to :ref:`h264`, +- section 7.4.3.2 "Prediction Weight Table Semantics". For further +- documentation, refer to the above specification, unless there is +- an explicit comment stating otherwise. ++ .. note:: ++ ++ This compound control is not yet part of the public kernel API and ++ it is expected to change. + +-.. c:type:: v4l2_h264_pred_weight_table ++.. c:type:: v4l2_ctrl_h264_pred_weights + + .. cssclass:: longtable + +-.. flat-table:: struct v4l2_h264_pred_weight_table ++.. flat-table:: struct v4l2_ctrl_h264_pred_weights + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 +diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c +index 3f3fbcd60cc6..76c8dc8fb31c 100644 +--- a/drivers/media/v4l2-core/v4l2-ctrls.c ++++ b/drivers/media/v4l2-core/v4l2-ctrls.c +@@ -897,6 +897,7 @@ const char *v4l2_ctrl_get_name(u32 id) + case V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS: return "H264 Decode Parameters"; + case V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE: return "H264 Decode Mode"; + case V4L2_CID_MPEG_VIDEO_H264_START_CODE: return "H264 Start Code"; ++ case V4L2_CID_MPEG_VIDEO_H264_PRED_WEIGHTS: return "H264 Prediction Weight Table"; + case V4L2_CID_MPEG_VIDEO_MPEG2_LEVEL: return "MPEG2 Level"; + case V4L2_CID_MPEG_VIDEO_MPEG2_PROFILE: return "MPEG2 Profile"; + case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP: return "MPEG4 I-Frame QP Value"; +@@ -1412,6 +1413,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, + case V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS: + *type = V4L2_CTRL_TYPE_H264_DECODE_PARAMS; + break; ++ case V4L2_CID_MPEG_VIDEO_H264_PRED_WEIGHTS: ++ *type = V4L2_CTRL_TYPE_H264_PRED_WEIGHTS; ++ break; + case V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER: + *type = V4L2_CTRL_TYPE_VP8_FRAME_HEADER; + break; +@@ -1790,6 +1794,7 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, + case V4L2_CTRL_TYPE_H264_SPS: + case V4L2_CTRL_TYPE_H264_PPS: + case V4L2_CTRL_TYPE_H264_SCALING_MATRIX: ++ case V4L2_CTRL_TYPE_H264_PRED_WEIGHTS: + case V4L2_CTRL_TYPE_H264_SLICE_PARAMS: + case V4L2_CTRL_TYPE_H264_DECODE_PARAMS: + break; +@@ -2553,6 +2558,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, + case V4L2_CTRL_TYPE_H264_DECODE_PARAMS: + elem_size = sizeof(struct v4l2_ctrl_h264_decode_params); + break; ++ case V4L2_CTRL_TYPE_H264_PRED_WEIGHTS: ++ elem_size = sizeof(struct v4l2_ctrl_h264_pred_weights); ++ break; + case V4L2_CTRL_TYPE_VP8_FRAME_HEADER: + elem_size = sizeof(struct v4l2_ctrl_vp8_frame_header); + break; +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c +index bc27f9430eeb..826324faad7e 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.c +@@ -78,6 +78,13 @@ static const struct cedrus_control cedrus_controls[] = { + .codec = CEDRUS_CODEC_H264, + .required = true, + }, ++ { ++ .cfg = { ++ .id = V4L2_CID_MPEG_VIDEO_H264_PRED_WEIGHTS, ++ }, ++ .codec = CEDRUS_CODEC_H264, ++ .required = false, ++ }, + { + .cfg = { + .id = V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE, +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h +index 96765555ab8a..93c843ae14bb 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.h +@@ -62,6 +62,7 @@ struct cedrus_h264_run { + const struct v4l2_ctrl_h264_scaling_matrix *scaling_matrix; + const struct v4l2_ctrl_h264_slice_params *slice_params; + const struct v4l2_ctrl_h264_sps *sps; ++ const struct v4l2_ctrl_h264_pred_weights *pred_weights; + }; + + struct cedrus_mpeg2_run { +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c +index 58c48e4fdfe9..6385026d1b6b 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c +@@ -57,6 +57,8 @@ void cedrus_device_run(void *priv) + V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS); + run.h264.sps = cedrus_find_control_data(ctx, + V4L2_CID_MPEG_VIDEO_H264_SPS); ++ run.h264.pred_weights = cedrus_find_control_data(ctx, ++ V4L2_CID_MPEG_VIDEO_H264_PRED_WEIGHTS); + break; + + case V4L2_PIX_FMT_HEVC_SLICE: +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +index cce527bbdf86..d5636dbbb622 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +@@ -256,10 +256,8 @@ static void cedrus_write_scaling_lists(struct cedrus_ctx *ctx, + static void cedrus_write_pred_weight_table(struct cedrus_ctx *ctx, + struct cedrus_run *run) + { +- const struct v4l2_ctrl_h264_slice_params *slice = +- run->h264.slice_params; +- const struct v4l2_h264_pred_weight_table *pred_weight = +- &slice->pred_weight_table; ++ const struct v4l2_ctrl_h264_pred_weights *pred_weight = ++ run->h264.pred_weights; + struct cedrus_dev *dev = ctx->dev; + int i, j, k; + +@@ -367,11 +365,7 @@ static void cedrus_set_params(struct cedrus_ctx *ctx, + + cedrus_skip_bits(dev, slice->header_bit_size); + +- if (((pps->flags & V4L2_H264_PPS_FLAG_WEIGHTED_PRED) && +- (slice->slice_type == V4L2_H264_SLICE_TYPE_P || +- slice->slice_type == V4L2_H264_SLICE_TYPE_SP)) || +- (pps->weighted_bipred_idc == 1 && +- slice->slice_type == V4L2_H264_SLICE_TYPE_B)) ++ if (V4L2_H264_CTRL_PRED_WEIGHTS_REQUIRED(pps, slice)) + cedrus_write_pred_weight_table(ctx, run); + + if ((slice->slice_type == V4L2_H264_SLICE_TYPE_P) || +diff --git a/include/media/h264-ctrls.h b/include/media/h264-ctrls.h +index 5f635e8d25e2..d995614be159 100644 +--- a/include/media/h264-ctrls.h ++++ b/include/media/h264-ctrls.h +@@ -36,6 +36,7 @@ + #define V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS (V4L2_CID_MPEG_BASE+1004) + #define V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE (V4L2_CID_MPEG_BASE+1005) + #define V4L2_CID_MPEG_VIDEO_H264_START_CODE (V4L2_CID_MPEG_BASE+1006) ++#define V4L2_CID_MPEG_VIDEO_H264_PRED_WEIGHTS (V4L2_CID_MPEG_BASE+1007) + + /* enum v4l2_ctrl_type type values */ + #define V4L2_CTRL_TYPE_H264_SPS 0x0110 +@@ -43,6 +44,7 @@ + #define V4L2_CTRL_TYPE_H264_SCALING_MATRIX 0x0112 + #define V4L2_CTRL_TYPE_H264_SLICE_PARAMS 0x0113 + #define V4L2_CTRL_TYPE_H264_DECODE_PARAMS 0x0114 ++#define V4L2_CTRL_TYPE_H264_PRED_WEIGHTS 0x0115 + + enum v4l2_mpeg_video_h264_decode_mode { + V4L2_MPEG_VIDEO_H264_DECODE_MODE_SLICE_BASED, +@@ -125,7 +127,14 @@ struct v4l2_h264_weight_factors { + __s16 chroma_offset[32][2]; + }; + +-struct v4l2_h264_pred_weight_table { ++#define V4L2_H264_CTRL_PRED_WEIGHTS_REQUIRED(pps, slice) \ ++ ((((pps)->flags & V4L2_H264_PPS_FLAG_WEIGHTED_PRED) && \ ++ ((slice)->slice_type == V4L2_H264_SLICE_TYPE_P || \ ++ (slice)->slice_type == V4L2_H264_SLICE_TYPE_SP)) || \ ++ ((pps)->weighted_bipred_idc == 1 && \ ++ (slice)->slice_type == V4L2_H264_SLICE_TYPE_B)) ++ ++struct v4l2_ctrl_h264_pred_weights { + __u16 luma_log2_weight_denom; + __u16 chroma_log2_weight_denom; + struct v4l2_h264_weight_factors weight_factors[2]; +@@ -177,7 +186,6 @@ struct v4l2_ctrl_h264_slice_params { + __s32 delta_pic_order_cnt0; + __s32 delta_pic_order_cnt1; + +- struct v4l2_h264_pred_weight_table pred_weight_table; + /* Size in bits of dec_ref_pic_marking() syntax element. */ + __u32 dec_ref_pic_marking_bit_size; + /* Size in bits of pic order count syntax. */ +diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h +index f40e2cbb21d3..cb25f345e9ad 100644 +--- a/include/media/v4l2-ctrls.h ++++ b/include/media/v4l2-ctrls.h +@@ -51,6 +51,7 @@ struct video_device; + * @p_h264_scaling_matrix: Pointer to a struct v4l2_ctrl_h264_scaling_matrix. + * @p_h264_slice_params: Pointer to a struct v4l2_ctrl_h264_slice_params. + * @p_h264_decode_params: Pointer to a struct v4l2_ctrl_h264_decode_params. ++ * @p_h264_pred_weights: Pointer to a struct v4l2_ctrl_h264_pred_weights. + * @p_vp8_frame_header: Pointer to a VP8 frame header structure. + * @p_hevc_sps: Pointer to an HEVC sequence parameter set structure. + * @p_hevc_pps: Pointer to an HEVC picture parameter set structure. +@@ -74,6 +75,7 @@ union v4l2_ctrl_ptr { + struct v4l2_ctrl_h264_scaling_matrix *p_h264_scaling_matrix; + struct v4l2_ctrl_h264_slice_params *p_h264_slice_params; + struct v4l2_ctrl_h264_decode_params *p_h264_decode_params; ++ struct v4l2_ctrl_h264_pred_weights *p_h264_pred_weights; + struct v4l2_ctrl_vp8_frame_header *p_vp8_frame_header; + struct v4l2_ctrl_hevc_sps *p_hevc_sps; + struct v4l2_ctrl_hevc_pps *p_hevc_pps; + +From 82c12e79f57d0b51b81efb2bb87a91288988d958 Mon Sep 17 00:00:00 2001 +From: Philipp Zabel +Date: Fri, 14 Aug 2020 10:36:19 -0300 +Subject: [PATCH] media: uapi: h264: Clarify pic_order_cnt_bit_size field + +Since pic_order_cnt_bit_size is not a syntax element itself, explicitly +state that it is the total size in bits of the pic_order_cnt_lsb, +delta_pic_order_cnt_bottom, delta_pic_order_cnt[0], and +delta_pic_order_cnt[1] syntax elements contained in the slice. + +Signed-off-by: Philipp Zabel +[Ezequiel: rebase] +Signed-off-by: Ezequiel Garcia +Reviewed-by: Nicolas Dufresne +--- + Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +index ddf9c6af7d0a..32f3cebf16e5 100644 +--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst ++++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +@@ -1815,7 +1815,9 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + - Size in bits of the dec_ref_pic_marking() syntax element. + * - __u32 + - ``pic_order_cnt_bit_size`` +- - ++ - Combined size in bits of the picture order count related syntax ++ elements: pic_order_cnt_lsb, delta_pic_order_cnt_bottom, ++ delta_pic_order_cnt0, and delta_pic_order_cnt1. + * - __u8 + - ``cabac_init_idc`` + - + +From fced897398d6228473f01df99fd09fd4410f623d Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Fri, 14 Aug 2020 10:36:20 -0300 +Subject: [PATCH] media: uapi: h264: Increase size of 'first_mb_in_slice' field + +Slice header syntax element 'first_mb_in_slice' can point +to the last macroblock, currently the field can only reference +65536 macroblocks which is insufficient for 8K videos. + +Although unlikely, a 8192x4320 video (where macroblocks are 16x16), +would contain 138240 macroblocks on a frame. + +As per the H264 specification, 'first_mb_in_slice' can be up to +PicSizeInMbs - 1, so increase the size of the field to 32-bits. + +Note that v4l2_ctrl_h264_slice_params struct will be modified +in a follow-up commit, and so we defer its 64-bit padding. + +Signed-off-by: Ezequiel Garcia +--- + Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst | 2 +- + include/media/h264-ctrls.h | 3 ++- + 2 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +index 32f3cebf16e5..714a8d9ae6a0 100644 +--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst ++++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +@@ -1774,7 +1774,7 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + * - __u32 + - ``header_bit_size`` + - +- * - __u16 ++ * - __u32 + - ``first_mb_in_slice`` + - + * - __u8 +diff --git a/include/media/h264-ctrls.h b/include/media/h264-ctrls.h +index d995614be159..9ff085fdc9ab 100644 +--- a/include/media/h264-ctrls.h ++++ b/include/media/h264-ctrls.h +@@ -174,7 +174,8 @@ struct v4l2_ctrl_h264_slice_params { + /* Offset in bits to slice_data() from the beginning of this slice. */ + __u32 header_bit_size; + +- __u16 first_mb_in_slice; ++ __u32 first_mb_in_slice; ++ + __u8 slice_type; + __u8 pic_parameter_set_id; + __u8 colour_plane_id; + +From 52266e3675e9359f13aa4d44a4ab392fd1f079c0 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Fri, 14 Aug 2020 10:36:21 -0300 +Subject: [PATCH] media: uapi: h264: Clean DPB entry interface + +As discussed recently, the current interface for the +Decoded Picture Buffer is not enough to properly +support field coding. + +This commit introduces enough semantics to support +frame and field coding, and to signal how DPB entries +are "used for reference". + +Signed-off-by: Ezequiel Garcia +--- + .../media/v4l/ext-ctrls-codec.rst | 24 ++++++------------- + drivers/media/v4l2-core/v4l2-h264.c | 4 ++-- + drivers/staging/media/rkvdec/rkvdec-h264.c | 17 ++++++------- + include/media/h264-ctrls.h | 2 +- + 4 files changed, 19 insertions(+), 28 deletions(-) + +diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +index 714a8d9ae6a0..d14da8325382 100644 +--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst ++++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +@@ -2063,6 +2063,9 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + * - __s32 + - ``bottom_field_order_cnt`` + - ++ * - enum :c:type:`v4l2_h264_field_reference` ++ - ``reference`` ++ - Specifies how the DPB entry is referenced. + * - __u32 + - ``flags`` + - See :ref:`DPB Entry Flags ` +@@ -2080,29 +2083,16 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + + * - ``V4L2_H264_DPB_ENTRY_FLAG_VALID`` + - 0x00000001 +- - The DPB entry is valid and should be considered ++ - The DPB entry is valid (non-empty) and should be considered. + * - ``V4L2_H264_DPB_ENTRY_FLAG_ACTIVE`` + - 0x00000002 +- - The DPB entry is currently being used as a reference frame ++ - The DPB entry is used for reference. + * - ``V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM`` + - 0x00000004 +- - The DPB entry is a long term reference frame ++ - The DPB entry is used for long-term reference. + * - ``V4L2_H264_DPB_ENTRY_FLAG_FIELD`` + - 0x00000008 +- - The DPB entry is a field reference, which means only one of the field +- will be used when decoding the new frame/field. When not set the DPB +- entry is a frame reference (both fields will be used). Note that this +- flag does not say anything about the number of fields contained in the +- reference frame, it just describes the one used to decode the new +- field/frame +- * - ``V4L2_H264_DPB_ENTRY_FLAG_BOTTOM_FIELD`` +- - 0x00000010 +- - The DPB entry is a bottom field reference (only the bottom field of the +- reference frame is needed to decode the new frame/field). Only valid if +- V4L2_H264_DPB_ENTRY_FLAG_FIELD is set. When +- V4L2_H264_DPB_ENTRY_FLAG_FIELD is set but +- V4L2_H264_DPB_ENTRY_FLAG_BOTTOM_FIELD is not, that means the +- DPB entry is a top field reference ++ - The DPB entry is a single field or a complementary field pair. + + ``V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE (enum)`` + Specifies the decoding mode to use. Currently exposes slice-based and +diff --git a/drivers/media/v4l2-core/v4l2-h264.c b/drivers/media/v4l2-core/v4l2-h264.c +index edf6225f0522..12b751c09016 100644 +--- a/drivers/media/v4l2-core/v4l2-h264.c ++++ b/drivers/media/v4l2-core/v4l2-h264.c +@@ -66,10 +66,10 @@ v4l2_h264_init_reflist_builder(struct v4l2_h264_reflist_builder *b, + else + b->refs[i].frame_num = dpb[i].frame_num; + +- if (!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_FIELD)) ++ if (dpb[i].reference == V4L2_H264_FRAME_REF) + pic_order_count = min(dpb[i].top_field_order_cnt, + dpb[i].bottom_field_order_cnt); +- else if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_BOTTOM_FIELD) ++ else if (dpb[i].reference & V4L2_H264_BOTTOM_FIELD_REF) + pic_order_count = dpb[i].bottom_field_order_cnt; + else + pic_order_count = dpb[i].top_field_order_cnt; +diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c +index 7b66e2743a4f..07a80e9a9df2 100644 +--- a/drivers/staging/media/rkvdec/rkvdec-h264.c ++++ b/drivers/staging/media/rkvdec/rkvdec-h264.c +@@ -949,16 +949,17 @@ static void config_registers(struct rkvdec_ctx *ctx, + for (i = 0; i < ARRAY_SIZE(dec_params->dpb); i++) { + struct vb2_buffer *vb_buf = get_ref_buf(ctx, run, i); + +- refer_addr = vb2_dma_contig_plane_dma_addr(vb_buf, 0) | +- RKVDEC_COLMV_USED_FLAG_REF; ++ refer_addr = vb2_dma_contig_plane_dma_addr(vb_buf, 0); + +- if (!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_FIELD)) +- refer_addr |= RKVDEC_TOPFIELD_USED_REF | +- RKVDEC_BOTFIELD_USED_REF; +- else if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_BOTTOM_FIELD) +- refer_addr |= RKVDEC_BOTFIELD_USED_REF; +- else ++ if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE) ++ refer_addr |= RKVDEC_COLMV_USED_FLAG_REF; ++ if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_FIELD) ++ refer_addr |= RKVDEC_FIELD_REF; ++ ++ if (dpb[i].reference & V4L2_H264_TOP_FIELD_REF) + refer_addr |= RKVDEC_TOPFIELD_USED_REF; ++ if (dpb[i].reference & V4L2_H264_BOTTOM_FIELD_REF) ++ refer_addr |= RKVDEC_BOTFIELD_USED_REF; + + writel_relaxed(dpb[i].top_field_order_cnt, + rkvdec->regs + poc_reg_tbl_top_field[i]); +diff --git a/include/media/h264-ctrls.h b/include/media/h264-ctrls.h +index 9ff085fdc9ab..4447697e9465 100644 +--- a/include/media/h264-ctrls.h ++++ b/include/media/h264-ctrls.h +@@ -212,7 +212,6 @@ struct v4l2_ctrl_h264_slice_params { + #define V4L2_H264_DPB_ENTRY_FLAG_ACTIVE 0x02 + #define V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM 0x04 + #define V4L2_H264_DPB_ENTRY_FLAG_FIELD 0x08 +-#define V4L2_H264_DPB_ENTRY_FLAG_BOTTOM_FIELD 0x10 + + struct v4l2_h264_dpb_entry { + __u64 reference_ts; +@@ -221,6 +220,7 @@ struct v4l2_h264_dpb_entry { + /* Note that field is indicated by v4l2_buffer.field */ + __s32 top_field_order_cnt; + __s32 bottom_field_order_cnt; ++ enum v4l2_h264_field_reference reference; + __u32 flags; /* V4L2_H264_DPB_ENTRY_FLAG_* */ + }; + + +From cd2980d0ab75400656f854ac48a147ef07b9f9ba Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Fri, 14 Aug 2020 10:36:22 -0300 +Subject: [PATCH] media: uapi: h264: Increase size of DPB entry pic_num + +DPB entry PicNum maximum value is 2*MaxFrameNum for interlaced +content (field_pic_flag=1). + +As specified, MaxFrameNum is 2^(log2_max_frame_num_minus4 + 4) +and log2_max_frame_num_minus4 is in the range of 0 to 12, +which means pic_num should be a 32-bit field. + +The v4l2_h264_dpb_entry struct needs to be padded to avoid a hole, +which might be also useful to allow future uAPI extensions. + +Signed-off-by: Ezequiel Garcia +--- + .../userspace-api/media/v4l/ext-ctrls-codec.rst | 5 ++++- + drivers/media/v4l2-core/v4l2-ctrls.c | 13 +++++++++++++ + include/media/h264-ctrls.h | 3 ++- + include/media/v4l2-h264.h | 2 +- + 4 files changed, 20 insertions(+), 3 deletions(-) + +diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +index d14da8325382..c0ae7fda803e 100644 +--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst ++++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +@@ -2054,7 +2054,10 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + * - __u16 + - ``frame_num`` + - +- * - __u16 ++ * - __u8 ++ - ``reserved[2]`` ++ - Applications and drivers must set this to zero. ++ * - __u32 + - ``pic_num`` + - + * - __s32 +diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c +index 76c8dc8fb31c..b9457789fa55 100644 +--- a/drivers/media/v4l2-core/v4l2-ctrls.c ++++ b/drivers/media/v4l2-core/v4l2-ctrls.c +@@ -1725,6 +1725,8 @@ static void std_log(const struct v4l2_ctrl *ctrl) + + #define zero_padding(s) \ + memset(&(s).padding, 0, sizeof((s).padding)) ++#define zero_reserved(s) \ ++ memset(&(s).reserved, 0, sizeof((s).reserved)) + + /* + * Compound controls validation requires setting unused fields/flags to zero +@@ -1735,6 +1737,7 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, + { + struct v4l2_ctrl_mpeg2_slice_params *p_mpeg2_slice_params; + struct v4l2_ctrl_vp8_frame_header *p_vp8_frame_header; ++ struct v4l2_ctrl_h264_decode_params *p_h264_dec_params; + struct v4l2_ctrl_hevc_sps *p_hevc_sps; + struct v4l2_ctrl_hevc_pps *p_hevc_pps; + struct v4l2_ctrl_hevc_slice_params *p_hevc_slice_params; +@@ -1796,7 +1799,17 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, + case V4L2_CTRL_TYPE_H264_SCALING_MATRIX: + case V4L2_CTRL_TYPE_H264_PRED_WEIGHTS: + case V4L2_CTRL_TYPE_H264_SLICE_PARAMS: ++ break; ++ + case V4L2_CTRL_TYPE_H264_DECODE_PARAMS: ++ p_h264_dec_params = p; ++ ++ for (i = 0; i < V4L2_H264_NUM_DPB_ENTRIES; i++) { ++ struct v4l2_h264_dpb_entry *dpb_entry = ++ &p_h264_dec_params->dpb[i]; ++ ++ zero_reserved(*dpb_entry); ++ } + break; + + case V4L2_CTRL_TYPE_VP8_FRAME_HEADER: +diff --git a/include/media/h264-ctrls.h b/include/media/h264-ctrls.h +index 4447697e9465..d178d7ad53b6 100644 +--- a/include/media/h264-ctrls.h ++++ b/include/media/h264-ctrls.h +@@ -216,7 +216,8 @@ struct v4l2_ctrl_h264_slice_params { + struct v4l2_h264_dpb_entry { + __u64 reference_ts; + __u16 frame_num; +- __u16 pic_num; ++ __u8 reserved[2]; ++ __u32 pic_num; + /* Note that field is indicated by v4l2_buffer.field */ + __s32 top_field_order_cnt; + __s32 bottom_field_order_cnt; +diff --git a/include/media/v4l2-h264.h b/include/media/v4l2-h264.h +index bc9ebb560ccf..1a5f26fc2a9a 100644 +--- a/include/media/v4l2-h264.h ++++ b/include/media/v4l2-h264.h +@@ -33,7 +33,7 @@ struct v4l2_h264_reflist_builder { + struct { + s32 pic_order_count; + int frame_num; +- u16 pic_num; ++ u32 pic_num; + u16 longterm : 1; + } refs[V4L2_H264_NUM_DPB_ENTRIES]; + s32 cur_pic_order_count; + +From c380a6c41ab18183ff5d6342d8dc6cf7f22e6ed5 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Fri, 14 Aug 2020 10:36:23 -0300 +Subject: [PATCH] media: uapi: h264: Drop SLICE_PARAMS 'size' field + +The SLICE_PARAMS control is intended for slice-based +devices. In this mode, the OUTPUT buffer contains +a single slice, and so the buffer's plane payload size +can be used to query the slice size. + +To reduce the API surface drop the size from the +SLICE_PARAMS control. + +A follow-up change will remove other members in SLICE_PARAMS +so we don't need to add padding fields here. + +Signed-off-by: Ezequiel Garcia +--- + Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst | 3 --- + drivers/staging/media/sunxi/cedrus/cedrus_h264.c | 7 +++---- + include/media/h264-ctrls.h | 3 --- + 3 files changed, 3 insertions(+), 10 deletions(-) + +diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +index c0ae7fda803e..e88c207d945b 100644 +--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst ++++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +@@ -1760,9 +1760,6 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + :stub-columns: 0 + :widths: 1 1 2 + +- * - __u32 +- - ``size`` +- - + * - __u32 + - ``start_byte_offset`` + Offset (in bytes) from the beginning of the OUTPUT buffer to the start +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +index d5636dbbb622..7d9bd5860a1b 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +@@ -324,17 +324,16 @@ static void cedrus_set_params(struct cedrus_ctx *ctx, + struct vb2_buffer *src_buf = &run->src->vb2_buf; + struct cedrus_dev *dev = ctx->dev; + dma_addr_t src_buf_addr; +- u32 len = slice->size * 8; ++ size_t slice_bytes = vb2_get_plane_payload(src_buf, 0); + unsigned int pic_width_in_mbs; + bool mbaff_pic; + u32 reg; + +- cedrus_write(dev, VE_H264_VLD_LEN, len); ++ cedrus_write(dev, VE_H264_VLD_LEN, slice_bytes * 8); + cedrus_write(dev, VE_H264_VLD_OFFSET, 0); + + src_buf_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0); +- cedrus_write(dev, VE_H264_VLD_END, +- src_buf_addr + vb2_get_plane_payload(src_buf, 0)); ++ cedrus_write(dev, VE_H264_VLD_END, src_buf_addr + slice_bytes); + cedrus_write(dev, VE_H264_VLD_ADDR, + VE_H264_VLD_ADDR_VAL(src_buf_addr) | + VE_H264_VLD_ADDR_FIRST | VE_H264_VLD_ADDR_VALID | +diff --git a/include/media/h264-ctrls.h b/include/media/h264-ctrls.h +index d178d7ad53b6..afcae3052085 100644 +--- a/include/media/h264-ctrls.h ++++ b/include/media/h264-ctrls.h +@@ -165,9 +165,6 @@ struct v4l2_h264_reference { + }; + + struct v4l2_ctrl_h264_slice_params { +- /* Size in bytes, including header */ +- __u32 size; +- + /* Offset in bytes to the start of slice in the OUTPUT buffer. */ + __u32 start_byte_offset; + + +From 37293295255bb5ad4063fe1ca6945a6890c65cd4 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Fri, 14 Aug 2020 10:36:24 -0300 +Subject: [PATCH] media: uapi: h264: Clarify SLICE_BASED mode + +Currently, the SLICE_BASED and FRAME_BASED modes documentation +is misleading and not matching the intended use-cases. + +Drop non-required fields SLICE_PARAMS 'start_byte_offset' and +DECODE_PARAMS 'num_slices' and clarify the decoding modes in the +documentation. + +On SLICE_BASED mode, a single slice is expected per OUTPUT buffer, +and therefore 'start_byte_offset' is not needed (since the offset +to the slice is the start of the buffer). + +This mode requires the use of CAPTURE buffer holding, and so +the number of slices shall not be required. + +On FRAME_BASED mode, the devices are expected to take care of slice +parsing. Neither SLICE_PARAMS are required (and shouldn't be +exposed by frame-based drivers), nor the number of slices. + +Signed-off-by: Ezequiel Garcia +--- + .../media/v4l/ext-ctrls-codec.rst | 39 +++++-------------- + include/media/h264-ctrls.h | 4 -- + 2 files changed, 10 insertions(+), 33 deletions(-) + +diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +index e88c207d945b..90caf6a0d5a0 100644 +--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst ++++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +@@ -1748,9 +1748,6 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + This compound control is not yet part of the public kernel API + and it is expected to change. + +- This structure is expected to be passed as an array, with one +- entry for each slice included in the bitstream buffer. +- + .. c:type:: v4l2_ctrl_h264_slice_params + + .. cssclass:: longtable +@@ -1760,17 +1757,9 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + :stub-columns: 0 + :widths: 1 1 2 + +- * - __u32 +- - ``start_byte_offset`` +- Offset (in bytes) from the beginning of the OUTPUT buffer to the start +- of the slice. If the slice starts with a start code, then this is the +- offset to such start code. When operating in slice-based decoding mode +- (see :c:type:`v4l2_mpeg_video_h264_decode_mode`), this field should +- be set to 0. When operating in frame-based decoding mode, this field +- should be 0 for the first slice. + * - __u32 + - ``header_bit_size`` +- - ++ - Offset in bits to slice_data() from the beginning of this slice. + * - __u32 + - ``first_mb_in_slice`` + - +@@ -1998,12 +1987,6 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + * - struct :c:type:`v4l2_h264_dpb_entry` + - ``dpb[16]`` + - +- * - __u16 +- - ``num_slices`` +- - Number of slices needed to decode the current frame/field. When +- operating in slice-based decoding mode (see +- :c:type:`v4l2_mpeg_video_h264_decode_mode`), this field +- should always be set to one. + * - __u16 + - ``nal_ref_idc`` + - NAL reference ID value coming from the NAL Unit header +@@ -2121,22 +2104,20 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + * - ``V4L2_MPEG_VIDEO_H264_DECODE_MODE_SLICE_BASED`` + - 0 + - Decoding is done at the slice granularity. +- In this mode, ``num_slices`` field in struct +- :c:type:`v4l2_ctrl_h264_decode_params` should be set to 1, +- and ``start_byte_offset`` in struct +- :c:type:`v4l2_ctrl_h264_slice_params` should be set to 0. + The OUTPUT buffer must contain a single slice. ++ When this mode is selected, the ``V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS`` ++ control shall be set. When multiple slices compose a frame, ++ use of ``V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF`` flag ++ is required. + * - ``V4L2_MPEG_VIDEO_H264_DECODE_MODE_FRAME_BASED`` + - 1 +- - Decoding is done at the frame granularity. +- In this mode, ``num_slices`` field in struct +- :c:type:`v4l2_ctrl_h264_decode_params` should be set to the number +- of slices in the frame, and ``start_byte_offset`` in struct +- :c:type:`v4l2_ctrl_h264_slice_params` should be set accordingly +- for each slice. For the first slice, ``start_byte_offset`` should +- be zero. ++ - Decoding is done at the frame granularity, + The OUTPUT buffer must contain all slices needed to decode the + frame. The OUTPUT buffer must also contain both fields. ++ This mode will be supported by devices that ++ parse the slice(s) header(s) in hardware. When this mode is ++ selected, the ``V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS`` ++ control shall not be set. + + ``V4L2_CID_MPEG_VIDEO_H264_START_CODE (enum)`` + Specifies the H264 slice start code expected for each slice. +diff --git a/include/media/h264-ctrls.h b/include/media/h264-ctrls.h +index afcae3052085..e180501e6385 100644 +--- a/include/media/h264-ctrls.h ++++ b/include/media/h264-ctrls.h +@@ -165,9 +165,6 @@ struct v4l2_h264_reference { + }; + + struct v4l2_ctrl_h264_slice_params { +- /* Offset in bytes to the start of slice in the OUTPUT buffer. */ +- __u32 start_byte_offset; +- + /* Offset in bits to slice_data() from the beginning of this slice. */ + __u32 header_bit_size; + +@@ -226,7 +223,6 @@ struct v4l2_h264_dpb_entry { + + struct v4l2_ctrl_h264_decode_params { + struct v4l2_h264_dpb_entry dpb[V4L2_H264_NUM_DPB_ENTRIES]; +- __u16 num_slices; + __u16 nal_ref_idc; + __s32 top_field_order_cnt; + __s32 bottom_field_order_cnt; + +From ff81175260cd33feaa7d0407ef50186422215fae Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Fri, 14 Aug 2020 10:36:25 -0300 +Subject: [PATCH] media: uapi: h264: Clean slice invariants syntax elements + +The H.264 specification requires in section 7.4.3 "Slice header semantics", +that the following values shall be the same in all slice headers: + + pic_parameter_set_id + frame_num + field_pic_flag + bottom_field_flag + idr_pic_id + pic_order_cnt_lsb + delta_pic_order_cnt_bottom + delta_pic_order_cnt[ 0 ] + delta_pic_order_cnt[ 1 ] + sp_for_switch_flag + slice_group_change_cycle + +These bitstream fields are part of the slice header, and therefore +passed redundantly on each slice. The purpose of the redundancy +is to make the codec fault-tolerant in network scenarios. + +This is of course not needed to be reflected in the V4L2 controls, +given the bitstream has already been parsed by applications. +Therefore, move the redundant fields to the per-frame decode +parameters control (DECODE_PARAMS). + +Field 'pic_parameter_set_id' is simply removed in this case, +because the PPS control must currently contain the active PPS. + +Syntax elements dec_ref_pic_marking() and those related +to pic order count, remain invariant as well, and therefore, +the fields dec_ref_pic_marking_bit_size and pic_order_cnt_bit_size +are also common to all slices. + +Signed-off-by: Ezequiel Garcia +Reviewed-by: Nicolas Dufresne +--- + .../media/v4l/ext-ctrls-codec.rst | 86 +++++++++---------- + drivers/media/v4l2-core/v4l2-ctrls.c | 7 ++ + drivers/media/v4l2-core/v4l2-h264.c | 8 +- + .../staging/media/hantro/hantro_g1_h264_dec.c | 21 +++-- + drivers/staging/media/hantro/hantro_h264.c | 3 +- + drivers/staging/media/rkvdec/rkvdec-h264.c | 6 +- + .../staging/media/sunxi/cedrus/cedrus_h264.c | 9 +- + include/media/h264-ctrls.h | 39 +++++---- + include/media/v4l2-h264.h | 1 - + 9 files changed, 90 insertions(+), 90 deletions(-) + +diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +index 90caf6a0d5a0..69dd3961b99b 100644 +--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst ++++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +@@ -1766,44 +1766,12 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + * - __u8 + - ``slice_type`` + - +- * - __u8 +- - ``pic_parameter_set_id`` +- - + * - __u8 + - ``colour_plane_id`` + - + * - __u8 + - ``redundant_pic_cnt`` + - +- * - __u16 +- - ``frame_num`` +- - +- * - __u16 +- - ``idr_pic_id`` +- - +- * - __u16 +- - ``pic_order_cnt_lsb`` +- - +- * - __s32 +- - ``delta_pic_order_cnt_bottom`` +- - +- * - __s32 +- - ``delta_pic_order_cnt0`` +- - +- * - __s32 +- - ``delta_pic_order_cnt1`` +- - +- * - struct :c:type:`v4l2_h264_pred_weight_table` +- - ``pred_weight_table`` +- - +- * - __u32 +- - ``dec_ref_pic_marking_bit_size`` +- - Size in bits of the dec_ref_pic_marking() syntax element. +- * - __u32 +- - ``pic_order_cnt_bit_size`` +- - Combined size in bits of the picture order count related syntax +- elements: pic_order_cnt_lsb, delta_pic_order_cnt_bottom, +- delta_pic_order_cnt0, and delta_pic_order_cnt1. + * - __u8 + - ``cabac_init_idc`` + - +@@ -1830,9 +1798,9 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + - ``num_ref_idx_l1_active_minus1`` + - If num_ref_idx_active_override_flag is not set, this field must be + set to the value of num_ref_idx_l1_default_active_minus1. +- * - __u32 +- - ``slice_group_change_cycle`` +- - ++ * - __u8 ++ - ``reserved`` ++ - Applications and drivers must set this to zero. + * - struct :c:type:`v4l2_h264_reference` + - ``ref_pic_list0[32]`` + - Reference picture list after applying the per-slice modifications +@@ -1854,17 +1822,11 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + :stub-columns: 0 + :widths: 1 1 2 + +- * - ``V4L2_H264_SLICE_FLAG_FIELD_PIC`` +- - 0x00000001 +- - +- * - ``V4L2_H264_SLICE_FLAG_BOTTOM_FIELD`` +- - 0x00000002 +- - + * - ``V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED`` +- - 0x00000004 ++ - 0x00000001 + - + * - ``V4L2_H264_SLICE_FLAG_SP_FOR_SWITCH`` +- - 0x00000008 ++ - 0x00000002 + - + + ``V4L2_CID_MPEG_VIDEO_H264_PRED_WEIGHTS (struct)`` +@@ -1990,12 +1952,44 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + * - __u16 + - ``nal_ref_idc`` + - NAL reference ID value coming from the NAL Unit header ++ * - __u16 ++ - ``frame_num`` ++ - + * - __s32 + - ``top_field_order_cnt`` + - Picture Order Count for the coded top field + * - __s32 + - ``bottom_field_order_cnt`` + - Picture Order Count for the coded bottom field ++ * - __u16 ++ - ``idr_pic_id`` ++ - ++ * - __u16 ++ - ``pic_order_cnt_lsb`` ++ - ++ * - __s32 ++ - ``delta_pic_order_cnt_bottom`` ++ - ++ * - __s32 ++ - ``delta_pic_order_cnt0`` ++ - ++ * - __s32 ++ - ``delta_pic_order_cnt1`` ++ - ++ * - __u32 ++ - ``dec_ref_pic_marking_bit_size`` ++ - Size in bits of the dec_ref_pic_marking() syntax element. ++ * - __u32 ++ - ``pic_order_cnt_bit_size`` ++ - Combined size in bits of the picture order count related syntax ++ elements: pic_order_cnt_lsb, delta_pic_order_cnt_bottom, ++ delta_pic_order_cnt0, and delta_pic_order_cnt1. ++ * - __u32 ++ - ``slice_group_change_cycle`` ++ - ++ * - __u32 ++ - ``reserved`` ++ - Applications and drivers must set this to zero. + * - __u32 + - ``flags`` + - See :ref:`Decode Parameters Flags ` +@@ -2014,6 +2008,12 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + * - ``V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC`` + - 0x00000001 + - That picture is an IDR picture ++ * - ``V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC`` ++ - 0x00000002 ++ - ++ * - ``V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD`` ++ - 0x00000004 ++ - + + .. c:type:: v4l2_h264_dpb_entry + +diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c +index b9457789fa55..b846f5b089c9 100644 +--- a/drivers/media/v4l2-core/v4l2-ctrls.c ++++ b/drivers/media/v4l2-core/v4l2-ctrls.c +@@ -1737,6 +1737,7 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, + { + struct v4l2_ctrl_mpeg2_slice_params *p_mpeg2_slice_params; + struct v4l2_ctrl_vp8_frame_header *p_vp8_frame_header; ++ struct v4l2_ctrl_h264_slice_params *p_h264_slice_params; + struct v4l2_ctrl_h264_decode_params *p_h264_dec_params; + struct v4l2_ctrl_hevc_sps *p_hevc_sps; + struct v4l2_ctrl_hevc_pps *p_hevc_pps; +@@ -1798,7 +1799,12 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, + case V4L2_CTRL_TYPE_H264_PPS: + case V4L2_CTRL_TYPE_H264_SCALING_MATRIX: + case V4L2_CTRL_TYPE_H264_PRED_WEIGHTS: ++ break; ++ + case V4L2_CTRL_TYPE_H264_SLICE_PARAMS: ++ p_h264_slice_params = p; ++ ++ zero_reserved(*p_h264_slice_params); + break; + + case V4L2_CTRL_TYPE_H264_DECODE_PARAMS: +@@ -1810,6 +1816,7 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, + + zero_reserved(*dpb_entry); + } ++ zero_reserved(*p_h264_dec_params); + break; + + case V4L2_CTRL_TYPE_VP8_FRAME_HEADER: +diff --git a/drivers/media/v4l2-core/v4l2-h264.c b/drivers/media/v4l2-core/v4l2-h264.c +index 12b751c09016..101fdeabfb06 100644 +--- a/drivers/media/v4l2-core/v4l2-h264.c ++++ b/drivers/media/v4l2-core/v4l2-h264.c +@@ -18,14 +18,12 @@ + * + * @b: the builder context to initialize + * @dec_params: decode parameters control +- * @slice_params: first slice parameters control + * @sps: SPS control + * @dpb: DPB to use when creating the reference list + */ + void + v4l2_h264_init_reflist_builder(struct v4l2_h264_reflist_builder *b, + const struct v4l2_ctrl_h264_decode_params *dec_params, +- const struct v4l2_ctrl_h264_slice_params *slice_params, + const struct v4l2_ctrl_h264_sps *sps, + const struct v4l2_h264_dpb_entry dpb[V4L2_H264_NUM_DPB_ENTRIES]) + { +@@ -33,13 +31,13 @@ v4l2_h264_init_reflist_builder(struct v4l2_h264_reflist_builder *b, + unsigned int i; + + max_frame_num = 1 << (sps->log2_max_frame_num_minus4 + 4); +- cur_frame_num = slice_params->frame_num; ++ cur_frame_num = dec_params->frame_num; + + memset(b, 0, sizeof(*b)); +- if (!(slice_params->flags & V4L2_H264_SLICE_FLAG_FIELD_PIC)) ++ if (!(dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC)) + b->cur_pic_order_count = min(dec_params->bottom_field_order_cnt, + dec_params->top_field_order_cnt); +- else if (slice_params->flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD) ++ else if (dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD) + b->cur_pic_order_count = dec_params->bottom_field_order_cnt; + else + b->cur_pic_order_count = dec_params->top_field_order_cnt; +diff --git a/drivers/staging/media/hantro/hantro_g1_h264_dec.c b/drivers/staging/media/hantro/hantro_g1_h264_dec.c +index 424c648ce9fc..f9839e9c6da5 100644 +--- a/drivers/staging/media/hantro/hantro_g1_h264_dec.c ++++ b/drivers/staging/media/hantro/hantro_g1_h264_dec.c +@@ -23,7 +23,6 @@ static void set_params(struct hantro_ctx *ctx) + { + const struct hantro_h264_dec_ctrls *ctrls = &ctx->h264_dec.ctrls; + const struct v4l2_ctrl_h264_decode_params *dec_param = ctrls->decode; +- const struct v4l2_ctrl_h264_slice_params *slices = ctrls->slices; + const struct v4l2_ctrl_h264_sps *sps = ctrls->sps; + const struct v4l2_ctrl_h264_pps *pps = ctrls->pps; + struct vb2_v4l2_buffer *src_buf = hantro_get_src_buf(ctx); +@@ -42,11 +41,11 @@ static void set_params(struct hantro_ctx *ctx) + + if (!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY) && + (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD || +- slices[0].flags & V4L2_H264_SLICE_FLAG_FIELD_PIC)) ++ dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC)) + reg |= G1_REG_DEC_CTRL0_PIC_INTERLACE_E; +- if (slices[0].flags & V4L2_H264_SLICE_FLAG_FIELD_PIC) ++ if (dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC) + reg |= G1_REG_DEC_CTRL0_PIC_FIELDMODE_E; +- if (!(slices[0].flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD)) ++ if (!(dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD)) + reg |= G1_REG_DEC_CTRL0_PIC_TOPFIELD_E; + vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL0); + +@@ -75,7 +74,7 @@ static void set_params(struct hantro_ctx *ctx) + + /* Decoder control register 4. */ + reg = G1_REG_DEC_CTRL4_FRAMENUM_LEN(sps->log2_max_frame_num_minus4 + 4) | +- G1_REG_DEC_CTRL4_FRAMENUM(slices[0].frame_num) | ++ G1_REG_DEC_CTRL4_FRAMENUM(dec_param->frame_num) | + G1_REG_DEC_CTRL4_WEIGHT_BIPR_IDC(pps->weighted_bipred_idc); + if (pps->flags & V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE) + reg |= G1_REG_DEC_CTRL4_CABAC_E; +@@ -88,8 +87,8 @@ static void set_params(struct hantro_ctx *ctx) + vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL4); + + /* Decoder control register 5. */ +- reg = G1_REG_DEC_CTRL5_REFPIC_MK_LEN(slices[0].dec_ref_pic_marking_bit_size) | +- G1_REG_DEC_CTRL5_IDR_PIC_ID(slices[0].idr_pic_id); ++ reg = G1_REG_DEC_CTRL5_REFPIC_MK_LEN(dec_param->dec_ref_pic_marking_bit_size) | ++ G1_REG_DEC_CTRL5_IDR_PIC_ID(dec_param->idr_pic_id); + if (pps->flags & V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED) + reg |= G1_REG_DEC_CTRL5_CONST_INTRA_E; + if (pps->flags & V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT) +@@ -103,10 +102,10 @@ static void set_params(struct hantro_ctx *ctx) + vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL5); + + /* Decoder control register 6. */ +- reg = G1_REG_DEC_CTRL6_PPS_ID(slices[0].pic_parameter_set_id) | ++ reg = G1_REG_DEC_CTRL6_PPS_ID(pps->pic_parameter_set_id) | + G1_REG_DEC_CTRL6_REFIDX0_ACTIVE(pps->num_ref_idx_l0_default_active_minus1 + 1) | + G1_REG_DEC_CTRL6_REFIDX1_ACTIVE(pps->num_ref_idx_l1_default_active_minus1 + 1) | +- G1_REG_DEC_CTRL6_POC_LENGTH(slices[0].pic_order_cnt_bit_size); ++ G1_REG_DEC_CTRL6_POC_LENGTH(dec_param->pic_order_cnt_bit_size); + vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL6); + + /* Error concealment register. */ +@@ -246,7 +245,7 @@ static void set_buffers(struct hantro_ctx *ctx) + /* Destination (decoded frame) buffer. */ + dst_dma = hantro_get_dec_buf_addr(ctx, &dst_buf->vb2_buf); + /* Adjust dma addr to start at second line for bottom field */ +- if (ctrls->slices[0].flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD) ++ if (ctrls->decode->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD) + offset = ALIGN(ctx->src_fmt.width, MB_DIM); + vdpu_write_relaxed(vpu, dst_dma + offset, G1_REG_ADDR_DST); + +@@ -265,7 +264,7 @@ static void set_buffers(struct hantro_ctx *ctx) + * DMV buffer is split in two for field encoded frames, + * adjust offset for bottom field + */ +- if (ctrls->slices[0].flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD) ++ if (ctrls->decode->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD) + offset += 32 * MB_WIDTH(ctx->src_fmt.width) * + MB_HEIGHT(ctx->src_fmt.height); + vdpu_write_relaxed(vpu, dst_dma + offset, G1_REG_ADDR_DIR_MV); +diff --git a/drivers/staging/media/hantro/hantro_h264.c b/drivers/staging/media/hantro/hantro_h264.c +index 6dcd47bd9ed3..7578a4fc1b16 100644 +--- a/drivers/staging/media/hantro/hantro_h264.c ++++ b/drivers/staging/media/hantro/hantro_h264.c +@@ -372,8 +372,7 @@ int hantro_h264_dec_prepare_run(struct hantro_ctx *ctx) + + /* Build the P/B{0,1} ref lists. */ + v4l2_h264_init_reflist_builder(&reflist_builder, ctrls->decode, +- &ctrls->slices[0], ctrls->sps, +- ctx->h264_dec.dpb); ++ ctrls->sps, ctx->h264_dec.dpb); + v4l2_h264_build_p_ref_list(&reflist_builder, h264_ctx->reflists.p); + v4l2_h264_build_b_ref_lists(&reflist_builder, h264_ctx->reflists.b0, + h264_ctx->reflists.b1); +diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c +index 07a80e9a9df2..70752e30b3a3 100644 +--- a/drivers/staging/media/rkvdec/rkvdec-h264.c ++++ b/drivers/staging/media/rkvdec/rkvdec-h264.c +@@ -730,7 +730,6 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx, + struct rkvdec_h264_run *run) + { + const struct v4l2_ctrl_h264_decode_params *dec_params = run->decode_params; +- const struct v4l2_ctrl_h264_slice_params *sl_params = &run->slices_params[0]; + const struct v4l2_h264_dpb_entry *dpb = dec_params->dpb; + struct rkvdec_h264_ctx *h264_ctx = ctx->priv; + const struct v4l2_ctrl_h264_sps *sps = run->sps; +@@ -754,7 +753,7 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx, + continue; + + if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM || +- dpb[i].frame_num < sl_params->frame_num) { ++ dpb[i].frame_num < dec_params->frame_num) { + p[i] = dpb[i].frame_num; + continue; + } +@@ -1094,8 +1093,7 @@ static int rkvdec_h264_run(struct rkvdec_ctx *ctx) + + /* Build the P/B{0,1} ref lists. */ + v4l2_h264_init_reflist_builder(&reflist_builder, run.decode_params, +- &run.slices_params[0], run.sps, +- run.decode_params->dpb); ++ run.sps, run.decode_params->dpb); + h264_ctx->reflists.num_valid = reflist_builder.num_valid; + v4l2_h264_build_p_ref_list(&reflist_builder, h264_ctx->reflists.p); + v4l2_h264_build_b_ref_lists(&reflist_builder, h264_ctx->reflists.b0, +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +index 7d9bd5860a1b..c8f626fdd3dd 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +@@ -95,7 +95,6 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx, + { + struct cedrus_h264_sram_ref_pic pic_list[CEDRUS_H264_FRAME_NUM]; + const struct v4l2_ctrl_h264_decode_params *decode = run->h264.decode_params; +- const struct v4l2_ctrl_h264_slice_params *slice = run->h264.slice_params; + const struct v4l2_ctrl_h264_sps *sps = run->h264.sps; + struct vb2_queue *cap_q; + struct cedrus_buffer *output_buf; +@@ -144,7 +143,7 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx, + output_buf = vb2_to_cedrus_buffer(&run->dst->vb2_buf); + output_buf->codec.h264.position = position; + +- if (slice->flags & V4L2_H264_SLICE_FLAG_FIELD_PIC) ++ if (decode->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC) + output_buf->codec.h264.pic_type = CEDRUS_H264_PIC_TYPE_FIELD; + else if (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD) + output_buf->codec.h264.pic_type = CEDRUS_H264_PIC_TYPE_MBAFF; +@@ -407,7 +406,7 @@ static void cedrus_set_params(struct cedrus_ctx *ctx, + reg |= VE_H264_SPS_DIRECT_8X8_INFERENCE; + cedrus_write(dev, VE_H264_SPS, reg); + +- mbaff_pic = !(slice->flags & V4L2_H264_SLICE_FLAG_FIELD_PIC) && ++ mbaff_pic = !(decode->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC) && + (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD); + pic_width_in_mbs = sps->pic_width_in_mbs_minus1 + 1; + +@@ -421,9 +420,9 @@ static void cedrus_set_params(struct cedrus_ctx *ctx, + reg |= slice->cabac_init_idc & 0x3; + if (ctx->fh.m2m_ctx->new_frame) + reg |= VE_H264_SHS_FIRST_SLICE_IN_PIC; +- if (slice->flags & V4L2_H264_SLICE_FLAG_FIELD_PIC) ++ if (decode->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC) + reg |= VE_H264_SHS_FIELD_PIC; +- if (slice->flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD) ++ if (decode->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD) + reg |= VE_H264_SHS_BOTTOM_FIELD; + if (slice->flags & V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED) + reg |= VE_H264_SHS_DIRECT_SPATIAL_MV_PRED; +diff --git a/include/media/h264-ctrls.h b/include/media/h264-ctrls.h +index e180501e6385..1217b706128e 100644 +--- a/include/media/h264-ctrls.h ++++ b/include/media/h264-ctrls.h +@@ -146,10 +146,8 @@ struct v4l2_ctrl_h264_pred_weights { + #define V4L2_H264_SLICE_TYPE_SP 3 + #define V4L2_H264_SLICE_TYPE_SI 4 + +-#define V4L2_H264_SLICE_FLAG_FIELD_PIC 0x01 +-#define V4L2_H264_SLICE_FLAG_BOTTOM_FIELD 0x02 +-#define V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED 0x04 +-#define V4L2_H264_SLICE_FLAG_SP_FOR_SWITCH 0x08 ++#define V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED 0x01 ++#define V4L2_H264_SLICE_FLAG_SP_FOR_SWITCH 0x02 + + enum v4l2_h264_field_reference { + V4L2_H264_TOP_FIELD_REF = 0x1, +@@ -171,21 +169,8 @@ struct v4l2_ctrl_h264_slice_params { + __u32 first_mb_in_slice; + + __u8 slice_type; +- __u8 pic_parameter_set_id; + __u8 colour_plane_id; + __u8 redundant_pic_cnt; +- __u16 frame_num; +- __u16 idr_pic_id; +- __u16 pic_order_cnt_lsb; +- __s32 delta_pic_order_cnt_bottom; +- __s32 delta_pic_order_cnt0; +- __s32 delta_pic_order_cnt1; +- +- /* Size in bits of dec_ref_pic_marking() syntax element. */ +- __u32 dec_ref_pic_marking_bit_size; +- /* Size in bits of pic order count syntax. */ +- __u32 pic_order_cnt_bit_size; +- + __u8 cabac_init_idc; + __s8 slice_qp_delta; + __s8 slice_qs_delta; +@@ -194,7 +179,8 @@ struct v4l2_ctrl_h264_slice_params { + __s8 slice_beta_offset_div2; + __u8 num_ref_idx_l0_active_minus1; + __u8 num_ref_idx_l1_active_minus1; +- __u32 slice_group_change_cycle; ++ ++ __u8 reserved; + + struct v4l2_h264_reference ref_pic_list0[V4L2_H264_REF_LIST_LEN]; + struct v4l2_h264_reference ref_pic_list1[V4L2_H264_REF_LIST_LEN]; +@@ -219,13 +205,28 @@ struct v4l2_h264_dpb_entry { + __u32 flags; /* V4L2_H264_DPB_ENTRY_FLAG_* */ + }; + +-#define V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC 0x01 ++#define V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC 0x01 ++#define V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC 0x02 ++#define V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD 0x04 + + struct v4l2_ctrl_h264_decode_params { + struct v4l2_h264_dpb_entry dpb[V4L2_H264_NUM_DPB_ENTRIES]; + __u16 nal_ref_idc; ++ __u16 frame_num; + __s32 top_field_order_cnt; + __s32 bottom_field_order_cnt; ++ __u16 idr_pic_id; ++ __u16 pic_order_cnt_lsb; ++ __s32 delta_pic_order_cnt_bottom; ++ __s32 delta_pic_order_cnt0; ++ __s32 delta_pic_order_cnt1; ++ /* Size in bits of dec_ref_pic_marking() syntax element. */ ++ __u32 dec_ref_pic_marking_bit_size; ++ /* Size in bits of pic order count syntax. */ ++ __u32 pic_order_cnt_bit_size; ++ __u32 slice_group_change_cycle; ++ ++ __u32 reserved; + __u32 flags; /* V4L2_H264_DECODE_PARAM_FLAG_* */ + }; + +diff --git a/include/media/v4l2-h264.h b/include/media/v4l2-h264.h +index 1a5f26fc2a9a..f08ba181263d 100644 +--- a/include/media/v4l2-h264.h ++++ b/include/media/v4l2-h264.h +@@ -44,7 +44,6 @@ struct v4l2_h264_reflist_builder { + void + v4l2_h264_init_reflist_builder(struct v4l2_h264_reflist_builder *b, + const struct v4l2_ctrl_h264_decode_params *dec_params, +- const struct v4l2_ctrl_h264_slice_params *slice_params, + const struct v4l2_ctrl_h264_sps *sps, + const struct v4l2_h264_dpb_entry dpb[V4L2_H264_NUM_DPB_ENTRIES]); + + +From c94048bd00c4faa5bf1be0b3b01d3cc41cb475bb Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Fri, 14 Aug 2020 10:36:26 -0300 +Subject: [PATCH] media: uapi: h264: Rename and clarify + PPS_FLAG_SCALING_MATRIX_PRESENT + +Applications are expected to fill V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX +if a non-flat scaling matrix applies to the picture. This is the case if +SPS scaling_matrix_present_flag or PPS pic_scaling_matrix_present_flag +are set, and should be handled by applications. + +On one hand, the PPS bitstream syntax element signals the presence of a +Picture scaling matrix modifying the Sequence (SPS) scaling matrix. +On the other hand, our flag should indicate if the scaling matrix +V4L2 control is applicable to this request. + +Rename the flag from PPS_FLAG_PIC_SCALING_MATRIX_PRESENT to +PPS_FLAG_SCALING_MATRIX_PRESENT, to avoid mixing this flag with +bitstream syntax element pic_scaling_matrix_present_flag, +and clarify the meaning of our flag. + +Signed-off-by: Ezequiel Garcia +--- + Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst | 5 +++-- + include/media/h264-ctrls.h | 2 +- + 2 files changed, 4 insertions(+), 3 deletions(-) + +diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +index 69dd3961b99b..03ce87aa5488 100644 +--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst ++++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +@@ -1695,9 +1695,10 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + * - ``V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE`` + - 0x00000040 + - +- * - ``V4L2_H264_PPS_FLAG_PIC_SCALING_MATRIX_PRESENT`` ++ * - ``V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT`` + - 0x00000080 +- - ++ - Indicates that ``V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX`` ++ must be used for this picture. + + ``V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX (struct)`` + Specifies the scaling matrix (as extracted from the bitstream) for +diff --git a/include/media/h264-ctrls.h b/include/media/h264-ctrls.h +index 1217b706128e..070b9499d7bc 100644 +--- a/include/media/h264-ctrls.h ++++ b/include/media/h264-ctrls.h +@@ -99,7 +99,7 @@ struct v4l2_ctrl_h264_sps { + #define V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED 0x0010 + #define V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT 0x0020 + #define V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE 0x0040 +-#define V4L2_H264_PPS_FLAG_PIC_SCALING_MATRIX_PRESENT 0x0080 ++#define V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT 0x0080 + + struct v4l2_ctrl_h264_pps { + __u8 pic_parameter_set_id; + +From 2344f270ec7a9f9559e6d1e57a124c6a89ce0602 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Fri, 14 Aug 2020 10:36:27 -0300 +Subject: [PATCH] media: hantro: Don't require unneeded H264_SLICE_PARAMS + +Now that slice invariant parameters have been moved, +the driver no longer needs this control, so drop it. + +Signed-off-by: Ezequiel Garcia +--- + drivers/staging/media/hantro/hantro_drv.c | 5 ----- + drivers/staging/media/hantro/hantro_h264.c | 5 ----- + drivers/staging/media/hantro/hantro_hw.h | 2 -- + 3 files changed, 12 deletions(-) + +diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c +index 34797507f214..3cd00cc0a364 100644 +--- a/drivers/staging/media/hantro/hantro_drv.c ++++ b/drivers/staging/media/hantro/hantro_drv.c +@@ -306,11 +306,6 @@ static const struct hantro_ctrl controls[] = { + .cfg = { + .id = V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS, + }, +- }, { +- .codec = HANTRO_H264_DECODER, +- .cfg = { +- .id = V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS, +- }, + }, { + .codec = HANTRO_H264_DECODER, + .cfg = { +diff --git a/drivers/staging/media/hantro/hantro_h264.c b/drivers/staging/media/hantro/hantro_h264.c +index 7578a4fc1b16..089bfa9c625b 100644 +--- a/drivers/staging/media/hantro/hantro_h264.c ++++ b/drivers/staging/media/hantro/hantro_h264.c +@@ -349,11 +349,6 @@ int hantro_h264_dec_prepare_run(struct hantro_ctx *ctx) + if (WARN_ON(!ctrls->decode)) + return -EINVAL; + +- ctrls->slices = +- hantro_get_ctrl(ctx, V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS); +- if (WARN_ON(!ctrls->slices)) +- return -EINVAL; +- + ctrls->sps = + hantro_get_ctrl(ctx, V4L2_CID_MPEG_VIDEO_H264_SPS); + if (WARN_ON(!ctrls->sps)) +diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h +index f066de6b592d..219283a06f52 100644 +--- a/drivers/staging/media/hantro/hantro_hw.h ++++ b/drivers/staging/media/hantro/hantro_hw.h +@@ -56,14 +56,12 @@ struct hantro_jpeg_enc_hw_ctx { + * struct hantro_h264_dec_ctrls + * @decode: Decode params + * @scaling: Scaling info +- * @slice: Slice params + * @sps: SPS info + * @pps: PPS info + */ + struct hantro_h264_dec_ctrls { + const struct v4l2_ctrl_h264_decode_params *decode; + const struct v4l2_ctrl_h264_scaling_matrix *scaling; +- const struct v4l2_ctrl_h264_slice_params *slices; + const struct v4l2_ctrl_h264_sps *sps; + const struct v4l2_ctrl_h264_pps *pps; + }; + +From 419ccc9852409f2553c92ee3be909afa53d24d1d Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Fri, 14 Aug 2020 10:36:28 -0300 +Subject: [PATCH] media: rkvdec: Don't require unneeded H264_SLICE_PARAMS + +Now that slice invariant parameters have been moved, +the driver no longer needs this control, so drop it. + +Signed-off-by: Ezequiel Garcia +Reviewed-by: Jonas Karlman +--- + drivers/staging/media/rkvdec/rkvdec-h264.c | 4 ---- + drivers/staging/media/rkvdec/rkvdec.c | 5 ----- + 2 files changed, 9 deletions(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c +index 70752e30b3a3..584e0d5c493b 100644 +--- a/drivers/staging/media/rkvdec/rkvdec-h264.c ++++ b/drivers/staging/media/rkvdec/rkvdec-h264.c +@@ -109,7 +109,6 @@ struct rkvdec_h264_reflists { + struct rkvdec_h264_run { + struct rkvdec_run base; + const struct v4l2_ctrl_h264_decode_params *decode_params; +- const struct v4l2_ctrl_h264_slice_params *slices_params; + const struct v4l2_ctrl_h264_sps *sps; + const struct v4l2_ctrl_h264_pps *pps; + const struct v4l2_ctrl_h264_scaling_matrix *scaling_matrix; +@@ -1066,9 +1065,6 @@ static void rkvdec_h264_run_preamble(struct rkvdec_ctx *ctx, + ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, + V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS); + run->decode_params = ctrl ? ctrl->p_cur.p : NULL; +- ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, +- V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS); +- run->slices_params = ctrl ? ctrl->p_cur.p : NULL; + ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, + V4L2_CID_MPEG_VIDEO_H264_SPS); + run->sps = ctrl ? ctrl->p_cur.p : NULL; +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index c8151328fb70..7c5129593921 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -59,11 +59,6 @@ static const struct rkvdec_ctrl_desc rkvdec_h264_ctrl_descs[] = { + .mandatory = true, + .cfg.id = V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS, + }, +- { +- .per_request = true, +- .mandatory = true, +- .cfg.id = V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS, +- }, + { + .per_request = true, + .mandatory = true, + +From 85567a00727331d7a3269bd76319a048ef1ed505 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Fri, 14 Aug 2020 10:36:29 -0300 +Subject: [PATCH] media: cedrus: h264: Properly configure reference field + +When interlaced H264 content is being decoded, references must indicate +which field is being referenced. Currently this was done by checking +capture buffer flags. However, that is not correct because capture +buffer may hold both fields. + +Fix this by checking newly introduced flags in reference lists. + +Signed-off-by: Jernej Skrabec +Reviewed-by: Nicolas Dufresne +--- + drivers/staging/media/sunxi/cedrus/cedrus_h264.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +index c8f626fdd3dd..1e89a8438f36 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +@@ -182,7 +182,6 @@ static void _cedrus_write_ref_list(struct cedrus_ctx *ctx, + for (i = 0; i < num_ref; i++) { + const struct v4l2_h264_dpb_entry *dpb; + const struct cedrus_buffer *cedrus_buf; +- const struct vb2_v4l2_buffer *ref_buf; + unsigned int position; + int buf_idx; + u8 dpb_idx; +@@ -197,12 +196,11 @@ static void _cedrus_write_ref_list(struct cedrus_ctx *ctx, + if (buf_idx < 0) + continue; + +- ref_buf = to_vb2_v4l2_buffer(cap_q->bufs[buf_idx]); +- cedrus_buf = vb2_v4l2_to_cedrus_buffer(ref_buf); ++ cedrus_buf = vb2_to_cedrus_buffer(cap_q->bufs[buf_idx]); + position = cedrus_buf->codec.h264.position; + + sram_array[i] |= position << 1; +- if (ref_buf->field == V4L2_FIELD_BOTTOM) ++ if (ref_list[i].fields & V4L2_H264_BOTTOM_FIELD_REF) + sram_array[i] |= BIT(0); + } + + +From 102efa220abfcf3c08ceaf0a7c3ac5f88db5bc0c Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Fri, 14 Aug 2020 10:36:30 -0300 +Subject: [PATCH] media: cedrus: h264: Fix frame list construction + +Current frame list construction algorithm assumes that decoded image +will be output into its own buffer. That is true for progressive content +but not for interlaced where each field is decoded separately into same +buffer. + +Fix that by checking if capture buffer is listed in DPB. If it is, reuse +it. + +Signed-off-by: Jernej Skrabec +--- + drivers/staging/media/sunxi/cedrus/cedrus_h264.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +index 1e89a8438f36..fe041b444385 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +@@ -101,7 +101,7 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx, + struct cedrus_dev *dev = ctx->dev; + unsigned long used_dpbs = 0; + unsigned int position; +- unsigned int output = 0; ++ int output = -1; + unsigned int i; + + cap_q = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); +@@ -124,6 +124,11 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx, + position = cedrus_buf->codec.h264.position; + used_dpbs |= BIT(position); + ++ if (run->dst->vb2_buf.timestamp == dpb->reference_ts) { ++ output = position; ++ continue; ++ } ++ + if (!(dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)) + continue; + +@@ -131,13 +136,11 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx, + dpb->top_field_order_cnt, + dpb->bottom_field_order_cnt, + &pic_list[position]); +- +- output = max(position, output); + } + +- position = find_next_zero_bit(&used_dpbs, CEDRUS_H264_FRAME_NUM, +- output); +- if (position >= CEDRUS_H264_FRAME_NUM) ++ if (output >= 0) ++ position = output; ++ else + position = find_first_zero_bit(&used_dpbs, CEDRUS_H264_FRAME_NUM); + + output_buf = vb2_to_cedrus_buffer(&run->dst->vb2_buf); + +From 47f1224e5d7f2d3d566d1da9df0f72ee0564a0d1 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Wed, 19 Aug 2020 11:37:55 -0300 +Subject: [PATCH] media: rkvdec: Drop unneeded per_request driver-specific + control flag + +Currently, the drivers makes no distinction between per_request +and mandatory, as both are used in the same request validate check. + +The driver only cares to know if a given control is +required to be part of a request, so only one flag is needed. + +Signed-off-by: Ezequiel Garcia +--- + drivers/staging/media/rkvdec/rkvdec.c | 8 +------- + drivers/staging/media/rkvdec/rkvdec.h | 1 - + 2 files changed, 1 insertion(+), 8 deletions(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index 7c5129593921..9f59dfb62d3f 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -55,35 +55,29 @@ static const struct v4l2_ctrl_ops rkvdec_ctrl_ops = { + + static const struct rkvdec_ctrl_desc rkvdec_h264_ctrl_descs[] = { + { +- .per_request = true, + .mandatory = true, + .cfg.id = V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS, + }, + { +- .per_request = true, + .mandatory = true, + .cfg.id = V4L2_CID_MPEG_VIDEO_H264_SPS, + .cfg.ops = &rkvdec_ctrl_ops, + }, + { +- .per_request = true, + .mandatory = true, + .cfg.id = V4L2_CID_MPEG_VIDEO_H264_PPS, + }, + { +- .per_request = true, + .mandatory = true, + .cfg.id = V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX, + }, + { +- .mandatory = true, + .cfg.id = V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE, + .cfg.min = V4L2_MPEG_VIDEO_H264_DECODE_MODE_FRAME_BASED, + .cfg.max = V4L2_MPEG_VIDEO_H264_DECODE_MODE_FRAME_BASED, + .cfg.def = V4L2_MPEG_VIDEO_H264_DECODE_MODE_FRAME_BASED, + }, + { +- .mandatory = true, + .cfg.id = V4L2_CID_MPEG_VIDEO_H264_START_CODE, + .cfg.min = V4L2_MPEG_VIDEO_H264_START_CODE_ANNEX_B, + .cfg.def = V4L2_MPEG_VIDEO_H264_START_CODE_ANNEX_B, +@@ -615,7 +609,7 @@ static int rkvdec_request_validate(struct media_request *req) + u32 id = ctrls->ctrls[i].cfg.id; + struct v4l2_ctrl *ctrl; + +- if (!ctrls->ctrls[i].per_request || !ctrls->ctrls[i].mandatory) ++ if (!ctrls->ctrls[i].mandatory) + continue; + + ctrl = v4l2_ctrl_request_hdl_ctrl_find(hdl, id); +diff --git a/drivers/staging/media/rkvdec/rkvdec.h b/drivers/staging/media/rkvdec/rkvdec.h +index 2fc9f46b6910..77a137cca88e 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.h ++++ b/drivers/staging/media/rkvdec/rkvdec.h +@@ -25,7 +25,6 @@ + struct rkvdec_ctx; + + struct rkvdec_ctrl_desc { +- u32 per_request : 1; + u32 mandatory : 1; + struct v4l2_ctrl_config cfg; + }; + +From 90ea71bc465216778ac6fda4ca151f324df4d516 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Fri, 14 Aug 2020 10:36:32 -0300 +Subject: [PATCH] media: rkvdec: Use H264_SCALING_MATRIX only when required + +Baseline, Main and Extended profiles are specified to +not support a scaling matrix. Also, High profiles +can optionally specify a scaling matrix, using +SPS and PPS NAL units. + +To meet this expectation, applications are required to +set the V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX control +and set the V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT +flag only when a scaling matrix is specified for a picture. + +Implement this on rkvdec, which has hardware support for this +case. + +Signed-off-by: Ezequiel Garcia +--- + drivers/staging/media/rkvdec/rkvdec-h264.c | 10 +++++++--- + drivers/staging/media/rkvdec/rkvdec.c | 1 - + 2 files changed, 7 insertions(+), 4 deletions(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c +index 584e0d5c493b..9233260e14c1 100644 +--- a/drivers/staging/media/rkvdec/rkvdec-h264.c ++++ b/drivers/staging/media/rkvdec/rkvdec-h264.c +@@ -708,9 +708,9 @@ static void assemble_hw_pps(struct rkvdec_ctx *ctx, + WRITE_PPS(pps->second_chroma_qp_index_offset, + SECOND_CHROMA_QP_INDEX_OFFSET); + +- /* always use the matrix sent from userspace */ +- WRITE_PPS(1, SCALING_LIST_ENABLE_FLAG); +- ++ WRITE_PPS(!!(pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT), ++ SCALING_LIST_ENABLE_FLAG); ++ /* To be on the safe side, program the scaling matrix address */ + scaling_distance = offsetof(struct rkvdec_h264_priv_tbl, scaling_list); + scaling_list_address = h264_ctx->priv_tbl.dma + scaling_distance; + WRITE_PPS(scaling_list_address, SCALING_LIST_ADDRESS); +@@ -792,9 +792,13 @@ static void assemble_hw_scaling_list(struct rkvdec_ctx *ctx, + struct rkvdec_h264_run *run) + { + const struct v4l2_ctrl_h264_scaling_matrix *scaling = run->scaling_matrix; ++ const struct v4l2_ctrl_h264_pps *pps = run->pps; + struct rkvdec_h264_ctx *h264_ctx = ctx->priv; + struct rkvdec_h264_priv_tbl *tbl = h264_ctx->priv_tbl.cpu; + ++ if (!(pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT)) ++ return; ++ + BUILD_BUG_ON(sizeof(tbl->scaling_list.scaling_list_4x4) != + sizeof(scaling->scaling_list_4x4)); + BUILD_BUG_ON(sizeof(tbl->scaling_list.scaling_list_8x8) != +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index 9f59dfb62d3f..d25c4a37e2af 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -68,7 +68,6 @@ static const struct rkvdec_ctrl_desc rkvdec_h264_ctrl_descs[] = { + .cfg.id = V4L2_CID_MPEG_VIDEO_H264_PPS, + }, + { +- .mandatory = true, + .cfg.id = V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX, + }, + { + +From 70d39439f485d511c9c929934a26341ef3b736ef Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Fri, 14 Aug 2020 10:36:33 -0300 +Subject: [PATCH] media: hantro: Use H264_SCALING_MATRIX only when required + +Baseline, Main and Extended profiles are specified to +not support a scaling matrix. Also, High profiles +can optionally specify a scaling matrix, using +SPS and PPS NAL units. + +To meet this expectation, applications are required to +set the V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX control +and set the V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT +flag only when a scaling matrix is specified for a picture. + +Implement this on hantro, which has hardware support for this +case. + +Signed-off-by: Ezequiel Garcia +--- + drivers/staging/media/hantro/hantro_g1_h264_dec.c | 5 ++--- + drivers/staging/media/hantro/hantro_h264.c | 4 ++++ + 2 files changed, 6 insertions(+), 3 deletions(-) + +diff --git a/drivers/staging/media/hantro/hantro_g1_h264_dec.c b/drivers/staging/media/hantro/hantro_g1_h264_dec.c +index f9839e9c6da5..845bef73d218 100644 +--- a/drivers/staging/media/hantro/hantro_g1_h264_dec.c ++++ b/drivers/staging/media/hantro/hantro_g1_h264_dec.c +@@ -59,9 +59,8 @@ static void set_params(struct hantro_ctx *ctx) + reg = G1_REG_DEC_CTRL2_CH_QP_OFFSET(pps->chroma_qp_index_offset) | + G1_REG_DEC_CTRL2_CH_QP_OFFSET2(pps->second_chroma_qp_index_offset); + +- /* always use the matrix sent from userspace */ +- reg |= G1_REG_DEC_CTRL2_TYPE1_QUANT_E; +- ++ if (pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT) ++ reg |= G1_REG_DEC_CTRL2_TYPE1_QUANT_E; + if (!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY)) + reg |= G1_REG_DEC_CTRL2_FIELDPIC_FLAG_E; + vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL2); +diff --git a/drivers/staging/media/hantro/hantro_h264.c b/drivers/staging/media/hantro/hantro_h264.c +index 089bfa9c625b..b1bdc00ac262 100644 +--- a/drivers/staging/media/hantro/hantro_h264.c ++++ b/drivers/staging/media/hantro/hantro_h264.c +@@ -197,6 +197,7 @@ assemble_scaling_list(struct hantro_ctx *ctx) + { + const struct hantro_h264_dec_ctrls *ctrls = &ctx->h264_dec.ctrls; + const struct v4l2_ctrl_h264_scaling_matrix *scaling = ctrls->scaling; ++ const struct v4l2_ctrl_h264_pps *pps = ctrls->pps; + const size_t num_list_4x4 = ARRAY_SIZE(scaling->scaling_list_4x4); + const size_t list_len_4x4 = ARRAY_SIZE(scaling->scaling_list_4x4[0]); + const size_t list_len_8x8 = ARRAY_SIZE(scaling->scaling_list_8x8[0]); +@@ -205,6 +206,9 @@ assemble_scaling_list(struct hantro_ctx *ctx) + const u32 *src; + int i, j; + ++ if (!(pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT)) ++ return; ++ + for (i = 0; i < num_list_4x4; i++) { + src = (u32 *)&scaling->scaling_list_4x4[i]; + for (j = 0; j < list_len_4x4 / 4; j++) + +From 6390458815944ce231b6282771e2a6c3fc6f2fa6 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Fri, 14 Aug 2020 10:36:34 -0300 +Subject: [PATCH] media: cedrus: Use H264_SCALING_MATRIX only when required + +Baseline, Main and Extended profiles are specified to +not support a scaling matrix. Also, High profiles +can optionally specify a scaling matrix, using +SPS and PPS NAL units. + +To meet this expectation, applications are required to +set the V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX control +and set the V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT +flag only when a scaling matrix is specified for a picture. + +Implement this on cedrus, which has hardware support for this +case. + +Signed-off-by: Ezequiel Garcia +--- + drivers/staging/media/sunxi/cedrus/cedrus.c | 2 +- + drivers/staging/media/sunxi/cedrus/cedrus_h264.c | 6 ++++++ + 2 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c +index 826324faad7e..6ebb39e0c0ce 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.c +@@ -76,7 +76,7 @@ static const struct cedrus_control cedrus_controls[] = { + .id = V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX, + }, + .codec = CEDRUS_CODEC_H264, +- .required = true, ++ .required = false, + }, + { + .cfg = { +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +index fe041b444385..28319351e909 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +@@ -238,8 +238,12 @@ static void cedrus_write_scaling_lists(struct cedrus_ctx *ctx, + { + const struct v4l2_ctrl_h264_scaling_matrix *scaling = + run->h264.scaling_matrix; ++ const struct v4l2_ctrl_h264_pps *pps = run->h264.pps; + struct cedrus_dev *dev = ctx->dev; + ++ if (!(pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT)) ++ return; ++ + cedrus_h264_write_sram(dev, CEDRUS_SRAM_H264_SCALING_LIST_8x8_0, + scaling->scaling_list_8x8[0], + sizeof(scaling->scaling_list_8x8[0])); +@@ -442,6 +446,8 @@ static void cedrus_set_params(struct cedrus_ctx *ctx, + reg |= (pps->second_chroma_qp_index_offset & 0x3f) << 16; + reg |= (pps->chroma_qp_index_offset & 0x3f) << 8; + reg |= (pps->pic_init_qp_minus26 + 26 + slice->slice_qp_delta) & 0x3f; ++ if (pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT) ++ reg |= VE_H264_SHS_QP_SCALING_MATRIX_DEFAULT; + cedrus_write(dev, VE_H264_SHS_QP, reg); + + // clear status flags + +From 711f57301ef4368ba23f70f6596994b7242803cc Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 6 Jul 2020 21:54:33 +0000 +Subject: [PATCH] media: rkvdec: h264: Fix reference frame_num wrap for second + field + +When decoding the second field in a complementary field pair the second +field is sharing the same frame_num with the first field. + +Currently the frame_num for the first field is wrapped when it matches the +field being decoded, this cause issues to decode the second field in a +complementary field pair. + +Fix this by using inclusive comparison, less than or equal. + +Signed-off-by: Jonas Karlman +Reviewed-by: Ezequiel Garcia +--- + drivers/staging/media/rkvdec/rkvdec-h264.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c +index 9233260e14c1..8fab0151b884 100644 +--- a/drivers/staging/media/rkvdec/rkvdec-h264.c ++++ b/drivers/staging/media/rkvdec/rkvdec-h264.c +@@ -752,7 +752,7 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx, + continue; + + if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM || +- dpb[i].frame_num < dec_params->frame_num) { ++ dpb[i].frame_num <= dec_params->frame_num) { + p[i] = dpb[i].frame_num; + continue; + } + +From a957b522403e98c67b8c184fa3b7709c6e874d40 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 6 Jul 2020 21:54:34 +0000 +Subject: [PATCH] media: rkvdec: Ensure decoded resolution fit coded resolution + +Ensure decoded CAPTURE buffer resolution is larger or equal to the coded +OPTUPT buffer resolution. + +Signed-off-by: Jonas Karlman +--- + drivers/staging/media/rkvdec/rkvdec.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index d25c4a37e2af..b3e067031c83 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -223,6 +223,8 @@ static int rkvdec_try_capture_fmt(struct file *file, void *priv, + pix_mp->pixelformat = coded_desc->decoded_fmts[0]; + + /* Always apply the frmsize constraint of the coded end. */ ++ pix_mp->width = max(pix_mp->width, ctx->coded_fmt.fmt.pix_mp.width); ++ pix_mp->height = max(pix_mp->height, ctx->coded_fmt.fmt.pix_mp.height); + v4l2_apply_frmsize_constraints(&pix_mp->width, + &pix_mp->height, + &coded_desc->frmsize); + +From 7c3bb86b8d315c1939a35c4dfe31e120758e5395 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 6 Jul 2020 21:54:34 +0000 +Subject: [PATCH] media: rkvdec: h264: Validate and use pic width and height in + mbs + +The width and height in mbs is currently configured based on OUTPUT buffer +resolution, this works for frame pictures but can cause issues for field +pictures. + +When frame_mbs_only_flag is 0 the height in mbs should be height of +the field instead of height of frame. + +Validate pic_width_in_mbs_minus1 and pic_height_in_map_units_minus1 +against OUTPUT buffer resolution and use these values to configure HW. + +Signed-off-by: Jonas Karlman +--- + drivers/staging/media/rkvdec/rkvdec-h264.c | 4 ++-- + drivers/staging/media/rkvdec/rkvdec.c | 10 ++++++++++ + 2 files changed, 12 insertions(+), 2 deletions(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c +index 8fab0151b884..20a783a1bcc7 100644 +--- a/drivers/staging/media/rkvdec/rkvdec-h264.c ++++ b/drivers/staging/media/rkvdec/rkvdec-h264.c +@@ -671,8 +671,8 @@ static void assemble_hw_pps(struct rkvdec_ctx *ctx, + LOG2_MAX_PIC_ORDER_CNT_LSB_MINUS4); + WRITE_PPS(!!(sps->flags & V4L2_H264_SPS_FLAG_DELTA_PIC_ORDER_ALWAYS_ZERO), + DELTA_PIC_ORDER_ALWAYS_ZERO_FLAG); +- WRITE_PPS(DIV_ROUND_UP(ctx->coded_fmt.fmt.pix_mp.width, 16), PIC_WIDTH_IN_MBS); +- WRITE_PPS(DIV_ROUND_UP(ctx->coded_fmt.fmt.pix_mp.height, 16), PIC_HEIGHT_IN_MBS); ++ WRITE_PPS(sps->pic_width_in_mbs_minus1 + 1, PIC_WIDTH_IN_MBS); ++ WRITE_PPS(sps->pic_height_in_map_units_minus1 + 1, PIC_HEIGHT_IN_MBS); + WRITE_PPS(!!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY), + FRAME_MBS_ONLY_FLAG); + WRITE_PPS(!!(sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD), +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index b3e067031c83..06fc58440cd3 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -29,8 +29,11 @@ + + static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl) + { ++ struct rkvdec_ctx *ctx = container_of(ctrl->handler, struct rkvdec_ctx, ctrl_hdl); ++ + if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_SPS) { + const struct v4l2_ctrl_h264_sps *sps = ctrl->p_new.p_h264_sps; ++ unsigned int width, height; + /* + * TODO: The hardware supports 10-bit and 4:2:2 profiles, + * but it's currently broken in the driver. +@@ -45,6 +48,13 @@ static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl) + if (sps->bit_depth_luma_minus8 != 0) + /* Only 8-bit is supported */ + return -EINVAL; ++ ++ width = (sps->pic_width_in_mbs_minus1 + 1) * 16; ++ height = (sps->pic_height_in_map_units_minus1 + 1) * 16; ++ ++ if (width > ctx->coded_fmt.fmt.pix_mp.width || ++ height > ctx->coded_fmt.fmt.pix_mp.height) ++ return -EINVAL; + } + return 0; + } + +From f28529ac6fd75419e2b1806777158b5912ea0cb4 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 6 Jul 2020 21:54:35 +0000 +Subject: [PATCH] media: rkvdec: h264: Fix bit depth wrap in pps packet + +The luma and chroma bit depth fields in the pps packet is 3 bits wide. +8 is wrongly added to the bit depth value written to these 3-bit fields. +Because only the 3 LSB is written the hardware is configured correctly. + +Correct this by not adding 8 to the luma and chroma bit depth value. + +Signed-off-by: Jonas Karlman +Reviewed-by: Ezequiel Garcia +--- + drivers/staging/media/rkvdec/rkvdec-h264.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c +index 20a783a1bcc7..f4b61dd45e7f 100644 +--- a/drivers/staging/media/rkvdec/rkvdec-h264.c ++++ b/drivers/staging/media/rkvdec/rkvdec-h264.c +@@ -661,8 +661,8 @@ static void assemble_hw_pps(struct rkvdec_ctx *ctx, + WRITE_PPS(0xff, PROFILE_IDC); + WRITE_PPS(1, CONSTRAINT_SET3_FLAG); + WRITE_PPS(sps->chroma_format_idc, CHROMA_FORMAT_IDC); +- WRITE_PPS(sps->bit_depth_luma_minus8 + 8, BIT_DEPTH_LUMA); +- WRITE_PPS(sps->bit_depth_chroma_minus8 + 8, BIT_DEPTH_CHROMA); ++ WRITE_PPS(sps->bit_depth_luma_minus8, BIT_DEPTH_LUMA); ++ WRITE_PPS(sps->bit_depth_chroma_minus8, BIT_DEPTH_CHROMA); + WRITE_PPS(0, QPPRIME_Y_ZERO_TRANSFORM_BYPASS_FLAG); + WRITE_PPS(sps->log2_max_frame_num_minus4, LOG2_MAX_FRAME_NUM_MINUS4); + WRITE_PPS(sps->max_num_ref_frames, MAX_NUM_REF_FRAMES); + +From a0de7efadd3058c3837714fd1c71e31dd00b9eac Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 6 Jul 2020 21:54:35 +0000 +Subject: [PATCH] media: rkvdec: h264: Do not override output buffer sizeimage + +The output buffer sizeimage is currently forced to 2 bytes per pixel, this +can lead to high memory usage for 4K content when multiple output buffers +is created by userspace. + +Do not override output buffer sizeimage and let userspace have control of +output buffer sizeimage by only setting sizeimage if none is provided. + +Signed-off-by: Jonas Karlman +--- + drivers/staging/media/rkvdec/rkvdec-h264.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c +index f4b61dd45e7f..2e7749bac417 100644 +--- a/drivers/staging/media/rkvdec/rkvdec-h264.c ++++ b/drivers/staging/media/rkvdec/rkvdec-h264.c +@@ -1015,8 +1015,9 @@ static int rkvdec_h264_adjust_fmt(struct rkvdec_ctx *ctx, + struct v4l2_pix_format_mplane *fmt = &f->fmt.pix_mp; + + fmt->num_planes = 1; +- fmt->plane_fmt[0].sizeimage = fmt->width * fmt->height * +- RKVDEC_H264_MAX_DEPTH_IN_BYTES; ++ if (!fmt->plane_fmt[0].sizeimage) ++ fmt->plane_fmt[0].sizeimage = fmt->width * fmt->height * ++ RKVDEC_H264_MAX_DEPTH_IN_BYTES; + return 0; + } + + +From 2fd027124722012155dda6bf4af57d978ce0655c Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 6 Jul 2020 21:54:35 +0000 +Subject: [PATCH] media: v4l2-common: Add helpers to calculate bytesperline and + sizeimage + +Add helper functions to calculate plane bytesperline and sizeimage, these +new helpers consider block width and height when calculating plane +bytesperline and sizeimage. + +This prepare support for new pixel formats added in next patch that make +use of block width and height. + +Signed-off-by: Jonas Karlman +--- + drivers/media/v4l2-core/v4l2-common.c | 77 +++++++++++++-------------- + 1 file changed, 38 insertions(+), 39 deletions(-) + +diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c +index 3dc17ebe14fa..4102c373b48a 100644 +--- a/drivers/media/v4l2-core/v4l2-common.c ++++ b/drivers/media/v4l2-core/v4l2-common.c +@@ -333,6 +333,33 @@ static inline unsigned int v4l2_format_block_height(const struct v4l2_format_inf + return info->block_h[plane]; + } + ++static inline unsigned int v4l2_format_plane_width(const struct v4l2_format_info *info, int plane, ++ unsigned int width) ++{ ++ unsigned int hdiv = plane ? info->hdiv : 1; ++ unsigned int bytes = DIV_ROUND_UP(width * info->bpp[plane], ++ v4l2_format_block_width(info, plane) * ++ v4l2_format_block_height(info, plane)); ++ ++ return DIV_ROUND_UP(bytes, hdiv); ++} ++ ++static inline unsigned int v4l2_format_plane_height(const struct v4l2_format_info *info, int plane, ++ unsigned int height) ++{ ++ unsigned int vdiv = plane ? info->vdiv : 1; ++ unsigned int lines = ALIGN(height, v4l2_format_block_height(info, plane)); ++ ++ return DIV_ROUND_UP(lines, vdiv); ++} ++ ++static inline unsigned int v4l2_format_plane_size(const struct v4l2_format_info *info, int plane, ++ unsigned int width, unsigned int height) ++{ ++ return v4l2_format_plane_width(info, plane, width) * ++ v4l2_format_plane_height(info, plane, height); ++} ++ + void v4l2_apply_frmsize_constraints(u32 *width, u32 *height, + const struct v4l2_frmsize_stepwise *frmsize) + { +@@ -368,37 +395,19 @@ int v4l2_fill_pixfmt_mp(struct v4l2_pix_format_mplane *pixfmt, + + if (info->mem_planes == 1) { + plane = &pixfmt->plane_fmt[0]; +- plane->bytesperline = ALIGN(width, v4l2_format_block_width(info, 0)) * info->bpp[0]; ++ plane->bytesperline = v4l2_format_plane_width(info, 0, width); + plane->sizeimage = 0; + +- for (i = 0; i < info->comp_planes; i++) { +- unsigned int hdiv = (i == 0) ? 1 : info->hdiv; +- unsigned int vdiv = (i == 0) ? 1 : info->vdiv; +- unsigned int aligned_width; +- unsigned int aligned_height; +- +- aligned_width = ALIGN(width, v4l2_format_block_width(info, i)); +- aligned_height = ALIGN(height, v4l2_format_block_height(info, i)); +- +- plane->sizeimage += info->bpp[i] * +- DIV_ROUND_UP(aligned_width, hdiv) * +- DIV_ROUND_UP(aligned_height, vdiv); +- } ++ for (i = 0; i < info->comp_planes; i++) ++ plane->sizeimage += ++ v4l2_format_plane_size(info, i, width, height); + } else { + for (i = 0; i < info->comp_planes; i++) { +- unsigned int hdiv = (i == 0) ? 1 : info->hdiv; +- unsigned int vdiv = (i == 0) ? 1 : info->vdiv; +- unsigned int aligned_width; +- unsigned int aligned_height; +- +- aligned_width = ALIGN(width, v4l2_format_block_width(info, i)); +- aligned_height = ALIGN(height, v4l2_format_block_height(info, i)); +- + plane = &pixfmt->plane_fmt[i]; + plane->bytesperline = +- info->bpp[i] * DIV_ROUND_UP(aligned_width, hdiv); +- plane->sizeimage = +- plane->bytesperline * DIV_ROUND_UP(aligned_height, vdiv); ++ v4l2_format_plane_width(info, i, width); ++ plane->sizeimage = plane->bytesperline * ++ v4l2_format_plane_height(info, i, height); + } + } + return 0; +@@ -422,22 +431,12 @@ int v4l2_fill_pixfmt(struct v4l2_pix_format *pixfmt, u32 pixelformat, + pixfmt->width = width; + pixfmt->height = height; + pixfmt->pixelformat = pixelformat; +- pixfmt->bytesperline = ALIGN(width, v4l2_format_block_width(info, 0)) * info->bpp[0]; ++ pixfmt->bytesperline = v4l2_format_plane_width(info, 0, width); + pixfmt->sizeimage = 0; + +- for (i = 0; i < info->comp_planes; i++) { +- unsigned int hdiv = (i == 0) ? 1 : info->hdiv; +- unsigned int vdiv = (i == 0) ? 1 : info->vdiv; +- unsigned int aligned_width; +- unsigned int aligned_height; +- +- aligned_width = ALIGN(width, v4l2_format_block_width(info, i)); +- aligned_height = ALIGN(height, v4l2_format_block_height(info, i)); +- +- pixfmt->sizeimage += info->bpp[i] * +- DIV_ROUND_UP(aligned_width, hdiv) * +- DIV_ROUND_UP(aligned_height, vdiv); +- } ++ for (i = 0; i < info->comp_planes; i++) ++ pixfmt->sizeimage += ++ v4l2_format_plane_size(info, i, width, height); + return 0; + } + EXPORT_SYMBOL_GPL(v4l2_fill_pixfmt); + +From 889f4693a0947c22188ca643ed9ba3579f0abc66 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 6 Jul 2020 21:54:36 +0000 +Subject: [PATCH] media: v4l2: Add NV15 and NV20 pixel formats + +Add NV15 and NV20 pixel formats used by the Rockchip Video Decoder for +10-bit buffers. + +NV15 and NV20 is a packed 10-bit 4:2:0/4:2:2 semi-planar Y/CbCr format +similar to P010 and P210 but has no padding between components. Instead, +luminance and chrominance samples are grouped into 4s so that each group is +packed into an integer number of bytes: + +YYYY = UVUV = 4 * 10 bits = 40 bits = 5 bytes + +The '15' and '20' suffix refers to the optimum effective bits per pixel +which is achieved when the total number of luminance samples is a multiple +of 8 for NV15 and 4 for NV20. + +Signed-off-by: Jonas Karlman +--- + .../userspace-api/media/v4l/pixfmt-nv15.rst | 101 ++++++++++++++++++ + .../userspace-api/media/v4l/pixfmt-nv20.rst | 99 +++++++++++++++++ + .../userspace-api/media/v4l/yuv-formats.rst | 2 + + drivers/media/v4l2-core/v4l2-common.c | 3 + + drivers/media/v4l2-core/v4l2-ioctl.c | 2 + + include/uapi/linux/videodev2.h | 3 + + 6 files changed, 210 insertions(+) + create mode 100644 Documentation/userspace-api/media/v4l/pixfmt-nv15.rst + create mode 100644 Documentation/userspace-api/media/v4l/pixfmt-nv20.rst + +diff --git a/Documentation/userspace-api/media/v4l/pixfmt-nv15.rst b/Documentation/userspace-api/media/v4l/pixfmt-nv15.rst +new file mode 100644 +index 000000000000..d059db58c6e0 +--- /dev/null ++++ b/Documentation/userspace-api/media/v4l/pixfmt-nv15.rst +@@ -0,0 +1,101 @@ ++.. Permission is granted to copy, distribute and/or modify this ++.. document under the terms of the GNU Free Documentation License, ++.. Version 1.1 or any later version published by the Free Software ++.. Foundation, with no Invariant Sections, no Front-Cover Texts ++.. and no Back-Cover Texts. A copy of the license is included at ++.. Documentation/userspace-api/media/fdl-appendix.rst. ++.. ++.. TODO: replace it to GFDL-1.1-or-later WITH no-invariant-sections ++ ++.. _V4L2-PIX-FMT-NV15: ++ ++************************** ++V4L2_PIX_FMT_NV15 ('NV15') ++************************** ++ ++Format with ½ horizontal and vertical chroma resolution, also known as ++YUV 4:2:0. One luminance and one chrominance plane with alternating ++chroma samples similar to ``V4L2_PIX_FMT_NV12`` but with 10-bit samples ++that are grouped into four and packed into five bytes. ++ ++The '15' suffix refers to the optimum effective bits per pixel which is ++achieved when the total number of luminance samples is a multiple of 8. ++ ++ ++Description ++=========== ++ ++This is a packed 10-bit two-plane version of the YUV 4:2:0 format. The ++three components are separated into two sub-images or planes. The Y plane ++is first. The Y plane has five bytes per each group of four pixels. A ++combined CbCr plane immediately follows the Y plane in memory. The CbCr ++plane is the same width, in bytes, as the Y plane (and of the image), but ++is half as tall in pixels. Each CbCr pair belongs to four pixels. For ++example, Cb\ :sub:`00`/Cr\ :sub:`00` belongs to Y'\ :sub:`00`, ++Y'\ :sub:`01`, Y'\ :sub:`10`, Y'\ :sub:`11`. ++ ++If the Y plane has pad bytes after each row, then the CbCr plane has as ++many pad bytes after its rows. ++ ++**Byte Order.** ++Little endian. Each cell is one byte. Pixels cross the byte boundary. ++ ++ ++.. flat-table:: ++ :header-rows: 0 ++ :stub-columns: 0 ++ ++ * - start + 0: ++ - Y'\ :sub:`00[7:0]` ++ - Y'\ :sub:`01[5:0]`\ Y'\ :sub:`00[9:8]` ++ - Y'\ :sub:`02[3:0]`\ Y'\ :sub:`01[9:6]` ++ - Y'\ :sub:`03[1:0]`\ Y'\ :sub:`02[9:4]` ++ - Y'\ :sub:`03[9:2]` ++ * - start + 5: ++ - Y'\ :sub:`10[7:0]` ++ - Y'\ :sub:`11[5:0]`\ Y'\ :sub:`10[9:8]` ++ - Y'\ :sub:`12[3:0]`\ Y'\ :sub:`11[9:6]` ++ - Y'\ :sub:`13[1:0]`\ Y'\ :sub:`12[9:4]` ++ - Y'\ :sub:`13[9:2]` ++ * - start + 10: ++ - Cb'\ :sub:`00[7:0]` ++ - Cr'\ :sub:`00[5:0]`\ Cb'\ :sub:`00[9:8]` ++ - Cb'\ :sub:`01[3:0]`\ Cr'\ :sub:`00[9:6]` ++ - Cr'\ :sub:`01[1:0]`\ Cb'\ :sub:`01[9:4]` ++ - Cr'\ :sub:`01[9:2]` ++ ++ ++**Color Sample Location:** ++ ++.. flat-table:: ++ :header-rows: 0 ++ :stub-columns: 0 ++ ++ * - ++ - 0 ++ - ++ - 1 ++ - 2 ++ - ++ - 3 ++ * - 0 ++ - Y ++ - ++ - Y ++ - Y ++ - ++ - Y ++ * - ++ - ++ - C ++ - ++ - ++ - C ++ - ++ * - 1 ++ - Y ++ - ++ - Y ++ - Y ++ - ++ - Y +diff --git a/Documentation/userspace-api/media/v4l/pixfmt-nv20.rst b/Documentation/userspace-api/media/v4l/pixfmt-nv20.rst +new file mode 100644 +index 000000000000..a8123be0baa3 +--- /dev/null ++++ b/Documentation/userspace-api/media/v4l/pixfmt-nv20.rst +@@ -0,0 +1,99 @@ ++.. Permission is granted to copy, distribute and/or modify this ++.. document under the terms of the GNU Free Documentation License, ++.. Version 1.1 or any later version published by the Free Software ++.. Foundation, with no Invariant Sections, no Front-Cover Texts ++.. and no Back-Cover Texts. A copy of the license is included at ++.. Documentation/userspace-api/media/fdl-appendix.rst. ++.. ++.. TODO: replace it to GFDL-1.1-or-later WITH no-invariant-sections ++ ++.. _V4L2-PIX-FMT-NV20: ++ ++************************** ++V4L2_PIX_FMT_NV20 ('NV20') ++************************** ++ ++Format with ½ horizontal chroma resolution, also known as YUV 4:2:2. ++One luminance and one chrominance plane with alternating chroma samples ++similar to ``V4L2_PIX_FMT_NV16`` but with 10-bit samples ++that are grouped into four and packed into five bytes. ++ ++The '20' suffix refers to the optimum effective bits per pixel which is ++achieved when the total number of luminance samples is a multiple of 4. ++ ++ ++Description ++=========== ++ ++This is a packed 10-bit two-plane version of the YUV 4:2:2 format. The ++three components are separated into two sub-images or planes. The Y plane ++is first. The Y plane has five bytes per each group of four pixels. A ++combined CbCr plane immediately follows the Y plane in memory. The CbCr ++plane is the same width and height, in bytes, as the Y plane (and of the ++image). Each CbCr pair belongs to two pixels. For example, ++Cb\ :sub:`00`/Cr\ :sub:`00` belongs to Y'\ :sub:`00`, Y'\ :sub:`01`. ++ ++If the Y plane has pad bytes after each row, then the CbCr plane has as ++many pad bytes after its rows. ++ ++**Byte Order.** ++Little endian. Each cell is one byte. Pixels cross the byte boundary. ++ ++ ++.. flat-table:: ++ :header-rows: 0 ++ :stub-columns: 0 ++ ++ * - start + 0: ++ - Y'\ :sub:`00[7:0]` ++ - Y'\ :sub:`01[5:0]`\ Y'\ :sub:`00[9:8]` ++ - Y'\ :sub:`02[3:0]`\ Y'\ :sub:`01[9:6]` ++ - Y'\ :sub:`03[1:0]`\ Y'\ :sub:`02[9:4]` ++ - Y'\ :sub:`03[9:2]` ++ * - start + 5: ++ - Y'\ :sub:`10[7:0]` ++ - Y'\ :sub:`11[5:0]`\ Y'\ :sub:`10[9:8]` ++ - Y'\ :sub:`12[3:0]`\ Y'\ :sub:`11[9:6]` ++ - Y'\ :sub:`13[1:0]`\ Y'\ :sub:`12[9:4]` ++ - Y'\ :sub:`13[9:2]` ++ * - start + 10: ++ - Cb'\ :sub:`00[7:0]` ++ - Cr'\ :sub:`00[5:0]`\ Cb'\ :sub:`00[9:8]` ++ - Cb'\ :sub:`01[3:0]`\ Cr'\ :sub:`00[9:6]` ++ - Cr'\ :sub:`01[1:0]`\ Cb'\ :sub:`01[9:4]` ++ - Cr'\ :sub:`01[9:2]` ++ * - start + 15: ++ - Cb'\ :sub:`10[7:0]` ++ - Cr'\ :sub:`10[5:0]`\ Cb'\ :sub:`10[9:8]` ++ - Cb'\ :sub:`11[3:0]`\ Cr'\ :sub:`10[9:6]` ++ - Cr'\ :sub:`11[1:0]`\ Cb'\ :sub:`11[9:4]` ++ - Cr'\ :sub:`11[9:2]` ++ ++ ++**Color Sample Location:** ++ ++.. flat-table:: ++ :header-rows: 0 ++ :stub-columns: 0 ++ ++ * - ++ - 0 ++ - ++ - 1 ++ - 2 ++ - ++ - 3 ++ * - 0 ++ - Y ++ - C ++ - Y ++ - Y ++ - C ++ - Y ++ * - 1 ++ - Y ++ - C ++ - Y ++ - Y ++ - C ++ - Y +diff --git a/Documentation/userspace-api/media/v4l/yuv-formats.rst b/Documentation/userspace-api/media/v4l/yuv-formats.rst +index 8ee92d0cd769..7cca883f178a 100644 +--- a/Documentation/userspace-api/media/v4l/yuv-formats.rst ++++ b/Documentation/userspace-api/media/v4l/yuv-formats.rst +@@ -61,4 +61,6 @@ to brightness information. + pixfmt-nv16 + pixfmt-nv16m + pixfmt-nv24 ++ pixfmt-nv15 ++ pixfmt-nv20 + pixfmt-m420 +diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c +index 4102c373b48a..0caac755d303 100644 +--- a/drivers/media/v4l2-core/v4l2-common.c ++++ b/drivers/media/v4l2-core/v4l2-common.c +@@ -267,6 +267,9 @@ const struct v4l2_format_info *v4l2_format_info(u32 format) + { .format = V4L2_PIX_FMT_NV24, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_NV42, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + ++ { .format = V4L2_PIX_FMT_NV15, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 5, 5, 0, 0 }, .hdiv = 2, .vdiv = 2, .block_w = { 4, 2, 0, 0 }, .block_h = { 1, 1, 0, 0 } }, ++ { .format = V4L2_PIX_FMT_NV20, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 5, 5, 0, 0 }, .hdiv = 2, .vdiv = 1, .block_w = { 4, 2, 0, 0 }, .block_h = { 1, 1, 0, 0 } }, ++ + { .format = V4L2_PIX_FMT_YUV410, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 4 }, + { .format = V4L2_PIX_FMT_YVU410, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 4 }, + { .format = V4L2_PIX_FMT_YUV411P, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 1 }, +diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c +index ccf947632a3b..53de49087938 100644 +--- a/drivers/media/v4l2-core/v4l2-ioctl.c ++++ b/drivers/media/v4l2-core/v4l2-ioctl.c +@@ -1321,6 +1321,8 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) + case V4L2_PIX_FMT_NV61: descr = "Y/CrCb 4:2:2"; break; + case V4L2_PIX_FMT_NV24: descr = "Y/CbCr 4:4:4"; break; + case V4L2_PIX_FMT_NV42: descr = "Y/CrCb 4:4:4"; break; ++ case V4L2_PIX_FMT_NV15: descr = "10-bit Y/CbCr 4:2:0 (Packed)"; break; ++ case V4L2_PIX_FMT_NV20: descr = "10-bit Y/CbCr 4:2:2 (Packed)"; break; + case V4L2_PIX_FMT_NV12M: descr = "Y/CbCr 4:2:0 (N-C)"; break; + case V4L2_PIX_FMT_NV21M: descr = "Y/CrCb 4:2:0 (N-C)"; break; + case V4L2_PIX_FMT_NV16M: descr = "Y/CbCr 4:2:2 (N-C)"; break; +diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h +index 6fe8822d2cb4..c8d7148cd9ae 100644 +--- a/include/uapi/linux/videodev2.h ++++ b/include/uapi/linux/videodev2.h +@@ -610,6 +610,9 @@ struct v4l2_pix_format { + #define V4L2_PIX_FMT_NV24 v4l2_fourcc('N', 'V', '2', '4') /* 24 Y/CbCr 4:4:4 */ + #define V4L2_PIX_FMT_NV42 v4l2_fourcc('N', 'V', '4', '2') /* 24 Y/CrCb 4:4:4 */ + ++#define V4L2_PIX_FMT_NV15 v4l2_fourcc('N', 'V', '1', '5') /* 15 Y/CbCr 4:2:0 10-bit packed */ ++#define V4L2_PIX_FMT_NV20 v4l2_fourcc('N', 'V', '2', '0') /* 20 Y/CbCr 4:2:2 10-bit packed */ ++ + /* two non contiguous planes - one Y, one Cr + Cb interleaved */ + #define V4L2_PIX_FMT_NV12M v4l2_fourcc('N', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 */ + #define V4L2_PIX_FMT_NV21M v4l2_fourcc('N', 'M', '2', '1') /* 21 Y/CrCb 4:2:0 */ + +From d09e5dfbcc096eddf5c5d11744d53bae5f1f7d00 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 6 Jul 2020 21:54:36 +0000 +Subject: [PATCH] media: rkvdec: h264: Use bytesperline and buffer height to + calculate stride + +Use bytesperline and buffer height to calculate the strides configured. + +This does not really change anything other than ensuring the bytesperline +that is signaled to userspace matches what is configured in HW. + +Signed-off-by: Jonas Karlman +--- + drivers/staging/media/rkvdec/rkvdec-h264.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c +index 2e7749bac417..d33fccc92205 100644 +--- a/drivers/staging/media/rkvdec/rkvdec-h264.c ++++ b/drivers/staging/media/rkvdec/rkvdec-h264.c +@@ -893,9 +893,9 @@ static void config_registers(struct rkvdec_ctx *ctx, + dma_addr_t rlc_addr; + dma_addr_t refer_addr; + u32 rlc_len; +- u32 hor_virstride = 0; +- u32 ver_virstride = 0; +- u32 y_virstride = 0; ++ u32 hor_virstride; ++ u32 ver_virstride; ++ u32 y_virstride; + u32 yuv_virstride = 0; + u32 offset; + dma_addr_t dst_addr; +@@ -906,8 +906,8 @@ static void config_registers(struct rkvdec_ctx *ctx, + + f = &ctx->decoded_fmt; + dst_fmt = &f->fmt.pix_mp; +- hor_virstride = (sps->bit_depth_luma_minus8 + 8) * dst_fmt->width / 8; +- ver_virstride = round_up(dst_fmt->height, 16); ++ hor_virstride = dst_fmt->plane_fmt[0].bytesperline; ++ ver_virstride = dst_fmt->height; + y_virstride = hor_virstride * ver_virstride; + + if (sps->chroma_format_idc == 0) + +From f0e873d66825fcd9ea314dcdab0d214226b2b8b4 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 6 Jul 2020 21:54:37 +0000 +Subject: [PATCH] media: rkvdec: Extract rkvdec_fill_decoded_pixfmt helper + method + +This extract setting decoded pixfmt into a helper method, current code is +replaced with a call to the new helper method. + +The helper method is also called from a new function in next patch. + +Signed-off-by: Jonas Karlman +--- + drivers/staging/media/rkvdec/rkvdec.c | 29 ++++++++++++++------------- + 1 file changed, 15 insertions(+), 14 deletions(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index 06fc58440cd3..dc16bf8d57a9 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -27,6 +27,17 @@ + #include "rkvdec.h" + #include "rkvdec-regs.h" + ++static void rkvdec_fill_decoded_pixfmt(struct rkvdec_ctx *ctx, ++ struct v4l2_pix_format_mplane *pix_mp) ++{ ++ v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat, ++ pix_mp->width, pix_mp->height); ++ pix_mp->plane_fmt[0].sizeimage += 128 * ++ DIV_ROUND_UP(pix_mp->width, 16) * ++ DIV_ROUND_UP(pix_mp->height, 16); ++ pix_mp->field = V4L2_FIELD_NONE; ++} ++ + static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl) + { + struct rkvdec_ctx *ctx = container_of(ctrl->handler, struct rkvdec_ctx, ctrl_hdl); +@@ -167,13 +178,9 @@ static void rkvdec_reset_decoded_fmt(struct rkvdec_ctx *ctx) + + rkvdec_reset_fmt(ctx, f, ctx->coded_fmt_desc->decoded_fmts[0]); + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; +- v4l2_fill_pixfmt_mp(&f->fmt.pix_mp, +- ctx->coded_fmt_desc->decoded_fmts[0], +- ctx->coded_fmt.fmt.pix_mp.width, +- ctx->coded_fmt.fmt.pix_mp.height); +- f->fmt.pix_mp.plane_fmt[0].sizeimage += 128 * +- DIV_ROUND_UP(f->fmt.pix_mp.width, 16) * +- DIV_ROUND_UP(f->fmt.pix_mp.height, 16); ++ f->fmt.pix_mp.width = ctx->coded_fmt.fmt.pix_mp.width; ++ f->fmt.pix_mp.height = ctx->coded_fmt.fmt.pix_mp.height; ++ rkvdec_fill_decoded_pixfmt(ctx, &f->fmt.pix_mp); + } + + static int rkvdec_enum_framesizes(struct file *file, void *priv, +@@ -239,13 +246,7 @@ static int rkvdec_try_capture_fmt(struct file *file, void *priv, + &pix_mp->height, + &coded_desc->frmsize); + +- v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat, +- pix_mp->width, pix_mp->height); +- pix_mp->plane_fmt[0].sizeimage += +- 128 * +- DIV_ROUND_UP(pix_mp->width, 16) * +- DIV_ROUND_UP(pix_mp->height, 16); +- pix_mp->field = V4L2_FIELD_NONE; ++ rkvdec_fill_decoded_pixfmt(ctx, pix_mp); + + return 0; + } + +From 7743a31004da67bfd0f6246deaa59e670230c84e Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 6 Jul 2020 21:54:37 +0000 +Subject: [PATCH] media: rkvdec: Lock capture pixel format in s_ctrl and s_fmt + +Add an optional valid_fmt operation that should return the valid +pixelformat of CAPTURE buffers. + +This is used in next patch to ensure correct pixelformat is used for 10-bit +and 4:2:2 content. + +Signed-off-by: Jonas Karlman +--- + drivers/staging/media/rkvdec/rkvdec.c | 59 ++++++++++++++++++++++++--- + drivers/staging/media/rkvdec/rkvdec.h | 2 + + 2 files changed, 55 insertions(+), 6 deletions(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index dc16bf8d57a9..6b2a2f4164b2 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -38,6 +38,16 @@ static void rkvdec_fill_decoded_pixfmt(struct rkvdec_ctx *ctx, + pix_mp->field = V4L2_FIELD_NONE; + } + ++static u32 rkvdec_valid_fmt(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl) ++{ ++ const struct rkvdec_coded_fmt_desc *coded_desc = ctx->coded_fmt_desc; ++ ++ if (coded_desc->ops->valid_fmt) ++ return coded_desc->ops->valid_fmt(ctx, ctrl); ++ ++ return ctx->valid_fmt; ++} ++ + static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl) + { + struct rkvdec_ctx *ctx = container_of(ctrl->handler, struct rkvdec_ctx, ctrl_hdl); +@@ -60,6 +70,10 @@ static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl) + /* Only 8-bit is supported */ + return -EINVAL; + ++ if (ctx->valid_fmt && ctx->valid_fmt != rkvdec_valid_fmt(ctx, ctrl)) ++ /* Only current valid format */ ++ return -EINVAL; ++ + width = (sps->pic_width_in_mbs_minus1 + 1) * 16; + height = (sps->pic_height_in_map_units_minus1 + 1) * 16; + +@@ -70,8 +84,27 @@ static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl) + return 0; + } + ++static int rkvdec_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct rkvdec_ctx *ctx = container_of(ctrl->handler, struct rkvdec_ctx, ctrl_hdl); ++ ++ if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_SPS && !ctx->valid_fmt) { ++ ctx->valid_fmt = rkvdec_valid_fmt(ctx, ctrl); ++ if (ctx->valid_fmt) { ++ struct v4l2_pix_format_mplane *pix_mp; ++ ++ pix_mp = &ctx->decoded_fmt.fmt.pix_mp; ++ pix_mp->pixelformat = ctx->valid_fmt; ++ rkvdec_fill_decoded_pixfmt(ctx, pix_mp); ++ } ++ } ++ ++ return 0; ++} ++ + static const struct v4l2_ctrl_ops rkvdec_ctrl_ops = { + .try_ctrl = rkvdec_try_ctrl, ++ .s_ctrl = rkvdec_s_ctrl, + }; + + static const struct rkvdec_ctrl_desc rkvdec_h264_ctrl_descs[] = { +@@ -176,6 +209,7 @@ static void rkvdec_reset_decoded_fmt(struct rkvdec_ctx *ctx) + { + struct v4l2_format *f = &ctx->decoded_fmt; + ++ ctx->valid_fmt = 0; + rkvdec_reset_fmt(ctx, f, ctx->coded_fmt_desc->decoded_fmts[0]); + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + f->fmt.pix_mp.width = ctx->coded_fmt.fmt.pix_mp.width; +@@ -231,13 +265,17 @@ static int rkvdec_try_capture_fmt(struct file *file, void *priv, + if (WARN_ON(!coded_desc)) + return -EINVAL; + +- for (i = 0; i < coded_desc->num_decoded_fmts; i++) { +- if (coded_desc->decoded_fmts[i] == pix_mp->pixelformat) +- break; +- } ++ if (ctx->valid_fmt) { ++ pix_mp->pixelformat = ctx->valid_fmt; ++ } else { ++ for (i = 0; i < coded_desc->num_decoded_fmts; i++) { ++ if (coded_desc->decoded_fmts[i] == pix_mp->pixelformat) ++ break; ++ } + +- if (i == coded_desc->num_decoded_fmts) +- pix_mp->pixelformat = coded_desc->decoded_fmts[0]; ++ if (i == coded_desc->num_decoded_fmts) ++ pix_mp->pixelformat = coded_desc->decoded_fmts[0]; ++ } + + /* Always apply the frmsize constraint of the coded end. */ + pix_mp->width = max(pix_mp->width, ctx->coded_fmt.fmt.pix_mp.width); +@@ -312,6 +350,7 @@ static int rkvdec_s_capture_fmt(struct file *file, void *priv, + return ret; + + ctx->decoded_fmt = *f; ++ ctx->valid_fmt = f->fmt.pix_mp.pixelformat; + return 0; + } + +@@ -401,6 +440,14 @@ static int rkvdec_enum_capture_fmt(struct file *file, void *priv, + if (WARN_ON(!ctx->coded_fmt_desc)) + return -EINVAL; + ++ if (ctx->valid_fmt) { ++ if (f->index) ++ return -EINVAL; ++ ++ f->pixelformat = ctx->valid_fmt; ++ return 0; ++ } ++ + if (f->index >= ctx->coded_fmt_desc->num_decoded_fmts) + return -EINVAL; + +diff --git a/drivers/staging/media/rkvdec/rkvdec.h b/drivers/staging/media/rkvdec/rkvdec.h +index 77a137cca88e..e95c52e3168a 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.h ++++ b/drivers/staging/media/rkvdec/rkvdec.h +@@ -63,6 +63,7 @@ vb2_to_rkvdec_decoded_buf(struct vb2_buffer *buf) + struct rkvdec_coded_fmt_ops { + int (*adjust_fmt)(struct rkvdec_ctx *ctx, + struct v4l2_format *f); ++ u32 (*valid_fmt)(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl); + int (*start)(struct rkvdec_ctx *ctx); + void (*stop)(struct rkvdec_ctx *ctx); + int (*run)(struct rkvdec_ctx *ctx); +@@ -96,6 +97,7 @@ struct rkvdec_ctx { + struct v4l2_fh fh; + struct v4l2_format coded_fmt; + struct v4l2_format decoded_fmt; ++ u32 valid_fmt; + const struct rkvdec_coded_fmt_desc *coded_fmt_desc; + struct v4l2_ctrl_handler ctrl_hdl; + struct rkvdec_dev *dev; + +From 15bb8d006a05aecc371e530769f06bf52c2c65bc Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 6 Jul 2020 21:54:37 +0000 +Subject: [PATCH] media: rkvdec: h264: Support High 10 and 4:2:2 profiles + +Add support and enable decoding of H264 High 10 and 4:2:2 profiles. + +Decoded CAPTURE buffer width is aligned to 64 pixels to accommodate HW +requirement on 10-bit format buffers. + +The new valid_fmt operation is implemented and return a valid pixelformat +for the provided SPS control. + +Signed-off-by: Jonas Karlman +--- + drivers/staging/media/rkvdec/rkvdec-h264.c | 20 ++++++++++++++++++++ + drivers/staging/media/rkvdec/rkvdec.c | 19 +++++++++---------- + 2 files changed, 29 insertions(+), 10 deletions(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c +index d33fccc92205..afc695d32186 100644 +--- a/drivers/staging/media/rkvdec/rkvdec-h264.c ++++ b/drivers/staging/media/rkvdec/rkvdec-h264.c +@@ -1021,6 +1021,25 @@ static int rkvdec_h264_adjust_fmt(struct rkvdec_ctx *ctx, + return 0; + } + ++static u32 rkvdec_h264_valid_fmt(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl) ++{ ++ const struct v4l2_ctrl_h264_sps *sps = ctrl->p_new.p_h264_sps; ++ ++ if (sps->bit_depth_luma_minus8 == 0) { ++ if (sps->chroma_format_idc == 2) ++ return V4L2_PIX_FMT_NV16; ++ else ++ return V4L2_PIX_FMT_NV12; ++ } else if (sps->bit_depth_luma_minus8 == 2) { ++ if (sps->chroma_format_idc == 2) ++ return V4L2_PIX_FMT_NV20; ++ else ++ return V4L2_PIX_FMT_NV15; ++ } ++ ++ return 0; ++} ++ + static int rkvdec_h264_start(struct rkvdec_ctx *ctx) + { + struct rkvdec_dev *rkvdec = ctx->dev; +@@ -1124,6 +1143,7 @@ static int rkvdec_h264_run(struct rkvdec_ctx *ctx) + + const struct rkvdec_coded_fmt_ops rkvdec_h264_fmt_ops = { + .adjust_fmt = rkvdec_h264_adjust_fmt, ++ .valid_fmt = rkvdec_h264_valid_fmt, + .start = rkvdec_h264_start, + .stop = rkvdec_h264_stop, + .run = rkvdec_h264_run, +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index 6b2a2f4164b2..bd8ec2915fe9 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -31,7 +31,7 @@ static void rkvdec_fill_decoded_pixfmt(struct rkvdec_ctx *ctx, + struct v4l2_pix_format_mplane *pix_mp) + { + v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat, +- pix_mp->width, pix_mp->height); ++ ALIGN(pix_mp->width, 64), pix_mp->height); + pix_mp->plane_fmt[0].sizeimage += 128 * + DIV_ROUND_UP(pix_mp->width, 16) * + DIV_ROUND_UP(pix_mp->height, 16); +@@ -55,19 +55,15 @@ static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl) + if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_SPS) { + const struct v4l2_ctrl_h264_sps *sps = ctrl->p_new.p_h264_sps; + unsigned int width, height; +- /* +- * TODO: The hardware supports 10-bit and 4:2:2 profiles, +- * but it's currently broken in the driver. +- * Reject them for now, until it's fixed. +- */ +- if (sps->chroma_format_idc > 1) +- /* Only 4:0:0 and 4:2:0 are supported */ ++ ++ if (sps->chroma_format_idc > 2) ++ /* Only 4:0:0, 4:2:0 and 4:2:2 are supported */ + return -EINVAL; + if (sps->bit_depth_luma_minus8 != sps->bit_depth_chroma_minus8) + /* Luma and chroma bit depth mismatch */ + return -EINVAL; +- if (sps->bit_depth_luma_minus8 != 0) +- /* Only 8-bit is supported */ ++ if (sps->bit_depth_luma_minus8 != 0 && sps->bit_depth_luma_minus8 != 2) ++ /* Only 8-bit and 10-bit is supported */ + return -EINVAL; + + if (ctx->valid_fmt && ctx->valid_fmt != rkvdec_valid_fmt(ctx, ctrl)) +@@ -145,6 +141,9 @@ static const struct rkvdec_ctrls rkvdec_h264_ctrls = { + + static const u32 rkvdec_h264_decoded_fmts[] = { + V4L2_PIX_FMT_NV12, ++ V4L2_PIX_FMT_NV15, ++ V4L2_PIX_FMT_NV16, ++ V4L2_PIX_FMT_NV20, + }; + + static const struct rkvdec_coded_fmt_desc rkvdec_coded_fmts[] = { + +From 26aca7fda4117f4bff16e3fb5349878fb322410b Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 6 Jul 2020 21:54:38 +0000 +Subject: [PATCH] media: rkvdec: h264: Support profile and level controls + +The Rockchip Video Decoder used in RK3399 supports H.264 profiles from +Baseline to High 4:2:2 up to Level 5.1, except for the Extended profile. + +Expose the V4L2_CID_MPEG_VIDEO_H264_PROFILE and the +V4L2_CID_MPEG_VIDEO_H264_LEVEL control, so that userspace can query the +driver for the list of supported profiles and level. + +Signed-off-by: Jonas Karlman +Reviewed-by: Ezequiel Garcia +--- + drivers/staging/media/rkvdec/rkvdec.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index bd8ec2915fe9..87987a782d75 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -132,6 +132,19 @@ static const struct rkvdec_ctrl_desc rkvdec_h264_ctrl_descs[] = { + .cfg.def = V4L2_MPEG_VIDEO_H264_START_CODE_ANNEX_B, + .cfg.max = V4L2_MPEG_VIDEO_H264_START_CODE_ANNEX_B, + }, ++ { ++ .cfg.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE, ++ .cfg.min = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE, ++ .cfg.max = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422, ++ .cfg.menu_skip_mask = ++ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED), ++ .cfg.def = V4L2_MPEG_VIDEO_H264_PROFILE_MAIN, ++ }, ++ { ++ .cfg.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL, ++ .cfg.min = V4L2_MPEG_VIDEO_H264_LEVEL_1_0, ++ .cfg.max = V4L2_MPEG_VIDEO_H264_LEVEL_5_1, ++ }, + }; + + static const struct rkvdec_ctrls rkvdec_h264_ctrls = { + +From 272e8a34d1803cc88e74de99b10330cd57d18f26 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Mon, 18 May 2020 14:40:09 -0300 +Subject: [PATCH] media: rkvdec: Fix .buf_prepare + +The driver should only set the payload on .buf_prepare +if the buffer is CAPTURE type, or if an OUTPUT buffer +has a zeroed payload. + +Fix it. + +Fixes: cd33c830448ba ("media: rkvdec: Add the rkvdec driver") +Signed-off-by: Ezequiel Garcia +--- + drivers/staging/media/rkvdec/rkvdec.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index 87987a782d75..91f8a1bb6176 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -543,7 +543,15 @@ static int rkvdec_buf_prepare(struct vb2_buffer *vb) + if (vb2_plane_size(vb, i) < sizeimage) + return -EINVAL; + } +- vb2_set_plane_payload(vb, 0, f->fmt.pix_mp.plane_fmt[0].sizeimage); ++ ++ /* ++ * Buffer's bytesused is written by the driver for CAPTURE buffers, ++ * or if the application passed zero bytesused on an OUTPUT buffer. ++ */ ++ if (!V4L2_TYPE_IS_OUTPUT(vq->type) || ++ (V4L2_TYPE_IS_OUTPUT(vq->type) && !vb2_get_plane_payload(vb, 0))) ++ vb2_set_plane_payload(vb, 0, ++ f->fmt.pix_mp.plane_fmt[0].sizeimage); + return 0; + } + + +From 6e771db436797df6146b1fe0ec94d4138bdaa2bc Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Mon, 18 May 2020 14:40:10 -0300 +Subject: [PATCH] media: uapi: Add VP9 stateless decoder controls + +Add the VP9 stateless decoder controls plus the documentation that goes +with it. + +Signed-off-by: Boris Brezillon +Signed-off-by: Ezequiel Garcia +--- + .../userspace-api/media/v4l/biblio.rst | 10 + + .../media/v4l/ext-ctrls-codec.rst | 550 ++++++++++++++++++ + drivers/media/v4l2-core/v4l2-ctrls.c | 239 ++++++++ + drivers/media/v4l2-core/v4l2-ioctl.c | 1 + + include/media/v4l2-ctrls.h | 1 + + include/media/vp9-ctrls.h | 485 +++++++++++++++ + 6 files changed, 1286 insertions(+) + create mode 100644 include/media/vp9-ctrls.h + +diff --git a/Documentation/userspace-api/media/v4l/biblio.rst b/Documentation/userspace-api/media/v4l/biblio.rst +index 3c9634173e82..e09102e572fd 100644 +--- a/Documentation/userspace-api/media/v4l/biblio.rst ++++ b/Documentation/userspace-api/media/v4l/biblio.rst +@@ -414,3 +414,13 @@ VP8 + :title: RFC 6386: "VP8 Data Format and Decoding Guide" + + :author: J. Bankoski et al. ++ ++.. _vp9: ++ ++VP9 ++=== ++ ++ ++:title: VP9 Bitstream & Decoding Process Specification ++ ++:author: Adrian Grange (Google), Peter de Rivaz (Argon Design), Jonathan Hunt (Argon Design) +diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +index 03ce87aa5488..ca13b141d8c2 100644 +--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst ++++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +@@ -2689,6 +2689,556 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - + - ``padding[3]`` + - Applications and drivers must set this to zero. + ++.. _v4l2-mpeg-vp9: ++ ++``V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(0..3) (struct)`` ++ Stores VP9 probabilities attached to a specific frame context. The VP9 ++ specification allows using a maximum of 4 contexts. Each frame being ++ decoded refers to one of those context. See section '7.1.2 Refresh ++ probs semantics' section of :ref:`vp9` for more details about these ++ contexts. ++ ++ This control is bi-directional: ++ ++ * all 4 contexts must be initialized by userspace just after the ++ stream is started and before the first decoding request is submitted. ++ * the referenced context might be read by the kernel when a decoding ++ request is submitted, and will be updated after the decoder is done ++ decoding the frame if the `V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX` flag ++ is set. ++ * contexts will be read back by user space before each decoding request ++ to retrieve the updated probabilities. ++ * userspace will re-initialize the context to their default values when ++ a reset context is required. ++ ++ .. note:: ++ ++ This compound control is not yet part of the public kernel API and ++ it is expected to change. ++ ++.. c:type:: v4l2_ctrl_vp9_frame_ctx ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{5.8cm}|p{4.8cm}|p{6.6cm}| ++ ++.. flat-table:: struct v4l2_ctrl_vp9_frame_ctx ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - struct :c:type:`v4l2_vp9_probabilities` ++ - ``probs`` ++ - Structure with VP9 probabilities attached to the context. ++ ++.. c:type:: v4l2_vp9_probabilities ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: struct v4l2_vp9_probabilities ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - __u8 ++ - ``tx8[2][1]`` ++ - TX 8x8 probabilities. ++ * - __u8 ++ - ``tx16[2][2]`` ++ - TX 16x16 probabilities. ++ * - __u8 ++ - ``tx32[2][3]`` ++ - TX 32x32 probabilities. ++ * - __u8 ++ - ``coef[4][2][2][6][6][3]`` ++ - Coefficient probabilities. ++ * - __u8 ++ - ``skip[3]`` ++ - Skip probabilities. ++ * - __u8 ++ - ``inter_mode[7][3]`` ++ - Inter prediction mode probabilities. ++ * - __u8 ++ - ``interp_filter[4][2]`` ++ - Interpolation filter probabilities. ++ * - __u8 ++ - ``is_inter[4]`` ++ - Is inter-block probabilities. ++ * - __u8 ++ - ``comp_mode[5]`` ++ - Compound prediction mode probabilities. ++ * - __u8 ++ - ``single_ref[5][2]`` ++ - Single reference probabilities. ++ * - __u8 ++ - ``comp_mode[5]`` ++ - Compound reference probabilities. ++ * - __u8 ++ - ``y_mode[4][9]`` ++ - Y prediction mode probabilities. ++ * - __u8 ++ - ``uv_mode[10][9]`` ++ - UV prediction mode probabilities. ++ * - __u8 ++ - ``partition[16][3]`` ++ - Partition probabilities. ++ * - __u8 ++ - ``mv.joint[3]`` ++ - Motion vector joint probabilities. ++ * - __u8 ++ - ``mv.sign[2]`` ++ - Motion vector sign probabilities. ++ * - __u8 ++ - ``mv.class[2][10]`` ++ - Motion vector class probabilities. ++ * - __u8 ++ - ``mv.class0_bit[2]`` ++ - Motion vector class0 bit probabilities. ++ * - __u8 ++ - ``mv.bits[2][10]`` ++ - Motion vector bits probabilities. ++ * - __u8 ++ - ``mv.class0_fr[2][2][3]`` ++ - Motion vector class0 fractional bit probabilities. ++ * - __u8 ++ - ``mv.fr[2][3]`` ++ - Motion vector fractional bit probabilities. ++ * - __u8 ++ - ``mv.class0_hp[2]`` ++ - Motion vector class0 high precision fractional bit probabilities. ++ * - __u8 ++ - ``mv.hp[2]`` ++ - Motion vector high precision fractional bit probabilities. ++ ++``V4L2_CID_MPEG_VIDEO_VP9_FRAME_DECODE_PARAMS (struct)`` ++ Specifies the frame parameters for the associated VP9 frame decode request. ++ This includes the necessary parameters for configuring a stateless hardware ++ decoding pipeline for VP9. The bitstream parameters are defined according ++ to :ref:`vp9`. ++ ++ .. note:: ++ ++ This compound control is not yet part of the public kernel API and ++ it is expected to change. ++ ++.. c:type:: v4l2_ctrl_vp9_frame_decode_params ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: struct v4l2_ctrl_vp9_frame_decode_params ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - __u32 ++ - ``flags`` ++ - Combination of V4L2_VP9_FRAME_FLAG_* flags. See ++ :c:type:`v4l2_vp9_frame_flags`. ++ * - __u16 ++ - ``compressed_header_size`` ++ - Compressed header size in bytes. ++ * - __u16 ++ - ``uncompressed_header_size`` ++ - Uncompressed header size in bytes. ++ * - __u8 ++ - ``profile`` ++ - VP9 profile. Can be 0, 1, 2 or 3. ++ * - __u8 ++ - ``reset_frame_context`` ++ - Frame context that should be used/updated when decoding the frame. ++ * - __u8 ++ - ``bit_depth`` ++ - Component depth in bits. Must be 8 for profile 0 and 1. Must 10 or 12 ++ for profile 2 and 3. ++ * - __u8 ++ - ``interpolation_filter`` ++ - Specifies the filter selection used for performing inter prediction. See ++ :c:type:`v4l2_vp9_interpolation_filter`. ++ * - __u8 ++ - ``tile_cols_log2`` ++ - Specifies the base 2 logarithm of the width of each tile (where the ++ width is measured in units of 8x8 blocks). Shall be less than or equal ++ to 6. ++ * - __u8 ++ - ``tile_rows_log2`` ++ - Specifies the base 2 logarithm of the height of each tile (where the ++ height is measured in units of 8x8 blocks) ++ * - __u8 ++ - ``tx_mode`` ++ - Specifies the TX mode. See :c:type:`v4l2_vp9_tx_mode`. ++ * - __u8 ++ - ``reference_mode`` ++ - Specifies the type of inter prediction to be used. See ++ :c:type:`v4l2_vp9_reference_mode`. ++ * - __u8 ++ - ``padding`` ++ - Needed to make this struct 64 bit aligned. Shall be filled with zeroes. ++ * - __u16 ++ - ``frame_width_minus_1`` ++ - Add 1 to get the frame width expressed in pixels. ++ * - __u16 ++ - ``frame_height_minus_1`` ++ - Add 1 to to get the frame height expressed in pixels. ++ * - __u16 ++ - ``frame_width_minus_1`` ++ - Add 1 to to get the expected render width expressed in pixels. This is ++ not used during the decoding process but might be used by HW scalers to ++ prepare a frame that's ready for scanout. ++ * - __u16 ++ - frame_height_minus_1 ++ - Add 1 to get the expected render height expressed in pixels. This is ++ not used during the decoding process but might be used by HW scalers to ++ prepare a frame that's ready for scanout. ++ * - __u64 ++ - ``refs[3]`` ++ - Array of reference frame timestamps. ++ * - struct :c:type:`v4l2_vp9_loop_filter` ++ - ``lf`` ++ - Loop filter parameters. See struct :c:type:`v4l2_vp9_loop_filter`. ++ * - struct :c:type:`v4l2_vp9_quantization` ++ - ``quant`` ++ - Quantization parameters. See :c:type:`v4l2_vp9_quantization`. ++ * - struct :c:type:`v4l2_vp9_segmentation` ++ - ``seg`` ++ - Segmentation parameters. See :c:type:`v4l2_vp9_segmentation`. ++ * - struct :c:type:`v4l2_vp9_probabilities` ++ - ``probs`` ++ - Probabilities. See :c:type:`v4l2_vp9_probabilities`. ++ ++.. c:type:: v4l2_vp9_frame_flags ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: enum v4l2_vp9_frame_flags ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 2 ++ ++ * - ``V4L2_VP9_FRAME_FLAG_KEY_FRAME`` ++ - The frame is a key frame. ++ * - ``V4L2_VP9_FRAME_FLAG_SHOW_FRAME`` ++ - The frame should be displayed. ++ * - ``V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT`` ++ - The decoding should be error resilient. ++ * - ``V4L2_VP9_FRAME_FLAG_INTRA_ONLY`` ++ - The frame does not reference other frames. ++ * - ``V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV`` ++ - the frame might can high precision motion vectors. ++ * - ``V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX`` ++ - Frame context should be updated after decoding. ++ * - ``V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE`` ++ - Parallel decoding is used. ++ * - ``V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING`` ++ - Vertical subsampling is enabled. ++ * - ``V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING`` ++ - Horizontal subsampling is enabled. ++ * - ``V4L2_VP9_FRAME_FLAG_COLOR_RANGE_FULL_SWING`` ++ - The full UV range is used. ++ ++.. c:type:: v4l2_vp9_ref_id ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: enum v4l2_vp9_ref_id ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 2 ++ ++ * - ``V4L2_REF_ID_LAST`` ++ - Last reference frame. ++ * - ``V4L2_REF_ID_GOLDEN`` ++ - Golden reference frame. ++ * - ``V4L2_REF_ID_ALTREF`` ++ - Alternative reference frame. ++ * - ``V4L2_REF_ID_CNT`` ++ - Number of reference frames. ++ ++.. c:type:: v4l2_vp9_tx_mode ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: enum v4l2_vp9_tx_mode ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 2 ++ ++ * - ``V4L2_VP9_TX_MODE_ONLY_4X4`` ++ - Transform size is 4x4. ++ * - ``V4L2_VP9_TX_MODE_ALLOW_8X8`` ++ - Transform size can be up to 8x8. ++ * - ``V4L2_VP9_TX_MODE_ALLOW_16X16`` ++ - Transform size can be up to 16x16. ++ * - ``V4L2_VP9_TX_MODE_ALLOW_32X32`` ++ - transform size can be up to 32x32. ++ * - ``V4L2_VP9_TX_MODE_SELECT`` ++ - Bitstream contains transform size for each block. ++ ++.. c:type:: v4l2_vp9_reference_mode ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: enum v4l2_vp9_reference_mode ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 2 ++ ++ * - ``V4L2_VP9_REF_MODE_SINGLE`` ++ - Indicates that all the inter blocks use only a single reference frame ++ to generate motion compensated prediction. ++ * - ``V4L2_VP9_REF_MODE_COMPOUND`` ++ - Requires all the inter blocks to use compound mode. Single reference ++ frame prediction is not allowed. ++ * - ``V4L2_VP9_REF_MODE_SELECT`` ++ - Allows each individual inter block to select between single and ++ compound prediction modes. ++ ++.. c:type:: v4l2_vp9_interpolation_filter ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: enum v4l2_vp9_interpolation_filter ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 2 ++ ++ * - ``V4L2_VP9_INTERP_FILTER_8TAP`` ++ - Height tap filter. ++ * - ``V4L2_VP9_INTERP_FILTER_8TAP_SMOOTH`` ++ - Height tap smooth filter. ++ * - ``V4L2_VP9_INTERP_FILTER_8TAP_SHARP`` ++ - Height tap sharp filter. ++ * - ``V4L2_VP9_INTERP_FILTER_BILINEAR`` ++ - Bilinear filter. ++ * - ``V4L2_VP9_INTERP_FILTER_SWITCHABLE`` ++ - Filter selection is signaled at the block level. ++ ++.. c:type:: v4l2_vp9_reset_frame_context ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: enum v4l2_vp9_reset_frame_context ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 2 ++ ++ * - ``V4L2_VP9_RESET_FRAME_CTX_NONE`` ++ - Do not reset any frame context. ++ * - ``V4L2_VP9_RESET_FRAME_CTX_SPEC`` ++ - Reset the frame context pointed by ++ :c:type:`v4l2_ctrl_vp9_frame_decode_params`.frame_context_idx. ++ * - ``V4L2_VP9_RESET_FRAME_CTX_ALL`` ++ - Reset all frame contexts. ++ ++.. c:type:: v4l2_vp9_intra_prediction_mode ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: enum v4l2_vp9_intra_prediction_mode ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 2 ++ ++ * - ``V4L2_VP9_INTRA_PRED_DC`` ++ - DC intra prediction. ++ * - ``V4L2_VP9_INTRA_PRED_MODE_V`` ++ - Vertical intra prediction. ++ * - ``V4L2_VP9_INTRA_PRED_MODE_H`` ++ - Horizontal intra prediction. ++ * - ``V4L2_VP9_INTRA_PRED_MODE_D45`` ++ - D45 intra prediction. ++ * - ``V4L2_VP9_INTRA_PRED_MODE_D135`` ++ - D135 intra prediction. ++ * - ``V4L2_VP9_INTRA_PRED_MODE_D117`` ++ - D117 intra prediction. ++ * - ``V4L2_VP9_INTRA_PRED_MODE_D153`` ++ - D153 intra prediction. ++ * - ``V4L2_VP9_INTRA_PRED_MODE_D207`` ++ - D207 intra prediction. ++ * - ``V4L2_VP9_INTRA_PRED_MODE_D63`` ++ - D63 intra prediction. ++ * - ``V4L2_VP9_INTRA_PRED_MODE_TM`` ++ - True motion intra prediction. ++ ++.. c:type:: v4l2_vp9_segmentation ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: struct v4l2_vp9_segmentation ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - __u8 ++ - ``flags`` ++ - Combination of V4L2_VP9_SEGMENTATION_FLAG_* flags. See ++ :c:type:`v4l2_vp9_segmentation_flags`. ++ * - __u8 ++ - ``tree_probs[7]`` ++ - Specifies the probability values to be used when decoding a Segment-ID. ++ See '5.15. Segmentation map' section of :ref:`vp9` for more details. ++ * - __u8 ++ - ``pred_prob[3]`` ++ - Specifies the probability values to be used when decoding a ++ Predicted-Segment-ID. See '6.4.14. Get segment id syntax' ++ section of :ref:`vp9` for more details. ++ * - __u8 ++ - ``padding[5]`` ++ - Used to align this struct on 64 bit. Shall be filled with zeroes. ++ * - __u8 ++ - ``feature_enabled[8]`` ++ - Bitmask defining which features are enabled in each segment. ++ * - __u8 ++ - ``feature_data[8][4]`` ++ - Data attached to each feature. Data entry is only valid if the feature ++ is enabled. ++ ++.. c:type:: v4l2_vp9_segment_feature ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: enum v4l2_vp9_segment_feature ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 2 ++ ++ * - ``V4L2_VP9_SEGMENT_FEATURE_QP_DELTA`` ++ - QP delta segment feature. ++ * - ``V4L2_VP9_SEGMENT_FEATURE_LF`` ++ - Loop filter segment feature. ++ * - ``V4L2_VP9_SEGMENT_FEATURE_REF_FRAME`` ++ - Reference frame segment feature. ++ * - ``V4L2_VP9_SEGMENT_FEATURE_SKIP`` ++ - Skip segment feature. ++ * - ``V4L2_VP9_SEGMENT_FEATURE_CNT`` ++ - Number of segment features. ++ ++.. c:type:: v4l2_vp9_segmentation_flags ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: enum v4l2_vp9_segmentation_flags ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 2 ++ ++ * - ``V4L2_VP9_SEGMENTATION_FLAG_ENABLED`` ++ - Indicates that this frame makes use of the segmentation tool. ++ * - ``V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP`` ++ - Indicates that the segmentation map should be updated during the ++ decoding of this frame. ++ * - ``V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE`` ++ - Indicates that the updates to the segmentation map are coded ++ relative to the existing segmentation map. ++ * - ``V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA`` ++ - Indicates that new parameters are about to be specified for each ++ segment. ++ * - ``V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE`` ++ - Indicates that the segmentation parameters represent the actual values ++ to be used. ++ ++.. c:type:: v4l2_vp9_quantization ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: struct v4l2_vp9_quantization ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - __u8 ++ - ``base_q_idx`` ++ - Indicates the base frame qindex. ++ * - __s8 ++ - ``delta_q_y_dc`` ++ - Indicates the Y DC quantizer relative to base_q_idx. ++ * - __s8 ++ - ``delta_q_uv_dc`` ++ - Indicates the UV DC quantizer relative to base_q_idx. ++ * - __s8 ++ - ``delta_q_uv_ac`` ++ - Indicates the UV AC quantizer relative to base_q_idx. ++ * - __u8 ++ - ``padding[4]`` ++ - Padding bytes used to align this struct on 64 bit. Must be set to 0. ++ ++.. c:type:: v4l2_vp9_loop_filter ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: struct v4l2_vp9_loop_filter ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - __u8 ++ - ``flags`` ++ - Combination of V4L2_VP9_LOOP_FILTER_FLAG_* flags. ++ See :c:type:`v4l2_vp9_loop_filter_flags`. ++ * - __u8 ++ - ``level`` ++ - Indicates the loop filter strength. ++ * - __u8 ++ - ``sharpness`` ++ - Indicates the sharpness level. ++ * - __s8 ++ - ``ref_deltas[4]`` ++ - Contains the adjustment needed for the filter level based on the chosen ++ reference frame. ++ * - __s8 ++ - ``mode_deltas[2]`` ++ - Contains the adjustment needed for the filter level based on the chosen ++ mode ++ * - __u8 ++ - ``level_lookup[8][4][2]`` ++ - Level lookup table. ++ ++ ++.. c:type:: v4l2_vp9_loop_filter_flags ++ ++.. cssclass:: longtable ++ ++.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| ++ ++.. flat-table:: enum v4l2_vp9_loop_filter_flags ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 2 ++ ++ * - ``V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED`` ++ - When set, the filter level depends on the mode and reference frame used ++ to predict a block. ++ * - ``V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE`` ++ - When set, the bitstream contains additional syntax elements that ++ specify which mode and reference frame deltas are to be updated. ++ + .. raw:: latex + + \normalsize +diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c +index b846f5b089c9..5913088cbc6f 100644 +--- a/drivers/media/v4l2-core/v4l2-ctrls.c ++++ b/drivers/media/v4l2-core/v4l2-ctrls.c +@@ -940,6 +940,11 @@ const char *v4l2_ctrl_get_name(u32 id) + case V4L2_CID_MPEG_VIDEO_VP8_PROFILE: return "VP8 Profile"; + case V4L2_CID_MPEG_VIDEO_VP9_PROFILE: return "VP9 Profile"; + case V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER: return "VP8 Frame Header"; ++ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_DECODE_PARAMS: return "VP9 Frame Decode Parameters"; ++ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(0): return "VP9 Frame Context 0"; ++ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(1): return "VP9 Frame Context 1"; ++ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(2): return "VP9 Frame Context 2"; ++ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(3): return "VP9 Frame Context 3"; + + /* HEVC controls */ + case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP: return "HEVC I-Frame QP Value"; +@@ -1419,6 +1424,15 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, + case V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER: + *type = V4L2_CTRL_TYPE_VP8_FRAME_HEADER; + break; ++ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_DECODE_PARAMS: ++ *type = V4L2_CTRL_TYPE_VP9_FRAME_DECODE_PARAMS; ++ break; ++ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(0): ++ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(1): ++ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(2): ++ case V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(3): ++ *type = V4L2_CTRL_TYPE_VP9_FRAME_CONTEXT; ++ break; + case V4L2_CID_MPEG_VIDEO_HEVC_SPS: + *type = V4L2_CTRL_TYPE_HEVC_SPS; + break; +@@ -1721,6 +1735,219 @@ static void std_log(const struct v4l2_ctrl *ctrl) + 0; \ + }) + ++static int ++validate_vp9_lf_params(struct v4l2_vp9_loop_filter *lf) ++{ ++ unsigned int i, j, k; ++ ++ if (lf->flags & ++ ~(V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED | ++ V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE)) ++ return -EINVAL; ++ ++ /* ++ * V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED implies ++ * V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE. ++ */ ++ if (lf->flags & V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE && ++ !(lf->flags & V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED)) ++ return -EINVAL; ++ ++ /* That all values are in the accepted range. */ ++ if (lf->level > GENMASK(5, 0)) ++ return -EINVAL; ++ ++ if (lf->sharpness > GENMASK(2, 0)) ++ return -EINVAL; ++ ++ for (i = 0; i < ARRAY_SIZE(lf->ref_deltas); i++) { ++ if (lf->ref_deltas[i] < -63 || lf->ref_deltas[i] > 63) ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(lf->mode_deltas); i++) { ++ if (lf->mode_deltas[i] < -63 || lf->mode_deltas[i] > 63) ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(lf->level_lookup); i++) { ++ for (j = 0; j < ARRAY_SIZE(lf->level_lookup[0]); j++) { ++ for (k = 0; k < ARRAY_SIZE(lf->level_lookup[0][0]); k++) { ++ if (lf->level_lookup[i][j][k] > 63) ++ return -EINVAL; ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++static int ++validate_vp9_quant_params(struct v4l2_vp9_quantization *quant) ++{ ++ if (quant->delta_q_y_dc < -15 || quant->delta_q_y_dc > 15 || ++ quant->delta_q_uv_dc < -15 || quant->delta_q_uv_dc > 15 || ++ quant->delta_q_uv_ac < -15 || quant->delta_q_uv_ac > 15) ++ return -EINVAL; ++ ++ memset(quant->padding, 0, sizeof(quant->padding)); ++ return 0; ++} ++ ++static int ++validate_vp9_seg_params(struct v4l2_vp9_segmentation *seg) ++{ ++ unsigned int i, j; ++ ++ if (seg->flags & ++ ~(V4L2_VP9_SEGMENTATION_FLAG_ENABLED | ++ V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP | ++ V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE | ++ V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA | ++ V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE)) ++ return -EINVAL; ++ ++ /* ++ * V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP and ++ * V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA imply ++ * V4L2_VP9_SEGMENTATION_FLAG_ENABLED. ++ */ ++ if ((seg->flags & ++ (V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP | ++ V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA)) && ++ !(seg->flags & V4L2_VP9_SEGMENTATION_FLAG_ENABLED)) ++ return -EINVAL; ++ ++ /* ++ * V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE implies ++ * V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP. ++ */ ++ if (seg->flags & V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE && ++ !(seg->flags & V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP)) ++ return -EINVAL; ++ ++ /* ++ * V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE implies ++ * V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA. ++ */ ++ if (seg->flags & V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE && ++ !(seg->flags & V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA)) ++ return -EINVAL; ++ ++ for (i = 0; i < ARRAY_SIZE(seg->feature_enabled); i++) { ++ if (seg->feature_enabled[i] & ++ ~(V4L2_VP9_SEGMENT_FEATURE_QP_DELTA | ++ V4L2_VP9_SEGMENT_FEATURE_LF | ++ V4L2_VP9_SEGMENT_FEATURE_REF_FRAME | ++ V4L2_VP9_SEGMENT_FEATURE_SKIP)) ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(seg->feature_data); i++) { ++ const int range[] = {255, 63, 3, 0}; ++ ++ for (j = 0; j < ARRAY_SIZE(seg->feature_data[j]); j++) { ++ if (seg->feature_data[i][j] < -range[j] || ++ seg->feature_data[i][j] > range[j]) ++ return -EINVAL; ++ } ++ } ++ ++ memset(seg->padding, 0, sizeof(seg->padding)); ++ return 0; ++} ++ ++static int ++validate_vp9_frame_decode_params(struct v4l2_ctrl_vp9_frame_decode_params *dec_params) ++{ ++ int ret; ++ ++ /* Make sure we're not passed invalid flags. */ ++ if (dec_params->flags & ++ ~(V4L2_VP9_FRAME_FLAG_KEY_FRAME | ++ V4L2_VP9_FRAME_FLAG_SHOW_FRAME | ++ V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT | ++ V4L2_VP9_FRAME_FLAG_INTRA_ONLY | ++ V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV | ++ V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX | ++ V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE | ++ V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING | ++ V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING | ++ V4L2_VP9_FRAME_FLAG_COLOR_RANGE_FULL_SWING)) ++ return -EINVAL; ++ ++ /* ++ * The refresh context and error resilient flags are mutually exclusive. ++ * Same goes for parallel decoding and error resilient modes. ++ */ ++ if (dec_params->flags & V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT && ++ dec_params->flags & ++ (V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX | ++ V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE)) ++ return -EINVAL; ++ ++ if (dec_params->profile > V4L2_VP9_PROFILE_MAX) ++ return -EINVAL; ++ ++ if (dec_params->reset_frame_context > V4L2_VP9_RESET_FRAME_CTX_ALL) ++ return -EINVAL; ++ ++ if (dec_params->frame_context_idx >= V4L2_VP9_NUM_FRAME_CTX) ++ return -EINVAL; ++ ++ /* ++ * Profiles 0 and 1 only support 8-bit depth, profiles 2 and 3 only 10 ++ * and 12 bit depths. ++ */ ++ if ((dec_params->profile < 2 && dec_params->bit_depth != 8) || ++ (dec_params->profile >= 2 && ++ (dec_params->bit_depth != 10 && dec_params->bit_depth != 12))) ++ return -EINVAL; ++ ++ /* Profile 0 and 2 only accept YUV 4:2:0. */ ++ if ((dec_params->profile == 0 || dec_params->profile == 2) && ++ (!(dec_params->flags & V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING) || ++ !(dec_params->flags & V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING))) ++ return -EINVAL; ++ ++ /* Profile 1 and 3 only accept YUV 4:2:2, 4:4:0 and 4:4:4. */ ++ if ((dec_params->profile == 1 || dec_params->profile == 3) && ++ ((dec_params->flags & V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING) && ++ (dec_params->flags & V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING))) ++ return -EINVAL; ++ ++ if (dec_params->interpolation_filter > V4L2_VP9_INTERP_FILTER_SWITCHABLE) ++ return -EINVAL; ++ ++ /* ++ * According to the spec, tile_cols_log2 shall be less than or equal ++ * to 6. ++ */ ++ if (dec_params->tile_cols_log2 > 6) ++ return -EINVAL; ++ ++ if (dec_params->tx_mode > V4L2_VP9_TX_MODE_SELECT) ++ return -EINVAL; ++ ++ if (dec_params->reference_mode > V4L2_VP9_REF_MODE_SELECT) ++ return -EINVAL; ++ ++ ret = validate_vp9_lf_params(&dec_params->lf); ++ if (ret) ++ return ret; ++ ++ ret = validate_vp9_quant_params(&dec_params->quant); ++ if (ret) ++ return ret; ++ ++ ret = validate_vp9_seg_params(&dec_params->seg); ++ if (ret) ++ return ret; ++ ++ memset(dec_params->padding, 0, sizeof(dec_params->padding)); ++ return 0; ++} ++ + /* Validate a new control */ + + #define zero_padding(s) \ +@@ -1838,6 +2065,12 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, + zero_padding(p_vp8_frame_header->coder_state); + break; + ++ case V4L2_CTRL_TYPE_VP9_FRAME_DECODE_PARAMS: ++ return validate_vp9_frame_decode_params(p); ++ ++ case V4L2_CTRL_TYPE_VP9_FRAME_CONTEXT: ++ break; ++ + case V4L2_CTRL_TYPE_HEVC_SPS: + p_hevc_sps = p; + +@@ -2584,6 +2817,12 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, + case V4L2_CTRL_TYPE_VP8_FRAME_HEADER: + elem_size = sizeof(struct v4l2_ctrl_vp8_frame_header); + break; ++ case V4L2_CTRL_TYPE_VP9_FRAME_CONTEXT: ++ elem_size = sizeof(struct v4l2_ctrl_vp9_frame_ctx); ++ break; ++ case V4L2_CTRL_TYPE_VP9_FRAME_DECODE_PARAMS: ++ elem_size = sizeof(struct v4l2_ctrl_vp9_frame_decode_params); ++ break; + case V4L2_CTRL_TYPE_HEVC_SPS: + elem_size = sizeof(struct v4l2_ctrl_hevc_sps); + break; +diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c +index 53de49087938..22eab942c8d4 100644 +--- a/drivers/media/v4l2-core/v4l2-ioctl.c ++++ b/drivers/media/v4l2-core/v4l2-ioctl.c +@@ -1431,6 +1431,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) + case V4L2_PIX_FMT_VP8: descr = "VP8"; break; + case V4L2_PIX_FMT_VP8_FRAME: descr = "VP8 Frame"; break; + case V4L2_PIX_FMT_VP9: descr = "VP9"; break; ++ case V4L2_PIX_FMT_VP9_FRAME: descr = "VP9 Frame"; break; + case V4L2_PIX_FMT_HEVC: descr = "HEVC"; break; /* aka H.265 */ + case V4L2_PIX_FMT_HEVC_SLICE: descr = "HEVC Parsed Slice Data"; break; + case V4L2_PIX_FMT_FWHT: descr = "FWHT"; break; /* used in vicodec */ +diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h +index cb25f345e9ad..c427acc964b9 100644 +--- a/include/media/v4l2-ctrls.h ++++ b/include/media/v4l2-ctrls.h +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + #include + + /* forward references */ +diff --git a/include/media/vp9-ctrls.h b/include/media/vp9-ctrls.h +new file mode 100644 +index 000000000000..0cdea8a18b72 +--- /dev/null ++++ b/include/media/vp9-ctrls.h +@@ -0,0 +1,485 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * These are the VP9 state controls for use with stateless VP9 ++ * codec drivers. ++ * ++ * It turns out that these structs are not stable yet and will undergo ++ * more changes. So keep them private until they are stable and ready to ++ * become part of the official public API. ++ */ ++ ++#ifndef _VP9_CTRLS_H_ ++#define _VP9_CTRLS_H_ ++ ++#include ++ ++#define V4L2_PIX_FMT_VP9_FRAME v4l2_fourcc('V', 'P', '9', 'F') ++ ++#define V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(i) (V4L2_CID_MPEG_BASE + 4000 + (i)) ++#define V4L2_CID_MPEG_VIDEO_VP9_FRAME_DECODE_PARAMS (V4L2_CID_MPEG_BASE + 4004) ++#define V4L2_CTRL_TYPE_VP9_FRAME_CONTEXT 0x400 ++#define V4L2_CTRL_TYPE_VP9_FRAME_DECODE_PARAMS 0x404 ++ ++/** ++ * enum v4l2_vp9_loop_filter_flags - VP9 loop filter flags ++ * ++ * @V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED: the filter level depends on ++ * the mode and reference frame used ++ * to predict a block ++ * @V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE: the bitstream contains additional ++ * syntax elements that specify which ++ * mode and reference frame deltas ++ * are to be updated ++ * ++ * Those are the flags you should pass to &v4l2_vp9_loop_filter.flags. See ++ * section '7.2.8 Loop filter semantics' of the VP9 specification for more ++ * details. ++ */ ++enum v4l2_vp9_loop_filter_flags { ++ V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED = 1 << 0, ++ V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE = 1 << 1, ++}; ++ ++/** ++ * struct v4l2_vp9_loop_filter - VP9 loop filter parameters ++ * ++ * @flags: combination of V4L2_VP9_LOOP_FILTER_FLAG_* flags ++ * @level: indicates the loop filter strength ++ * @sharpness: indicates the sharpness level ++ * @ref_deltas: contains the adjustment needed for the filter level based on ++ * the chosen reference frame ++ * @mode_deltas: contains the adjustment needed for the filter level based on ++ * the chosen mode ++ * @level_lookup: level lookup table ++ * ++ * This structure contains all loop filter related parameters. See sections ++ * '7.2.8 Loop filter semantics' and '8.8.1 Loop filter frame init process' ++ * of the VP9 specification for more details. ++ */ ++struct v4l2_vp9_loop_filter { ++ __u8 flags; ++ __u8 level; ++ __u8 sharpness; ++ __s8 ref_deltas[4]; ++ __s8 mode_deltas[2]; ++ __u8 level_lookup[8][4][2]; ++}; ++ ++/** ++ * struct v4l2_vp9_quantization - VP9 quantization parameters ++ * ++ * @base_q_idx: indicates the base frame qindex ++ * @delta_q_y_dc: indicates the Y DC quantizer relative to base_q_idx ++ * @delta_q_uv_dc: indicates the UV DC quantizer relative to base_q_idx ++ * @delta_q_uv_ac indicates the UV AC quantizer relative to base_q_idx ++ * @padding: padding bytes to align things on 64 bits. Must be set to 0 ++ * ++ * Encodes the quantization parameters. See section '7.2.9 Quantization params ++ * syntax' of the VP9 specification for more details. ++ */ ++struct v4l2_vp9_quantization { ++ __u8 base_q_idx; ++ __s8 delta_q_y_dc; ++ __s8 delta_q_uv_dc; ++ __s8 delta_q_uv_ac; ++ __u8 padding[4]; ++}; ++ ++/** ++ * enum v4l2_vp9_segmentation_flags - VP9 segmentation flags ++ * ++ * @V4L2_VP9_SEGMENTATION_FLAG_ENABLED: indicates that this frame makes use of ++ * the segmentation tool ++ * @V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP: indicates that the segmentation map ++ * should be updated during the ++ * decoding of this frame ++ * @V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE: indicates that the updates to ++ * the segmentation map are coded ++ * relative to the existing ++ * segmentation map ++ * @V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA: indicates that new parameters are ++ * about to be specified for each ++ * segment ++ * @V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE: indicates that the ++ * segmentation parameters ++ * represent the actual values ++ * to be used ++ * ++ * Those are the flags you should pass to &v4l2_vp9_segmentation.flags. See ++ * section '7.2.10 Segmentation params syntax' of the VP9 specification for ++ * more details. ++ */ ++enum v4l2_vp9_segmentation_flags { ++ V4L2_VP9_SEGMENTATION_FLAG_ENABLED = 1 << 0, ++ V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP = 1 << 1, ++ V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE = 1 << 2, ++ V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA = 1 << 3, ++ V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE = 1 << 4, ++}; ++ ++#define V4L2_VP9_SEGMENT_FEATURE_ENABLED(id) (1 << (id)) ++#define V4L2_VP9_SEGMENT_FEATURE_ENABLED_MASK 0xf ++ ++/** ++ * enum v4l2_vp9_segment_feature - VP9 segment feature IDs ++ * ++ * @V4L2_VP9_SEGMENT_FEATURE_QP_DELTA: QP delta segment feature ++ * @V4L2_VP9_SEGMENT_FEATURE_LF: loop filter segment feature ++ * @V4L2_VP9_SEGMENT_FEATURE_REF_FRAME: reference frame segment feature ++ * @V4L2_VP9_SEGMENT_FEATURE_SKIP: skip segment feature ++ * @V4L2_VP9_SEGMENT_FEATURE_CNT: number of segment features ++ * ++ * Segment feature IDs. See section '7.2.10 Segmentation params syntax' of the ++ * VP9 specification for more details. ++ */ ++enum v4l2_vp9_segment_feature { ++ V4L2_VP9_SEGMENT_FEATURE_QP_DELTA, ++ V4L2_VP9_SEGMENT_FEATURE_LF, ++ V4L2_VP9_SEGMENT_FEATURE_REF_FRAME, ++ V4L2_VP9_SEGMENT_FEATURE_SKIP, ++ V4L2_VP9_SEGMENT_FEATURE_CNT, ++}; ++ ++/** ++ * struct v4l2_vp9_segmentation - VP9 segmentation parameters ++ * ++ * @flags: combination of V4L2_VP9_SEGMENTATION_FLAG_* flags ++ * @tree_probs: specifies the probability values to be used when ++ * decoding a Segment-ID. See '5.15. Segmentation map' ++ * section of the VP9 specification for more details. ++ * @pred_prob: specifies the probability values to be used when decoding a ++ * Predicted-Segment-ID. See '6.4.14. Get segment id syntax' ++ * section of :ref:`vp9` for more details.. ++ * @padding: padding used to make things aligned on 64 bits. Shall be zero ++ * filled ++ * @feature_enabled: bitmask defining which features are enabled in each ++ * segment ++ * @feature_data: data attached to each feature. Data entry is only valid if ++ * the feature is enabled ++ * ++ * Encodes the quantization parameters. See section '7.2.10 Segmentation ++ * params syntax' of the VP9 specification for more details. ++ */ ++struct v4l2_vp9_segmentation { ++ __u8 flags; ++ __u8 tree_probs[7]; ++ __u8 pred_probs[3]; ++ __u8 padding[5]; ++ __u8 feature_enabled[8]; ++ __s16 feature_data[8][4]; ++}; ++ ++/** ++ * enum v4l2_vp9_intra_prediction_mode - VP9 Intra prediction modes ++ * ++ * @V4L2_VP9_INTRA_PRED_DC: DC intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_V: vertical intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_H: horizontal intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_D45: D45 intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_D135: D135 intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_D117: D117 intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_D153: D153 intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_D207: D207 intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_D63: D63 intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_TM: True Motion intra prediction ++ * ++ * See section '7.4.5 Intra frame mode info semantics' for more details. ++ */ ++enum v4l2_vp9_intra_prediction_mode { ++ V4L2_VP9_INTRA_PRED_MODE_DC, ++ V4L2_VP9_INTRA_PRED_MODE_V, ++ V4L2_VP9_INTRA_PRED_MODE_H, ++ V4L2_VP9_INTRA_PRED_MODE_D45, ++ V4L2_VP9_INTRA_PRED_MODE_D135, ++ V4L2_VP9_INTRA_PRED_MODE_D117, ++ V4L2_VP9_INTRA_PRED_MODE_D153, ++ V4L2_VP9_INTRA_PRED_MODE_D207, ++ V4L2_VP9_INTRA_PRED_MODE_D63, ++ V4L2_VP9_INTRA_PRED_MODE_TM, ++}; ++ ++/** ++ * struct v4l2_vp9_mv_probabilities - VP9 Motion vector probabilities ++ * @joint: motion vector joint probabilities ++ * @sign: motion vector sign probabilities ++ * @class: motion vector class probabilities ++ * @class0_bit: motion vector class0 bit probabilities ++ * @bits: motion vector bits probabilities ++ * @class0_fr: motion vector class0 fractional bit probabilities ++ * @fr: motion vector fractional bit probabilities ++ * @class0_hp: motion vector class0 high precision fractional bit probabilities ++ * @hp: motion vector high precision fractional bit probabilities ++ */ ++struct v4l2_vp9_mv_probabilities { ++ __u8 joint[3]; ++ __u8 sign[2]; ++ __u8 class[2][10]; ++ __u8 class0_bit[2]; ++ __u8 bits[2][10]; ++ __u8 class0_fr[2][2][3]; ++ __u8 fr[2][3]; ++ __u8 class0_hp[2]; ++ __u8 hp[2]; ++}; ++ ++/** ++ * struct v4l2_vp9_probabilities - VP9 Probabilities ++ * ++ * @tx8: TX 8x8 probabilities ++ * @tx16: TX 16x16 probabilities ++ * @tx32: TX 32x32 probabilities ++ * @coef: coefficient probabilities ++ * @skip: skip probabilities ++ * @inter_mode: inter mode probabilities ++ * @interp_filter: interpolation filter probabilities ++ * @is_inter: is inter-block probabilities ++ * @comp_mode: compound prediction mode probabilities ++ * @single_ref: single ref probabilities ++ * @comp_ref: compound ref probabilities ++ * @y_mode: Y prediction mode probabilities ++ * @uv_mode: UV prediction mode probabilities ++ * @partition: partition probabilities ++ * @mv: motion vector probabilities ++ * ++ * Structure containing most VP9 probabilities. See the VP9 specification ++ * for more details. ++ */ ++struct v4l2_vp9_probabilities { ++ __u8 tx8[2][1]; ++ __u8 tx16[2][2]; ++ __u8 tx32[2][3]; ++ __u8 coef[4][2][2][6][6][3]; ++ __u8 skip[3]; ++ __u8 inter_mode[7][3]; ++ __u8 interp_filter[4][2]; ++ __u8 is_inter[4]; ++ __u8 comp_mode[5]; ++ __u8 single_ref[5][2]; ++ __u8 comp_ref[5]; ++ __u8 y_mode[4][9]; ++ __u8 uv_mode[10][9]; ++ __u8 partition[16][3]; ++ ++ struct v4l2_vp9_mv_probabilities mv; ++}; ++ ++/** ++ * enum v4l2_vp9_reset_frame_context - Valid values for ++ * &v4l2_ctrl_vp9_frame_decode_params->reset_frame_context ++ * ++ * @V4L2_VP9_RESET_FRAME_CTX_NONE: don't reset any frame context ++ * @V4L2_VP9_RESET_FRAME_CTX_SPEC: reset the frame context pointed by ++ * &v4l2_ctrl_vp9_frame_decode_params.frame_context_idx ++ * @V4L2_VP9_RESET_FRAME_CTX_ALL: reset all frame contexts ++ * ++ * See section '7.2 Uncompressed header semantics' of the VP9 specification ++ * for more details. ++ */ ++enum v4l2_vp9_reset_frame_context { ++ V4L2_VP9_RESET_FRAME_CTX_NONE, ++ V4L2_VP9_RESET_FRAME_CTX_SPEC, ++ V4L2_VP9_RESET_FRAME_CTX_ALL, ++}; ++ ++/** ++ * enum v4l2_vp9_interpolation_filter - VP9 interpolation filter types ++ * ++ * @V4L2_VP9_INTERP_FILTER_8TAP: height tap filter ++ * @V4L2_VP9_INTERP_FILTER_8TAP_SMOOTH: height tap smooth filter ++ * @V4L2_VP9_INTERP_FILTER_8TAP_SHARP: height tap sharp filter ++ * @V4L2_VP9_INTERP_FILTER_BILINEAR: bilinear filter ++ * @V4L2_VP9_INTERP_FILTER_SWITCHABLE: filter selection is signaled at the ++ * block level ++ * ++ * See section '7.2.7 Interpolation filter semantics' of the VP9 specification ++ * for more details. ++ */ ++enum v4l2_vp9_interpolation_filter { ++ V4L2_VP9_INTERP_FILTER_8TAP, ++ V4L2_VP9_INTERP_FILTER_8TAP_SMOOTH, ++ V4L2_VP9_INTERP_FILTER_8TAP_SHARP, ++ V4L2_VP9_INTERP_FILTER_BILINEAR, ++ V4L2_VP9_INTERP_FILTER_SWITCHABLE, ++}; ++ ++/** ++ * enum v4l2_vp9_reference_mode - VP9 reference modes ++ * ++ * @V4L2_VP9_REF_MODE_SINGLE: indicates that all the inter blocks use only a ++ * single reference frame to generate motion ++ * compensated prediction ++ * @V4L2_VP9_REF_MODE_COMPOUND: requires all the inter blocks to use compound ++ * mode. Single reference frame prediction is not ++ * allowed ++ * @V4L2_VP9_REF_MODE_SELECT: allows each individual inter block to select ++ * between single and compound prediction modes ++ * ++ * See section '7.3.6 Frame reference mode semantics' of the VP9 specification ++ * for more details. ++ */ ++enum v4l2_vp9_reference_mode { ++ V4L2_VP9_REF_MODE_SINGLE, ++ V4L2_VP9_REF_MODE_COMPOUND, ++ V4L2_VP9_REF_MODE_SELECT, ++}; ++ ++/** ++ * enum v4l2_vp9_tx_mode - VP9 TX modes ++ * ++ * @V4L2_VP9_TX_MODE_ONLY_4X4: transform size is 4x4 ++ * @V4L2_VP9_TX_MODE_ALLOW_8X8: transform size can be up to 8x8 ++ * @V4L2_VP9_TX_MODE_ALLOW_16X16: transform size can be up to 16x16 ++ * @V4L2_VP9_TX_MODE_ALLOW_32X32: transform size can be up to 32x32 ++ * @V4L2_VP9_TX_MODE_SELECT: bitstream contains transform size for each block ++ * ++ * See section '7.3.1 Tx mode semantics' of the VP9 specification for more ++ * details. ++ */ ++enum v4l2_vp9_tx_mode { ++ V4L2_VP9_TX_MODE_ONLY_4X4, ++ V4L2_VP9_TX_MODE_ALLOW_8X8, ++ V4L2_VP9_TX_MODE_ALLOW_16X16, ++ V4L2_VP9_TX_MODE_ALLOW_32X32, ++ V4L2_VP9_TX_MODE_SELECT, ++}; ++ ++/** ++ * enum v4l2_vp9_ref_id - VP9 Reference frame IDs ++ * ++ * @V4L2_REF_ID_LAST: last reference frame ++ * @V4L2_REF_ID_GOLDEN: golden reference frame ++ * @V4L2_REF_ID_ALTREF: alternative reference frame ++ * @V4L2_REF_ID_CNT: number of reference frames ++ * ++ * See section '7.4.12 Ref frames semantics' of the VP9 specification for more ++ * details. ++ */ ++enum v4l2_vp9_ref_id { ++ V4L2_REF_ID_LAST, ++ V4L2_REF_ID_GOLDEN, ++ V4L2_REF_ID_ALTREF, ++ V4L2_REF_ID_CNT, ++}; ++ ++/** ++ * enum v4l2_vp9_frame_flags - VP9 frame flags ++ * @V4L2_VP9_FRAME_FLAG_KEY_FRAME: the frame is a key frame ++ * @V4L2_VP9_FRAME_FLAG_SHOW_FRAME: the frame should be displayed ++ * @V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT: the decoding should be error resilient ++ * @V4L2_VP9_FRAME_FLAG_INTRA_ONLY: the frame does not reference other frames ++ * @V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV: the frame might can high precision ++ * motion vectors ++ * @V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX: frame context should be updated ++ * after decoding ++ * @V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE: parallel decoding is used ++ * @V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING: vertical subsampling is enabled ++ * @V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING: horizontal subsampling is enabled ++ * @V4L2_VP9_FRAME_FLAG_COLOR_RANGE_FULL_SWING: full UV range is used ++ * ++ * Check the VP9 specification for more details. ++ */ ++enum v4l2_vp9_frame_flags { ++ V4L2_VP9_FRAME_FLAG_KEY_FRAME = 1 << 0, ++ V4L2_VP9_FRAME_FLAG_SHOW_FRAME = 1 << 1, ++ V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT = 1 << 2, ++ V4L2_VP9_FRAME_FLAG_INTRA_ONLY = 1 << 3, ++ V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV = 1 << 4, ++ V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX = 1 << 5, ++ V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE = 1 << 6, ++ V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING = 1 << 7, ++ V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING = 1 << 8, ++ V4L2_VP9_FRAME_FLAG_COLOR_RANGE_FULL_SWING = 1 << 9, ++}; ++ ++#define V4L2_VP9_PROFILE_MAX 3 ++ ++/** ++ * struct v4l2_ctrl_vp9_frame_decode_params - VP9 frame decoding control ++ * ++ * @flags: combination of V4L2_VP9_FRAME_FLAG_* flags ++ * @compressed_header_size: compressed header size in bytes ++ * @uncompressed_header_size: uncompressed header size in bytes ++ * @profile: VP9 profile. Can be 0, 1, 2 or 3 ++ * @reset_frame_context: specifies whether the frame context should be reset ++ * to default values. See &v4l2_vp9_reset_frame_context ++ * for more details ++ * @frame_context_idx: frame context that should be used/updated ++ * @bit_depth: bits per components. Can be 8, 10 or 12. Note that not all ++ * profiles support 10 and/or 12 bits depths ++ * @interpolation_filter: specifies the filter selection used for performing ++ * inter prediction. See &v4l2_vp9_interpolation_filter ++ * for more details ++ * @tile_cols_log2: specifies the base 2 logarithm of the width of each tile ++ * (where the width is measured in units of 8x8 blocks). ++ * Shall be less than or equal to 6 ++ * @tile_rows_log2: specifies the base 2 logarithm of the height of each tile ++ * (where the height is measured in units of 8x8 blocks) ++ * @tx_mode: specifies the TX mode. See &v4l2_vp9_tx_mode for more details ++ * @reference_mode: specifies the type of inter prediction to be used. See ++ * &v4l2_vp9_reference_mode for more details ++ * @padding: needed to make this struct 64 bit aligned. Shall be filled with ++ * zeros ++ * @frame_width_minus_1: add 1 to it and you'll get the frame width expressed ++ * in pixels ++ * @frame_height_minus_1: add 1 to it and you'll get the frame height expressed ++ * in pixels ++ * @frame_width_minus_1: add 1 to it and you'll get the expected render width ++ * expressed in pixels. This is not used during the ++ * decoding process but might be used by HW scalers to ++ * prepare a frame that's ready for scanout ++ * @frame_height_minus_1: add 1 to it and you'll get the expected render height ++ * expressed in pixels. This is not used during the ++ * decoding process but might be used by HW scalers to ++ * prepare a frame that's ready for scanout ++ * @refs: array of reference frames. See &v4l2_vp9_ref_id for more details ++ * @lf: loop filter parameters. See &v4l2_vp9_loop_filter for more details ++ * @quant: quantization parameters. See &v4l2_vp9_quantization for more details ++ * @seg: segmentation parameters. See &v4l2_vp9_segmentation for more details ++ * @probs: probabilities. See &v4l2_vp9_probabilities for more details ++ */ ++struct v4l2_ctrl_vp9_frame_decode_params { ++ __u32 flags; ++ __u16 compressed_header_size; ++ __u16 uncompressed_header_size; ++ __u8 profile; ++ __u8 reset_frame_context; ++ __u8 frame_context_idx; ++ __u8 bit_depth; ++ __u8 interpolation_filter; ++ __u8 tile_cols_log2; ++ __u8 tile_rows_log2; ++ __u8 tx_mode; ++ __u8 reference_mode; ++ __u8 padding[6]; ++ __u16 frame_width_minus_1; ++ __u16 frame_height_minus_1; ++ __u16 render_width_minus_1; ++ __u16 render_height_minus_1; ++ __u64 refs[V4L2_REF_ID_CNT]; ++ struct v4l2_vp9_loop_filter lf; ++ struct v4l2_vp9_quantization quant; ++ struct v4l2_vp9_segmentation seg; ++ struct v4l2_vp9_probabilities probs; ++}; ++ ++#define V4L2_VP9_NUM_FRAME_CTX 4 ++ ++/** ++ * struct v4l2_ctrl_vp9_frame_ctx - VP9 frame context control ++ * ++ * @probs: VP9 probabilities ++ * ++ * This control is accessed in both direction. The user should initialize the ++ * 4 contexts with default values just after starting the stream. Then before ++ * decoding a frame it should query the current frame context (the one passed ++ * through &v4l2_ctrl_vp9_frame_decode_params.frame_context_idx) to initialize ++ * &v4l2_ctrl_vp9_frame_decode_params.probs. The probs are then adjusted based ++ * on the bitstream info and passed to the kernel. The codec should update ++ * the frame context after the frame has been decoded, so that next time ++ * userspace query this context it contains the updated probabilities. ++ */ ++struct v4l2_ctrl_vp9_frame_ctx { ++ struct v4l2_vp9_probabilities probs; ++}; ++ ++#endif /* _VP9_CTRLS_H_ */ + +From 3e089d23e73a5eb2b070f875845ff423a492f3ba Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Mon, 18 May 2020 14:40:11 -0300 +Subject: [PATCH] media: rkvdec: Add the VP9 backend + +The Rockchip VDEC supports VP9 profile 0 up to 4096x2304@30fps. Add +a backend for this new format. + +Signed-off-by: Boris Brezillon +Signed-off-by: Ezequiel Garcia +--- + drivers/staging/media/rkvdec/Makefile | 2 +- + drivers/staging/media/rkvdec/rkvdec-vp9.c | 1577 +++++++++++++++++++++ + drivers/staging/media/rkvdec/rkvdec.c | 54 + + drivers/staging/media/rkvdec/rkvdec.h | 6 + + 4 files changed, 1638 insertions(+), 1 deletion(-) + create mode 100644 drivers/staging/media/rkvdec/rkvdec-vp9.c + +diff --git a/drivers/staging/media/rkvdec/Makefile b/drivers/staging/media/rkvdec/Makefile +index c08fed0a39f9..cb86b429cfaa 100644 +--- a/drivers/staging/media/rkvdec/Makefile ++++ b/drivers/staging/media/rkvdec/Makefile +@@ -1,3 +1,3 @@ + obj-$(CONFIG_VIDEO_ROCKCHIP_VDEC) += rockchip-vdec.o + +-rockchip-vdec-y += rkvdec.o rkvdec-h264.o ++rockchip-vdec-y += rkvdec.o rkvdec-h264.o rkvdec-vp9.o +diff --git a/drivers/staging/media/rkvdec/rkvdec-vp9.c b/drivers/staging/media/rkvdec/rkvdec-vp9.c +new file mode 100644 +index 000000000000..37d0ea4e3570 +--- /dev/null ++++ b/drivers/staging/media/rkvdec/rkvdec-vp9.c +@@ -0,0 +1,1577 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Rockchip Video Decoder VP9 backend ++ * ++ * Copyright (C) 2019 Collabora, Ltd. ++ * Boris Brezillon ++ * ++ * Copyright (C) 2016 Rockchip Electronics Co., Ltd. ++ * Alpha Lin ++ */ ++ ++#include ++#include ++#include ++ ++#include "rkvdec.h" ++#include "rkvdec-regs.h" ++ ++#define RKVDEC_VP9_PROBE_SIZE 4864 ++#define RKVDEC_VP9_COUNT_SIZE 13232 ++#define RKVDEC_VP9_MAX_SEGMAP_SIZE 73728 ++ ++struct rkvdec_vp9_intra_mode_probs { ++ u8 y_mode[105]; ++ u8 uv_mode[23]; ++}; ++ ++struct rkvdec_vp9_intra_only_frame_probs { ++ u8 coef_intra[4][2][128]; ++ struct rkvdec_vp9_intra_mode_probs intra_mode[10]; ++}; ++ ++struct rkvdec_vp9_inter_frame_probs { ++ u8 y_mode[4][9]; ++ u8 comp_mode[5]; ++ u8 comp_ref[5]; ++ u8 single_ref[5][2]; ++ u8 inter_mode[7][3]; ++ u8 interp_filter[4][2]; ++ u8 padding0[11]; ++ u8 coef[2][4][2][128]; ++ u8 uv_mode_0_2[3][9]; ++ u8 padding1[5]; ++ u8 uv_mode_3_5[3][9]; ++ u8 padding2[5]; ++ u8 uv_mode_6_8[3][9]; ++ u8 padding3[5]; ++ u8 uv_mode_9[9]; ++ u8 padding4[7]; ++ u8 padding5[16]; ++ struct { ++ u8 joint[3]; ++ u8 sign[2]; ++ u8 class[2][10]; ++ u8 class0_bit[2]; ++ u8 bits[2][10]; ++ u8 class0_fr[2][2][3]; ++ u8 fr[2][3]; ++ u8 class0_hp[2]; ++ u8 hp[2]; ++ } mv; ++}; ++ ++struct rkvdec_vp9_probs { ++ u8 partition[16][3]; ++ u8 pred[3]; ++ u8 tree[7]; ++ u8 skip[3]; ++ u8 tx32[2][3]; ++ u8 tx16[2][2]; ++ u8 tx8[2][1]; ++ u8 is_inter[4]; ++ /* 128 bit alignment */ ++ u8 padding0[3]; ++ union { ++ struct rkvdec_vp9_inter_frame_probs inter; ++ struct rkvdec_vp9_intra_only_frame_probs intra_only; ++ }; ++}; ++ ++/* Data structure describing auxiliary buffer format. */ ++struct rkvdec_vp9_priv_tbl { ++ struct rkvdec_vp9_probs probs; ++ u8 segmap[2][RKVDEC_VP9_MAX_SEGMAP_SIZE]; ++}; ++ ++struct rkvdec_vp9_refs_counts { ++ u32 eob[2]; ++ u32 coeff[3]; ++}; ++ ++struct rkvdec_vp9_inter_frame_symbol_counts { ++ u32 partition[16][4]; ++ u32 skip[3][2]; ++ u32 inter[4][2]; ++ u32 tx32p[2][4]; ++ u32 tx16p[2][4]; ++ u32 tx8p[2][2]; ++ u32 y_mode[4][10]; ++ u32 uv_mode[10][10]; ++ u32 comp[5][2]; ++ u32 comp_ref[5][2]; ++ u32 single_ref[5][2][2]; ++ u32 mv_mode[7][4]; ++ u32 filter[4][3]; ++ u32 mv_joint[4]; ++ u32 sign[2][2]; ++ /* add 1 element for align */ ++ u32 classes[2][11 + 1]; ++ u32 class0[2][2]; ++ u32 bits[2][10][2]; ++ u32 class0_fp[2][2][4]; ++ u32 fp[2][4]; ++ u32 class0_hp[2][2]; ++ u32 hp[2][2]; ++ struct rkvdec_vp9_refs_counts ref_cnt[2][4][2][6][6]; ++}; ++ ++struct rkvdec_vp9_intra_frame_symbol_counts { ++ u32 partition[4][4][4]; ++ u32 skip[3][2]; ++ u32 intra[4][2]; ++ u32 tx32p[2][4]; ++ u32 tx16p[2][4]; ++ u32 tx8p[2][2]; ++ struct rkvdec_vp9_refs_counts ref_cnt[2][4][2][6][6]; ++}; ++ ++struct rkvdec_vp9_run { ++ struct rkvdec_run base; ++ const struct v4l2_ctrl_vp9_frame_decode_params *decode_params; ++}; ++ ++struct rkvdec_vp9_frame_info { ++ u32 valid : 1; ++ u32 segmapid : 1; ++ u32 frame_context_idx : 2; ++ u32 reference_mode : 2; ++ u32 tx_mode : 3; ++ u32 interpolation_filter : 3; ++ u32 flags; ++ u64 timestamp; ++ struct v4l2_vp9_segmentation seg; ++ struct v4l2_vp9_loop_filter lf; ++}; ++ ++struct rkvdec_vp9_ctx { ++ struct rkvdec_aux_buf priv_tbl; ++ struct rkvdec_aux_buf count_tbl; ++ struct v4l2_ctrl_vp9_frame_ctx frame_context; ++ struct rkvdec_vp9_frame_info cur; ++ struct rkvdec_vp9_frame_info last; ++}; ++ ++static u32 rkvdec_fastdiv(u32 dividend, u16 divisor) ++{ ++#define DIV_INV(d) (u32)(((1ULL << 32) + ((d) - 1)) / (d)) ++#define DIVS_INV(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9) \ ++ DIV_INV(d0), DIV_INV(d1), DIV_INV(d2), DIV_INV(d3), \ ++ DIV_INV(d4), DIV_INV(d5), DIV_INV(d6), DIV_INV(d7), \ ++ DIV_INV(d8), DIV_INV(d9) ++ ++ static const u32 inv[] = { ++ DIV_INV(2), DIV_INV(3), DIV_INV(4), DIV_INV(5), ++ DIV_INV(6), DIV_INV(7), DIV_INV(8), DIV_INV(9), ++ DIVS_INV(10, 11, 12, 13, 14, 15, 16, 17, 18, 19), ++ DIVS_INV(20, 21, 22, 23, 24, 25, 26, 27, 28, 29), ++ DIVS_INV(30, 31, 32, 33, 34, 35, 36, 37, 38, 39), ++ DIVS_INV(40, 41, 42, 43, 44, 45, 46, 47, 48, 49), ++ DIVS_INV(50, 51, 52, 53, 54, 55, 56, 57, 58, 59), ++ DIVS_INV(60, 61, 62, 63, 64, 65, 66, 67, 68, 69), ++ DIVS_INV(70, 71, 72, 73, 74, 75, 76, 77, 78, 79), ++ DIVS_INV(80, 81, 82, 83, 84, 85, 86, 87, 88, 89), ++ DIVS_INV(90, 91, 92, 93, 94, 95, 96, 97, 98, 99), ++ DIVS_INV(100, 101, 102, 103, 104, 105, 106, 107, 108, 109), ++ DIVS_INV(110, 111, 112, 113, 114, 115, 116, 117, 118, 119), ++ DIVS_INV(120, 121, 122, 123, 124, 125, 126, 127, 128, 129), ++ DIVS_INV(130, 131, 132, 133, 134, 135, 136, 137, 138, 139), ++ DIVS_INV(140, 141, 142, 143, 144, 145, 146, 147, 148, 149), ++ DIVS_INV(150, 151, 152, 153, 154, 155, 156, 157, 158, 159), ++ DIVS_INV(160, 161, 162, 163, 164, 165, 166, 167, 168, 169), ++ DIVS_INV(170, 171, 172, 173, 174, 175, 176, 177, 178, 179), ++ DIVS_INV(180, 181, 182, 183, 184, 185, 186, 187, 188, 189), ++ DIVS_INV(190, 191, 192, 193, 194, 195, 196, 197, 198, 199), ++ DIVS_INV(200, 201, 202, 203, 204, 205, 206, 207, 208, 209), ++ DIVS_INV(210, 211, 212, 213, 214, 215, 216, 217, 218, 219), ++ DIVS_INV(220, 221, 222, 223, 224, 225, 226, 227, 228, 229), ++ DIVS_INV(230, 231, 232, 233, 234, 235, 236, 237, 238, 239), ++ DIVS_INV(240, 241, 242, 243, 244, 245, 246, 247, 248, 249), ++ DIV_INV(250), DIV_INV(251), DIV_INV(252), DIV_INV(253), ++ DIV_INV(254), DIV_INV(255), DIV_INV(256), ++ }; ++ ++ if (divisor == 0) ++ return 0; ++ else if (divisor == 1) ++ return dividend; ++ ++ if (WARN_ON(divisor - 2 >= ARRAY_SIZE(inv))) ++ return dividend; ++ ++ return ((u64)dividend * inv[divisor - 2]) >> 32; ++} ++ ++static const u8 vp9_kf_y_mode_prob[10][10][9] = { ++ { ++ /* above = dc */ ++ { 137, 30, 42, 148, 151, 207, 70, 52, 91 },/*left = dc */ ++ { 92, 45, 102, 136, 116, 180, 74, 90, 100 },/*left = v */ ++ { 73, 32, 19, 187, 222, 215, 46, 34, 100 },/*left = h */ ++ { 91, 30, 32, 116, 121, 186, 93, 86, 94 },/*left = d45 */ ++ { 72, 35, 36, 149, 68, 206, 68, 63, 105 },/*left = d135*/ ++ { 73, 31, 28, 138, 57, 124, 55, 122, 151 },/*left = d117*/ ++ { 67, 23, 21, 140, 126, 197, 40, 37, 171 },/*left = d153*/ ++ { 86, 27, 28, 128, 154, 212, 45, 43, 53 },/*left = d207*/ ++ { 74, 32, 27, 107, 86, 160, 63, 134, 102 },/*left = d63 */ ++ { 59, 67, 44, 140, 161, 202, 78, 67, 119 } /*left = tm */ ++ }, { /* above = v */ ++ { 63, 36, 126, 146, 123, 158, 60, 90, 96 },/*left = dc */ ++ { 43, 46, 168, 134, 107, 128, 69, 142, 92 },/*left = v */ ++ { 44, 29, 68, 159, 201, 177, 50, 57, 77 },/*left = h */ ++ { 58, 38, 76, 114, 97, 172, 78, 133, 92 },/*left = d45 */ ++ { 46, 41, 76, 140, 63, 184, 69, 112, 57 },/*left = d135*/ ++ { 38, 32, 85, 140, 46, 112, 54, 151, 133 },/*left = d117*/ ++ { 39, 27, 61, 131, 110, 175, 44, 75, 136 },/*left = d153*/ ++ { 52, 30, 74, 113, 130, 175, 51, 64, 58 },/*left = d207*/ ++ { 47, 35, 80, 100, 74, 143, 64, 163, 74 },/*left = d63 */ ++ { 36, 61, 116, 114, 128, 162, 80, 125, 82 } /*left = tm */ ++ }, { /* above = h */ ++ { 82, 26, 26, 171, 208, 204, 44, 32, 105 },/*left = dc */ ++ { 55, 44, 68, 166, 179, 192, 57, 57, 108 },/*left = v */ ++ { 42, 26, 11, 199, 241, 228, 23, 15, 85 },/*left = h */ ++ { 68, 42, 19, 131, 160, 199, 55, 52, 83 },/*left = d45 */ ++ { 58, 50, 25, 139, 115, 232, 39, 52, 118 },/*left = d135*/ ++ { 50, 35, 33, 153, 104, 162, 64, 59, 131 },/*left = d117*/ ++ { 44, 24, 16, 150, 177, 202, 33, 19, 156 },/*left = d153*/ ++ { 55, 27, 12, 153, 203, 218, 26, 27, 49 },/*left = d207*/ ++ { 53, 49, 21, 110, 116, 168, 59, 80, 76 },/*left = d63 */ ++ { 38, 72, 19, 168, 203, 212, 50, 50, 107 } /*left = tm */ ++ }, { /* above = d45 */ ++ { 103, 26, 36, 129, 132, 201, 83, 80, 93 },/*left = dc */ ++ { 59, 38, 83, 112, 103, 162, 98, 136, 90 },/*left = v */ ++ { 62, 30, 23, 158, 200, 207, 59, 57, 50 },/*left = h */ ++ { 67, 30, 29, 84, 86, 191, 102, 91, 59 },/*left = d45 */ ++ { 60, 32, 33, 112, 71, 220, 64, 89, 104 },/*left = d135*/ ++ { 53, 26, 34, 130, 56, 149, 84, 120, 103 },/*left = d117*/ ++ { 53, 21, 23, 133, 109, 210, 56, 77, 172 },/*left = d153*/ ++ { 77, 19, 29, 112, 142, 228, 55, 66, 36 },/*left = d207*/ ++ { 61, 29, 29, 93, 97, 165, 83, 175, 162 },/*left = d63 */ ++ { 47, 47, 43, 114, 137, 181, 100, 99, 95 } /*left = tm */ ++ }, { /* above = d135 */ ++ { 69, 23, 29, 128, 83, 199, 46, 44, 101 },/*left = dc */ ++ { 53, 40, 55, 139, 69, 183, 61, 80, 110 },/*left = v */ ++ { 40, 29, 19, 161, 180, 207, 43, 24, 91 },/*left = h */ ++ { 60, 34, 19, 105, 61, 198, 53, 64, 89 },/*left = d45 */ ++ { 52, 31, 22, 158, 40, 209, 58, 62, 89 },/*left = d135*/ ++ { 44, 31, 29, 147, 46, 158, 56, 102, 198 },/*left = d117*/ ++ { 35, 19, 12, 135, 87, 209, 41, 45, 167 },/*left = d153*/ ++ { 55, 25, 21, 118, 95, 215, 38, 39, 66 },/*left = d207*/ ++ { 51, 38, 25, 113, 58, 164, 70, 93, 97 },/*left = d63 */ ++ { 47, 54, 34, 146, 108, 203, 72, 103, 151 } /*left = tm */ ++ }, { /* above = d117 */ ++ { 64, 19, 37, 156, 66, 138, 49, 95, 133 },/*left = dc */ ++ { 46, 27, 80, 150, 55, 124, 55, 121, 135 },/*left = v */ ++ { 36, 23, 27, 165, 149, 166, 54, 64, 118 },/*left = h */ ++ { 53, 21, 36, 131, 63, 163, 60, 109, 81 },/*left = d45 */ ++ { 40, 26, 35, 154, 40, 185, 51, 97, 123 },/*left = d135*/ ++ { 35, 19, 34, 179, 19, 97, 48, 129, 124 },/*left = d117*/ ++ { 36, 20, 26, 136, 62, 164, 33, 77, 154 },/*left = d153*/ ++ { 45, 18, 32, 130, 90, 157, 40, 79, 91 },/*left = d207*/ ++ { 45, 26, 28, 129, 45, 129, 49, 147, 123 },/*left = d63 */ ++ { 38, 44, 51, 136, 74, 162, 57, 97, 121 } /*left = tm */ ++ }, { /* above = d153 */ ++ { 75, 17, 22, 136, 138, 185, 32, 34, 166 },/*left = dc */ ++ { 56, 39, 58, 133, 117, 173, 48, 53, 187 },/*left = v */ ++ { 35, 21, 12, 161, 212, 207, 20, 23, 145 },/*left = h */ ++ { 56, 29, 19, 117, 109, 181, 55, 68, 112 },/*left = d45 */ ++ { 47, 29, 17, 153, 64, 220, 59, 51, 114 },/*left = d135*/ ++ { 46, 16, 24, 136, 76, 147, 41, 64, 172 },/*left = d117*/ ++ { 34, 17, 11, 108, 152, 187, 13, 15, 209 },/*left = d153*/ ++ { 51, 24, 14, 115, 133, 209, 32, 26, 104 },/*left = d207*/ ++ { 55, 30, 18, 122, 79, 179, 44, 88, 116 },/*left = d63 */ ++ { 37, 49, 25, 129, 168, 164, 41, 54, 148 } /*left = tm */ ++ }, { /* above = d207 */ ++ { 82, 22, 32, 127, 143, 213, 39, 41, 70 },/*left = dc */ ++ { 62, 44, 61, 123, 105, 189, 48, 57, 64 },/*left = v */ ++ { 47, 25, 17, 175, 222, 220, 24, 30, 86 },/*left = h */ ++ { 68, 36, 17, 106, 102, 206, 59, 74, 74 },/*left = d45 */ ++ { 57, 39, 23, 151, 68, 216, 55, 63, 58 },/*left = d135*/ ++ { 49, 30, 35, 141, 70, 168, 82, 40, 115 },/*left = d117*/ ++ { 51, 25, 15, 136, 129, 202, 38, 35, 139 },/*left = d153*/ ++ { 68, 26, 16, 111, 141, 215, 29, 28, 28 },/*left = d207*/ ++ { 59, 39, 19, 114, 75, 180, 77, 104, 42 },/*left = d63 */ ++ { 40, 61, 26, 126, 152, 206, 61, 59, 93 } /*left = tm */ ++ }, { /* above = d63 */ ++ { 78, 23, 39, 111, 117, 170, 74, 124, 94 },/*left = dc */ ++ { 48, 34, 86, 101, 92, 146, 78, 179, 134 },/*left = v */ ++ { 47, 22, 24, 138, 187, 178, 68, 69, 59 },/*left = h */ ++ { 56, 25, 33, 105, 112, 187, 95, 177, 129 },/*left = d45 */ ++ { 48, 31, 27, 114, 63, 183, 82, 116, 56 },/*left = d135*/ ++ { 43, 28, 37, 121, 63, 123, 61, 192, 169 },/*left = d117*/ ++ { 42, 17, 24, 109, 97, 177, 56, 76, 122 },/*left = d153*/ ++ { 58, 18, 28, 105, 139, 182, 70, 92, 63 },/*left = d207*/ ++ { 46, 23, 32, 74, 86, 150, 67, 183, 88 },/*left = d63 */ ++ { 36, 38, 48, 92, 122, 165, 88, 137, 91 } /*left = tm */ ++ }, { /* above = tm */ ++ { 65, 70, 60, 155, 159, 199, 61, 60, 81 },/*left = dc */ ++ { 44, 78, 115, 132, 119, 173, 71, 112, 93 },/*left = v */ ++ { 39, 38, 21, 184, 227, 206, 42, 32, 64 },/*left = h */ ++ { 58, 47, 36, 124, 137, 193, 80, 82, 78 },/*left = d45 */ ++ { 49, 50, 35, 144, 95, 205, 63, 78, 59 },/*left = d135*/ ++ { 41, 53, 52, 148, 71, 142, 65, 128, 51 },/*left = d117*/ ++ { 40, 36, 28, 143, 143, 202, 40, 55, 137 },/*left = d153*/ ++ { 52, 34, 29, 129, 183, 227, 42, 35, 43 },/*left = d207*/ ++ { 42, 44, 44, 104, 105, 164, 64, 130, 80 },/*left = d63 */ ++ { 43, 81, 53, 140, 169, 204, 68, 84, 72 } /*left = tm */ ++ } ++}; ++ ++static const u8 kf_partition_probs[16][3] = { ++ /* 8x8 -> 4x4 */ ++ { 158, 97, 94 }, /* a/l both not split */ ++ { 93, 24, 99 }, /* a split, l not split */ ++ { 85, 119, 44 }, /* l split, a not split */ ++ { 62, 59, 67 }, /* a/l both split */ ++ /* 16x16 -> 8x8 */ ++ { 149, 53, 53 }, /* a/l both not split */ ++ { 94, 20, 48 }, /* a split, l not split */ ++ { 83, 53, 24 }, /* l split, a not split */ ++ { 52, 18, 18 }, /* a/l both split */ ++ /* 32x32 -> 16x16 */ ++ { 150, 40, 39 }, /* a/l both not split */ ++ { 78, 12, 26 }, /* a split, l not split */ ++ { 67, 33, 11 }, /* l split, a not split */ ++ { 24, 7, 5 }, /* a/l both split */ ++ /* 64x64 -> 32x32 */ ++ { 174, 35, 49 }, /* a/l both not split */ ++ { 68, 11, 27 }, /* a split, l not split */ ++ { 57, 15, 9 }, /* l split, a not split */ ++ { 12, 3, 3 }, /* a/l both split */ ++}; ++ ++static const u8 kf_uv_mode_prob[10][9] = { ++ { 144, 11, 54, 157, 195, 130, 46, 58, 108 }, /* y = dc */ ++ { 118, 15, 123, 148, 131, 101, 44, 93, 131 }, /* y = v */ ++ { 113, 12, 23, 188, 226, 142, 26, 32, 125 }, /* y = h */ ++ { 120, 11, 50, 123, 163, 135, 64, 77, 103 }, /* y = d45 */ ++ { 113, 9, 36, 155, 111, 157, 32, 44, 161 }, /* y = d135 */ ++ { 116, 9, 55, 176, 76, 96, 37, 61, 149 }, /* y = d117 */ ++ { 115, 9, 28, 141, 161, 167, 21, 25, 193 }, /* y = d153 */ ++ { 120, 12, 32, 145, 195, 142, 32, 38, 86 }, /* y = d207 */ ++ { 116, 12, 64, 120, 140, 125, 49, 115, 121 }, /* y = d63 */ ++ { 102, 19, 66, 162, 182, 122, 35, 59, 128 } /* y = tm */ ++}; ++ ++static void write_coeff_plane(const u8 coef[6][6][3], u8 *coeff_plane) ++{ ++ unsigned int idx = 0; ++ u8 byte_count = 0, p; ++ s32 k, m, n; ++ ++ for (k = 0; k < 6; k++) { ++ for (m = 0; m < 6; m++) { ++ for (n = 0; n < 3; n++) { ++ p = coef[k][m][n]; ++ coeff_plane[idx++] = p; ++ byte_count++; ++ if (byte_count == 27) { ++ idx += 5; ++ byte_count = 0; ++ } ++ } ++ } ++ } ++} ++ ++static void init_intra_only_probs(struct rkvdec_ctx *ctx, ++ const struct rkvdec_vp9_run *run) ++{ ++ const struct v4l2_ctrl_vp9_frame_decode_params *dec_params; ++ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; ++ struct rkvdec_vp9_priv_tbl *tbl = vp9_ctx->priv_tbl.cpu; ++ struct rkvdec_vp9_intra_only_frame_probs *rkprobs; ++ const struct v4l2_vp9_probabilities *probs; ++ unsigned int i, j, k, m; ++ ++ rkprobs = &tbl->probs.intra_only; ++ dec_params = run->decode_params; ++ probs = &dec_params->probs; ++ ++ /* ++ * intra only 149 x 128 bits ,aligned to 152 x 128 bits coeff related ++ * prob 64 x 128 bits ++ */ ++ for (i = 0; i < ARRAY_SIZE(probs->coef); i++) { ++ for (j = 0; j < ARRAY_SIZE(probs->coef[0]); j++) ++ write_coeff_plane(probs->coef[i][j][0], ++ rkprobs->coef_intra[i][j]); ++ } ++ ++ /* intra mode prob 80 x 128 bits */ ++ for (i = 0; i < ARRAY_SIZE(vp9_kf_y_mode_prob); i++) { ++ u32 byte_count = 0; ++ int idx = 0; ++ ++ /* vp9_kf_y_mode_prob */ ++ for (j = 0; j < ARRAY_SIZE(vp9_kf_y_mode_prob[0]); j++) { ++ for (k = 0; k < ARRAY_SIZE(vp9_kf_y_mode_prob[0][0]); ++ k++) { ++ u8 val = vp9_kf_y_mode_prob[i][j][k]; ++ ++ rkprobs->intra_mode[i].y_mode[idx++] = val; ++ byte_count++; ++ if (byte_count == 27) { ++ byte_count = 0; ++ idx += 5; ++ } ++ } ++ } ++ ++ idx = 0; ++ if (i < 4) { ++ for (m = 0; m < (i < 3 ? 23 : 21); m++) { ++ const u8 *ptr = (const u8 *)kf_uv_mode_prob; ++ ++ rkprobs->intra_mode[i].uv_mode[idx++] = ptr[i * 23 + m]; ++ } ++ } ++ } ++} ++ ++static void init_inter_probs(struct rkvdec_ctx *ctx, ++ const struct rkvdec_vp9_run *run) ++{ ++ const struct v4l2_ctrl_vp9_frame_decode_params *dec_params; ++ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; ++ struct rkvdec_vp9_priv_tbl *tbl = vp9_ctx->priv_tbl.cpu; ++ struct rkvdec_vp9_inter_frame_probs *rkprobs; ++ const struct v4l2_vp9_probabilities *probs; ++ unsigned int i, j, k; ++ ++ rkprobs = &tbl->probs.inter; ++ dec_params = run->decode_params; ++ probs = &dec_params->probs; ++ ++ /* ++ * inter probs ++ * 151 x 128 bits, aligned to 152 x 128 bits ++ * inter only ++ * intra_y_mode & inter_block info 6 x 128 bits ++ */ ++ ++ memcpy(rkprobs->y_mode, probs->y_mode, sizeof(rkprobs->y_mode)); ++ memcpy(rkprobs->comp_mode, probs->comp_mode, ++ sizeof(rkprobs->comp_mode)); ++ memcpy(rkprobs->comp_ref, probs->comp_ref, ++ sizeof(rkprobs->comp_ref)); ++ memcpy(rkprobs->single_ref, probs->single_ref, ++ sizeof(rkprobs->single_ref)); ++ memcpy(rkprobs->inter_mode, probs->inter_mode, ++ sizeof(rkprobs->inter_mode)); ++ memcpy(rkprobs->interp_filter, probs->interp_filter, ++ sizeof(rkprobs->interp_filter)); ++ ++ /* 128 x 128 bits coeff related */ ++ for (i = 0; i < ARRAY_SIZE(probs->coef); i++) { ++ for (j = 0; j < ARRAY_SIZE(probs->coef[0]); j++) { ++ for (k = 0; k < ARRAY_SIZE(probs->coef[0][0]); k++) ++ write_coeff_plane(probs->coef[i][j][k], ++ rkprobs->coef[k][i][j]); ++ } ++ } ++ ++ /* intra uv mode 6 x 128 */ ++ memcpy(rkprobs->uv_mode_0_2, &probs->uv_mode[0], ++ sizeof(rkprobs->uv_mode_0_2)); ++ memcpy(rkprobs->uv_mode_3_5, &probs->uv_mode[3], ++ sizeof(rkprobs->uv_mode_3_5)); ++ memcpy(rkprobs->uv_mode_6_8, &probs->uv_mode[6], ++ sizeof(rkprobs->uv_mode_6_8)); ++ memcpy(rkprobs->uv_mode_9, &probs->uv_mode[9], ++ sizeof(rkprobs->uv_mode_9)); ++ ++ /* mv related 6 x 128 */ ++ memcpy(rkprobs->mv.joint, probs->mv.joint, ++ sizeof(rkprobs->mv.joint)); ++ memcpy(rkprobs->mv.sign, probs->mv.sign, ++ sizeof(rkprobs->mv.sign)); ++ memcpy(rkprobs->mv.class, probs->mv.class, ++ sizeof(rkprobs->mv.class)); ++ memcpy(rkprobs->mv.class0_bit, probs->mv.class0_bit, ++ sizeof(rkprobs->mv.class0_bit)); ++ memcpy(rkprobs->mv.bits, probs->mv.bits, ++ sizeof(rkprobs->mv.bits)); ++ memcpy(rkprobs->mv.class0_fr, probs->mv.class0_fr, ++ sizeof(rkprobs->mv.class0_fr)); ++ memcpy(rkprobs->mv.fr, probs->mv.fr, ++ sizeof(rkprobs->mv.fr)); ++ memcpy(rkprobs->mv.class0_hp, probs->mv.class0_hp, ++ sizeof(rkprobs->mv.class0_hp)); ++ memcpy(rkprobs->mv.hp, probs->mv.hp, ++ sizeof(rkprobs->mv.hp)); ++} ++ ++static void init_probs(struct rkvdec_ctx *ctx, ++ const struct rkvdec_vp9_run *run) ++{ ++ const struct v4l2_ctrl_vp9_frame_decode_params *dec_params; ++ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; ++ struct rkvdec_vp9_priv_tbl *tbl = vp9_ctx->priv_tbl.cpu; ++ struct rkvdec_vp9_probs *rkprobs = &tbl->probs; ++ const struct v4l2_vp9_segmentation *seg; ++ const struct v4l2_vp9_probabilities *probs; ++ bool intra_only; ++ ++ dec_params = run->decode_params; ++ probs = &dec_params->probs; ++ seg = &dec_params->seg; ++ ++ memset(rkprobs, 0, sizeof(*rkprobs)); ++ ++ intra_only = !!(dec_params->flags & ++ (V4L2_VP9_FRAME_FLAG_KEY_FRAME | ++ V4L2_VP9_FRAME_FLAG_INTRA_ONLY)); ++ ++ /* sb info 5 x 128 bit */ ++ memcpy(rkprobs->partition, ++ intra_only ? kf_partition_probs : probs->partition, ++ sizeof(rkprobs->partition)); ++ ++ memcpy(rkprobs->pred, seg->pred_probs, sizeof(rkprobs->pred)); ++ memcpy(rkprobs->tree, seg->tree_probs, sizeof(rkprobs->tree)); ++ memcpy(rkprobs->skip, probs->skip, sizeof(rkprobs->skip)); ++ memcpy(rkprobs->tx32, probs->tx32, sizeof(rkprobs->tx32)); ++ memcpy(rkprobs->tx16, probs->tx16, sizeof(rkprobs->tx16)); ++ memcpy(rkprobs->tx8, probs->tx8, sizeof(rkprobs->tx8)); ++ memcpy(rkprobs->is_inter, probs->is_inter, sizeof(rkprobs->is_inter)); ++ ++ if (intra_only) ++ init_intra_only_probs(ctx, run); ++ else ++ init_inter_probs(ctx, run); ++} ++ ++struct vp9d_ref_config { ++ u32 reg_frm_size; ++ u32 reg_hor_stride; ++ u32 reg_y_stride; ++ u32 reg_yuv_stride; ++ u32 reg_ref_base; ++}; ++ ++static struct vp9d_ref_config ref_config[3] = { ++ { ++ .reg_frm_size = RKVDEC_REG_VP9_FRAME_SIZE(0), ++ .reg_hor_stride = RKVDEC_VP9_HOR_VIRSTRIDE(0), ++ .reg_y_stride = RKVDEC_VP9_LAST_FRAME_YSTRIDE, ++ .reg_yuv_stride = RKVDEC_VP9_LAST_FRAME_YUVSTRIDE, ++ .reg_ref_base = RKVDEC_REG_VP9_LAST_FRAME_BASE, ++ }, ++ { ++ .reg_frm_size = RKVDEC_REG_VP9_FRAME_SIZE(1), ++ .reg_hor_stride = RKVDEC_VP9_HOR_VIRSTRIDE(1), ++ .reg_y_stride = RKVDEC_VP9_GOLDEN_FRAME_YSTRIDE, ++ .reg_yuv_stride = 0, ++ .reg_ref_base = RKVDEC_REG_VP9_GOLDEN_FRAME_BASE, ++ }, ++ { ++ .reg_frm_size = RKVDEC_REG_VP9_FRAME_SIZE(2), ++ .reg_hor_stride = RKVDEC_VP9_HOR_VIRSTRIDE(2), ++ .reg_y_stride = RKVDEC_VP9_ALTREF_FRAME_YSTRIDE, ++ .reg_yuv_stride = 0, ++ .reg_ref_base = RKVDEC_REG_VP9_ALTREF_FRAME_BASE, ++ } ++}; ++ ++static struct rkvdec_decoded_buffer * ++get_ref_buf(struct rkvdec_ctx *ctx, struct vb2_v4l2_buffer *dst, u64 timestamp) ++{ ++ struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx; ++ struct vb2_queue *cap_q = &m2m_ctx->cap_q_ctx.q; ++ int buf_idx; ++ ++ /* ++ * If a ref is unused or invalid, address of current destination ++ * buffer is returned. ++ */ ++ buf_idx = vb2_find_timestamp(cap_q, timestamp, 0); ++ if (buf_idx < 0) ++ return vb2_to_rkvdec_decoded_buf(&dst->vb2_buf); ++ ++ return vb2_to_rkvdec_decoded_buf(vb2_get_buffer(cap_q, buf_idx)); ++} ++ ++static dma_addr_t get_mv_base_addr(struct rkvdec_decoded_buffer *buf) ++{ ++ u32 aligned_pitch, aligned_height, yuv_len; ++ ++ aligned_height = round_up(buf->vp9.height, 64); ++ aligned_pitch = round_up(buf->vp9.width * buf->vp9.bit_depth, 512) / 8; ++ yuv_len = (aligned_height * aligned_pitch * 3) / 2; ++ ++ return vb2_dma_contig_plane_dma_addr(&buf->base.vb.vb2_buf, 0) + ++ yuv_len; ++} ++ ++static void ++config_ref_registers(struct rkvdec_ctx *ctx, ++ const struct rkvdec_vp9_run *run, ++ struct rkvdec_decoded_buffer **ref_bufs, ++ enum v4l2_vp9_ref_id id) ++{ ++ u32 aligned_pitch, aligned_height, y_len, yuv_len; ++ struct rkvdec_decoded_buffer *buf = ref_bufs[id]; ++ struct rkvdec_dev *rkvdec = ctx->dev; ++ ++ aligned_height = round_up(buf->vp9.height, 64); ++ writel_relaxed(RKVDEC_VP9_FRAMEWIDTH(buf->vp9.width) | ++ RKVDEC_VP9_FRAMEHEIGHT(buf->vp9.height), ++ rkvdec->regs + ref_config[id].reg_frm_size); ++ ++ writel_relaxed(vb2_dma_contig_plane_dma_addr(&buf->base.vb.vb2_buf, 0), ++ rkvdec->regs + ref_config[id].reg_ref_base); ++ ++ if (&buf->base.vb == run->base.bufs.dst) ++ return; ++ ++ aligned_pitch = round_up(buf->vp9.width * buf->vp9.bit_depth, 512) / 8; ++ y_len = aligned_height * aligned_pitch; ++ yuv_len = (y_len * 3) / 2; ++ ++ writel_relaxed(RKVDEC_HOR_Y_VIRSTRIDE(aligned_pitch / 16) | ++ RKVDEC_HOR_UV_VIRSTRIDE(aligned_pitch / 16), ++ rkvdec->regs + ref_config[id].reg_hor_stride); ++ writel_relaxed(RKVDEC_VP9_REF_YSTRIDE(y_len / 16), ++ rkvdec->regs + ref_config[id].reg_y_stride); ++ ++ if (!ref_config[id].reg_yuv_stride) ++ return; ++ ++ writel_relaxed(RKVDEC_VP9_REF_YUVSTRIDE(yuv_len / 16), ++ rkvdec->regs + ref_config[id].reg_yuv_stride); ++} ++ ++static bool seg_featured_enabled(const struct v4l2_vp9_segmentation *seg, ++ enum v4l2_vp9_segment_feature feature, ++ unsigned int segid) ++{ ++ u8 mask = V4L2_VP9_SEGMENT_FEATURE_ENABLED(feature); ++ ++ return !!(seg->feature_enabled[segid] & mask); ++} ++ ++static void ++config_seg_registers(struct rkvdec_ctx *ctx, ++ unsigned int segid) ++{ ++ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; ++ const struct v4l2_vp9_segmentation *seg; ++ struct rkvdec_dev *rkvdec = ctx->dev; ++ s16 feature_val; ++ u8 feature_id; ++ u32 val = 0; ++ ++ seg = vp9_ctx->last.valid ? &vp9_ctx->last.seg : &vp9_ctx->cur.seg; ++ feature_id = V4L2_VP9_SEGMENT_FEATURE_QP_DELTA; ++ if (seg_featured_enabled(seg, feature_id, segid)) { ++ feature_val = seg->feature_data[segid][feature_id]; ++ val |= RKVDEC_SEGID_FRAME_QP_DELTA_EN(1) | ++ RKVDEC_SEGID_FRAME_QP_DELTA(feature_val); ++ } ++ ++ feature_id = V4L2_VP9_SEGMENT_FEATURE_LF; ++ if (seg_featured_enabled(seg, feature_id, segid)) { ++ feature_val = seg->feature_data[segid][feature_id]; ++ val |= RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE_EN(1) | ++ RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE(feature_val); ++ } ++ ++ feature_id = V4L2_VP9_SEGMENT_FEATURE_REF_FRAME; ++ if (seg_featured_enabled(seg, feature_id, segid)) { ++ feature_val = seg->feature_data[segid][feature_id]; ++ val |= RKVDEC_SEGID_REFERINFO_EN(1) | ++ RKVDEC_SEGID_REFERINFO(feature_val); ++ } ++ ++ feature_id = V4L2_VP9_SEGMENT_FEATURE_SKIP; ++ if (seg_featured_enabled(seg, feature_id, segid)) ++ val |= RKVDEC_SEGID_FRAME_SKIP_EN(1); ++ ++ if (!segid && ++ (seg->flags & V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE)) ++ val |= RKVDEC_SEGID_ABS_DELTA(1); ++ ++ writel_relaxed(val, rkvdec->regs + RKVDEC_VP9_SEGID_GRP(segid)); ++} ++ ++static void ++update_dec_buf_info(struct rkvdec_decoded_buffer *buf, ++ const struct v4l2_ctrl_vp9_frame_decode_params *dec_params) ++{ ++ buf->vp9.width = dec_params->frame_width_minus_1 + 1; ++ buf->vp9.height = dec_params->frame_height_minus_1 + 1; ++ buf->vp9.bit_depth = dec_params->bit_depth; ++} ++ ++static void ++update_ctx_cur_info(struct rkvdec_vp9_ctx *vp9_ctx, ++ struct rkvdec_decoded_buffer *buf, ++ const struct v4l2_ctrl_vp9_frame_decode_params *dec_params) ++{ ++ vp9_ctx->cur.valid = true; ++ vp9_ctx->cur.frame_context_idx = dec_params->frame_context_idx; ++ vp9_ctx->cur.reference_mode = dec_params->reference_mode; ++ vp9_ctx->cur.tx_mode = dec_params->tx_mode; ++ vp9_ctx->cur.interpolation_filter = dec_params->interpolation_filter; ++ vp9_ctx->cur.flags = dec_params->flags; ++ vp9_ctx->cur.timestamp = buf->base.vb.vb2_buf.timestamp; ++ vp9_ctx->cur.seg = dec_params->seg; ++ vp9_ctx->cur.lf = dec_params->lf; ++} ++ ++static void ++update_ctx_last_info(struct rkvdec_vp9_ctx *vp9_ctx) ++{ ++ vp9_ctx->last = vp9_ctx->cur; ++} ++ ++static void config_registers(struct rkvdec_ctx *ctx, ++ const struct rkvdec_vp9_run *run) ++{ ++ u32 y_len, uv_len, yuv_len, bit_depth, aligned_height, aligned_pitch; ++ const struct v4l2_ctrl_vp9_frame_decode_params *dec_params; ++ struct rkvdec_decoded_buffer *ref_bufs[V4L2_REF_ID_CNT]; ++ struct rkvdec_decoded_buffer *dst, *last, *mv_ref; ++ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; ++ u32 val, stream_len, last_frame_info = 0; ++ const struct v4l2_vp9_segmentation *seg; ++ struct rkvdec_dev *rkvdec = ctx->dev; ++ dma_addr_t addr; ++ bool intra_only; ++ unsigned int i; ++ ++ dec_params = run->decode_params; ++ dst = vb2_to_rkvdec_decoded_buf(&run->base.bufs.dst->vb2_buf); ++ for (i = 0; i < ARRAY_SIZE(ref_bufs); i++) ++ ref_bufs[i] = get_ref_buf(ctx, &dst->base.vb, ++ dec_params->refs[i]); ++ ++ if (vp9_ctx->last.valid) ++ last = get_ref_buf(ctx, &dst->base.vb, vp9_ctx->last.timestamp); ++ else ++ last = dst; ++ ++ update_dec_buf_info(dst, dec_params); ++ update_ctx_cur_info(vp9_ctx, dst, dec_params); ++ seg = &dec_params->seg; ++ ++ intra_only = !!(dec_params->flags & ++ (V4L2_VP9_FRAME_FLAG_KEY_FRAME | ++ V4L2_VP9_FRAME_FLAG_INTRA_ONLY)); ++ ++ writel_relaxed(RKVDEC_MODE(RKVDEC_MODE_VP9), ++ rkvdec->regs + RKVDEC_REG_SYSCTRL); ++ ++ bit_depth = dec_params->bit_depth; ++ aligned_height = round_up(ctx->decoded_fmt.fmt.pix_mp.height, 64); ++ ++ aligned_pitch = round_up(ctx->decoded_fmt.fmt.pix_mp.width * ++ bit_depth, ++ 512) / 8; ++ y_len = aligned_height * aligned_pitch; ++ uv_len = y_len / 2; ++ yuv_len = y_len + uv_len; ++ ++ writel_relaxed(RKVDEC_Y_HOR_VIRSTRIDE(aligned_pitch / 16) | ++ RKVDEC_UV_HOR_VIRSTRIDE(aligned_pitch / 16), ++ rkvdec->regs + RKVDEC_REG_PICPAR); ++ writel_relaxed(RKVDEC_Y_VIRSTRIDE(y_len / 16), ++ rkvdec->regs + RKVDEC_REG_Y_VIRSTRIDE); ++ writel_relaxed(RKVDEC_YUV_VIRSTRIDE(yuv_len / 16), ++ rkvdec->regs + RKVDEC_REG_YUV_VIRSTRIDE); ++ ++ stream_len = vb2_get_plane_payload(&run->base.bufs.src->vb2_buf, 0); ++ writel_relaxed(RKVDEC_STRM_LEN(stream_len), ++ rkvdec->regs + RKVDEC_REG_STRM_LEN); ++ ++ /* ++ * Reset count buffer, because decoder only output intra related syntax ++ * counts when decoding intra frame, but update entropy need to update ++ * all the probabilities. ++ */ ++ if (intra_only) ++ memset(vp9_ctx->count_tbl.cpu, 0, vp9_ctx->count_tbl.size); ++ ++ vp9_ctx->cur.segmapid = vp9_ctx->last.segmapid; ++ if (!intra_only && ++ !(dec_params->flags & V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT) && ++ (!(seg->flags & V4L2_VP9_SEGMENTATION_FLAG_ENABLED) || ++ (seg->flags & V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP))) ++ vp9_ctx->cur.segmapid++; ++ ++ for (i = 0; i < ARRAY_SIZE(ref_bufs); i++) ++ config_ref_registers(ctx, run, ref_bufs, i); ++ ++ for (i = 0; i < 8; i++) ++ config_seg_registers(ctx, i); ++ ++ writel_relaxed(RKVDEC_VP9_TX_MODE(dec_params->tx_mode) | ++ RKVDEC_VP9_FRAME_REF_MODE(dec_params->reference_mode), ++ rkvdec->regs + RKVDEC_VP9_CPRHEADER_CONFIG); ++ ++ if (!intra_only) { ++ const struct v4l2_vp9_loop_filter *lf; ++ s8 delta; ++ ++ if (vp9_ctx->last.valid) ++ lf = &vp9_ctx->last.lf; ++ else ++ lf = &vp9_ctx->cur.lf; ++ ++ val = 0; ++ for (i = 0; i < ARRAY_SIZE(lf->ref_deltas); i++) { ++ delta = lf->ref_deltas[i]; ++ val |= RKVDEC_REF_DELTAS_LASTFRAME(i, delta); ++ } ++ ++ writel_relaxed(val, ++ rkvdec->regs + RKVDEC_VP9_REF_DELTAS_LASTFRAME); ++ ++ for (i = 0; i < ARRAY_SIZE(lf->mode_deltas); i++) { ++ delta = lf->mode_deltas[i]; ++ last_frame_info |= RKVDEC_MODE_DELTAS_LASTFRAME(i, ++ delta); ++ } ++ } ++ ++ if (vp9_ctx->last.valid && !intra_only && ++ vp9_ctx->last.seg.flags & V4L2_VP9_SEGMENTATION_FLAG_ENABLED) ++ last_frame_info |= RKVDEC_SEG_EN_LASTFRAME; ++ ++ if (vp9_ctx->last.valid && ++ vp9_ctx->last.flags & V4L2_VP9_FRAME_FLAG_SHOW_FRAME) ++ last_frame_info |= RKVDEC_LAST_SHOW_FRAME; ++ ++ if (vp9_ctx->last.valid && ++ vp9_ctx->last.flags & ++ (V4L2_VP9_FRAME_FLAG_KEY_FRAME | V4L2_VP9_FRAME_FLAG_INTRA_ONLY)) ++ last_frame_info |= RKVDEC_LAST_INTRA_ONLY; ++ ++ if (vp9_ctx->last.valid && ++ last->vp9.width == dst->vp9.width && ++ last->vp9.height == dst->vp9.height) ++ last_frame_info |= RKVDEC_LAST_WIDHHEIGHT_EQCUR; ++ ++ writel_relaxed(last_frame_info, ++ rkvdec->regs + RKVDEC_VP9_INFO_LASTFRAME); ++ ++ writel_relaxed(stream_len - dec_params->compressed_header_size - ++ dec_params->uncompressed_header_size, ++ rkvdec->regs + RKVDEC_VP9_LASTTILE_SIZE); ++ ++ for (i = 0; !intra_only && i < ARRAY_SIZE(ref_bufs); i++) { ++ u32 refw = ref_bufs[i]->vp9.width; ++ u32 refh = ref_bufs[i]->vp9.height; ++ u32 hscale, vscale; ++ ++ hscale = (refw << 14) / dst->vp9.width; ++ vscale = (refh << 14) / dst->vp9.height; ++ writel_relaxed(RKVDEC_VP9_REF_HOR_SCALE(hscale) | ++ RKVDEC_VP9_REF_VER_SCALE(vscale), ++ rkvdec->regs + RKVDEC_VP9_REF_SCALE(i)); ++ } ++ ++ addr = vb2_dma_contig_plane_dma_addr(&dst->base.vb.vb2_buf, 0); ++ writel_relaxed(addr, rkvdec->regs + RKVDEC_REG_DECOUT_BASE); ++ addr = vb2_dma_contig_plane_dma_addr(&run->base.bufs.src->vb2_buf, 0); ++ writel_relaxed(addr, rkvdec->regs + RKVDEC_REG_STRM_RLC_BASE); ++ writel_relaxed(vp9_ctx->priv_tbl.dma + ++ offsetof(struct rkvdec_vp9_priv_tbl, probs), ++ rkvdec->regs + RKVDEC_REG_CABACTBL_PROB_BASE); ++ writel_relaxed(vp9_ctx->count_tbl.dma, ++ rkvdec->regs + RKVDEC_REG_VP9COUNT_BASE); ++ ++ writel_relaxed(vp9_ctx->priv_tbl.dma + ++ offsetof(struct rkvdec_vp9_priv_tbl, segmap) + ++ (RKVDEC_VP9_MAX_SEGMAP_SIZE * vp9_ctx->cur.segmapid), ++ rkvdec->regs + RKVDEC_REG_VP9_SEGIDCUR_BASE); ++ writel_relaxed(vp9_ctx->priv_tbl.dma + ++ offsetof(struct rkvdec_vp9_priv_tbl, segmap) + ++ (RKVDEC_VP9_MAX_SEGMAP_SIZE * (!vp9_ctx->cur.segmapid)), ++ rkvdec->regs + RKVDEC_REG_VP9_SEGIDLAST_BASE); ++ ++ if (!intra_only && ++ !(dec_params->flags & V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT) && ++ vp9_ctx->last.valid) ++ mv_ref = last; ++ else ++ mv_ref = dst; ++ ++ writel_relaxed(get_mv_base_addr(mv_ref), ++ rkvdec->regs + RKVDEC_VP9_REF_COLMV_BASE); ++ ++ writel_relaxed(ctx->decoded_fmt.fmt.pix_mp.width | ++ (ctx->decoded_fmt.fmt.pix_mp.height << 16), ++ rkvdec->regs + RKVDEC_REG_PERFORMANCE_CYCLE); ++} ++ ++static int ++validate_dec_params(struct rkvdec_ctx *ctx, ++ const struct v4l2_ctrl_vp9_frame_decode_params *dec_params) ++{ ++ unsigned int aligned_width, aligned_height; ++ ++ /* We only support profile 0. */ ++ if (dec_params->profile != 0) { ++ dev_err(ctx->dev->dev, "unsupported profile %d\n", ++ dec_params->profile); ++ return -EINVAL; ++ } ++ ++ aligned_width = round_up(dec_params->frame_width_minus_1 + 1, 64); ++ aligned_height = round_up(dec_params->frame_height_minus_1 + 1, 64); ++ ++ /* ++ * Userspace should update the capture/decoded format when the ++ * resolution changes. ++ */ ++ if (aligned_width != ctx->decoded_fmt.fmt.pix_mp.width || ++ aligned_height != ctx->decoded_fmt.fmt.pix_mp.height) { ++ dev_err(ctx->dev->dev, ++ "unexpected bitstream resolution %dx%d\n", ++ dec_params->frame_width_minus_1 + 1, ++ dec_params->frame_height_minus_1 +1); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int rkvdec_vp9_run_preamble(struct rkvdec_ctx *ctx, ++ struct rkvdec_vp9_run *run) ++{ ++ const struct v4l2_ctrl_vp9_frame_decode_params *dec_params; ++ const struct v4l2_ctrl_vp9_frame_ctx *fctx = NULL; ++ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; ++ struct v4l2_ctrl *ctrl; ++ u8 frm_ctx; ++ int ret; ++ ++ rkvdec_run_preamble(ctx, &run->base); ++ ++ ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, ++ V4L2_CID_MPEG_VIDEO_VP9_FRAME_DECODE_PARAMS); ++ WARN_ON(!ctrl); ++ ++ dec_params = ctrl ? ctrl->p_cur.p : NULL; ++ if (WARN_ON(!dec_params)) ++ return -EINVAL; ++ ++ ret = validate_dec_params(ctx, dec_params); ++ if (ret) ++ return ret; ++ ++ run->decode_params = dec_params; ++ ++ /* No need to load the frame context if we don't need to update it. */ ++ if (!(dec_params->flags & V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX)) ++ return 0; ++ ++ /* ++ * When a refresh context is requested in parallel mode, we should just ++ * update the context with the probs passed in the decode parameters. ++ */ ++ if (dec_params->flags & V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE) { ++ vp9_ctx->frame_context.probs = dec_params->probs; ++ return 0; ++ } ++ ++ frm_ctx = run->decode_params->frame_context_idx; ++ ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, ++ V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(frm_ctx)); ++ if (WARN_ON(!ctrl)) ++ return 0; ++ ++ fctx = ctrl->p_cur.p; ++ vp9_ctx->frame_context = *fctx; ++ ++ /* ++ * For intra-only frames, we must update the context TX and skip probs ++ * with the value passed in the decode params. ++ */ ++ if (dec_params->flags & ++ (V4L2_VP9_FRAME_FLAG_KEY_FRAME | V4L2_VP9_FRAME_FLAG_INTRA_ONLY)) { ++ struct v4l2_vp9_probabilities *probs; ++ ++ probs = &vp9_ctx->frame_context.probs; ++ memcpy(probs->skip, dec_params->probs.skip, ++ sizeof(probs->skip)); ++ memcpy(probs->tx8, dec_params->probs.tx8, ++ sizeof(probs->tx8)); ++ memcpy(probs->tx16, dec_params->probs.tx16, ++ sizeof(probs->tx16)); ++ memcpy(probs->tx32, dec_params->probs.tx32, ++ sizeof(probs->tx32)); ++ } ++ ++ return 0; ++} ++ ++static int rkvdec_vp9_run(struct rkvdec_ctx *ctx) ++{ ++ struct rkvdec_dev *rkvdec = ctx->dev; ++ struct rkvdec_vp9_run run = { }; ++ int ret; ++ ++ ret = rkvdec_vp9_run_preamble(ctx, &run); ++ if (ret) { ++ rkvdec_run_postamble(ctx, &run.base); ++ return ret; ++ } ++ ++ /* Prepare probs. */ ++ init_probs(ctx, &run); ++ ++ /* Configure hardware registers. */ ++ config_registers(ctx, &run); ++ ++ rkvdec_run_postamble(ctx, &run.base); ++ ++ schedule_delayed_work(&rkvdec->watchdog_work, msecs_to_jiffies(2000)); ++ ++ writel(1, rkvdec->regs + RKVDEC_REG_PREF_LUMA_CACHE_COMMAND); ++ writel(1, rkvdec->regs + RKVDEC_REG_PREF_CHR_CACHE_COMMAND); ++ ++ writel(0xe, rkvdec->regs + RKVDEC_REG_STRMD_ERR_EN); ++ /* Start decoding! */ ++ writel(RKVDEC_INTERRUPT_DEC_E | RKVDEC_CONFIG_DEC_CLK_GATE_E | ++ RKVDEC_TIMEOUT_E | RKVDEC_BUF_EMPTY_E, ++ rkvdec->regs + RKVDEC_REG_INTERRUPT); ++ ++ return 0; ++} ++ ++static u8 adapt_prob(u8 p1, u32 ct0, u32 ct1, u16 max_count, u32 update_factor) ++{ ++ u32 ct = ct0 + ct1, p2; ++ u32 lo = 1; ++ u32 hi = 255; ++ ++ if (!ct) ++ return p1; ++ ++ p2 = ((ct0 << 8) + (ct >> 1)) / ct; ++ p2 = clamp(p2, lo, hi); ++ ct = min_t(u32, ct, max_count); ++ ++ if (WARN_ON(max_count >= 257)) ++ return p1; ++ ++ update_factor = rkvdec_fastdiv(update_factor * ct, max_count); ++ ++ return p1 + (((p2 - p1) * update_factor + 128) >> 8); ++} ++ ++#define BAND_6(band) ((band) == 0 ? 3 : 6) ++ ++static void adapt_coeff(u8 coef[6][6][3], ++ const struct rkvdec_vp9_refs_counts ref_cnt[6][6], ++ u32 uf) ++{ ++ s32 l, m, n; ++ ++ for (l = 0; l < 6; l++) { ++ for (m = 0; m < BAND_6(l); m++) { ++ u8 *p = coef[l][m]; ++ const u32 n0 = ref_cnt[l][m].coeff[0]; ++ const u32 n1 = ref_cnt[l][m].coeff[1]; ++ const u32 n2 = ref_cnt[l][m].coeff[2]; ++ const u32 neob = ref_cnt[l][m].eob[1]; ++ const u32 eob_count = ref_cnt[l][m].eob[0]; ++ const u32 branch_ct[3][2] = { ++ { neob, eob_count - neob }, ++ { n0, n1 + n2 }, ++ { n1, n2 } ++ }; ++ ++ for (n = 0; n < 3; n++) ++ p[n] = adapt_prob(p[n], branch_ct[n][0], ++ branch_ct[n][1], 24, uf); ++ } ++ } ++} ++ ++static void ++adapt_coef_probs(struct v4l2_vp9_probabilities *probs, ++ const struct rkvdec_vp9_refs_counts ref_cnt[2][4][2][6][6], ++ unsigned int uf) ++{ ++ unsigned int i, j, k; ++ ++ for (i = 0; i < ARRAY_SIZE(probs->coef); i++) { ++ for (j = 0; j < ARRAY_SIZE(probs->coef[0]); j++) { ++ for (k = 0; k < ARRAY_SIZE(probs->coef[0][0]); ++ k++) { ++ adapt_coeff(probs->coef[i][j][k], ++ ref_cnt[k][i][j], ++ uf); ++ } ++ } ++ } ++} ++ ++static void adapt_intra_frame_probs(struct rkvdec_ctx *ctx) ++{ ++ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; ++ struct v4l2_vp9_probabilities *probs = &vp9_ctx->frame_context.probs; ++ const struct rkvdec_vp9_intra_frame_symbol_counts *sym_cnts; ++ ++ sym_cnts = vp9_ctx->count_tbl.cpu; ++ adapt_coef_probs(probs, sym_cnts->ref_cnt, 112); ++} ++ ++static void ++adapt_skip_probs(struct v4l2_vp9_probabilities *probs, ++ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(probs->skip); i++) ++ probs->skip[i] = adapt_prob(probs->skip[i], ++ sym_cnts->skip[i][0], ++ sym_cnts->skip[i][1], ++ 20, 128); ++} ++ ++static void ++adapt_is_inter_probs(struct v4l2_vp9_probabilities *probs, ++ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(probs->is_inter); i++) ++ probs->is_inter[i] = adapt_prob(probs->is_inter[i], ++ sym_cnts->inter[i][0], ++ sym_cnts->inter[i][1], ++ 20, 128); ++} ++ ++static void ++adapt_comp_mode_probs(struct v4l2_vp9_probabilities *probs, ++ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(probs->comp_mode); i++) ++ probs->comp_mode[i] = adapt_prob(probs->comp_mode[i], ++ sym_cnts->comp[i][0], ++ sym_cnts->comp[i][1], ++ 20, 128); ++} ++ ++static void ++adapt_comp_ref_probs(struct v4l2_vp9_probabilities *probs, ++ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(probs->comp_ref); i++) ++ probs->comp_ref[i] = adapt_prob(probs->comp_ref[i], ++ sym_cnts->comp_ref[i][0], ++ sym_cnts->comp_ref[i][1], ++ 20, 128); ++} ++ ++static void ++adapt_single_ref_probs(struct v4l2_vp9_probabilities *probs, ++ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(probs->single_ref); i++) { ++ u8 *p = probs->single_ref[i]; ++ ++ p[0] = adapt_prob(p[0], sym_cnts->single_ref[i][0][0], ++ sym_cnts->single_ref[i][0][1], 20, 128); ++ p[1] = adapt_prob(p[1], sym_cnts->single_ref[i][1][0], ++ sym_cnts->single_ref[i][1][1], 20, 128); ++ } ++} ++ ++static void ++adapt_partition_probs(struct v4l2_vp9_probabilities *probs, ++ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(probs->partition); i++) { ++ const u32 *c = sym_cnts->partition[i]; ++ u8 *p = probs->partition[i]; ++ ++ p[0] = adapt_prob(p[0], c[0], c[1] + c[2] + c[3], 20, 128); ++ p[1] = adapt_prob(p[1], c[1], c[2] + c[3], 20, 128); ++ p[2] = adapt_prob(p[2], c[2], c[3], 20, 128); ++ } ++} ++ ++static void ++adapt_tx_probs(struct v4l2_vp9_probabilities *probs, ++ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(probs->tx8); i++) { ++ u8 *p16x16 = probs->tx16[i]; ++ u8 *p32x32 = probs->tx32[i]; ++ const u32 *c16 = sym_cnts->tx16p[i]; ++ const u32 *c32 = sym_cnts->tx32p[i]; ++ const u32 *c8 = sym_cnts->tx8p[i]; ++ u8 *p8x8 = probs->tx8[i]; ++ ++ p8x8[0] = adapt_prob(p8x8[0], c8[0], c8[1], 20, 128); ++ p16x16[0] = adapt_prob(p16x16[0], c16[0], c16[1] + c16[2], ++ 20, 128); ++ p16x16[1] = adapt_prob(p16x16[1], c16[1], c16[2], 20, 128); ++ p32x32[0] = adapt_prob(p32x32[0], c32[0], ++ c32[1] + c32[2] + c32[3], 20, 128); ++ p32x32[1] = adapt_prob(p32x32[1], c32[1], c32[2] + c32[3], ++ 20, 128); ++ p32x32[2] = adapt_prob(p32x32[2], c32[2], c32[3], 20, 128); ++ } ++} ++ ++static void ++adapt_interp_filter_probs(struct v4l2_vp9_probabilities *probs, ++ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(probs->interp_filter); i++) { ++ u8 *p = probs->interp_filter[i]; ++ const u32 *c = sym_cnts->filter[i]; ++ ++ p[0] = adapt_prob(p[0], c[0], c[1] + c[2], 20, 128); ++ p[1] = adapt_prob(p[1], c[1], c[2], 20, 128); ++ } ++} ++ ++static void ++adapt_inter_mode_probs(struct v4l2_vp9_probabilities *probs, ++ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(probs->inter_mode); i++) { ++ const u32 *c = sym_cnts->mv_mode[i]; ++ u8 *p = probs->inter_mode[i]; ++ ++ p[0] = adapt_prob(p[0], c[2], c[1] + c[0] + c[3], 20, 128); ++ p[1] = adapt_prob(p[1], c[0], c[1] + c[3], 20, 128); ++ p[2] = adapt_prob(p[2], c[1], c[3], 20, 128); ++ } ++} ++ ++static void ++adapt_mv_probs(struct v4l2_vp9_probabilities *probs, ++ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts, ++ bool high_prec_mv) ++{ ++ const u32 *c = sym_cnts->mv_joint; ++ u8 *p = probs->mv.joint; ++ unsigned int i, j; ++ u32 sum; ++ ++ p[0] = adapt_prob(p[0], c[0], c[1] + c[2] + c[3], 20, 128); ++ p[1] = adapt_prob(p[1], c[1], c[2] + c[3], 20, 128); ++ p[2] = adapt_prob(p[2], c[2], c[3], 20, 128); ++ ++ for (i = 0; i < ARRAY_SIZE(probs->mv.sign); i++) { ++ p = probs->mv.sign; ++ ++ p[i] = adapt_prob(p[i], sym_cnts->sign[i][0], ++ sym_cnts->sign[i][1], 20, 128); ++ ++ p = probs->mv.class[i]; ++ c = sym_cnts->classes[i]; ++ sum = c[1] + c[2] + c[3] + c[4] + c[5] + c[6] + c[7] + c[8] + ++ c[9] + c[10]; ++ p[0] = adapt_prob(p[0], c[0], sum, 20, 128); ++ sum -= c[1]; ++ p[1] = adapt_prob(p[1], c[1], sum, 20, 128); ++ sum -= c[2] + c[3]; ++ p[2] = adapt_prob(p[2], c[2] + c[3], sum, 20, 128); ++ p[3] = adapt_prob(p[3], c[2], c[3], 20, 128); ++ sum -= c[4] + c[5]; ++ p[4] = adapt_prob(p[4], c[4] + c[5], sum, 20, 128); ++ p[5] = adapt_prob(p[5], c[4], c[5], 20, 128); ++ sum -= c[6]; ++ p[6] = adapt_prob(p[6], c[6], sum, 20, 128); ++ p[7] = adapt_prob(p[7], c[7] + c[8], c[9] + c[10], 20, 128); ++ p[8] = adapt_prob(p[8], c[7], c[8], 20, 128); ++ p[9] = adapt_prob(p[9], c[9], c[10], 20, 128); ++ ++ p = probs->mv.class0_bit; ++ p[i] = adapt_prob(p[i], ++ sym_cnts->class0[i][0], ++ sym_cnts->class0[i][1], 20, 128); ++ ++ p = probs->mv.bits[i]; ++ for (j = 0; j < 10; j++) ++ p[j] = adapt_prob(p[j], sym_cnts->bits[i][j][0], ++ sym_cnts->bits[i][j][1], 20, 128); ++ ++ for (j = 0; j < 2; j++) { ++ p = probs->mv.class0_fr[i][j]; ++ c = sym_cnts->class0_fp[i][j]; ++ p[0] = adapt_prob(p[0], c[0], c[1] + c[2] + c[3], ++ 20, 128); ++ p[1] = adapt_prob(p[1], c[1], c[2] + c[3], 20, 128); ++ p[2] = adapt_prob(p[2], c[2], c[3], 20, 128); ++ } ++ ++ p = probs->mv.fr[i]; ++ c = sym_cnts->fp[i]; ++ p[0] = adapt_prob(p[0], c[0], c[1] + c[2] + c[3], 20, 128); ++ p[1] = adapt_prob(p[1], c[1], c[2] + c[3], 20, 128); ++ p[2] = adapt_prob(p[2], c[2], c[3], 20, 128); ++ ++ if (!high_prec_mv) ++ continue; ++ ++ p = probs->mv.class0_hp; ++ p[i] = adapt_prob(p[i], sym_cnts->class0_hp[i][0], ++ sym_cnts->class0_hp[i][1], 20, 128); ++ ++ p = probs->mv.hp; ++ p[i] = adapt_prob(p[i], sym_cnts->hp[i][0], ++ sym_cnts->hp[i][1], 20, 128); ++ } ++} ++ ++static void ++adapt_intra_mode_probs(u8 *p, const u32 *c) ++{ ++ u32 sum = 0, s2; ++ unsigned int i; ++ ++ for (i = V4L2_VP9_INTRA_PRED_MODE_V; i <= V4L2_VP9_INTRA_PRED_MODE_TM; ++ i++) ++ sum += c[i]; ++ ++ p[0] = adapt_prob(p[0], c[V4L2_VP9_INTRA_PRED_MODE_DC], sum, 20, 128); ++ sum -= c[V4L2_VP9_INTRA_PRED_MODE_TM]; ++ p[1] = adapt_prob(p[1], c[V4L2_VP9_INTRA_PRED_MODE_TM], sum, 20, 128); ++ sum -= c[V4L2_VP9_INTRA_PRED_MODE_V]; ++ p[2] = adapt_prob(p[2], c[V4L2_VP9_INTRA_PRED_MODE_V], sum, 20, 128); ++ s2 = c[V4L2_VP9_INTRA_PRED_MODE_H] + c[V4L2_VP9_INTRA_PRED_MODE_D135] + ++ c[V4L2_VP9_INTRA_PRED_MODE_D117]; ++ sum -= s2; ++ p[3] = adapt_prob(p[3], s2, sum, 20, 128); ++ s2 -= c[V4L2_VP9_INTRA_PRED_MODE_H]; ++ p[4] = adapt_prob(p[4], c[V4L2_VP9_INTRA_PRED_MODE_H], s2, 20, 128); ++ p[5] = adapt_prob(p[5], c[V4L2_VP9_INTRA_PRED_MODE_D135], ++ c[V4L2_VP9_INTRA_PRED_MODE_D117], 20, 128); ++ sum -= c[V4L2_VP9_INTRA_PRED_MODE_D45]; ++ p[6] = adapt_prob(p[6], c[V4L2_VP9_INTRA_PRED_MODE_D45], ++ sum, 20, 128); ++ sum -= c[V4L2_VP9_INTRA_PRED_MODE_D63]; ++ p[7] = adapt_prob(p[7], c[V4L2_VP9_INTRA_PRED_MODE_D63], sum, ++ 20, 128); ++ p[8] = adapt_prob(p[8], c[V4L2_VP9_INTRA_PRED_MODE_D153], ++ c[V4L2_VP9_INTRA_PRED_MODE_D207], 20, 128); ++} ++ ++static void ++adapt_y_intra_mode_probs(struct v4l2_vp9_probabilities *probs, ++ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(probs->y_mode); i++) ++ adapt_intra_mode_probs(probs->y_mode[i], sym_cnts->y_mode[i]); ++} ++ ++static void ++adapt_uv_intra_mode_probs(struct v4l2_vp9_probabilities *probs, ++ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(probs->uv_mode); i++) ++ adapt_intra_mode_probs(probs->uv_mode[i], ++ sym_cnts->uv_mode[i]); ++} ++ ++static void ++adapt_inter_frame_probs(struct rkvdec_ctx *ctx) ++{ ++ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; ++ struct v4l2_vp9_probabilities *probs = &vp9_ctx->frame_context.probs; ++ const struct rkvdec_vp9_inter_frame_symbol_counts *sym_cnts; ++ ++ sym_cnts = vp9_ctx->count_tbl.cpu; ++ /* coefficients */ ++ if (vp9_ctx->last.valid && ++ !(vp9_ctx->last.flags & V4L2_VP9_FRAME_FLAG_KEY_FRAME)) ++ adapt_coef_probs(probs, sym_cnts->ref_cnt, 112); ++ else ++ adapt_coef_probs(probs, sym_cnts->ref_cnt, 128); ++ ++ /* skip flag */ ++ adapt_skip_probs(probs, sym_cnts); ++ ++ /* intra/inter flag */ ++ adapt_is_inter_probs(probs, sym_cnts); ++ ++ /* comppred flag */ ++ adapt_comp_mode_probs(probs, sym_cnts); ++ ++ /* reference frames */ ++ adapt_comp_ref_probs(probs, sym_cnts); ++ ++ if (vp9_ctx->cur.reference_mode != V4L2_VP9_REF_MODE_COMPOUND) ++ adapt_single_ref_probs(probs, sym_cnts); ++ ++ /* block partitioning */ ++ adapt_partition_probs(probs, sym_cnts); ++ ++ /* tx size */ ++ if (vp9_ctx->cur.tx_mode == V4L2_VP9_TX_MODE_SELECT) ++ adapt_tx_probs(probs, sym_cnts); ++ ++ /* interpolation filter */ ++ if (vp9_ctx->cur.interpolation_filter == V4L2_VP9_INTERP_FILTER_SWITCHABLE) ++ adapt_interp_filter_probs(probs, sym_cnts); ++ ++ /* inter modes */ ++ adapt_inter_mode_probs(probs, sym_cnts); ++ ++ /* mv probs */ ++ adapt_mv_probs(probs, sym_cnts, ++ !!(vp9_ctx->cur.flags & ++ V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV)); ++ ++ /* y intra modes */ ++ adapt_y_intra_mode_probs(probs, sym_cnts); ++ ++ /* uv intra modes */ ++ adapt_uv_intra_mode_probs(probs, sym_cnts); ++} ++ ++static void adapt_probs(struct rkvdec_ctx *ctx) ++{ ++ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; ++ bool intra_only; ++ ++ intra_only = !!(vp9_ctx->cur.flags & ++ (V4L2_VP9_FRAME_FLAG_KEY_FRAME | ++ V4L2_VP9_FRAME_FLAG_INTRA_ONLY)); ++ ++ if (intra_only) ++ adapt_intra_frame_probs(ctx); ++ else ++ adapt_inter_frame_probs(ctx); ++} ++ ++static void rkvdec_vp9_done(struct rkvdec_ctx *ctx, ++ struct vb2_v4l2_buffer *src_buf, ++ struct vb2_v4l2_buffer *dst_buf, ++ enum vb2_buffer_state result) ++{ ++ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; ++ struct v4l2_ctrl *ctrl; ++ unsigned int fctx_idx; ++ ++ if (result == VB2_BUF_STATE_ERROR) ++ goto out_update_last; ++ ++ if (!(vp9_ctx->cur.flags & V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX)) ++ goto out_update_last; ++ ++ fctx_idx = vp9_ctx->cur.frame_context_idx; ++ ++ if (!(vp9_ctx->cur.flags & ++ (V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT | ++ V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE))) ++ adapt_probs(ctx); ++ ++ ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, ++ V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(fctx_idx)); ++ if (WARN_ON(!ctrl)) ++ goto out_update_last; ++ ++ v4l2_ctrl_s_ctrl_compound(ctrl, V4L2_CTRL_TYPE_VP9_FRAME_CONTEXT, ++ &vp9_ctx->frame_context); ++ ++out_update_last: ++ update_ctx_last_info(vp9_ctx); ++} ++ ++static int rkvdec_vp9_start(struct rkvdec_ctx *ctx) ++{ ++ struct rkvdec_dev *rkvdec = ctx->dev; ++ struct rkvdec_vp9_priv_tbl *priv_tbl; ++ struct rkvdec_vp9_ctx *vp9_ctx; ++ u8 *count_tbl; ++ int ret; ++ ++ vp9_ctx = kzalloc(sizeof(*vp9_ctx), GFP_KERNEL); ++ if (!vp9_ctx) ++ return -ENOMEM; ++ ++ ctx->priv = vp9_ctx; ++ ++ priv_tbl = dma_alloc_coherent(rkvdec->dev, sizeof(*priv_tbl), ++ &vp9_ctx->priv_tbl.dma, GFP_KERNEL); ++ if (!priv_tbl) { ++ ret = -ENOMEM; ++ goto err_free_ctx; ++ } ++ ++ vp9_ctx->priv_tbl.size = sizeof(*priv_tbl); ++ vp9_ctx->priv_tbl.cpu = priv_tbl; ++ memset(priv_tbl, 0, sizeof(*priv_tbl)); ++ ++ count_tbl = dma_alloc_coherent(rkvdec->dev, RKVDEC_VP9_COUNT_SIZE, ++ &vp9_ctx->count_tbl.dma, GFP_KERNEL); ++ if (!count_tbl) { ++ ret = -ENOMEM; ++ goto err_free_priv_tbl; ++ } ++ ++ vp9_ctx->count_tbl.size = RKVDEC_VP9_COUNT_SIZE; ++ vp9_ctx->count_tbl.cpu = count_tbl; ++ memset(count_tbl, 0, sizeof(*count_tbl)); ++ ++ return 0; ++ ++err_free_priv_tbl: ++ dma_free_coherent(rkvdec->dev, vp9_ctx->priv_tbl.size, ++ vp9_ctx->priv_tbl.cpu, vp9_ctx->priv_tbl.dma); ++ ++err_free_ctx: ++ kfree(vp9_ctx); ++ return ret; ++} ++ ++static void rkvdec_vp9_stop(struct rkvdec_ctx *ctx) ++{ ++ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; ++ struct rkvdec_dev *rkvdec = ctx->dev; ++ ++ dma_free_coherent(rkvdec->dev, vp9_ctx->count_tbl.size, ++ vp9_ctx->count_tbl.cpu, vp9_ctx->count_tbl.dma); ++ dma_free_coherent(rkvdec->dev, vp9_ctx->priv_tbl.size, ++ vp9_ctx->priv_tbl.cpu, vp9_ctx->priv_tbl.dma); ++ kfree(vp9_ctx); ++} ++ ++static int rkvdec_vp9_adjust_fmt(struct rkvdec_ctx *ctx, ++ struct v4l2_format *f) ++{ ++ struct v4l2_pix_format_mplane *fmt = &f->fmt.pix_mp; ++ ++ fmt->num_planes = 1; ++ if (!fmt->plane_fmt[0].sizeimage) ++ fmt->plane_fmt[0].sizeimage = fmt->width * fmt->height * 2; ++ return 0; ++} ++ ++const struct rkvdec_coded_fmt_ops rkvdec_vp9_fmt_ops = { ++ .adjust_fmt = rkvdec_vp9_adjust_fmt, ++ .start = rkvdec_vp9_start, ++ .stop = rkvdec_vp9_stop, ++ .run = rkvdec_vp9_run, ++ .done = rkvdec_vp9_done, ++}; +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index 91f8a1bb6176..f0f28f6a68cf 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -159,6 +159,45 @@ static const u32 rkvdec_h264_decoded_fmts[] = { + V4L2_PIX_FMT_NV20, + }; + ++static const struct rkvdec_ctrl_desc rkvdec_vp9_ctrl_descs[] = { ++ { ++ .per_request = true, ++ .mandatory = true, ++ .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_DECODE_PARAMS, ++ }, ++ { ++ .mandatory = true, ++ .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(0), ++ }, ++ { ++ .mandatory = true, ++ .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(1), ++ }, ++ { ++ .mandatory = true, ++ .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(2), ++ }, ++ { ++ .mandatory = true, ++ .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(3), ++ }, ++ { ++ .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_PROFILE, ++ .cfg.min = V4L2_MPEG_VIDEO_VP9_PROFILE_0, ++ .cfg.max = V4L2_MPEG_VIDEO_VP9_PROFILE_0, ++ .cfg.def = V4L2_MPEG_VIDEO_VP9_PROFILE_0, ++ }, ++}; ++ ++static const struct rkvdec_ctrls rkvdec_vp9_ctrls = { ++ .ctrls = rkvdec_vp9_ctrl_descs, ++ .num_ctrls = ARRAY_SIZE(rkvdec_vp9_ctrl_descs), ++}; ++ ++static const u32 rkvdec_vp9_decoded_fmts[] = { ++ V4L2_PIX_FMT_NV12, ++}; ++ + static const struct rkvdec_coded_fmt_desc rkvdec_coded_fmts[] = { + { + .fourcc = V4L2_PIX_FMT_H264_SLICE, +@@ -174,6 +213,21 @@ static const struct rkvdec_coded_fmt_desc rkvdec_coded_fmts[] = { + .ops = &rkvdec_h264_fmt_ops, + .num_decoded_fmts = ARRAY_SIZE(rkvdec_h264_decoded_fmts), + .decoded_fmts = rkvdec_h264_decoded_fmts, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_VP9_FRAME, ++ .frmsize = { ++ .min_width = 64, ++ .max_width = 4096, ++ .step_width = 64, ++ .min_height = 64, ++ .max_height = 2304, ++ .step_height = 64, ++ }, ++ .ctrls = &rkvdec_vp9_ctrls, ++ .ops = &rkvdec_vp9_fmt_ops, ++ .num_decoded_fmts = ARRAY_SIZE(rkvdec_vp9_decoded_fmts), ++ .decoded_fmts = rkvdec_vp9_decoded_fmts, + } + }; + +diff --git a/drivers/staging/media/rkvdec/rkvdec.h b/drivers/staging/media/rkvdec/rkvdec.h +index e95c52e3168a..5f66f07acac5 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.h ++++ b/drivers/staging/media/rkvdec/rkvdec.h +@@ -51,6 +51,10 @@ struct rkvdec_vp9_decoded_buffer_info { + struct rkvdec_decoded_buffer { + /* Must be the first field in this struct. */ + struct v4l2_m2m_buffer base; ++ ++ union { ++ struct rkvdec_vp9_decoded_buffer_info vp9; ++ }; + }; + + static inline struct rkvdec_decoded_buffer * +@@ -119,4 +123,6 @@ void rkvdec_run_preamble(struct rkvdec_ctx *ctx, struct rkvdec_run *run); + void rkvdec_run_postamble(struct rkvdec_ctx *ctx, struct rkvdec_run *run); + + extern const struct rkvdec_coded_fmt_ops rkvdec_h264_fmt_ops; ++extern const struct rkvdec_coded_fmt_ops rkvdec_vp9_fmt_ops; ++ + #endif /* RKVDEC_H_ */ diff --git a/patch/kernel/rk322x-dev/01-linux-0015-fromlist-rga-for-rk322x.patch.disabled b/patch/kernel/rk322x-dev/01-linux-0015-fromlist-rga-for-rk322x.patch.disabled deleted file mode 100644 index be186ba1c..000000000 --- a/patch/kernel/rk322x-dev/01-linux-0015-fromlist-rga-for-rk322x.patch.disabled +++ /dev/null @@ -1,53 +0,0 @@ -Add a node to define the presence of RGA, a 2D raster -graphic acceleration unit. - -Signed-off-by: Justin Swartz ---- - arch/arm/boot/dts/rk322x.dtsi | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi -index 340ed6ccb..29d50bebc 100644 ---- a/arch/arm/boot/dts/rk322x.dtsi -+++ b/arch/arm/boot/dts/rk322x.dtsi -@@ -621,6 +621,17 @@ - status = "disabled"; - }; - -+ rga: rga@20060000 { -+ compatible = "rockchip,rk3228-rga", "rockchip,rk3288-rga"; -+ reg = <0x20060000 0x1000>; -+ interrupts = ; -+ clocks = <&cru ACLK_RGA>, <&cru HCLK_RGA>, <&cru SCLK_RGA>; -+ clock-names = "aclk", "hclk", "sclk"; -+ resets = <&cru SRST_RGA>, <&cru SRST_RGA_A>, <&cru SRST_RGA_H>; -+ reset-names = "core", "axi", "ahb"; -+ status = "disabled"; -+ }; -+ - iep_mmu: iommu@20070800 { - compatible = "rockchip,iommu"; - reg = <0x20070800 0x100>; - -Enable RGA for Mecer Xtreme Mini S6. - -Signed-off-by: Justin Swartz ---- - arch/arm/boot/dts/rk3229-xms6.dts | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/arch/arm/boot/dts/rk3229-xms6.dts b/arch/arm/boot/dts/rk3229-xms6.dts -index 679fc2b00..894f64a4a 100644 ---- a/arch/arm/boot/dts/rk3229-xms6.dts -+++ b/arch/arm/boot/dts/rk3229-xms6.dts -@@ -202,6 +202,10 @@ - status = "okay"; - }; - -+&rga { -+ status = "okay"; -+}; -+ - &sdmmc { - cap-mmc-highspeed; - disable-wp; diff --git a/patch/kernel/rk322x-dev/01-linux-0021-drm-from-5.9.patch b/patch/kernel/rk322x-dev/01-linux-0021-drm-from-5.9.patch new file mode 100644 index 000000000..d97f0818a --- /dev/null +++ b/patch/kernel/rk322x-dev/01-linux-0021-drm-from-5.9.patch @@ -0,0 +1,3500 @@ +From 761a6a88e4fc8d732b6d4319d0bf6f0206d280de Mon Sep 17 00:00:00 2001 +From: Emil Velikov +Date: Tue, 5 May 2020 16:16:13 +0100 +Subject: [PATCH] drm/rockchip: vop: call vop_cfg_done() under reg_lock +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The function vop_cfg_done() is a simple VOP_REG_SET(). As such it should +be done under a reg_lock. A quick look through the driver shows that all +other instances (apart from driver init) have the lock. Do the same here + +Cc: Sandy Huang +Cc: Heiko Stübner +Signed-off-by: Emil Velikov +Reviewed-by: Sandy Huang +Link: https://patchwork.freedesktop.org/patch/msgid/20200505151613.2932456-1-emil.l.velikov@gmail.com +(cherry picked from commit 5fa63f0773323b1d028f2da5c94b8f3e38619b69) +--- + drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +index 33463b79a37b..1d76455ca933 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +@@ -645,10 +645,10 @@ static int vop_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state) + s->enable_afbc = false; + } + +- spin_unlock(&vop->reg_lock); +- + vop_cfg_done(vop); + ++ spin_unlock(&vop->reg_lock); ++ + /* + * At here, vop clock & iommu is enable, R/W vop regs would be safe. + */ + +From 7e1b1997341632ffac3e1ab8fdac8923929403c9 Mon Sep 17 00:00:00 2001 +From: Bernard Zhao +Date: Mon, 27 Apr 2020 01:05:23 -0700 +Subject: [PATCH] drivers: video: hdmi: cleanup coding style in video a bit + +Eliminate the magic numbers, add vendor infoframe size macro +like other hdmi modules. + +Signed-off-by: Bernard Zhao +Cc: Uma Shankar +Cc: Ville Syrjala +Cc: Shashank Sharma +Cc: Laurent Pinchart +Cc: Daniel Vetter +Cc: opensource.kernel@vivo.com +[b.zolnierkie: add "hdmi" to the patch summary] +[b.zolnierkie: fix "vender" -> vendor" typo in the patch description] +Signed-off-by: Bartlomiej Zolnierkiewicz +Link: https://patchwork.freedesktop.org/patch/msgid/20200427080530.3234-1-bernard@vivo.com +(cherry picked from commit d43be2554b58621a21cb5f54b32db2263b3008b6) +--- + drivers/video/hdmi.c | 2 +- + include/linux/hdmi.h | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c +index e70792b3e367..b7a1d6fae90d 100644 +--- a/drivers/video/hdmi.c ++++ b/drivers/video/hdmi.c +@@ -495,7 +495,7 @@ int hdmi_vendor_infoframe_init(struct hdmi_vendor_infoframe *frame) + * value + */ + frame->s3d_struct = HDMI_3D_STRUCTURE_INVALID; +- frame->length = 4; ++ frame->length = HDMI_VENDOR_INFOFRAME_SIZE; + + return 0; + } +diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h +index 50c31f1a0a2d..9850d59d6f1c 100644 +--- a/include/linux/hdmi.h ++++ b/include/linux/hdmi.h +@@ -57,6 +57,7 @@ enum hdmi_infoframe_type { + #define HDMI_SPD_INFOFRAME_SIZE 25 + #define HDMI_AUDIO_INFOFRAME_SIZE 10 + #define HDMI_DRM_INFOFRAME_SIZE 26 ++#define HDMI_VENDOR_INFOFRAME_SIZE 4 + + #define HDMI_INFOFRAME_SIZE(type) \ + (HDMI_INFOFRAME_HEADER_SIZE + HDMI_ ## type ## _INFOFRAME_SIZE) + +From 86ce9313bd2561a632b4f3a03bdb894b92b988bb Mon Sep 17 00:00:00 2001 +From: Paul Kocialkowski +Date: Thu, 16 Apr 2020 16:05:26 +0200 +Subject: [PATCH] drm/rockchip: Add per-pixel alpha support for the PX30 VOP + +Compared to its predecessors, the PX30 VOP has a different register layout +for enabling per-pixel alpha. Instead of src_alpha_ctl and dst_alpha_ctl, +there is a single alpha control register. This register takes some fields +from src_alpha_ctl, but with a different layout. + +Add support for the required fields to the PX30 VOP window descriptions, +which makes per-pixel-alpha formats behave correctly. + +Signed-off-by: Paul Kocialkowski +Signed-off-by: Heiko Stuebner +Link: https://patchwork.freedesktop.org/patch/msgid/20200416140526.262533-1-paul.kocialkowski@bootlin.com +(cherry picked from commit 2aae8ed1f390a42ec752e4403ffca877fb3260e1) +--- + drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 4 ++++ + drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 3 +++ + drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 9 +++++++++ + 3 files changed, 16 insertions(+) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +index 1d76455ca933..c80f7d9fd13f 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +@@ -1007,6 +1007,10 @@ static void vop_plane_atomic_update(struct drm_plane *plane, + SRC_ALPHA_CAL_M0(ALPHA_NO_SATURATION) | + SRC_FACTOR_M0(ALPHA_ONE); + VOP_WIN_SET(vop, win, src_alpha_ctl, val); ++ ++ VOP_WIN_SET(vop, win, alpha_pre_mul, ALPHA_SRC_PRE_MUL); ++ VOP_WIN_SET(vop, win, alpha_mode, ALPHA_PER_PIX); ++ VOP_WIN_SET(vop, win, alpha_en, 1); + } else { + VOP_WIN_SET(vop, win, src_alpha_ctl, SRC_ALPHA_EN(0)); + } +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +index d03bdb531ef2..4a2099cb582e 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +@@ -167,6 +167,9 @@ struct vop_win_phy { + + struct vop_reg dst_alpha_ctl; + struct vop_reg src_alpha_ctl; ++ struct vop_reg alpha_pre_mul; ++ struct vop_reg alpha_mode; ++ struct vop_reg alpha_en; + struct vop_reg channel; + }; + +diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +index 2413deded22c..80053d91a301 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c ++++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +@@ -264,6 +264,9 @@ static const struct vop_win_phy px30_win0_data = { + .uv_mst = VOP_REG(PX30_WIN0_CBR_MST0, 0xffffffff, 0), + .yrgb_vir = VOP_REG(PX30_WIN0_VIR, 0x1fff, 0), + .uv_vir = VOP_REG(PX30_WIN0_VIR, 0x1fff, 16), ++ .alpha_pre_mul = VOP_REG(PX30_WIN0_ALPHA_CTRL, 0x1, 2), ++ .alpha_mode = VOP_REG(PX30_WIN0_ALPHA_CTRL, 0x1, 1), ++ .alpha_en = VOP_REG(PX30_WIN0_ALPHA_CTRL, 0x1, 0), + }; + + static const struct vop_win_phy px30_win1_data = { +@@ -277,6 +280,9 @@ static const struct vop_win_phy px30_win1_data = { + .dsp_st = VOP_REG(PX30_WIN1_DSP_ST, 0xffffffff, 0), + .yrgb_mst = VOP_REG(PX30_WIN1_MST, 0xffffffff, 0), + .yrgb_vir = VOP_REG(PX30_WIN1_VIR, 0x1fff, 0), ++ .alpha_pre_mul = VOP_REG(PX30_WIN1_ALPHA_CTRL, 0x1, 2), ++ .alpha_mode = VOP_REG(PX30_WIN1_ALPHA_CTRL, 0x1, 1), ++ .alpha_en = VOP_REG(PX30_WIN1_ALPHA_CTRL, 0x1, 0), + }; + + static const struct vop_win_phy px30_win2_data = { +@@ -291,6 +297,9 @@ static const struct vop_win_phy px30_win2_data = { + .dsp_st = VOP_REG(PX30_WIN2_DSP_ST0, 0x1fff1fff, 0), + .yrgb_mst = VOP_REG(PX30_WIN2_MST0, 0xffffffff, 0), + .yrgb_vir = VOP_REG(PX30_WIN2_VIR0_1, 0x1fff, 0), ++ .alpha_pre_mul = VOP_REG(PX30_WIN2_ALPHA_CTRL, 0x1, 2), ++ .alpha_mode = VOP_REG(PX30_WIN2_ALPHA_CTRL, 0x1, 1), ++ .alpha_en = VOP_REG(PX30_WIN2_ALPHA_CTRL, 0x1, 0), + }; + + static const struct vop_win_data px30_vop_big_win_data[] = { + +From 022f13fb762722cc81f51f2615131fd4b4cd72e6 Mon Sep 17 00:00:00 2001 +From: Krzysztof Kozlowski +Date: Wed, 27 May 2020 22:05:44 +0200 +Subject: [PATCH] drm/panfrost: Reduce the amount of logs on deferred probe + +There is no point to print deferred probe (and its failures to get +resources) as an error. Also there is no need to print regulator errors +twice. + +In case of multiple probe tries this would pollute the dmesg. + +Signed-off-by: Krzysztof Kozlowski +Reviewed-by: Steven Price +Signed-off-by: Steven Price +Link: https://patchwork.freedesktop.org/patch/msgid/20200527200544.7849-1-krzk@kernel.org +(cherry picked from commit e63adeccc0bbba34a7b988b8898bebbd5bbb6461) +--- + drivers/gpu/drm/panfrost/panfrost_device.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/panfrost/panfrost_device.c b/drivers/gpu/drm/panfrost/panfrost_device.c +index 8136babd3ba9..b172087eee6a 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_device.c ++++ b/drivers/gpu/drm/panfrost/panfrost_device.c +@@ -101,7 +101,9 @@ static int panfrost_regulator_init(struct panfrost_device *pfdev) + pfdev->comp->num_supplies, + pfdev->regulators); + if (ret < 0) { +- dev_err(pfdev->dev, "failed to get regulators: %d\n", ret); ++ if (ret != -EPROBE_DEFER) ++ dev_err(pfdev->dev, "failed to get regulators: %d\n", ++ ret); + return ret; + } + +@@ -213,10 +215,8 @@ int panfrost_device_init(struct panfrost_device *pfdev) + } + + err = panfrost_regulator_init(pfdev); +- if (err) { +- dev_err(pfdev->dev, "regulator init failed %d\n", err); ++ if (err) + goto err_out0; +- } + + err = panfrost_reset_init(pfdev); + if (err) { + +From 9bda1bca65f6067e191b056e6884ba7a9a0c4c09 Mon Sep 17 00:00:00 2001 +From: Dinghao Liu +Date: Fri, 22 May 2020 21:41:09 +0800 +Subject: [PATCH] drm/panfrost: Fix runtime PM imbalance on error + +The caller expects panfrost_job_hw_submit() to increase +runtime PM usage counter. The refcount decrement on the +error branch of WARN_ON() will break the counter balance +and needs to be removed. + +Signed-off-by: Dinghao Liu +Reviewed-by: Steven Price +Signed-off-by: Steven Price +Link: https://patchwork.freedesktop.org/patch/msgid/20200522134109.27204-1-dinghao.liu@zju.edu.cn +(cherry picked from commit 64092598c4566dc80a71ca57396dc36fdbf3da4b) +--- + drivers/gpu/drm/panfrost/panfrost_job.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c b/drivers/gpu/drm/panfrost/panfrost_job.c +index f9519afca29d..c6242fe34840 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_job.c ++++ b/drivers/gpu/drm/panfrost/panfrost_job.c +@@ -152,7 +152,6 @@ static void panfrost_job_hw_submit(struct panfrost_job *job, int js) + return; + + if (WARN_ON(job_read(pfdev, JS_COMMAND_NEXT(js)))) { +- pm_runtime_put_sync_autosuspend(pfdev->dev); + return; + } + + +From 3c403361c554bd46a9ddb2b0d794785916327a83 Mon Sep 17 00:00:00 2001 +From: Ben Davis +Date: Mon, 1 Jun 2020 17:28:17 +0100 +Subject: [PATCH] drm: drm_fourcc: add NV15, Q410, Q401 YUV formats + +DRM_FORMAT_NV15 is a 2 plane format suitable for linear and 16x16 +block-linear memory layouts (DRM_FORMAT_MOD_SAMSUNG_16_16_TILE). The +format is similar to P010 with 4:2:0 sub-sampling but has no padding +between components. Instead, luminance and chrominance samples are +grouped into 4s so that each group is packed into an integer number +of bytes: + +YYYY = UVUV = 4 * 10 bits = 40 bits = 5 bytes + +The '15' suffix refers to the optimum effective bits per pixel which is +achieved when the total number of luminance samples is a multiple of 8. + +Q410 and Q401 are both 3 plane non-subsampled formats with 16 bits per +component, but only 10 bits are used and 6 are padded. 'Q' is chosen +as the first letter to denote 3 plane YUV444, (and is the next letter +along from P which is usually 2 plane). + +V2: Updated block_w of NV15 to {4, 2, 0} +V3: Updated commit message to include specific modifier name + +NV15: +Tested-by: Jonas Karlman + +Reviewed-by: Brian Starkey +Signed-off-by: Ben Davis +Signed-off-by: Liviu Dudau +Link: https://patchwork.freedesktop.org/patch/msgid/20200601162817.18230-1-ben.davis@arm.com +(cherry picked from commit 94b292b277343190175d39172c903c0c5fb814f1) +--- + drivers/gpu/drm/drm_fourcc.c | 12 ++++++++++++ + include/uapi/drm/drm_fourcc.h | 22 ++++++++++++++++++++++ + 2 files changed, 34 insertions(+) + +diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c +index b234bfaeda06..722c7ebe4e88 100644 +--- a/drivers/gpu/drm/drm_fourcc.c ++++ b/drivers/gpu/drm/drm_fourcc.c +@@ -274,6 +274,18 @@ const struct drm_format_info *__drm_format_info(u32 format) + { .format = DRM_FORMAT_YUV420_10BIT, .depth = 0, + .num_planes = 1, .cpp = { 0, 0, 0 }, .hsub = 2, .vsub = 2, + .is_yuv = true }, ++ { .format = DRM_FORMAT_NV15, .depth = 0, ++ .num_planes = 2, .char_per_block = { 5, 5, 0 }, ++ .block_w = { 4, 2, 0 }, .block_h = { 1, 1, 0 }, .hsub = 2, ++ .vsub = 2, .is_yuv = true }, ++ { .format = DRM_FORMAT_Q410, .depth = 0, ++ .num_planes = 3, .char_per_block = { 2, 2, 2 }, ++ .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 }, .hsub = 0, ++ .vsub = 0, .is_yuv = true }, ++ { .format = DRM_FORMAT_Q401, .depth = 0, ++ .num_planes = 3, .char_per_block = { 2, 2, 2 }, ++ .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 }, .hsub = 0, ++ .vsub = 0, .is_yuv = true }, + }; + + unsigned int i; +diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h +index 490143500a50..8ba2d9153a94 100644 +--- a/include/uapi/drm/drm_fourcc.h ++++ b/include/uapi/drm/drm_fourcc.h +@@ -236,6 +236,12 @@ extern "C" { + #define DRM_FORMAT_NV61 fourcc_code('N', 'V', '6', '1') /* 2x1 subsampled Cb:Cr plane */ + #define DRM_FORMAT_NV24 fourcc_code('N', 'V', '2', '4') /* non-subsampled Cr:Cb plane */ + #define DRM_FORMAT_NV42 fourcc_code('N', 'V', '4', '2') /* non-subsampled Cb:Cr plane */ ++/* ++ * 2 plane YCbCr ++ * index 0 = Y plane, [39:0] Y3:Y2:Y1:Y0 little endian ++ * index 1 = Cr:Cb plane, [39:0] Cr1:Cb1:Cr0:Cb0 little endian ++ */ ++#define DRM_FORMAT_NV15 fourcc_code('N', 'V', '1', '5') /* 2x2 subsampled Cr:Cb plane */ + + /* + * 2 plane YCbCr MSB aligned +@@ -265,6 +271,22 @@ extern "C" { + */ + #define DRM_FORMAT_P016 fourcc_code('P', '0', '1', '6') /* 2x2 subsampled Cr:Cb plane 16 bits per channel */ + ++/* 3 plane non-subsampled (444) YCbCr ++ * 16 bits per component, but only 10 bits are used and 6 bits are padded ++ * index 0: Y plane, [15:0] Y:x [10:6] little endian ++ * index 1: Cb plane, [15:0] Cb:x [10:6] little endian ++ * index 2: Cr plane, [15:0] Cr:x [10:6] little endian ++ */ ++#define DRM_FORMAT_Q410 fourcc_code('Q', '4', '1', '0') ++ ++/* 3 plane non-subsampled (444) YCrCb ++ * 16 bits per component, but only 10 bits are used and 6 bits are padded ++ * index 0: Y plane, [15:0] Y:x [10:6] little endian ++ * index 1: Cr plane, [15:0] Cr:x [10:6] little endian ++ * index 2: Cb plane, [15:0] Cb:x [10:6] little endian ++ */ ++#define DRM_FORMAT_Q401 fourcc_code('Q', '4', '0', '1') ++ + /* + * 3 plane YCbCr + * index 0: Y plane, [7:0] Y + +From 7e57394c63258ac63d5c74cbd2a700916c31d4f6 Mon Sep 17 00:00:00 2001 +From: Ben Davis +Date: Thu, 30 Apr 2020 09:32:20 +0100 +Subject: [PATCH] drm: drm_fourcc: Add uncompressed AFBC modifier + +AFBC has a mode that guarantees use of AFBC with an uncompressed +payloads, we add a new modifier to support this mode. + +V2: updated modifier comment + +Signed-off-by: Ben Davis +Acked-by: Liviu Dudau +Signed-off-by: Liviu Dudau +Link: https://patchwork.freedesktop.org/patch/msgid/20200430083220.17347-1-ben.davis@arm.com +(cherry picked from commit 79ce058032c391b12af928b1e30abf92482a270f) +--- + include/uapi/drm/drm_fourcc.h | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h +index 8ba2d9153a94..993c1b342315 100644 +--- a/include/uapi/drm/drm_fourcc.h ++++ b/include/uapi/drm/drm_fourcc.h +@@ -914,6 +914,18 @@ drm_fourcc_canonicalize_nvidia_format_mod(__u64 modifier) + */ + #define AFBC_FORMAT_MOD_BCH (1ULL << 11) + ++/* AFBC uncompressed storage mode ++ * ++ * Indicates that the buffer is using AFBC uncompressed storage mode. ++ * In this mode all superblock payloads in the buffer use the uncompressed ++ * storage mode, which is usually only used for data which cannot be compressed. ++ * The buffer layout is the same as for AFBC buffers without USM set, this only ++ * affects the storage mode of the individual superblocks. Note that even a ++ * buffer without USM set may use uncompressed storage mode for some or all ++ * superblocks, USM just guarantees it for all. ++ */ ++#define AFBC_FORMAT_MOD_USM (1ULL << 12) ++ + /* + * Arm 16x16 Block U-Interleaved modifier + * + +From 32b33df85c3c84ce2a145f2d68305116fbec91fd Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Tue, 26 May 2020 04:14:47 +0300 +Subject: [PATCH] drm: edid: Constify connector argument to infoframe functions + +The drm_hdmi_avi_infoframe_from_display_mode(), +drm_hdmi_vendor_infoframe_from_display_mode() and +drm_hdmi_avi_infoframe_quant_range() functions take a drm_connector that +they don't modify. Mark it as const. + +Signed-off-by: Laurent Pinchart +Acked-by: Sam Ravnborg +Signed-off-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/20200526011505.31884-10-laurent.pinchart+renesas@ideasonboard.com +(cherry picked from commit 192a3aa0e4e20e1087baa29183c5d64d48716fa9) +--- + drivers/gpu/drm/drm_edid.c | 12 ++++++------ + include/drm/drm_edid.h | 6 +++--- + 2 files changed, 9 insertions(+), 9 deletions(-) + +diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c +index fed653f13c26..b3f659759adb 100644 +--- a/drivers/gpu/drm/drm_edid.c ++++ b/drivers/gpu/drm/drm_edid.c +@@ -5366,7 +5366,7 @@ void drm_set_preferred_mode(struct drm_connector *connector, + } + EXPORT_SYMBOL(drm_set_preferred_mode); + +-static bool is_hdmi2_sink(struct drm_connector *connector) ++static bool is_hdmi2_sink(const struct drm_connector *connector) + { + /* + * FIXME: sil-sii8620 doesn't have a connector around when +@@ -5451,7 +5451,7 @@ drm_hdmi_infoframe_set_hdr_metadata(struct hdmi_drm_infoframe *frame, + } + EXPORT_SYMBOL(drm_hdmi_infoframe_set_hdr_metadata); + +-static u8 drm_mode_hdmi_vic(struct drm_connector *connector, ++static u8 drm_mode_hdmi_vic(const struct drm_connector *connector, + const struct drm_display_mode *mode) + { + bool has_hdmi_infoframe = connector ? +@@ -5467,7 +5467,7 @@ static u8 drm_mode_hdmi_vic(struct drm_connector *connector, + return drm_match_hdmi_mode(mode); + } + +-static u8 drm_mode_cea_vic(struct drm_connector *connector, ++static u8 drm_mode_cea_vic(const struct drm_connector *connector, + const struct drm_display_mode *mode) + { + u8 vic; +@@ -5505,7 +5505,7 @@ static u8 drm_mode_cea_vic(struct drm_connector *connector, + */ + int + drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame, +- struct drm_connector *connector, ++ const struct drm_connector *connector, + const struct drm_display_mode *mode) + { + enum hdmi_picture_aspect picture_aspect; +@@ -5652,7 +5652,7 @@ EXPORT_SYMBOL(drm_hdmi_avi_infoframe_colorspace); + */ + void + drm_hdmi_avi_infoframe_quant_range(struct hdmi_avi_infoframe *frame, +- struct drm_connector *connector, ++ const struct drm_connector *connector, + const struct drm_display_mode *mode, + enum hdmi_quantization_range rgb_quant_range) + { +@@ -5756,7 +5756,7 @@ s3d_structure_from_display_mode(const struct drm_display_mode *mode) + */ + int + drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame, +- struct drm_connector *connector, ++ const struct drm_connector *connector, + const struct drm_display_mode *mode) + { + /* +diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h +index 34b15e3d070c..43254319ab19 100644 +--- a/include/drm/drm_edid.h ++++ b/include/drm/drm_edid.h +@@ -361,11 +361,11 @@ drm_load_edid_firmware(struct drm_connector *connector) + + int + drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame, +- struct drm_connector *connector, ++ const struct drm_connector *connector, + const struct drm_display_mode *mode); + int + drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame, +- struct drm_connector *connector, ++ const struct drm_connector *connector, + const struct drm_display_mode *mode); + + void +@@ -378,7 +378,7 @@ drm_hdmi_avi_infoframe_bars(struct hdmi_avi_infoframe *frame, + + void + drm_hdmi_avi_infoframe_quant_range(struct hdmi_avi_infoframe *frame, +- struct drm_connector *connector, ++ const struct drm_connector *connector, + const struct drm_display_mode *mode, + enum hdmi_quantization_range rgb_quant_range); + + +From 23fe85a8775eb3c926be0f3d2bc99b70a6d0bb07 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Tue, 26 May 2020 04:14:48 +0300 +Subject: [PATCH] drm: bridge: Pass drm_display_info to drm_bridge_funcs + .mode_valid() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When validating a mode, bridges may need to do so in the context of a +display, as specified by drm_display_info. An example is the meson +dw-hdmi bridge that needs to consider the YUV 4:2:0 output format to +perform clock calculations. + +Bridges that need the display info currently retrieve it from the +drm_connector created by the bridge. This gets in the way of moving +connector creation out of bridge drivers. To make this possible, pass +the drm_display_info to drm_bridge_funcs .mode_valid(). + +Changes to the bridge drivers have been performed with the following +coccinelle semantic patch and have been compile-tested. + +@ rule1 @ +identifier funcs; +identifier fn; +@@ + struct drm_bridge_funcs funcs = { + ..., + .mode_valid = fn + }; + +@ depends on rule1 @ +identifier rule1.fn; +identifier bridge; +identifier mode; +@@ + enum drm_mode_status fn( + struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode + ) + { + ... + } + +Signed-off-by: Laurent Pinchart +Reviewed-by: Neil Armstrong +Reviewed-by: Boris Brezillon +Reviewed-by: Guido Günther # for the nwl-dsi part: +Signed-off-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/20200526011505.31884-11-laurent.pinchart+renesas@ideasonboard.com +(cherry picked from commit 12c683e12cd8e2dcf7b7143bebceae484d17727a) +--- + drivers/gpu/drm/bridge/analogix/analogix-anx6345.c | 1 + + drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c | 1 + + drivers/gpu/drm/bridge/cdns-dsi.c | 1 + + drivers/gpu/drm/bridge/chrontel-ch7033.c | 1 + + drivers/gpu/drm/bridge/nwl-dsi.c | 1 + + drivers/gpu/drm/bridge/sii9234.c | 1 + + drivers/gpu/drm/bridge/sil-sii8620.c | 1 + + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 1 + + drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 1 + + drivers/gpu/drm/bridge/tc358767.c | 1 + + drivers/gpu/drm/bridge/tc358768.c | 1 + + drivers/gpu/drm/bridge/thc63lvd1024.c | 1 + + drivers/gpu/drm/bridge/ti-tfp410.c | 1 + + drivers/gpu/drm/drm_atomic_helper.c | 3 ++- + drivers/gpu/drm/drm_bridge.c | 4 +++- + drivers/gpu/drm/drm_probe_helper.c | 4 +++- + drivers/gpu/drm/i2c/tda998x_drv.c | 1 + + drivers/gpu/drm/omapdrm/dss/dpi.c | 1 + + drivers/gpu/drm/omapdrm/dss/sdi.c | 1 + + drivers/gpu/drm/omapdrm/dss/venc.c | 1 + + include/drm/drm_bridge.h | 3 +++ + 21 files changed, 28 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c b/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c +index 9af39ec958db..f082b4ed4878 100644 +--- a/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c ++++ b/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c +@@ -588,6 +588,7 @@ static int anx6345_bridge_attach(struct drm_bridge *bridge, + + static enum drm_mode_status + anx6345_bridge_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + if (mode->flags & DRM_MODE_FLAG_INTERLACE) +diff --git a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c +index 0d5a5ad0c9ee..81debd02c169 100644 +--- a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c ++++ b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c +@@ -944,6 +944,7 @@ static int anx78xx_bridge_attach(struct drm_bridge *bridge, + + static enum drm_mode_status + anx78xx_bridge_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + if (mode->flags & DRM_MODE_FLAG_INTERLACE) +diff --git a/drivers/gpu/drm/bridge/cdns-dsi.c b/drivers/gpu/drm/bridge/cdns-dsi.c +index 69c3892caee5..76373e31df92 100644 +--- a/drivers/gpu/drm/bridge/cdns-dsi.c ++++ b/drivers/gpu/drm/bridge/cdns-dsi.c +@@ -663,6 +663,7 @@ static int cdns_dsi_bridge_attach(struct drm_bridge *bridge, + + static enum drm_mode_status + cdns_dsi_bridge_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge); +diff --git a/drivers/gpu/drm/bridge/chrontel-ch7033.c b/drivers/gpu/drm/bridge/chrontel-ch7033.c +index f8675d82974b..486f405c2e16 100644 +--- a/drivers/gpu/drm/bridge/chrontel-ch7033.c ++++ b/drivers/gpu/drm/bridge/chrontel-ch7033.c +@@ -317,6 +317,7 @@ static void ch7033_bridge_detach(struct drm_bridge *bridge) + } + + static enum drm_mode_status ch7033_bridge_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + if (mode->clock > 165000) +diff --git a/drivers/gpu/drm/bridge/nwl-dsi.c b/drivers/gpu/drm/bridge/nwl-dsi.c +index c7bc194bbce3..ce94f797d090 100644 +--- a/drivers/gpu/drm/bridge/nwl-dsi.c ++++ b/drivers/gpu/drm/bridge/nwl-dsi.c +@@ -818,6 +818,7 @@ static bool nwl_dsi_bridge_mode_fixup(struct drm_bridge *bridge, + + static enum drm_mode_status + nwl_dsi_bridge_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + struct nwl_dsi *dsi = bridge_to_dsi(bridge); +diff --git a/drivers/gpu/drm/bridge/sii9234.c b/drivers/gpu/drm/bridge/sii9234.c +index b1258f0ed205..15c98a7bd81c 100644 +--- a/drivers/gpu/drm/bridge/sii9234.c ++++ b/drivers/gpu/drm/bridge/sii9234.c +@@ -873,6 +873,7 @@ static inline struct sii9234 *bridge_to_sii9234(struct drm_bridge *bridge) + } + + static enum drm_mode_status sii9234_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + if (mode->clock > MHL1_MAX_CLK) +diff --git a/drivers/gpu/drm/bridge/sil-sii8620.c b/drivers/gpu/drm/bridge/sil-sii8620.c +index ca98133411aa..95f3d8cfe9ec 100644 +--- a/drivers/gpu/drm/bridge/sil-sii8620.c ++++ b/drivers/gpu/drm/bridge/sil-sii8620.c +@@ -2244,6 +2244,7 @@ static int sii8620_is_packing_required(struct sii8620 *ctx, + } + + static enum drm_mode_status sii8620_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + struct sii8620 *ctx = bridge_to_sii8620(bridge); +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 30681398cfb0..b535354150db 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -2767,6 +2767,7 @@ static void dw_hdmi_bridge_detach(struct drm_bridge *bridge) + + static enum drm_mode_status + dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + struct dw_hdmi *hdmi = bridge->driver_private; +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c +index 5ef0f154aa7b..c223fb9a04cb 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c +@@ -924,6 +924,7 @@ static void dw_mipi_dsi_bridge_enable(struct drm_bridge *bridge) + + static enum drm_mode_status + dw_mipi_dsi_bridge_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge); +diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c +index e4c0ea03ae3a..c2777b226c75 100644 +--- a/drivers/gpu/drm/bridge/tc358767.c ++++ b/drivers/gpu/drm/bridge/tc358767.c +@@ -1306,6 +1306,7 @@ static bool tc_bridge_mode_fixup(struct drm_bridge *bridge, + } + + static enum drm_mode_status tc_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + struct tc_data *tc = bridge_to_tc(bridge); +diff --git a/drivers/gpu/drm/bridge/tc358768.c b/drivers/gpu/drm/bridge/tc358768.c +index 6650fe4cfc20..4a463fadf743 100644 +--- a/drivers/gpu/drm/bridge/tc358768.c ++++ b/drivers/gpu/drm/bridge/tc358768.c +@@ -529,6 +529,7 @@ static int tc358768_bridge_attach(struct drm_bridge *bridge, + + static enum drm_mode_status + tc358768_bridge_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + struct tc358768_priv *priv = bridge_to_tc358768(bridge); +diff --git a/drivers/gpu/drm/bridge/thc63lvd1024.c b/drivers/gpu/drm/bridge/thc63lvd1024.c +index 97d8129760e9..86b06975bfdd 100644 +--- a/drivers/gpu/drm/bridge/thc63lvd1024.c ++++ b/drivers/gpu/drm/bridge/thc63lvd1024.c +@@ -51,6 +51,7 @@ static int thc63_attach(struct drm_bridge *bridge, + } + + static enum drm_mode_status thc63_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + struct thc63_dev *thc63 = to_thc63(bridge); +diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c +index e3eb6364c0f7..30230c552aeb 100644 +--- a/drivers/gpu/drm/bridge/ti-tfp410.c ++++ b/drivers/gpu/drm/bridge/ti-tfp410.c +@@ -188,6 +188,7 @@ static void tfp410_disable(struct drm_bridge *bridge) + } + + static enum drm_mode_status tfp410_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + if (mode->clock < 25000) +diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c +index b78e142a5620..ab9078eaa912 100644 +--- a/drivers/gpu/drm/drm_atomic_helper.c ++++ b/drivers/gpu/drm/drm_atomic_helper.c +@@ -507,7 +507,8 @@ static enum drm_mode_status mode_valid_path(struct drm_connector *connector, + } + + bridge = drm_bridge_chain_get_first_bridge(encoder); +- ret = drm_bridge_chain_mode_valid(bridge, mode); ++ ret = drm_bridge_chain_mode_valid(bridge, &connector->display_info, ++ mode); + if (ret != MODE_OK) { + DRM_DEBUG_ATOMIC("[BRIDGE] mode_valid() failed\n"); + return ret; +diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c +index afdec8e5fc68..8e31af64e8fe 100644 +--- a/drivers/gpu/drm/drm_bridge.c ++++ b/drivers/gpu/drm/drm_bridge.c +@@ -377,6 +377,7 @@ EXPORT_SYMBOL(drm_bridge_chain_mode_fixup); + * drm_bridge_chain_mode_valid - validate the mode against all bridges in the + * encoder chain. + * @bridge: bridge control structure ++ * @info: display info against which the mode shall be validated + * @mode: desired mode to be validated + * + * Calls &drm_bridge_funcs.mode_valid for all the bridges in the encoder +@@ -390,6 +391,7 @@ EXPORT_SYMBOL(drm_bridge_chain_mode_fixup); + */ + enum drm_mode_status + drm_bridge_chain_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + struct drm_encoder *encoder; +@@ -404,7 +406,7 @@ drm_bridge_chain_mode_valid(struct drm_bridge *bridge, + if (!bridge->funcs->mode_valid) + continue; + +- ret = bridge->funcs->mode_valid(bridge, mode); ++ ret = bridge->funcs->mode_valid(bridge, info, mode); + if (ret != MODE_OK) + return ret; + } +diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c +index 576b4b7dcd89..f5d141e0400f 100644 +--- a/drivers/gpu/drm/drm_probe_helper.c ++++ b/drivers/gpu/drm/drm_probe_helper.c +@@ -114,7 +114,9 @@ drm_mode_validate_pipeline(struct drm_display_mode *mode, + } + + bridge = drm_bridge_chain_get_first_bridge(encoder); +- ret = drm_bridge_chain_mode_valid(bridge, mode); ++ ret = drm_bridge_chain_mode_valid(bridge, ++ &connector->display_info, ++ mode); + if (ret != MODE_OK) { + /* There is also no point in continuing for crtc check + * here. */ +diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c +index 9517f522dcb9..50fd119a5276 100644 +--- a/drivers/gpu/drm/i2c/tda998x_drv.c ++++ b/drivers/gpu/drm/i2c/tda998x_drv.c +@@ -1379,6 +1379,7 @@ static void tda998x_bridge_detach(struct drm_bridge *bridge) + } + + static enum drm_mode_status tda998x_bridge_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + /* TDA19988 dotclock can go up to 165MHz */ +diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c b/drivers/gpu/drm/omapdrm/dss/dpi.c +index 5110acb0c6c1..1d2992daef40 100644 +--- a/drivers/gpu/drm/omapdrm/dss/dpi.c ++++ b/drivers/gpu/drm/omapdrm/dss/dpi.c +@@ -434,6 +434,7 @@ static int dpi_bridge_attach(struct drm_bridge *bridge, + + static enum drm_mode_status + dpi_bridge_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + struct dpi_data *dpi = drm_bridge_to_dpi(bridge); +diff --git a/drivers/gpu/drm/omapdrm/dss/sdi.c b/drivers/gpu/drm/omapdrm/dss/sdi.c +index 417a8740ad0a..033fd30074b0 100644 +--- a/drivers/gpu/drm/omapdrm/dss/sdi.c ++++ b/drivers/gpu/drm/omapdrm/dss/sdi.c +@@ -140,6 +140,7 @@ static int sdi_bridge_attach(struct drm_bridge *bridge, + + static enum drm_mode_status + sdi_bridge_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + struct sdi_device *sdi = drm_bridge_to_sdi(bridge); +diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c +index 01ee6c50b663..e0817934ee16 100644 +--- a/drivers/gpu/drm/omapdrm/dss/venc.c ++++ b/drivers/gpu/drm/omapdrm/dss/venc.c +@@ -548,6 +548,7 @@ static int venc_bridge_attach(struct drm_bridge *bridge, + + static enum drm_mode_status + venc_bridge_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + switch (venc_get_videomode(mode)) { +diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h +index ea2aa5ebae34..e3d7f36d8c39 100644 +--- a/include/drm/drm_bridge.h ++++ b/include/drm/drm_bridge.h +@@ -35,6 +35,7 @@ + struct drm_bridge; + struct drm_bridge_timings; + struct drm_connector; ++struct drm_display_info; + struct drm_panel; + struct edid; + struct i2c_adapter; +@@ -112,6 +113,7 @@ struct drm_bridge_funcs { + * drm_mode_status Enum + */ + enum drm_mode_status (*mode_valid)(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode); + + /** +@@ -836,6 +838,7 @@ bool drm_bridge_chain_mode_fixup(struct drm_bridge *bridge, + struct drm_display_mode *adjusted_mode); + enum drm_mode_status + drm_bridge_chain_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode); + void drm_bridge_chain_disable(struct drm_bridge *bridge); + void drm_bridge_chain_post_disable(struct drm_bridge *bridge); + +From a9ae85591e16f342fc822ce27a514f2879ac4c06 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Tue, 26 May 2020 04:14:49 +0300 +Subject: [PATCH] drm: bridge: dw-hdmi: Pass private data pointer to + .mode_valid() + +Platform glue drivers for dw_hdmi may need to access device-specific +data from their .mode_valid() implementation. They currently have no +clean way to do so, and one driver hacks around it by accessing the +dev_private data of the drm_device retrieved from the connector. + +Add a priv_data void pointer to the dw_hdmi_plat_data structure, and +pass it to the .mode_valid() function. + +Signed-off-by: Laurent Pinchart +Reviewed-by: Neil Armstrong +Signed-off-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/20200526011505.31884-12-laurent.pinchart+renesas@ideasonboard.com +(cherry picked from commit 96591a4b93fb8b335941783dd6e7ded9d6d49f09) +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 6 ++++-- + drivers/gpu/drm/imx/dw_hdmi-imx.c | 6 ++++-- + drivers/gpu/drm/meson/meson_dw_hdmi.c | 3 ++- + drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c | 3 ++- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 3 ++- + drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 6 ++++-- + drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 3 ++- + include/drm/bridge/dw_hdmi.h | 14 ++++++++++++-- + 8 files changed, 32 insertions(+), 12 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index b535354150db..2b3f203cf467 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -2771,6 +2771,7 @@ dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge, + const struct drm_display_mode *mode) + { + struct dw_hdmi *hdmi = bridge->driver_private; ++ const struct dw_hdmi_plat_data *pdata = hdmi->plat_data; + struct drm_connector *connector = &hdmi->connector; + enum drm_mode_status mode_status = MODE_OK; + +@@ -2778,8 +2779,9 @@ dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge, + if (mode->flags & DRM_MODE_FLAG_DBLCLK) + return MODE_BAD; + +- if (hdmi->plat_data->mode_valid) +- mode_status = hdmi->plat_data->mode_valid(connector, mode); ++ if (pdata->mode_valid) ++ mode_status = pdata->mode_valid(hdmi, pdata->priv_data, ++ connector, mode); + + return mode_status; + } +diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c +index 87869b9997a6..ff4fde0eb5f6 100644 +--- a/drivers/gpu/drm/imx/dw_hdmi-imx.c ++++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c +@@ -145,7 +145,8 @@ static const struct drm_encoder_helper_funcs dw_hdmi_imx_encoder_helper_funcs = + }; + + static enum drm_mode_status +-imx6q_hdmi_mode_valid(struct drm_connector *con, ++imx6q_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, ++ struct drm_connector *con, + const struct drm_display_mode *mode) + { + if (mode->clock < 13500) +@@ -158,7 +159,8 @@ imx6q_hdmi_mode_valid(struct drm_connector *con, + } + + static enum drm_mode_status +-imx6dl_hdmi_mode_valid(struct drm_connector *con, ++imx6dl_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, ++ struct drm_connector *con, + const struct drm_display_mode *mode) + { + if (mode->clock < 13500) +diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c +index 24a12c453095..fc594213c0e0 100644 +--- a/drivers/gpu/drm/meson/meson_dw_hdmi.c ++++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c +@@ -630,7 +630,8 @@ static irqreturn_t dw_hdmi_top_thread_irq(int irq, void *dev_id) + } + + static enum drm_mode_status +-dw_hdmi_mode_valid(struct drm_connector *connector, ++dw_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, ++ struct drm_connector *connector, + const struct drm_display_mode *mode) + { + struct meson_drm *priv = connector->dev->dev_private; +diff --git a/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c b/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c +index 452461dc96f2..4d837a4d302d 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c ++++ b/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c +@@ -38,7 +38,8 @@ static const struct rcar_hdmi_phy_params rcar_hdmi_phy_params[] = { + }; + + static enum drm_mode_status +-rcar_hdmi_mode_valid(struct drm_connector *connector, ++rcar_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, ++ struct drm_connector *connector, + const struct drm_display_mode *mode) + { + /* +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index 121aa8a63a76..d08f86783a28 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -220,7 +220,8 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) + } + + static enum drm_mode_status +-dw_hdmi_rockchip_mode_valid(struct drm_connector *connector, ++dw_hdmi_rockchip_mode_valid(struct dw_hdmi *hdmi, void *data, ++ struct drm_connector *connector, + const struct drm_display_mode *mode) + { + const struct dw_hdmi_mpll_config *mpll_cfg = rockchip_mpll_cfg; +diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c +index 972682bb8000..0a3637442ba6 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c ++++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c +@@ -31,7 +31,8 @@ sun8i_dw_hdmi_encoder_helper_funcs = { + }; + + static enum drm_mode_status +-sun8i_dw_hdmi_mode_valid_a83t(struct drm_connector *connector, ++sun8i_dw_hdmi_mode_valid_a83t(struct dw_hdmi *hdmi, void *data, ++ struct drm_connector *connector, + const struct drm_display_mode *mode) + { + if (mode->clock > 297000) +@@ -41,7 +42,8 @@ sun8i_dw_hdmi_mode_valid_a83t(struct drm_connector *connector, + } + + static enum drm_mode_status +-sun8i_dw_hdmi_mode_valid_h6(struct drm_connector *connector, ++sun8i_dw_hdmi_mode_valid_h6(struct dw_hdmi *hdmi, void *data, ++ struct drm_connector *connector, + const struct drm_display_mode *mode) + { + /* +diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h +index 8e64945167e9..8587b8d2590e 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h ++++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h +@@ -176,7 +176,8 @@ struct sun8i_hdmi_phy { + }; + + struct sun8i_dw_hdmi_quirks { +- enum drm_mode_status (*mode_valid)(struct drm_connector *connector, ++ enum drm_mode_status (*mode_valid)(struct dw_hdmi *hdmi, void *data, ++ struct drm_connector *connector, + const struct drm_display_mode *mode); + unsigned int set_rate : 1; + unsigned int use_drm_infoframe : 1; +diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h +index 0b34a12c4a1c..66a811f75b91 100644 +--- a/include/drm/bridge/dw_hdmi.h ++++ b/include/drm/bridge/dw_hdmi.h +@@ -124,13 +124,23 @@ struct dw_hdmi_phy_ops { + + struct dw_hdmi_plat_data { + struct regmap *regm; +- enum drm_mode_status (*mode_valid)(struct drm_connector *connector, +- const struct drm_display_mode *mode); ++ + unsigned long input_bus_format; + unsigned long input_bus_encoding; + bool use_drm_infoframe; + bool ycbcr_420_allowed; + ++ /* ++ * Private data passed to all the .mode_valid() and .configure_phy() ++ * callback functions. ++ */ ++ void *priv_data; ++ ++ /* Platform-specific mode validation (optional). */ ++ enum drm_mode_status (*mode_valid)(struct dw_hdmi *hdmi, void *data, ++ struct drm_connector *connector, ++ const struct drm_display_mode *mode); ++ + /* Vendor PHY support */ + const struct dw_hdmi_phy_ops *phy_ops; + const char *phy_name; + +From 5a367989e0577a22f143fd9a0ae8bc3c5e187144 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Tue, 26 May 2020 04:14:50 +0300 +Subject: [PATCH] drm: bridge: dw-hdmi: Pass private data pointer to + .configure_phy() + +The .configure_phy() operation takes a dw_hdmi_plat_data pointer as a +context argument. This differs from .mode_valid() that takes a custom +private context pointer, causing possible confusion. Make the +dw_hdmi_plat_data operations more consistent by passing the private +context pointer to .configure_phy() as well. + +Signed-off-by: Laurent Pinchart +Reviewed-by: Neil Armstrong +Signed-off-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/20200526011505.31884-13-laurent.pinchart+renesas@ideasonboard.com +(cherry picked from commit 49da7e5d84e3b520355c0b6148d6dc9e5415a13e) +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 2 +- + drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c | 3 +-- + include/drm/bridge/dw_hdmi.h | 3 +-- + 3 files changed, 3 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 2b3f203cf467..6edb60e6c784 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -1514,7 +1514,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi) + + /* Write to the PHY as configured by the platform */ + if (pdata->configure_phy) +- ret = pdata->configure_phy(hdmi, pdata, mpixelclock); ++ ret = pdata->configure_phy(hdmi, pdata->priv_data, mpixelclock); + else + ret = phy->configure(hdmi, pdata, mpixelclock); + if (ret) { +diff --git a/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c b/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c +index 4d837a4d302d..d0dffe55a7cb 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c ++++ b/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c +@@ -52,8 +52,7 @@ rcar_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, + return MODE_OK; + } + +-static int rcar_hdmi_phy_configure(struct dw_hdmi *hdmi, +- const struct dw_hdmi_plat_data *pdata, ++static int rcar_hdmi_phy_configure(struct dw_hdmi *hdmi, void *data, + unsigned long mpixelclock) + { + const struct rcar_hdmi_phy_params *params = rcar_hdmi_phy_params; +diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h +index 66a811f75b91..09348c9cbd11 100644 +--- a/include/drm/bridge/dw_hdmi.h ++++ b/include/drm/bridge/dw_hdmi.h +@@ -151,8 +151,7 @@ struct dw_hdmi_plat_data { + const struct dw_hdmi_mpll_config *mpll_cfg; + const struct dw_hdmi_curr_ctrl *cur_ctr; + const struct dw_hdmi_phy_config *phy_config; +- int (*configure_phy)(struct dw_hdmi *hdmi, +- const struct dw_hdmi_plat_data *pdata, ++ int (*configure_phy)(struct dw_hdmi *hdmi, void *data, + unsigned long mpixelclock); + }; + + +From 93a10000d40b44c93674ca8b596019e0b3908541 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Tue, 26 May 2020 04:14:51 +0300 +Subject: [PATCH] drm: bridge: dw-hdmi: Remove unused field from + dw_hdmi_plat_data + +The input_bus_format field of struct dw_hdmi_plat_data is unused. Remove +it. + +Signed-off-by: Laurent Pinchart +Reviewed-by: Neil Armstrong +Signed-off-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/20200526011505.31884-14-laurent.pinchart+renesas@ideasonboard.com +(cherry picked from commit 29fc89719d396e81176974ce37e0cc81e23869d8) +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 5 +---- + include/drm/bridge/dw_hdmi.h | 1 - + 2 files changed, 1 insertion(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 6edb60e6c784..adc5a95a06e9 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -2137,10 +2137,7 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode) + hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 0; + hdmi->hdmi_data.video_mode.mpixelrepetitioninput = 0; + +- if (hdmi->plat_data->input_bus_format) +- hdmi->hdmi_data.enc_in_bus_format = +- hdmi->plat_data->input_bus_format; +- else if (hdmi->hdmi_data.enc_in_bus_format == MEDIA_BUS_FMT_FIXED) ++ if (hdmi->hdmi_data.enc_in_bus_format == MEDIA_BUS_FMT_FIXED) + hdmi->hdmi_data.enc_in_bus_format = MEDIA_BUS_FMT_RGB888_1X24; + + /* TOFIX: Get input encoding from plat data or fallback to none */ +diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h +index 09348c9cbd11..5dfa9d83e2d3 100644 +--- a/include/drm/bridge/dw_hdmi.h ++++ b/include/drm/bridge/dw_hdmi.h +@@ -125,7 +125,6 @@ struct dw_hdmi_phy_ops { + struct dw_hdmi_plat_data { + struct regmap *regm; + +- unsigned long input_bus_format; + unsigned long input_bus_encoding; + bool use_drm_infoframe; + bool ycbcr_420_allowed; + +From 69d79aec4b09b3dce733fedcef1c5f129220e745 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Tue, 26 May 2020 04:14:52 +0300 +Subject: [PATCH] drm: meson: dw-hdmi: Use dw_hdmi context to replace hack + +The meson-dw-hdmi driver needs to access its own context from the +.mode_valid() operation. It currently gets it from the dev_private field +of the drm_device retrieved from the connector, which is a hack. Use the +private data passed to the .mode_valid() operation instead. + +Signed-off-by: Laurent Pinchart +Reviewed-by: Neil Armstrong +Signed-off-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/20200526011505.31884-15-laurent.pinchart+renesas@ideasonboard.com +(cherry picked from commit 9bc78d6dc818701e47c5ebd0879877a512f039f0) +--- + drivers/gpu/drm/meson/meson_dw_hdmi.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c +index fc594213c0e0..607bd9f495b1 100644 +--- a/drivers/gpu/drm/meson/meson_dw_hdmi.c ++++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c +@@ -634,7 +634,8 @@ dw_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, + struct drm_connector *connector, + const struct drm_display_mode *mode) + { +- struct meson_drm *priv = connector->dev->dev_private; ++ struct meson_dw_hdmi *dw_hdmi = data; ++ struct meson_drm *priv = dw_hdmi->priv; + bool is_hdmi2_sink = connector->display_info.hdmi.scdc.supported; + unsigned int phy_freq; + unsigned int vclk_freq; +@@ -693,7 +694,7 @@ dw_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, + if (mode->flags & DRM_MODE_FLAG_DBLCLK) + venc_freq /= 2; + +- dev_dbg(connector->dev->dev, "%s: vclk:%d phy=%d venc=%d hdmi=%d\n", ++ dev_dbg(dw_hdmi->dev, "%s: vclk:%d phy=%d venc=%d hdmi=%d\n", + __func__, phy_freq, vclk_freq, venc_freq, hdmi_freq); + + return meson_vclk_vic_supported_freq(priv, phy_freq, vclk_freq); +@@ -1066,6 +1067,7 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master, + + /* Bridge / Connector */ + ++ dw_plat_data->priv_data = meson_dw_hdmi; + dw_plat_data->mode_valid = dw_hdmi_mode_valid; + dw_plat_data->phy_ops = &meson_dw_hdmi_phy_ops; + dw_plat_data->phy_name = "meson_dw_hdmi_phy"; + +From 76b17d37e5f17f622d947792abcf4477a27b609e Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Tue, 26 May 2020 04:14:53 +0300 +Subject: [PATCH] drm: bridge: dw-hdmi: Pass drm_display_info to .mode_valid() + +Replace the drm_connector pointer passed to the .mode_valid() function +with a const drm_display_info pointer, as that's all the function should +need. Use the display info passed to the bridge .mode_valid() operation +instead of retrieving it from the connector, to prepare for make +connector creation optional. + +Signed-off-by: Laurent Pinchart +Reviewed-by: Neil Armstrong +Signed-off-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/20200526011505.31884-16-laurent.pinchart+renesas@ideasonboard.com +(cherry picked from commit af05bba0fbe2c07fe500f697080d78d050be2fbf) +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 5 ++--- + drivers/gpu/drm/imx/dw_hdmi-imx.c | 4 ++-- + drivers/gpu/drm/meson/meson_dw_hdmi.c | 20 ++++++++++---------- + drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c | 2 +- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2 +- + drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 4 ++-- + drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 2 +- + include/drm/bridge/dw_hdmi.h | 4 ++-- + 8 files changed, 21 insertions(+), 22 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index adc5a95a06e9..23650e69604c 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -2769,7 +2769,6 @@ dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge, + { + struct dw_hdmi *hdmi = bridge->driver_private; + const struct dw_hdmi_plat_data *pdata = hdmi->plat_data; +- struct drm_connector *connector = &hdmi->connector; + enum drm_mode_status mode_status = MODE_OK; + + /* We don't support double-clocked modes */ +@@ -2777,8 +2776,8 @@ dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge, + return MODE_BAD; + + if (pdata->mode_valid) +- mode_status = pdata->mode_valid(hdmi, pdata->priv_data, +- connector, mode); ++ mode_status = pdata->mode_valid(hdmi, pdata->priv_data, info, ++ mode); + + return mode_status; + } +diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c +index ff4fde0eb5f6..71d84c7a5378 100644 +--- a/drivers/gpu/drm/imx/dw_hdmi-imx.c ++++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c +@@ -146,7 +146,7 @@ static const struct drm_encoder_helper_funcs dw_hdmi_imx_encoder_helper_funcs = + + static enum drm_mode_status + imx6q_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, +- struct drm_connector *con, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + if (mode->clock < 13500) +@@ -160,7 +160,7 @@ imx6q_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, + + static enum drm_mode_status + imx6dl_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, +- struct drm_connector *con, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + if (mode->clock < 13500) +diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c +index 607bd9f495b1..50b950f5ca3c 100644 +--- a/drivers/gpu/drm/meson/meson_dw_hdmi.c ++++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c +@@ -631,12 +631,12 @@ static irqreturn_t dw_hdmi_top_thread_irq(int irq, void *dev_id) + + static enum drm_mode_status + dw_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, +- struct drm_connector *connector, ++ const struct drm_display_info *display_info, + const struct drm_display_mode *mode) + { + struct meson_dw_hdmi *dw_hdmi = data; + struct meson_drm *priv = dw_hdmi->priv; +- bool is_hdmi2_sink = connector->display_info.hdmi.scdc.supported; ++ bool is_hdmi2_sink = display_info->hdmi.scdc.supported; + unsigned int phy_freq; + unsigned int vclk_freq; + unsigned int venc_freq; +@@ -647,10 +647,10 @@ dw_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, + DRM_DEBUG_DRIVER("Modeline " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode)); + + /* If sink does not support 540MHz, reject the non-420 HDMI2 modes */ +- if (connector->display_info.max_tmds_clock && +- mode->clock > connector->display_info.max_tmds_clock && +- !drm_mode_is_420_only(&connector->display_info, mode) && +- !drm_mode_is_420_also(&connector->display_info, mode)) ++ if (display_info->max_tmds_clock && ++ mode->clock > display_info->max_tmds_clock && ++ !drm_mode_is_420_only(display_info, mode) && ++ !drm_mode_is_420_also(display_info, mode)) + return MODE_BAD; + + /* Check against non-VIC supported modes */ +@@ -667,9 +667,9 @@ dw_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, + vclk_freq = mode->clock; + + /* For 420, pixel clock is half unlike venc clock */ +- if (drm_mode_is_420_only(&connector->display_info, mode) || ++ if (drm_mode_is_420_only(display_info, mode) || + (!is_hdmi2_sink && +- drm_mode_is_420_also(&connector->display_info, mode))) ++ drm_mode_is_420_also(display_info, mode))) + vclk_freq /= 2; + + /* TMDS clock is pixel_clock * 10 */ +@@ -684,9 +684,9 @@ dw_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, + + /* VENC double pixels for 1080i, 720p and YUV420 modes */ + if (meson_venc_hdmi_venc_repeat(vic) || +- drm_mode_is_420_only(&connector->display_info, mode) || ++ drm_mode_is_420_only(display_info, mode) || + (!is_hdmi2_sink && +- drm_mode_is_420_also(&connector->display_info, mode))) ++ drm_mode_is_420_also(display_info, mode))) + venc_freq *= 2; + + vclk_freq = max(venc_freq, hdmi_freq); +diff --git a/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c b/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c +index d0dffe55a7cb..7b8ec8310699 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c ++++ b/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c +@@ -39,7 +39,7 @@ static const struct rcar_hdmi_phy_params rcar_hdmi_phy_params[] = { + + static enum drm_mode_status + rcar_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, +- struct drm_connector *connector, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + /* +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index d08f86783a28..d286751bb333 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -221,7 +221,7 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) + + static enum drm_mode_status + dw_hdmi_rockchip_mode_valid(struct dw_hdmi *hdmi, void *data, +- struct drm_connector *connector, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + const struct dw_hdmi_mpll_config *mpll_cfg = rockchip_mpll_cfg; +diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c +index 0a3637442ba6..d4c08043dd81 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c ++++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c +@@ -32,7 +32,7 @@ sun8i_dw_hdmi_encoder_helper_funcs = { + + static enum drm_mode_status + sun8i_dw_hdmi_mode_valid_a83t(struct dw_hdmi *hdmi, void *data, +- struct drm_connector *connector, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + if (mode->clock > 297000) +@@ -43,7 +43,7 @@ sun8i_dw_hdmi_mode_valid_a83t(struct dw_hdmi *hdmi, void *data, + + static enum drm_mode_status + sun8i_dw_hdmi_mode_valid_h6(struct dw_hdmi *hdmi, void *data, +- struct drm_connector *connector, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode) + { + /* +diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h +index 8587b8d2590e..d983746fa194 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h ++++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h +@@ -177,7 +177,7 @@ struct sun8i_hdmi_phy { + + struct sun8i_dw_hdmi_quirks { + enum drm_mode_status (*mode_valid)(struct dw_hdmi *hdmi, void *data, +- struct drm_connector *connector, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode); + unsigned int set_rate : 1; + unsigned int use_drm_infoframe : 1; +diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h +index 5dfa9d83e2d3..fec293b21c2e 100644 +--- a/include/drm/bridge/dw_hdmi.h ++++ b/include/drm/bridge/dw_hdmi.h +@@ -8,7 +8,7 @@ + + #include + +-struct drm_connector; ++struct drm_display_info; + struct drm_display_mode; + struct drm_encoder; + struct dw_hdmi; +@@ -137,7 +137,7 @@ struct dw_hdmi_plat_data { + + /* Platform-specific mode validation (optional). */ + enum drm_mode_status (*mode_valid)(struct dw_hdmi *hdmi, void *data, +- struct drm_connector *connector, ++ const struct drm_display_info *info, + const struct drm_display_mode *mode); + + /* Vendor PHY support */ + +From 799196d6da0801a31a7129bbdae2aa760714b187 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Tue, 26 May 2020 04:14:54 +0300 +Subject: [PATCH] drm: bridge: dw-hdmi: Constify mode argument to + dw_hdmi_phy_ops .init() + +The PHY .init() must not modify the mode it receives. Make the pointer +const to enfore that. + +Signed-off-by: Laurent Pinchart +Reviewed-by: Neil Armstrong +Signed-off-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/20200526011505.31884-17-laurent.pinchart+renesas@ideasonboard.com +(cherry picked from commit 35a395f1134bbbd2984dcca28c04f09fbbb8b0a4) +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 2 +- + drivers/gpu/drm/meson/meson_dw_hdmi.c | 4 ++-- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2 +- + drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 2 +- + include/drm/bridge/dw_hdmi.h | 2 +- + 5 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 23650e69604c..6e6a3d95e68e 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -1531,7 +1531,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi) + } + + static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data, +- struct drm_display_mode *mode) ++ const struct drm_display_mode *mode) + { + int i, ret; + +diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c +index 50b950f5ca3c..a1217df5fe5a 100644 +--- a/drivers/gpu/drm/meson/meson_dw_hdmi.c ++++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c +@@ -297,7 +297,7 @@ static inline void dw_hdmi_dwc_write_bits(struct meson_dw_hdmi *dw_hdmi, + + /* Setup PHY bandwidth modes */ + static void meson_hdmi_phy_setup_mode(struct meson_dw_hdmi *dw_hdmi, +- struct drm_display_mode *mode) ++ const struct drm_display_mode *mode) + { + struct meson_drm *priv = dw_hdmi->priv; + unsigned int pixel_clock = mode->clock; +@@ -427,7 +427,7 @@ static void dw_hdmi_set_vclk(struct meson_dw_hdmi *dw_hdmi, + } + + static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data, +- struct drm_display_mode *mode) ++ const struct drm_display_mode *mode) + { + struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data; + struct meson_drm *priv = dw_hdmi->priv; +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index d286751bb333..10e210f6455d 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -312,7 +312,7 @@ static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_fun + }; + + static int dw_hdmi_rockchip_genphy_init(struct dw_hdmi *dw_hdmi, void *data, +- struct drm_display_mode *mode) ++ const struct drm_display_mode *mode) + { + struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; + +diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c +index 43643ad31730..8e078cacf063 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c ++++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c +@@ -341,7 +341,7 @@ static int sun8i_hdmi_phy_config_h3(struct dw_hdmi *hdmi, + } + + static int sun8i_hdmi_phy_config(struct dw_hdmi *hdmi, void *data, +- struct drm_display_mode *mode) ++ const struct drm_display_mode *mode) + { + struct sun8i_hdmi_phy *phy = (struct sun8i_hdmi_phy *)data; + u32 val = 0; +diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h +index fec293b21c2e..f930d218cc6b 100644 +--- a/include/drm/bridge/dw_hdmi.h ++++ b/include/drm/bridge/dw_hdmi.h +@@ -114,7 +114,7 @@ struct dw_hdmi_phy_config { + + struct dw_hdmi_phy_ops { + int (*init)(struct dw_hdmi *hdmi, void *data, +- struct drm_display_mode *mode); ++ const struct drm_display_mode *mode); + void (*disable)(struct dw_hdmi *hdmi, void *data); + enum drm_connector_status (*read_hpd)(struct dw_hdmi *hdmi, void *data); + void (*update_hpd)(struct dw_hdmi *hdmi, void *data, + +From 39e51f084a6c1b5a94151803063f5d2ec44c2389 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Tue, 26 May 2020 04:14:55 +0300 +Subject: [PATCH] drm: bridge: dw-hdmi: Constify mode argument to internal + functions + +Several internal functions take a drm_display_mode argument to configure +the HDMI encoder or the HDMI PHY. They must not modify the mode, make +the pointer const to enforce that. + +Signed-off-by: Laurent Pinchart +Reviewed-by: Neil Armstrong +Signed-off-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/20200526011505.31884-18-laurent.pinchart+renesas@ideasonboard.com +(cherry picked from commit 9fbfa320b435e6f25499a63f7bb74b4fc5341b30) +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 6e6a3d95e68e..5b5f07a23400 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -1628,7 +1628,8 @@ static void hdmi_tx_hdcp_config(struct dw_hdmi *hdmi) + HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK, HDMI_A_HDCPCFG1); + } + +-static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode) ++static void hdmi_config_AVI(struct dw_hdmi *hdmi, ++ const struct drm_display_mode *mode) + { + struct hdmi_avi_infoframe frame; + u8 val; +@@ -1756,7 +1757,7 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode) + } + + static void hdmi_config_vendor_specific_infoframe(struct dw_hdmi *hdmi, +- struct drm_display_mode *mode) ++ const struct drm_display_mode *mode) + { + struct hdmi_vendor_infoframe frame; + u8 buffer[10]; +@@ -2112,7 +2113,8 @@ static void hdmi_disable_overflow_interrupts(struct dw_hdmi *hdmi) + HDMI_IH_MUTE_FC_STAT2); + } + +-static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode) ++static int dw_hdmi_setup(struct dw_hdmi *hdmi, ++ const struct drm_display_mode *mode) + { + int ret; + + +From 9dd65c0f564ebe5257c3d5322e40200ac254570b Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Tue, 26 May 2020 04:14:56 +0300 +Subject: [PATCH] drm: bridge: dw-hdmi: Pass drm_display_info to + dw_hdmi_support_scdc() + +To prepare for making connector creation optional in the driver, pass +the drm_display_info explicitly to dw_hdmi_support_scdc(). The pointer +is passed to the callers where required, particularly to the +dw_hdmi_phy_ops .init() function. + +Signed-off-by: Laurent Pinchart +Reviewed-by: Neil Armstrong +Signed-off-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/20200526011505.31884-19-laurent.pinchart+renesas@ideasonboard.com +(cherry picked from commit 7be390d4c0a125266c558c30a3687d931c3b6101) +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 32 ++++++++++++--------- + drivers/gpu/drm/meson/meson_dw_hdmi.c | 3 +- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 1 + + drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 1 + + include/drm/bridge/dw_hdmi.h | 4 ++- + 5 files changed, 26 insertions(+), 15 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 5b5f07a23400..a18794cce0d8 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -1241,10 +1241,9 @@ void dw_hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data, + EXPORT_SYMBOL_GPL(dw_hdmi_phy_i2c_write); + + /* Filter out invalid setups to avoid configuring SCDC and scrambling */ +-static bool dw_hdmi_support_scdc(struct dw_hdmi *hdmi) ++static bool dw_hdmi_support_scdc(struct dw_hdmi *hdmi, ++ const struct drm_display_info *display) + { +- struct drm_display_info *display = &hdmi->connector.display_info; +- + /* Completely disable SCDC support for older controllers */ + if (hdmi->version < 0x200a) + return false; +@@ -1282,12 +1281,13 @@ static bool dw_hdmi_support_scdc(struct dw_hdmi *hdmi) + * helper should called right before enabling the TMDS Clock and Data in + * the PHY configuration callback. + */ +-void dw_hdmi_set_high_tmds_clock_ratio(struct dw_hdmi *hdmi) ++void dw_hdmi_set_high_tmds_clock_ratio(struct dw_hdmi *hdmi, ++ const struct drm_display_info *display) + { + unsigned long mtmdsclock = hdmi->hdmi_data.video_mode.mtmdsclock; + + /* Control for TMDS Bit Period/TMDS Clock-Period Ratio */ +- if (dw_hdmi_support_scdc(hdmi)) { ++ if (dw_hdmi_support_scdc(hdmi, display)) { + if (mtmdsclock > HDMI14_MAX_TMDSCLK) + drm_scdc_set_high_tmds_clock_ratio(hdmi->ddc, 1); + else +@@ -1490,7 +1490,8 @@ static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi, + return 0; + } + +-static int hdmi_phy_configure(struct dw_hdmi *hdmi) ++static int hdmi_phy_configure(struct dw_hdmi *hdmi, ++ const struct drm_display_info *display) + { + const struct dw_hdmi_phy_data *phy = hdmi->phy.data; + const struct dw_hdmi_plat_data *pdata = hdmi->plat_data; +@@ -1500,7 +1501,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi) + + dw_hdmi_phy_power_off(hdmi); + +- dw_hdmi_set_high_tmds_clock_ratio(hdmi); ++ dw_hdmi_set_high_tmds_clock_ratio(hdmi, display); + + /* Leave low power consumption mode by asserting SVSRET. */ + if (phy->has_svsret) +@@ -1531,6 +1532,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi) + } + + static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data, ++ const struct drm_display_info *display, + const struct drm_display_mode *mode) + { + int i, ret; +@@ -1540,7 +1542,7 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data, + dw_hdmi_phy_sel_data_en_pol(hdmi, 1); + dw_hdmi_phy_sel_interface_control(hdmi, 0); + +- ret = hdmi_phy_configure(hdmi); ++ ret = hdmi_phy_configure(hdmi, display); + if (ret) + return ret; + } +@@ -1846,10 +1848,11 @@ static void hdmi_config_drm_infoframe(struct dw_hdmi *hdmi) + } + + static void hdmi_av_composer(struct dw_hdmi *hdmi, ++ const struct drm_display_info *display, + const struct drm_display_mode *mode) + { + u8 inv_val, bytes; +- struct drm_hdmi_info *hdmi_info = &hdmi->connector.display_info.hdmi; ++ const struct drm_hdmi_info *hdmi_info = &display->hdmi; + struct hdmi_vmode *vmode = &hdmi->hdmi_data.video_mode; + int hblank, vblank, h_de_hs, v_de_vs, hsync_len, vsync_len; + unsigned int vdisplay, hdisplay; +@@ -1882,7 +1885,7 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi, + + /* Set up HDMI_FC_INVIDCONF */ + inv_val = (hdmi->hdmi_data.hdcp_enable || +- (dw_hdmi_support_scdc(hdmi) && ++ (dw_hdmi_support_scdc(hdmi, display) && + (vmode->mtmdsclock > HDMI14_MAX_TMDSCLK || + hdmi_info->scdc.scrambling.low_rates)) ? + HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE : +@@ -1950,7 +1953,7 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi, + } + + /* Scrambling Control */ +- if (dw_hdmi_support_scdc(hdmi)) { ++ if (dw_hdmi_support_scdc(hdmi, display)) { + if (vmode->mtmdsclock > HDMI14_MAX_TMDSCLK || + hdmi_info->scdc.scrambling.low_rates) { + /* +@@ -2116,6 +2119,7 @@ static void hdmi_disable_overflow_interrupts(struct dw_hdmi *hdmi) + static int dw_hdmi_setup(struct dw_hdmi *hdmi, + const struct drm_display_mode *mode) + { ++ struct drm_connector *connector = &hdmi->connector; + int ret; + + hdmi_disable_overflow_interrupts(hdmi); +@@ -2161,10 +2165,12 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, + hdmi->hdmi_data.video_mode.mdataenablepolarity = true; + + /* HDMI Initialization Step B.1 */ +- hdmi_av_composer(hdmi, mode); ++ hdmi_av_composer(hdmi, &connector->display_info, mode); + + /* HDMI Initializateion Step B.2 */ +- ret = hdmi->phy.ops->init(hdmi, hdmi->phy.data, &hdmi->previous_mode); ++ ret = hdmi->phy.ops->init(hdmi, hdmi->phy.data, ++ &connector->display_info, ++ &hdmi->previous_mode); + if (ret) + return ret; + hdmi->phy.enabled = true; +diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c +index a1217df5fe5a..29a8ff41595d 100644 +--- a/drivers/gpu/drm/meson/meson_dw_hdmi.c ++++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c +@@ -427,6 +427,7 @@ static void dw_hdmi_set_vclk(struct meson_dw_hdmi *dw_hdmi, + } + + static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data, ++ const struct drm_display_info *display, + const struct drm_display_mode *mode) + { + struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data; +@@ -496,7 +497,7 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data, + /* Disable clock, fifo, fifo_wr */ + regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 0xf, 0); + +- dw_hdmi_set_high_tmds_clock_ratio(hdmi); ++ dw_hdmi_set_high_tmds_clock_ratio(hdmi, display); + + msleep(100); + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index 10e210f6455d..23de359a1dec 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -312,6 +312,7 @@ static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_fun + }; + + static int dw_hdmi_rockchip_genphy_init(struct dw_hdmi *dw_hdmi, void *data, ++ const struct drm_display_info *display, + const struct drm_display_mode *mode) + { + struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; +diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c +index 8e078cacf063..156d00e5165b 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c ++++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c +@@ -341,6 +341,7 @@ static int sun8i_hdmi_phy_config_h3(struct dw_hdmi *hdmi, + } + + static int sun8i_hdmi_phy_config(struct dw_hdmi *hdmi, void *data, ++ const struct drm_display_info *display, + const struct drm_display_mode *mode) + { + struct sun8i_hdmi_phy *phy = (struct sun8i_hdmi_phy *)data; +diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h +index f930d218cc6b..ea34ca146b82 100644 +--- a/include/drm/bridge/dw_hdmi.h ++++ b/include/drm/bridge/dw_hdmi.h +@@ -114,6 +114,7 @@ struct dw_hdmi_phy_config { + + struct dw_hdmi_phy_ops { + int (*init)(struct dw_hdmi *hdmi, void *data, ++ const struct drm_display_info *display, + const struct drm_display_mode *mode); + void (*disable)(struct dw_hdmi *hdmi, void *data); + enum drm_connector_status (*read_hpd)(struct dw_hdmi *hdmi, void *data); +@@ -174,7 +175,8 @@ void dw_hdmi_set_channel_status(struct dw_hdmi *hdmi, u8 *channel_status); + void dw_hdmi_set_channel_allocation(struct dw_hdmi *hdmi, unsigned int ca); + void dw_hdmi_audio_enable(struct dw_hdmi *hdmi); + void dw_hdmi_audio_disable(struct dw_hdmi *hdmi); +-void dw_hdmi_set_high_tmds_clock_ratio(struct dw_hdmi *hdmi); ++void dw_hdmi_set_high_tmds_clock_ratio(struct dw_hdmi *hdmi, ++ const struct drm_display_info *display); + + /* PHY configuration */ + void dw_hdmi_phy_i2c_set_addr(struct dw_hdmi *hdmi, u8 address); + +From 57c01c57d5aff20753b3c418abb52b3b317c0166 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Tue, 26 May 2020 04:14:57 +0300 +Subject: [PATCH] drm: bridge: dw-hdmi: Split connector creation to a separate + function + +Isolate all the code related to connector creation to a new +dw_hdmi_connector_create() function, to prepare for making connector +creation optional. + +Signed-off-by: Laurent Pinchart +Reviewed-by: Neil Armstrong +Signed-off-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/20200526011505.31884-20-laurent.pinchart+renesas@ideasonboard.com +(cherry picked from commit 3f588fda4b80dbd7dafa08b0e16fd72a42676e3c) +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 107 +++++++++++++--------- + 1 file changed, 62 insertions(+), 45 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index a18794cce0d8..35d38b644912 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -2317,6 +2317,10 @@ static void dw_hdmi_update_phy_mask(struct dw_hdmi *hdmi) + hdmi->rxsense); + } + ++/* ----------------------------------------------------------------------------- ++ * DRM Connector Operations ++ */ ++ + static enum drm_connector_status + dw_hdmi_connector_detect(struct drm_connector *connector, bool force) + { +@@ -2438,6 +2442,59 @@ static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = + .atomic_check = dw_hdmi_connector_atomic_check, + }; + ++static int dw_hdmi_connector_create(struct dw_hdmi *hdmi) ++{ ++ struct drm_connector *connector = &hdmi->connector; ++ struct cec_connector_info conn_info; ++ struct cec_notifier *notifier; ++ ++ if (hdmi->version >= 0x200a) ++ connector->ycbcr_420_allowed = ++ hdmi->plat_data->ycbcr_420_allowed; ++ else ++ connector->ycbcr_420_allowed = false; ++ ++ connector->interlace_allowed = 1; ++ connector->polled = DRM_CONNECTOR_POLL_HPD; ++ ++ drm_connector_helper_add(connector, &dw_hdmi_connector_helper_funcs); ++ ++ drm_connector_init_with_ddc(hdmi->bridge.dev, connector, ++ &dw_hdmi_connector_funcs, ++ DRM_MODE_CONNECTOR_HDMIA, ++ hdmi->ddc); ++ ++ /* ++ * drm_connector_attach_max_bpc_property() requires the ++ * connector to have a state. ++ */ ++ drm_atomic_helper_connector_reset(connector); ++ ++ drm_connector_attach_max_bpc_property(connector, 8, 16); ++ ++ if (hdmi->version >= 0x200a && hdmi->plat_data->use_drm_infoframe) ++ drm_object_attach_property(&connector->base, ++ connector->dev->mode_config.hdr_output_metadata_property, 0); ++ ++ drm_connector_attach_encoder(connector, hdmi->bridge.encoder); ++ ++ cec_fill_conn_info_from_drm(&conn_info, connector); ++ ++ notifier = cec_notifier_conn_register(hdmi->dev, NULL, &conn_info); ++ if (!notifier) ++ return -ENOMEM; ++ ++ mutex_lock(&hdmi->cec_notifier_mutex); ++ hdmi->cec_notifier = notifier; ++ mutex_unlock(&hdmi->cec_notifier_mutex); ++ ++ return 0; ++} ++ ++/* ----------------------------------------------------------------------------- ++ * DRM Bridge Operations ++ */ ++ + /* + * Possible output formats : + * - MEDIA_BUS_FMT_UYYVYY16_0_5X48, +@@ -2713,51 +2770,13 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge, + enum drm_bridge_attach_flags flags) + { + struct dw_hdmi *hdmi = bridge->driver_private; +- struct drm_encoder *encoder = bridge->encoder; +- struct drm_connector *connector = &hdmi->connector; +- struct cec_connector_info conn_info; +- struct cec_notifier *notifier; + + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { + DRM_ERROR("Fix bridge driver to make connector optional!"); + return -EINVAL; + } + +- connector->interlace_allowed = 1; +- connector->polled = DRM_CONNECTOR_POLL_HPD; +- +- drm_connector_helper_add(connector, &dw_hdmi_connector_helper_funcs); +- +- drm_connector_init_with_ddc(bridge->dev, connector, +- &dw_hdmi_connector_funcs, +- DRM_MODE_CONNECTOR_HDMIA, +- hdmi->ddc); +- +- /* +- * drm_connector_attach_max_bpc_property() requires the +- * connector to have a state. +- */ +- drm_atomic_helper_connector_reset(connector); +- +- drm_connector_attach_max_bpc_property(connector, 8, 16); +- +- if (hdmi->version >= 0x200a && hdmi->plat_data->use_drm_infoframe) +- drm_object_attach_property(&connector->base, +- connector->dev->mode_config.hdr_output_metadata_property, 0); +- +- drm_connector_attach_encoder(connector, encoder); +- +- cec_fill_conn_info_from_drm(&conn_info, connector); +- +- notifier = cec_notifier_conn_register(hdmi->dev, NULL, &conn_info); +- if (!notifier) +- return -ENOMEM; +- +- mutex_lock(&hdmi->cec_notifier_mutex); +- hdmi->cec_notifier = notifier; +- mutex_unlock(&hdmi->cec_notifier_mutex); +- +- return 0; ++ return dw_hdmi_connector_create(hdmi); + } + + static void dw_hdmi_bridge_detach(struct drm_bridge *bridge) +@@ -2841,6 +2860,10 @@ static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = { + .mode_valid = dw_hdmi_bridge_mode_valid, + }; + ++/* ----------------------------------------------------------------------------- ++ * IRQ Handling ++ */ ++ + static irqreturn_t dw_hdmi_i2c_irq(struct dw_hdmi *hdmi) + { + struct dw_hdmi_i2c *i2c = hdmi->i2c; +@@ -3303,12 +3326,6 @@ __dw_hdmi_probe(struct platform_device *pdev, + hdmi->bridge.of_node = pdev->dev.of_node; + #endif + +- if (hdmi->version >= 0x200a) +- hdmi->connector.ycbcr_420_allowed = +- hdmi->plat_data->ycbcr_420_allowed; +- else +- hdmi->connector.ycbcr_420_allowed = false; +- + memset(&pdevinfo, 0, sizeof(pdevinfo)); + pdevinfo.parent = dev; + pdevinfo.id = PLATFORM_DEVID_AUTO; + +From a3b8c4bc7907f025862b25aca04c9edc999a44e5 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Tue, 26 May 2020 04:14:58 +0300 +Subject: [PATCH] drm: bridge: dw-hdmi: Store current connector in struct + dw_hdmi + +Store the connector that the bridge is currently wired to in the dw_hdmi +structure. This is currently identical to the connector field, but will +differ once the driver supports disabling connector creation. + +Signed-off-by: Laurent Pinchart +Reviewed-by: Neil Armstrong +Signed-off-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/20200526011505.31884-21-laurent.pinchart+renesas@ideasonboard.com +(cherry picked from commit ca7b6b7176ffea4d07afbd98ede7a94fb0f68fa1) +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 35d38b644912..16bffedb4715 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -181,6 +181,7 @@ struct dw_hdmi { + + struct mutex mutex; /* for state below and previous_mode */ + enum drm_connector_force force; /* mutex-protected force state */ ++ struct drm_connector *curr_conn;/* current connector (only valid when !disabled) */ + bool disabled; /* DRM has disabled our bridge */ + bool bridge_is_on; /* indicates the bridge is on */ + bool rxsense; /* rxsense state */ +@@ -2823,23 +2824,32 @@ static void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge, + mutex_unlock(&hdmi->mutex); + } + +-static void dw_hdmi_bridge_disable(struct drm_bridge *bridge) ++static void dw_hdmi_bridge_atomic_disable(struct drm_bridge *bridge, ++ struct drm_bridge_state *old_state) + { + struct dw_hdmi *hdmi = bridge->driver_private; + + mutex_lock(&hdmi->mutex); + hdmi->disabled = true; ++ hdmi->curr_conn = NULL; + dw_hdmi_update_power(hdmi); + dw_hdmi_update_phy_mask(hdmi); + mutex_unlock(&hdmi->mutex); + } + +-static void dw_hdmi_bridge_enable(struct drm_bridge *bridge) ++static void dw_hdmi_bridge_atomic_enable(struct drm_bridge *bridge, ++ struct drm_bridge_state *old_state) + { + struct dw_hdmi *hdmi = bridge->driver_private; ++ struct drm_atomic_state *state = old_state->base.state; ++ struct drm_connector *connector; ++ ++ connector = drm_atomic_get_new_connector_for_encoder(state, ++ bridge->encoder); + + mutex_lock(&hdmi->mutex); + hdmi->disabled = false; ++ hdmi->curr_conn = connector; + dw_hdmi_update_power(hdmi); + dw_hdmi_update_phy_mask(hdmi); + mutex_unlock(&hdmi->mutex); +@@ -2854,8 +2864,8 @@ static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = { + .atomic_check = dw_hdmi_bridge_atomic_check, + .atomic_get_output_bus_fmts = dw_hdmi_bridge_atomic_get_output_bus_fmts, + .atomic_get_input_bus_fmts = dw_hdmi_bridge_atomic_get_input_bus_fmts, +- .enable = dw_hdmi_bridge_enable, +- .disable = dw_hdmi_bridge_disable, ++ .atomic_enable = dw_hdmi_bridge_atomic_enable, ++ .atomic_disable = dw_hdmi_bridge_atomic_disable, + .mode_set = dw_hdmi_bridge_mode_set, + .mode_valid = dw_hdmi_bridge_mode_valid, + }; + +From 30b1907401f2475b4b7e8341269a36ef3a45a6bb Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Tue, 26 May 2020 04:14:59 +0300 +Subject: [PATCH] drm: bridge: dw-hdmi: Pass drm_connector to internal + functions as needed + +To prepare for making connector creation optional in the driver, pass +the drm_connector explicitly to the internal functions that require it. +The functions that still access the connector from the dw_hdmi structure +are dw_hdmi_connector_create() and __dw_hdmi_probe(). The former access +is expected, as that's where the internal connector is created. The +latter will be addressed separately. + +Signed-off-by: Laurent Pinchart +Reviewed-by: Neil Armstrong +Signed-off-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/20200526011505.31884-22-laurent.pinchart+renesas@ideasonboard.com +(cherry picked from commit 81980037fb275d9db1bbb0239682d707e8dd62a0) +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 31 +++++++++++++---------- + 1 file changed, 18 insertions(+), 13 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 16bffedb4715..b69c14b9de62 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -1632,18 +1632,17 @@ static void hdmi_tx_hdcp_config(struct dw_hdmi *hdmi) + } + + static void hdmi_config_AVI(struct dw_hdmi *hdmi, ++ const struct drm_connector *connector, + const struct drm_display_mode *mode) + { + struct hdmi_avi_infoframe frame; + u8 val; + + /* Initialise info frame from DRM mode */ +- drm_hdmi_avi_infoframe_from_display_mode(&frame, +- &hdmi->connector, mode); ++ drm_hdmi_avi_infoframe_from_display_mode(&frame, connector, mode); + + if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) { +- drm_hdmi_avi_infoframe_quant_range(&frame, &hdmi->connector, +- mode, ++ drm_hdmi_avi_infoframe_quant_range(&frame, connector, mode, + hdmi->hdmi_data.rgb_limited_range ? + HDMI_QUANTIZATION_RANGE_LIMITED : + HDMI_QUANTIZATION_RANGE_FULL); +@@ -1760,14 +1759,14 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, + } + + static void hdmi_config_vendor_specific_infoframe(struct dw_hdmi *hdmi, ++ const struct drm_connector *connector, + const struct drm_display_mode *mode) + { + struct hdmi_vendor_infoframe frame; + u8 buffer[10]; + ssize_t err; + +- err = drm_hdmi_vendor_infoframe_from_display_mode(&frame, +- &hdmi->connector, ++ err = drm_hdmi_vendor_infoframe_from_display_mode(&frame, connector, + mode); + if (err < 0) + /* +@@ -1813,9 +1812,10 @@ static void hdmi_config_vendor_specific_infoframe(struct dw_hdmi *hdmi, + HDMI_FC_DATAUTO0_VSD_MASK); + } + +-static void hdmi_config_drm_infoframe(struct dw_hdmi *hdmi) ++static void hdmi_config_drm_infoframe(struct dw_hdmi *hdmi, ++ const struct drm_connector *connector) + { +- const struct drm_connector_state *conn_state = hdmi->connector.state; ++ const struct drm_connector_state *conn_state = connector->state; + struct hdmi_drm_infoframe frame; + u8 buffer[30]; + ssize_t err; +@@ -2118,9 +2118,9 @@ static void hdmi_disable_overflow_interrupts(struct dw_hdmi *hdmi) + } + + static int dw_hdmi_setup(struct dw_hdmi *hdmi, ++ const struct drm_connector *connector, + const struct drm_display_mode *mode) + { +- struct drm_connector *connector = &hdmi->connector; + int ret; + + hdmi_disable_overflow_interrupts(hdmi); +@@ -2192,9 +2192,9 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, + dev_dbg(hdmi->dev, "%s HDMI mode\n", __func__); + + /* HDMI Initialization Step F - Configure AVI InfoFrame */ +- hdmi_config_AVI(hdmi, mode); +- hdmi_config_vendor_specific_infoframe(hdmi, mode); +- hdmi_config_drm_infoframe(hdmi); ++ hdmi_config_AVI(hdmi, connector, mode); ++ hdmi_config_vendor_specific_infoframe(hdmi, connector, mode); ++ hdmi_config_drm_infoframe(hdmi, connector); + } else { + dev_dbg(hdmi->dev, "%s DVI mode\n", __func__); + } +@@ -2263,7 +2263,12 @@ static void initialize_hdmi_ih_mutes(struct dw_hdmi *hdmi) + static void dw_hdmi_poweron(struct dw_hdmi *hdmi) + { + hdmi->bridge_is_on = true; +- dw_hdmi_setup(hdmi, &hdmi->previous_mode); ++ ++ /* ++ * The curr_conn field is guaranteed to be valid here, as this function ++ * is only be called when !hdmi->disabled. ++ */ ++ dw_hdmi_setup(hdmi, hdmi->curr_conn, &hdmi->previous_mode); + } + + static void dw_hdmi_poweroff(struct dw_hdmi *hdmi) + +From 26ccb66a87e10784ccfc8366494769888f21ebf2 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Tue, 26 May 2020 04:15:00 +0300 +Subject: [PATCH] drm: bridge: dw-hdmi: Make connector creation optional + +Implement the drm_bridge_funcs .detect() and .get_edid() operations, and +call drm_bridge_hpd_notify() notify to report HPD. This provides the +necessary API to support disabling connector creation, do so by +accepting DRM_BRIDGE_ATTACH_NO_CONNECTOR in dw_hdmi_bridge_attach(). + +Signed-off-by: Laurent Pinchart +Reviewed-by: Neil Armstrong +Signed-off-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/20200526011505.31884-23-laurent.pinchart+renesas@ideasonboard.com +(cherry picked from commit ec971aaa6775cff555b4f58777ceab1d9a8370e0) +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 104 +++++++++++++++------- + 1 file changed, 74 insertions(+), 30 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index b69c14b9de62..6148a022569a 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -2323,15 +2323,8 @@ static void dw_hdmi_update_phy_mask(struct dw_hdmi *hdmi) + hdmi->rxsense); + } + +-/* ----------------------------------------------------------------------------- +- * DRM Connector Operations +- */ +- +-static enum drm_connector_status +-dw_hdmi_connector_detect(struct drm_connector *connector, bool force) ++static enum drm_connector_status dw_hdmi_detect(struct dw_hdmi *hdmi) + { +- struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, +- connector); + enum drm_connector_status result; + + mutex_lock(&hdmi->mutex); +@@ -2354,31 +2347,57 @@ dw_hdmi_connector_detect(struct drm_connector *connector, bool force) + return result; + } + +-static int dw_hdmi_connector_get_modes(struct drm_connector *connector) ++static struct edid *dw_hdmi_get_edid(struct dw_hdmi *hdmi, ++ struct drm_connector *connector) + { +- struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, +- connector); + struct edid *edid; +- int ret = 0; + + if (!hdmi->ddc) +- return 0; ++ return NULL; + + edid = drm_get_edid(connector, hdmi->ddc); +- if (edid) { +- dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]\n", +- edid->width_cm, edid->height_cm); +- +- hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid); +- hdmi->sink_has_audio = drm_detect_monitor_audio(edid); +- drm_connector_update_edid_property(connector, edid); +- cec_notifier_set_phys_addr_from_edid(hdmi->cec_notifier, edid); +- ret = drm_add_edid_modes(connector, edid); +- kfree(edid); +- } else { ++ if (!edid) { + dev_dbg(hdmi->dev, "failed to get edid\n"); ++ return NULL; + } + ++ dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]\n", ++ edid->width_cm, edid->height_cm); ++ ++ hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid); ++ hdmi->sink_has_audio = drm_detect_monitor_audio(edid); ++ ++ return edid; ++} ++ ++/* ----------------------------------------------------------------------------- ++ * DRM Connector Operations ++ */ ++ ++static enum drm_connector_status ++dw_hdmi_connector_detect(struct drm_connector *connector, bool force) ++{ ++ struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, ++ connector); ++ return dw_hdmi_detect(hdmi); ++} ++ ++static int dw_hdmi_connector_get_modes(struct drm_connector *connector) ++{ ++ struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, ++ connector); ++ struct edid *edid; ++ int ret; ++ ++ edid = dw_hdmi_get_edid(hdmi, connector); ++ if (!edid) ++ return 0; ++ ++ drm_connector_update_edid_property(connector, edid); ++ cec_notifier_set_phys_addr_from_edid(hdmi->cec_notifier, edid); ++ ret = drm_add_edid_modes(connector, edid); ++ kfree(edid); ++ + return ret; + } + +@@ -2777,10 +2796,8 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge, + { + struct dw_hdmi *hdmi = bridge->driver_private; + +- if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { +- DRM_ERROR("Fix bridge driver to make connector optional!"); +- return -EINVAL; +- } ++ if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) ++ return 0; + + return dw_hdmi_connector_create(hdmi); + } +@@ -2860,6 +2877,21 @@ static void dw_hdmi_bridge_atomic_enable(struct drm_bridge *bridge, + mutex_unlock(&hdmi->mutex); + } + ++static enum drm_connector_status dw_hdmi_bridge_detect(struct drm_bridge *bridge) ++{ ++ struct dw_hdmi *hdmi = bridge->driver_private; ++ ++ return dw_hdmi_detect(hdmi); ++} ++ ++static struct edid *dw_hdmi_bridge_get_edid(struct drm_bridge *bridge, ++ struct drm_connector *connector) ++{ ++ struct dw_hdmi *hdmi = bridge->driver_private; ++ ++ return dw_hdmi_get_edid(hdmi, connector); ++} ++ + static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = { + .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, +@@ -2873,6 +2905,8 @@ static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = { + .atomic_disable = dw_hdmi_bridge_atomic_disable, + .mode_set = dw_hdmi_bridge_mode_set, + .mode_valid = dw_hdmi_bridge_mode_valid, ++ .detect = dw_hdmi_bridge_detect, ++ .get_edid = dw_hdmi_bridge_get_edid, + }; + + /* ----------------------------------------------------------------------------- +@@ -2988,10 +3022,18 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) + } + + if (intr_stat & HDMI_IH_PHY_STAT0_HPD) { ++ enum drm_connector_status status = phy_int_pol & HDMI_PHY_HPD ++ ? connector_status_connected ++ : connector_status_disconnected; ++ + dev_dbg(hdmi->dev, "EVENT=%s\n", +- phy_int_pol & HDMI_PHY_HPD ? "plugin" : "plugout"); +- if (hdmi->bridge.dev) ++ status == connector_status_connected ? ++ "plugin" : "plugout"); ++ ++ if (hdmi->bridge.dev) { + drm_helper_hpd_irq_event(hdmi->bridge.dev); ++ drm_bridge_hpd_notify(&hdmi->bridge, status); ++ } + } + + hdmi_writeb(hdmi, intr_stat, HDMI_IH_PHY_STAT0); +@@ -3337,6 +3379,8 @@ __dw_hdmi_probe(struct platform_device *pdev, + + hdmi->bridge.driver_private = hdmi; + hdmi->bridge.funcs = &dw_hdmi_bridge_funcs; ++ hdmi->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID ++ | DRM_BRIDGE_OP_HPD; + #ifdef CONFIG_OF + hdmi->bridge.of_node = pdev->dev.of_node; + #endif + +From 5631b3347b2c688d45a5804cc706702553873c3f Mon Sep 17 00:00:00 2001 +From: Stanislav Lisovskiy +Date: Tue, 30 Jun 2020 05:56:58 +0530 +Subject: [PATCH] drm: Add helper to compare edids. + +Many drivers would benefit from using +drm helper to compare edid, rather +than bothering with own implementation. + +v2: Added documentation for this function. + +Signed-off-by: Stanislav Lisovskiy +Signed-off-by: Maarten Lankhorst +Link: https://patchwork.freedesktop.org/patch/msgid/20200630002700.5451-2-kunal1.joshi@intel.com +(cherry picked from commit 536faa450e17f32fddb1a2124e3df71a966122cd) +--- + drivers/gpu/drm/drm_edid.c | 33 +++++++++++++++++++++++++++++++++ + include/drm/drm_edid.h | 9 +++++++++ + 2 files changed, 42 insertions(+) + +diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c +index b3f659759adb..aa0644d8272a 100644 +--- a/drivers/gpu/drm/drm_edid.c ++++ b/drivers/gpu/drm/drm_edid.c +@@ -1615,6 +1615,39 @@ static bool drm_edid_is_zero(const u8 *in_edid, int length) + return true; + } + ++/** ++ * drm_edid_are_equal - compare two edid blobs. ++ * @edid1: pointer to first blob ++ * @edid2: pointer to second blob ++ * This helper can be used during probing to determine if ++ * edid had changed. ++ */ ++bool drm_edid_are_equal(const struct edid *edid1, const struct edid *edid2) ++{ ++ int edid1_len, edid2_len; ++ bool edid1_present = edid1 != NULL; ++ bool edid2_present = edid2 != NULL; ++ ++ if (edid1_present != edid2_present) ++ return false; ++ ++ if (edid1) { ++ ++ edid1_len = EDID_LENGTH * (1 + edid1->extensions); ++ edid2_len = EDID_LENGTH * (1 + edid2->extensions); ++ ++ if (edid1_len != edid2_len) ++ return false; ++ ++ if (memcmp(edid1, edid2, edid1_len)) ++ return false; ++ } ++ ++ return true; ++} ++EXPORT_SYMBOL(drm_edid_are_equal); ++ ++ + /** + * drm_edid_block_valid - Sanity check the EDID block (base or extension) + * @raw_edid: pointer to raw EDID block +diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h +index 43254319ab19..cfa4f5af49af 100644 +--- a/include/drm/drm_edid.h ++++ b/include/drm/drm_edid.h +@@ -359,6 +359,15 @@ drm_load_edid_firmware(struct drm_connector *connector) + } + #endif + ++/** ++ * drm_edid_are_equal - compare two edid blobs. ++ * @edid1: pointer to first blob ++ * @edid2: pointer to second blob ++ * This helper can be used during probing to determine if ++ * edid had changed. ++ */ ++bool drm_edid_are_equal(const struct edid *edid1, const struct edid *edid2); ++ + int + drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame, + const struct drm_connector *connector, + +From 00fb1055155719f429be43ff1864959cea9a56e2 Mon Sep 17 00:00:00 2001 +From: Stanislav Lisovskiy +Date: Tue, 30 Jun 2020 05:56:59 +0530 +Subject: [PATCH] drm: Introduce epoch counter to drm_connector + +This counter will be used by drm_helper_probe_detect caller to determine +if anything had changed(including edid, connection status and etc). +Hardware specific driver detect hooks are responsible for updating this +counter when some change is detected to notify the drm part, +which can trigger for example hotplug event. + +Also now call drm_connector_update_edid_property +right after we get edid always to make sure there is a +unified way to handle edid change, without having to +change tons of source code as currently +drm_connector_update_edid_property is called only in +certain cases like reprobing and not right after edid is +actually updated. + +v2: Added documentation for the new counter. Rename change_counter to + epoch_counter. + +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=105540 + +Signed-off-by: Stanislav Lisovskiy +Signed-off-by: Maarten Lankhorst +Link: https://patchwork.freedesktop.org/patch/msgid/20200630002700.5451-3-kunal1.joshi@intel.com +(cherry picked from commit 5186421cbfe250002308d4d759674214b385752f) +--- + drivers/gpu/drm/drm_connector.c | 16 +++++++++++++ + drivers/gpu/drm/drm_edid.c | 8 ++++--- + drivers/gpu/drm/drm_probe_helper.c | 38 ++++++++++++++++++++++++++---- + include/drm/drm_connector.h | 2 ++ + 4 files changed, 56 insertions(+), 8 deletions(-) + +diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c +index d877ddc6dc57..c6d7fc45aeac 100644 +--- a/drivers/gpu/drm/drm_connector.c ++++ b/drivers/gpu/drm/drm_connector.c +@@ -269,6 +269,7 @@ int drm_connector_init(struct drm_device *dev, + INIT_LIST_HEAD(&connector->modes); + mutex_init(&connector->mutex); + connector->edid_blob_ptr = NULL; ++ connector->epoch_counter = 0; + connector->tile_blob_ptr = NULL; + connector->status = connector_status_unknown; + connector->display_info.panel_orientation = +@@ -1954,6 +1955,7 @@ int drm_connector_update_edid_property(struct drm_connector *connector, + struct drm_device *dev = connector->dev; + size_t size = 0; + int ret; ++ const struct edid *old_edid; + + /* ignore requests to set edid when overridden */ + if (connector->override_edid) +@@ -1977,6 +1979,20 @@ int drm_connector_update_edid_property(struct drm_connector *connector, + + drm_update_tile_info(connector, edid); + ++ if (connector->edid_blob_ptr) { ++ old_edid = (const struct edid *)connector->edid_blob_ptr->data; ++ if (old_edid) { ++ if (!drm_edid_are_equal(edid, old_edid)) { ++ DRM_DEBUG_KMS("[CONNECTOR:%d:%s] Edid was changed.\n", ++ connector->base.id, connector->name); ++ ++ connector->epoch_counter += 1; ++ DRM_DEBUG_KMS("Updating change counter to %llu\n", ++ connector->epoch_counter); ++ } ++ } ++ } ++ + drm_object_property_set_value(&connector->base, + dev->mode_config.non_desktop_property, + connector->display_info.non_desktop); +diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c +index aa0644d8272a..ddb9a093ad0d 100644 +--- a/drivers/gpu/drm/drm_edid.c ++++ b/drivers/gpu/drm/drm_edid.c +@@ -1632,7 +1632,6 @@ bool drm_edid_are_equal(const struct edid *edid1, const struct edid *edid2) + return false; + + if (edid1) { +- + edid1_len = EDID_LENGTH * (1 + edid1->extensions); + edid2_len = EDID_LENGTH * (1 + edid2->extensions); + +@@ -1647,7 +1646,6 @@ bool drm_edid_are_equal(const struct edid *edid1, const struct edid *edid2) + } + EXPORT_SYMBOL(drm_edid_are_equal); + +- + /** + * drm_edid_block_valid - Sanity check the EDID block (base or extension) + * @raw_edid: pointer to raw EDID block +@@ -2050,13 +2048,17 @@ EXPORT_SYMBOL(drm_probe_ddc); + struct edid *drm_get_edid(struct drm_connector *connector, + struct i2c_adapter *adapter) + { ++ struct edid *edid; ++ + if (connector->force == DRM_FORCE_OFF) + return NULL; + + if (connector->force == DRM_FORCE_UNSPECIFIED && !drm_probe_ddc(adapter)) + return NULL; + +- return drm_do_get_edid(connector, drm_do_probe_ddc_edid, adapter); ++ edid = drm_do_get_edid(connector, drm_do_probe_ddc_edid, adapter); ++ drm_connector_update_edid_property(connector, edid); ++ return edid; + } + EXPORT_SYMBOL(drm_get_edid); + +diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c +index f5d141e0400f..6d3a1dbfcba5 100644 +--- a/drivers/gpu/drm/drm_probe_helper.c ++++ b/drivers/gpu/drm/drm_probe_helper.c +@@ -290,6 +290,9 @@ drm_helper_probe_detect_ctx(struct drm_connector *connector, bool force) + if (WARN_ON(ret < 0)) + ret = connector_status_unknown; + ++ if (ret != connector->status) ++ connector->epoch_counter += 1; ++ + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); + +@@ -323,11 +326,16 @@ drm_helper_probe_detect(struct drm_connector *connector, + return ret; + + if (funcs->detect_ctx) +- return funcs->detect_ctx(connector, ctx, force); ++ ret = funcs->detect_ctx(connector, ctx, force); + else if (connector->funcs->detect) +- return connector->funcs->detect(connector, force); ++ ret = connector->funcs->detect(connector, force); + else +- return connector_status_connected; ++ ret = connector_status_connected; ++ ++ if (ret != connector->status) ++ connector->epoch_counter += 1; ++ ++ return ret; + } + EXPORT_SYMBOL(drm_helper_probe_detect); + +@@ -780,6 +788,7 @@ bool drm_helper_hpd_irq_event(struct drm_device *dev) + struct drm_connector_list_iter conn_iter; + enum drm_connector_status old_status; + bool changed = false; ++ u64 old_epoch_counter; + + if (!dev->mode_config.poll_enabled) + return false; +@@ -793,20 +802,39 @@ bool drm_helper_hpd_irq_event(struct drm_device *dev) + + old_status = connector->status; + ++ old_epoch_counter = connector->epoch_counter; ++ ++ DRM_DEBUG_KMS("[CONNECTOR:%d:%s] Old epoch counter %llu\n", connector->base.id, ++ connector->name, ++ old_epoch_counter); ++ + connector->status = drm_helper_probe_detect(connector, NULL, false); + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n", + connector->base.id, + connector->name, + drm_get_connector_status_name(old_status), + drm_get_connector_status_name(connector->status)); +- if (old_status != connector->status) ++ ++ DRM_DEBUG_KMS("[CONNECTOR:%d:%s] New epoch counter %llu\n", ++ connector->base.id, ++ connector->name, ++ connector->epoch_counter); ++ ++ /* ++ * Check if epoch counter had changed, meaning that we need ++ * to send a uevent. ++ */ ++ if (old_epoch_counter != connector->epoch_counter) + changed = true; ++ + } + drm_connector_list_iter_end(&conn_iter); + mutex_unlock(&dev->mode_config.mutex); + +- if (changed) ++ if (changed) { + drm_kms_helper_hotplug_event(dev); ++ DRM_DEBUG_KMS("Sent hotplug event\n"); ++ } + + return changed; + } +diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h +index fd543d1db9b2..6a451b86c454 100644 +--- a/include/drm/drm_connector.h ++++ b/include/drm/drm_connector.h +@@ -1329,6 +1329,8 @@ struct drm_connector { + enum drm_connector_force force; + /** @override_edid: has the EDID been overwritten through debugfs for testing? */ + bool override_edid; ++ /** @epoch_counter: used to detect any other changes in connector, besides status */ ++ u64 epoch_counter; + + /** + * @possible_encoders: Bit mask of encoders that can drive this + +From 0402c6b6ec3351cdf475a0a7b4196cea5e213bd0 Mon Sep 17 00:00:00 2001 +From: Neil Armstrong +Date: Fri, 3 Jul 2020 10:07:23 +0200 +Subject: [PATCH] drm/fourcc: Add modifier definitions for describing Amlogic + Video Framebuffer Compression + +Amlogic uses a proprietary lossless image compression protocol and format +for their hardware video codec accelerators, either video decoders or +video input encoders. + +It considerably reduces memory bandwidth while writing and reading +frames in memory. + +The underlying storage is considered to be 3 components, 8bit or 10-bit +per component, YCbCr 420, single plane : +- DRM_FORMAT_YUV420_8BIT +- DRM_FORMAT_YUV420_10BIT + +This modifier will be notably added to DMA-BUF frames imported from the V4L2 +Amlogic VDEC decoder. + +This introduces the basic layout composed of: +- a body content organized in 64x32 superblocks with 4096 bytes per + superblock in default mode. +- a 32 bytes per 128x64 header block + +This layout is tranferrable between Amlogic SoCs supporting this modifier. + +The Memory Saving option exist changing the layout superblock size to save memory when +using 8bit components pixels size. + +Finally is also adds the Scatter Memory layout, meaning the header contains IOMMU +references to the compressed frames content to optimize memory access +and layout. + +In this mode, only the header memory address is needed, thus the content +memory organization is tied to the current producer execution and cannot +be saved/dumped neither transferrable between Amlogic SoCs supporting this +modifier. + +Signed-off-by: Neil Armstrong +Tested-by: Kevin Hilman +Reviewed-by: Kevin Hilman +Acked-by: Daniel Vetter +Link: https://patchwork.freedesktop.org/patch/msgid/20200703080728.25207-2-narmstrong@baylibre.com +(cherry picked from commit d6528ec883096e7ccdb08257bcc45670bc878519) +--- + include/uapi/drm/drm_fourcc.h | 81 +++++++++++++++++++++++++++++++++++ + 1 file changed, 81 insertions(+) + +diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h +index 993c1b342315..cbf92fdf2712 100644 +--- a/include/uapi/drm/drm_fourcc.h ++++ b/include/uapi/drm/drm_fourcc.h +@@ -331,6 +331,7 @@ extern "C" { + #define DRM_FORMAT_MOD_VENDOR_BROADCOM 0x07 + #define DRM_FORMAT_MOD_VENDOR_ARM 0x08 + #define DRM_FORMAT_MOD_VENDOR_ALLWINNER 0x09 ++#define DRM_FORMAT_MOD_VENDOR_AMLOGIC 0x0a + + /* add more to the end as needed */ + +@@ -950,6 +951,86 @@ drm_fourcc_canonicalize_nvidia_format_mod(__u64 modifier) + */ + #define DRM_FORMAT_MOD_ALLWINNER_TILED fourcc_mod_code(ALLWINNER, 1) + ++/* ++ * Amlogic Video Framebuffer Compression modifiers ++ * ++ * Amlogic uses a proprietary lossless image compression protocol and format ++ * for their hardware video codec accelerators, either video decoders or ++ * video input encoders. ++ * ++ * It considerably reduces memory bandwidth while writing and reading ++ * frames in memory. ++ * ++ * The underlying storage is considered to be 3 components, 8bit or 10-bit ++ * per component YCbCr 420, single plane : ++ * - DRM_FORMAT_YUV420_8BIT ++ * - DRM_FORMAT_YUV420_10BIT ++ * ++ * The first 8 bits of the mode defines the layout, then the following 8 bits ++ * defines the options changing the layout. ++ * ++ * Not all combinations are valid, and different SoCs may support different ++ * combinations of layout and options. ++ */ ++#define __fourcc_mod_amlogic_layout_mask 0xf ++#define __fourcc_mod_amlogic_options_shift 8 ++#define __fourcc_mod_amlogic_options_mask 0xf ++ ++#define DRM_FORMAT_MOD_AMLOGIC_FBC(__layout, __options) \ ++ fourcc_mod_code(AMLOGIC, \ ++ ((__layout) & __fourcc_mod_amlogic_layout_mask) | \ ++ ((__options) & __fourcc_mod_amlogic_options_mask \ ++ << __fourcc_mod_amlogic_options_shift)) ++ ++/* Amlogic FBC Layouts */ ++ ++/* ++ * Amlogic FBC Basic Layout ++ * ++ * The basic layout is composed of: ++ * - a body content organized in 64x32 superblocks with 4096 bytes per ++ * superblock in default mode. ++ * - a 32 bytes per 128x64 header block ++ * ++ * This layout is transferrable between Amlogic SoCs supporting this modifier. ++ */ ++#define AMLOGIC_FBC_LAYOUT_BASIC (1ULL) ++ ++/* ++ * Amlogic FBC Scatter Memory layout ++ * ++ * Indicates the header contains IOMMU references to the compressed ++ * frames content to optimize memory access and layout. ++ * ++ * In this mode, only the header memory address is needed, thus the ++ * content memory organization is tied to the current producer ++ * execution and cannot be saved/dumped neither transferrable between ++ * Amlogic SoCs supporting this modifier. ++ * ++ * Due to the nature of the layout, these buffers are not expected to ++ * be accessible by the user-space clients, but only accessible by the ++ * hardware producers and consumers. ++ * ++ * The user-space clients should expect a failure while trying to mmap ++ * the DMA-BUF handle returned by the producer. ++ */ ++#define AMLOGIC_FBC_LAYOUT_SCATTER (2ULL) ++ ++/* Amlogic FBC Layout Options Bit Mask */ ++ ++/* ++ * Amlogic FBC Memory Saving mode ++ * ++ * Indicates the storage is packed when pixel size is multiple of word ++ * boudaries, i.e. 8bit should be stored in this mode to save allocation ++ * memory. ++ * ++ * This mode reduces body layout to 3072 bytes per 64x32 superblock with ++ * the basic layout and 3200 bytes per 64x32 superblock combined with ++ * the scatter layout. ++ */ ++#define AMLOGIC_FBC_OPTION_MEM_SAVING (1ULL << 0) ++ + #if defined(__cplusplus) + } + #endif + +From bca1f53e15b80ac4fa24a073f96e8f99d994ca8a Mon Sep 17 00:00:00 2001 +From: Brian Starkey +Date: Fri, 26 Jun 2020 17:48:00 +0100 +Subject: [PATCH] drm: drm_fourcc: Add generic alias for 16_16_TILE modifier + +In cases such as DRM_FORMAT_MOD_SAMSUNG_16_16_TILE, the modifier +describes a generic pixel re-ordering which can be applicable to +multiple vendors. + +Define an alias: DRM_FORMAT_MOD_GENERIC_16_16_TILE, which can be +used to describe this layout in a vendor-neutral way, and add a +comment about the expected usage of such "generic" modifiers. + +Changes in v2: + - Move note about future cases to comment (Daniel) + +Signed-off-by: Brian Starkey +Reviewed-by: Daniel Vetter +Signed-off-by: Liviu Dudau +Link: https://patchwork.freedesktop.org/patch/msgid/20200626164800.11595-1-brian.starkey@arm.com +(cherry picked from commit 9ac2b63791ef63935c71e2a7f5444a1118c4d084) +--- + include/uapi/drm/drm_fourcc.h | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h +index cbf92fdf2712..4bee7de5f306 100644 +--- a/include/uapi/drm/drm_fourcc.h ++++ b/include/uapi/drm/drm_fourcc.h +@@ -346,8 +346,33 @@ extern "C" { + * When adding a new token please document the layout with a code comment, + * similar to the fourcc codes above. drm_fourcc.h is considered the + * authoritative source for all of these. ++ * ++ * Generic modifier names: ++ * ++ * DRM_FORMAT_MOD_GENERIC_* definitions are used to provide vendor-neutral names ++ * for layouts which are common across multiple vendors. To preserve ++ * compatibility, in cases where a vendor-specific definition already exists and ++ * a generic name for it is desired, the common name is a purely symbolic alias ++ * and must use the same numerical value as the original definition. ++ * ++ * Note that generic names should only be used for modifiers which describe ++ * generic layouts (such as pixel re-ordering), which may have ++ * independently-developed support across multiple vendors. ++ * ++ * In future cases where a generic layout is identified before merging with a ++ * vendor-specific modifier, a new 'GENERIC' vendor or modifier using vendor ++ * 'NONE' could be considered. This should only be for obvious, exceptional ++ * cases to avoid polluting the 'GENERIC' namespace with modifiers which only ++ * apply to a single vendor. ++ * ++ * Generic names should not be used for cases where multiple hardware vendors ++ * have implementations of the same standardised compression scheme (such as ++ * AFBC). In those cases, all implementations should use the same format ++ * modifier(s), reflecting the vendor of the standard. + */ + ++#define DRM_FORMAT_MOD_GENERIC_16_16_TILE DRM_FORMAT_MOD_SAMSUNG_16_16_TILE ++ + /* + * Invalid Modifier + * + +From 01f7cea4ef8c373df777713ceef5599a3efa88cb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= +Date: Wed, 27 May 2020 16:03:08 +0300 +Subject: [PATCH] drm/edid: Allow looking for ext blocks starting from a + specified index +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Apparently EDIDs with multiple DispID ext blocks is a thing, so prepare +for iterating through multiple ext blocks of the same type by +passing the starting ext block index to drm_find_edid_extension(). Well +also have drm_find_edid_extension() update the index to point to the +next ext block on success. Thus we should be able to call +drm_find_edid_extension() in loop. + +Signed-off-by: Ville Syrjälä +Link: https://patchwork.freedesktop.org/patch/msgid/20200527130310.27099-1-ville.syrjala@linux.intel.com +Reviewed-by: José Roberto de Souza +(cherry picked from commit 8873cfa384055d0348c03161420b1e9b6c1dc5d0) +--- + drivers/gpu/drm/drm_edid.c | 30 +++++++++++++++++++++--------- + 1 file changed, 21 insertions(+), 9 deletions(-) + +diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c +index ddb9a093ad0d..06cb75b9fc44 100644 +--- a/drivers/gpu/drm/drm_edid.c ++++ b/drivers/gpu/drm/drm_edid.c +@@ -3226,7 +3226,8 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid, + /* + * Search EDID for CEA extension block. + */ +-static u8 *drm_find_edid_extension(const struct edid *edid, int ext_id) ++static u8 *drm_find_edid_extension(const struct edid *edid, ++ int ext_id, int *ext_index) + { + u8 *edid_ext = NULL; + int i; +@@ -3236,23 +3237,26 @@ static u8 *drm_find_edid_extension(const struct edid *edid, int ext_id) + return NULL; + + /* Find CEA extension */ +- for (i = 0; i < edid->extensions; i++) { ++ for (i = *ext_index; i < edid->extensions; i++) { + edid_ext = (u8 *)edid + EDID_LENGTH * (i + 1); + if (edid_ext[0] == ext_id) + break; + } + +- if (i == edid->extensions) ++ if (i >= edid->extensions) + return NULL; + ++ *ext_index = i + 1; ++ + return edid_ext; + } + + + static u8 *drm_find_displayid_extension(const struct edid *edid, +- int *length, int *idx) ++ int *length, int *idx, ++ int *ext_index) + { +- u8 *displayid = drm_find_edid_extension(edid, DISPLAYID_EXT); ++ u8 *displayid = drm_find_edid_extension(edid, DISPLAYID_EXT, ext_index); + struct displayid_hdr *base; + int ret; + +@@ -3279,14 +3283,18 @@ static u8 *drm_find_cea_extension(const struct edid *edid) + struct displayid_block *block; + u8 *cea; + u8 *displayid; ++ int ext_index; + + /* Look for a top level CEA extension block */ +- cea = drm_find_edid_extension(edid, CEA_EXT); ++ ext_index = 0; ++ cea = drm_find_edid_extension(edid, CEA_EXT, &ext_index); + if (cea) + return cea; + + /* CEA blocks can also be found embedded in a DisplayID block */ +- displayid = drm_find_displayid_extension(edid, &length, &idx); ++ ext_index = 0; ++ displayid = drm_find_displayid_extension(edid, &length, &idx, ++ &ext_index); + if (!displayid) + return NULL; + +@@ -5236,8 +5244,10 @@ static int add_displayid_detailed_modes(struct drm_connector *connector, + int length, idx; + struct displayid_block *block; + int num_modes = 0; ++ int ext_index = 0; + +- displayid = drm_find_displayid_extension(edid, &length, &idx); ++ displayid = drm_find_displayid_extension(edid, &length, &idx, ++ &ext_index); + if (!displayid) + return 0; + +@@ -5911,11 +5921,13 @@ void drm_update_tile_info(struct drm_connector *connector, + const struct edid *edid) + { + const void *displayid = NULL; ++ int ext_index = 0; + int length, idx; + int ret; + + connector->has_tile = false; +- displayid = drm_find_displayid_extension(edid, &length, &idx); ++ displayid = drm_find_displayid_extension(edid, &length, &idx, ++ &ext_index); + if (!displayid) { + /* drop reference to any tile group we had */ + goto out_drop_ref; + +From 181edc12e551c8194591969ee528ed6041e4ada4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= +Date: Wed, 27 May 2020 16:03:09 +0300 +Subject: [PATCH] drm/edid: Iterate through all DispID ext blocks +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Apparently there are EDIDs in the wild with multiple DispID extension +blocks. Iterate through them all. + +In one particular case the tile information is specicied in the +second DispID ext block, and since the current parser only looks +at the first DispID ext block we don't notice that we're dealing +with a tiled display. + +While at it change a few functions to return void since we have +no use for the errno. + +References: https://gitlab.freedesktop.org/drm/intel/-/issues/27 +Signed-off-by: Ville Syrjälä +Link: https://patchwork.freedesktop.org/patch/msgid/20200527130310.27099-2-ville.syrjala@linux.intel.com +Reviewed-by: José Roberto de Souza +(cherry picked from commit 7f261afdcfae363192e3eef52dd34855cc149c15) +--- + drivers/gpu/drm/drm_edid.c | 84 +++++++++++++++++--------------------- + 1 file changed, 38 insertions(+), 46 deletions(-) + +diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c +index 06cb75b9fc44..fcd739af570f 100644 +--- a/drivers/gpu/drm/drm_edid.c ++++ b/drivers/gpu/drm/drm_edid.c +@@ -3286,6 +3286,7 @@ static u8 *drm_find_cea_extension(const struct edid *edid) + int ext_index; + + /* Look for a top level CEA extension block */ ++ /* FIXME: make callers iterate through multiple CEA ext blocks? */ + ext_index = 0; + cea = drm_find_edid_extension(edid, CEA_EXT, &ext_index); + if (cea) +@@ -3293,20 +3294,20 @@ static u8 *drm_find_cea_extension(const struct edid *edid) + + /* CEA blocks can also be found embedded in a DisplayID block */ + ext_index = 0; +- displayid = drm_find_displayid_extension(edid, &length, &idx, +- &ext_index); +- if (!displayid) +- return NULL; ++ for (;;) { ++ displayid = drm_find_displayid_extension(edid, &length, &idx, ++ &ext_index); ++ if (!displayid) ++ return NULL; + +- idx += sizeof(struct displayid_hdr); +- for_each_displayid_db(displayid, block, idx, length) { +- if (block->tag == DATA_BLOCK_CTA) { +- cea = (u8 *)block; +- break; ++ idx += sizeof(struct displayid_hdr); ++ for_each_displayid_db(displayid, block, idx, length) { ++ if (block->tag == DATA_BLOCK_CTA) ++ return (u8 *)block; + } + } + +- return cea; ++ return NULL; + } + + static __always_inline const struct drm_display_mode *cea_mode_for_vic(u8 vic) +@@ -5246,19 +5247,22 @@ static int add_displayid_detailed_modes(struct drm_connector *connector, + int num_modes = 0; + int ext_index = 0; + +- displayid = drm_find_displayid_extension(edid, &length, &idx, +- &ext_index); +- if (!displayid) +- return 0; +- +- idx += sizeof(struct displayid_hdr); +- for_each_displayid_db(displayid, block, idx, length) { +- switch (block->tag) { +- case DATA_BLOCK_TYPE_1_DETAILED_TIMING: +- num_modes += add_displayid_detailed_1_modes(connector, block); ++ for (;;) { ++ displayid = drm_find_displayid_extension(edid, &length, &idx, ++ &ext_index); ++ if (!displayid) + break; ++ ++ idx += sizeof(struct displayid_hdr); ++ for_each_displayid_db(displayid, block, idx, length) { ++ switch (block->tag) { ++ case DATA_BLOCK_TYPE_1_DETAILED_TIMING: ++ num_modes += add_displayid_detailed_1_modes(connector, block); ++ break; ++ } + } + } ++ + return num_modes; + } + +@@ -5838,8 +5842,8 @@ drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame, + } + EXPORT_SYMBOL(drm_hdmi_vendor_infoframe_from_display_mode); + +-static int drm_parse_tiled_block(struct drm_connector *connector, +- const struct displayid_block *block) ++static void drm_parse_tiled_block(struct drm_connector *connector, ++ const struct displayid_block *block) + { + const struct displayid_tiled_block *tile = (struct displayid_tiled_block *)block; + u16 w, h; +@@ -5877,7 +5881,7 @@ static int drm_parse_tiled_block(struct drm_connector *connector, + tg = drm_mode_create_tile_group(connector->dev, tile->topology_id); + } + if (!tg) +- return -ENOMEM; ++ return; + + if (connector->tile_group != tg) { + /* if we haven't got a pointer, +@@ -5889,14 +5893,12 @@ static int drm_parse_tiled_block(struct drm_connector *connector, + } else + /* if same tile group, then release the ref we just took. */ + drm_mode_put_tile_group(connector->dev, tg); +- return 0; + } + +-static int drm_displayid_parse_tiled(struct drm_connector *connector, +- const u8 *displayid, int length, int idx) ++static void drm_displayid_parse_tiled(struct drm_connector *connector, ++ const u8 *displayid, int length, int idx) + { + const struct displayid_block *block; +- int ret; + + idx += sizeof(struct displayid_hdr); + for_each_displayid_db(displayid, block, idx, length) { +@@ -5905,16 +5907,13 @@ static int drm_displayid_parse_tiled(struct drm_connector *connector, + + switch (block->tag) { + case DATA_BLOCK_TILED_DISPLAY: +- ret = drm_parse_tiled_block(connector, block); +- if (ret) +- return ret; ++ drm_parse_tiled_block(connector, block); + break; + default: + DRM_DEBUG_KMS("found DisplayID tag 0x%x, unhandled\n", block->tag); + break; + } + } +- return 0; + } + + void drm_update_tile_info(struct drm_connector *connector, +@@ -5923,26 +5922,19 @@ void drm_update_tile_info(struct drm_connector *connector, + const void *displayid = NULL; + int ext_index = 0; + int length, idx; +- int ret; + + connector->has_tile = false; +- displayid = drm_find_displayid_extension(edid, &length, &idx, +- &ext_index); +- if (!displayid) { +- /* drop reference to any tile group we had */ +- goto out_drop_ref; ++ for (;;) { ++ displayid = drm_find_displayid_extension(edid, &length, &idx, ++ &ext_index); ++ if (!displayid) ++ break; ++ ++ drm_displayid_parse_tiled(connector, displayid, length, idx); + } + +- ret = drm_displayid_parse_tiled(connector, displayid, length, idx); +- if (ret < 0) +- goto out_drop_ref; +- if (!connector->has_tile) +- goto out_drop_ref; +- return; +-out_drop_ref: +- if (connector->tile_group) { ++ if (!connector->has_tile && connector->tile_group) { + drm_mode_put_tile_group(connector->dev, connector->tile_group); + connector->tile_group = NULL; + } +- return; + } + +From c4a01f31ea528f8a1057b720eed47d502b19a3fb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= +Date: Wed, 27 May 2020 16:03:10 +0300 +Subject: [PATCH] drm/edid: Clean up some curly braces +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Drop some pointless curly braces, and add some across the +else when the if has them too. + +Signed-off-by: Ville Syrjälä +Link: https://patchwork.freedesktop.org/patch/msgid/20200527130310.27099-3-ville.syrjala@linux.intel.com +Reviewed-by: José Roberto de Souza +(cherry picked from commit 392f9fcb159bf95ec3c7de340a880f4778167275) +--- + drivers/gpu/drm/drm_edid.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c +index fcd739af570f..c28e7678014d 100644 +--- a/drivers/gpu/drm/drm_edid.c ++++ b/drivers/gpu/drm/drm_edid.c +@@ -5877,22 +5877,21 @@ static void drm_parse_tiled_block(struct drm_connector *connector, + DRM_DEBUG_KMS("vend %c%c%c\n", tile->topology_id[0], tile->topology_id[1], tile->topology_id[2]); + + tg = drm_mode_get_tile_group(connector->dev, tile->topology_id); +- if (!tg) { ++ if (!tg) + tg = drm_mode_create_tile_group(connector->dev, tile->topology_id); +- } + if (!tg) + return; + + if (connector->tile_group != tg) { + /* if we haven't got a pointer, + take the reference, drop ref to old tile group */ +- if (connector->tile_group) { ++ if (connector->tile_group) + drm_mode_put_tile_group(connector->dev, connector->tile_group); +- } + connector->tile_group = tg; +- } else ++ } else { + /* if same tile group, then release the ref we just took. */ + drm_mode_put_tile_group(connector->dev, tg); ++ } + } + + static void drm_displayid_parse_tiled(struct drm_connector *connector, + +From 7a5d301a5077083f45d826c49248882eacec778d Mon Sep 17 00:00:00 2001 +From: Liu Ying +Date: Thu, 9 Jul 2020 10:02:35 +0800 +Subject: [PATCH] drm/bridge: dw-hdmi: Don't cleanup i2c adapter and ddc ptr in + __dw_hdmi_probe() bailout path + +It's unnecessary to cleanup the i2c adapter and the ddc pointer in +the bailout path of __dw_hdmi_probe(), since the adapter is not +added and the ddc pointer is not set. + +Fixes: a23d6265f033 ("drm: bridge: dw-hdmi: Extract PHY interrupt setup to a function") +Cc: Andrzej Hajda +Cc: Neil Armstrong +Cc: Laurent Pinchart +Cc: Jonas Karlman +Cc: Jernej Skrabec +Cc: David Airlie +Cc: Daniel Vetter +Cc: Boris Brezillon +Cc: Jerome Brunet +Cc: Cheng-Yi Chiang +Cc: Dariusz Marcinkiewicz +Cc: Archit Taneja +Cc: Jose Abreu +Cc: dri-devel@lists.freedesktop.org +Cc: NXP Linux Team +Signed-off-by: Liu Ying +Reviewed-by: Laurent Pinchart +Signed-off-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/1594260156-8316-1-git-send-email-victor.liu@nxp.com +(cherry picked from commit 2ae53e79f2dec41949d7b089c0b6d7edce292d10) +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 5 ----- + 1 file changed, 5 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 6148a022569a..137b6ebfed19 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -3441,11 +3441,6 @@ __dw_hdmi_probe(struct platform_device *pdev, + return hdmi; + + err_iahb: +- if (hdmi->i2c) { +- i2c_del_adapter(&hdmi->i2c->adap); +- hdmi->ddc = NULL; +- } +- + clk_disable_unprepare(hdmi->iahb_clk); + if (hdmi->cec_clk) + clk_disable_unprepare(hdmi->cec_clk); + +From fe98962cfe32f385bed8c1fea444aeb887b472e6 Mon Sep 17 00:00:00 2001 +From: Liu Ying +Date: Thu, 9 Jul 2020 10:02:36 +0800 +Subject: [PATCH] drm/bridge: dw-hdmi: Always add the bridge in the global + bridge list + +It doesn't hurt to add the bridge in the global bridge list also for +platform specific dw-hdmi drivers which are based on the component +framework. This can be achieved by moving the drm_bridge_add() function +call from dw_hdmi_probe() to __dw_hdmi_probe(). A counterpart movement +for drm_bridge_remove() is also needed then. Moreover, since drm_bridge_add() +initializes &bridge->hpd_mutex, this may help those platform specific +dw-hdmi drivers(based on the component framework) avoid accessing the +uninitialized mutex in drm_bridge_hpd_notify() which is called in +dw_hdmi_irq(). Putting drm_bridge_add() in __dw_hdmi_probe() just before +it returns successfully should bring no logic change for platforms based +on the DRM bridge API, which is a good choice from safety point of view. +Also, __dw_hdmi_probe() is renamed to dw_hdmi_probe() since dw_hdmi_probe() +does nothing else but calling __dw_hdmi_probe(). Similar renaming applies +to the __dw_hdmi_remove()/dw_hdmi_remove() pair. + +Fixes: ec971aaa6775 ("drm: bridge: dw-hdmi: Make connector creation optional") +Cc: Andrzej Hajda +Cc: Neil Armstrong +Cc: Laurent Pinchart +Cc: Jonas Karlman +Cc: Jernej Skrabec +Cc: David Airlie +Cc: Daniel Vetter +Cc: Boris Brezillon +Cc: Jerome Brunet +Cc: Cheng-Yi Chiang +Cc: Dariusz Marcinkiewicz +Cc: Archit Taneja +Cc: Jose Abreu +Cc: Sam Ravnborg +Cc: dri-devel@lists.freedesktop.org +Cc: NXP Linux Team +Signed-off-by: Liu Ying +Signed-off-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/1594260156-8316-2-git-send-email-victor.liu@nxp.com +(cherry picked from commit 0bf4f5b5d3972df7014df302b95b58b8de1a1e94) +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 44 +++++++---------------- + 1 file changed, 13 insertions(+), 31 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 137b6ebfed19..748df1cacd2b 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -3179,9 +3179,11 @@ static void dw_hdmi_init_hw(struct dw_hdmi *hdmi) + hdmi->phy.ops->setup_hpd(hdmi, hdmi->phy.data); + } + +-static struct dw_hdmi * +-__dw_hdmi_probe(struct platform_device *pdev, +- const struct dw_hdmi_plat_data *plat_data) ++/* ----------------------------------------------------------------------------- ++ * Probe/remove API, used from platforms based on the DRM bridge API. ++ */ ++struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev, ++ const struct dw_hdmi_plat_data *plat_data) + { + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; +@@ -3438,6 +3440,8 @@ __dw_hdmi_probe(struct platform_device *pdev, + hdmi->cec = platform_device_register_full(&pdevinfo); + } + ++ drm_bridge_add(&hdmi->bridge); ++ + return hdmi; + + err_iahb: +@@ -3451,9 +3455,12 @@ __dw_hdmi_probe(struct platform_device *pdev, + + return ERR_PTR(ret); + } ++EXPORT_SYMBOL_GPL(dw_hdmi_probe); + +-static void __dw_hdmi_remove(struct dw_hdmi *hdmi) ++void dw_hdmi_remove(struct dw_hdmi *hdmi) + { ++ drm_bridge_remove(&hdmi->bridge); ++ + if (hdmi->audio && !IS_ERR(hdmi->audio)) + platform_device_unregister(hdmi->audio); + if (!IS_ERR(hdmi->cec)) +@@ -3472,31 +3479,6 @@ static void __dw_hdmi_remove(struct dw_hdmi *hdmi) + else + i2c_put_adapter(hdmi->ddc); + } +- +-/* ----------------------------------------------------------------------------- +- * Probe/remove API, used from platforms based on the DRM bridge API. +- */ +-struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev, +- const struct dw_hdmi_plat_data *plat_data) +-{ +- struct dw_hdmi *hdmi; +- +- hdmi = __dw_hdmi_probe(pdev, plat_data); +- if (IS_ERR(hdmi)) +- return hdmi; +- +- drm_bridge_add(&hdmi->bridge); +- +- return hdmi; +-} +-EXPORT_SYMBOL_GPL(dw_hdmi_probe); +- +-void dw_hdmi_remove(struct dw_hdmi *hdmi) +-{ +- drm_bridge_remove(&hdmi->bridge); +- +- __dw_hdmi_remove(hdmi); +-} + EXPORT_SYMBOL_GPL(dw_hdmi_remove); + + /* ----------------------------------------------------------------------------- +@@ -3509,7 +3491,7 @@ struct dw_hdmi *dw_hdmi_bind(struct platform_device *pdev, + struct dw_hdmi *hdmi; + int ret; + +- hdmi = __dw_hdmi_probe(pdev, plat_data); ++ hdmi = dw_hdmi_probe(pdev, plat_data); + if (IS_ERR(hdmi)) + return hdmi; + +@@ -3526,7 +3508,7 @@ EXPORT_SYMBOL_GPL(dw_hdmi_bind); + + void dw_hdmi_unbind(struct dw_hdmi *hdmi) + { +- __dw_hdmi_remove(hdmi); ++ dw_hdmi_remove(hdmi); + } + EXPORT_SYMBOL_GPL(dw_hdmi_unbind); + + +From d046fd09e47e5ea681fa9a0ba441eb493a8b5b14 Mon Sep 17 00:00:00 2001 +From: Andrey Lebedev +Date: Fri, 19 Jun 2020 10:58:59 +0300 +Subject: [PATCH] drm/lima: Expose job_hang_limit module parameter + +Some pp or gp jobs can be successfully repeated even after they time outs. +Introduce lima module parameter to specify number of times a job can hang +before being dropped. + +Signed-off-by: Andrey Lebedev +Signed-off-by: Qiang Yu +Link: https://patchwork.freedesktop.org/patch/msgid/20200619075900.3030696-1-andrey.lebedev@gmail.com +(cherry picked from commit de48984486d942d4f23e2b29374639f21042bdaa) +--- + drivers/gpu/drm/lima/lima_drv.c | 4 ++++ + drivers/gpu/drm/lima/lima_drv.h | 1 + + drivers/gpu/drm/lima/lima_sched.c | 5 +++-- + 3 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/lima/lima_drv.c b/drivers/gpu/drm/lima/lima_drv.c +index a831565af813..ab460121fd52 100644 +--- a/drivers/gpu/drm/lima/lima_drv.c ++++ b/drivers/gpu/drm/lima/lima_drv.c +@@ -19,6 +19,7 @@ + int lima_sched_timeout_ms; + uint lima_heap_init_nr_pages = 8; + uint lima_max_error_tasks; ++uint lima_job_hang_limit; + + MODULE_PARM_DESC(sched_timeout_ms, "task run timeout in ms"); + module_param_named(sched_timeout_ms, lima_sched_timeout_ms, int, 0444); +@@ -29,6 +30,9 @@ module_param_named(heap_init_nr_pages, lima_heap_init_nr_pages, uint, 0444); + MODULE_PARM_DESC(max_error_tasks, "max number of error tasks to save"); + module_param_named(max_error_tasks, lima_max_error_tasks, uint, 0644); + ++MODULE_PARM_DESC(job_hang_limit, "number of times to allow a job to hang before dropping it (default 0)"); ++module_param_named(job_hang_limit, lima_job_hang_limit, uint, 0444); ++ + static int lima_ioctl_get_param(struct drm_device *dev, void *data, struct drm_file *file) + { + struct drm_lima_get_param *args = data; +diff --git a/drivers/gpu/drm/lima/lima_drv.h b/drivers/gpu/drm/lima/lima_drv.h +index fdbd4077c768..c738d288547b 100644 +--- a/drivers/gpu/drm/lima/lima_drv.h ++++ b/drivers/gpu/drm/lima/lima_drv.h +@@ -11,6 +11,7 @@ + extern int lima_sched_timeout_ms; + extern uint lima_heap_init_nr_pages; + extern uint lima_max_error_tasks; ++extern uint lima_job_hang_limit; + + struct lima_vm; + struct lima_bo; +diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c +index e6cefda00279..1602985dfa04 100644 +--- a/drivers/gpu/drm/lima/lima_sched.c ++++ b/drivers/gpu/drm/lima/lima_sched.c +@@ -503,8 +503,9 @@ int lima_sched_pipe_init(struct lima_sched_pipe *pipe, const char *name) + + INIT_WORK(&pipe->recover_work, lima_sched_recover_work); + +- return drm_sched_init(&pipe->base, &lima_sched_ops, 1, 0, +- msecs_to_jiffies(timeout), name); ++ return drm_sched_init(&pipe->base, &lima_sched_ops, 1, ++ lima_job_hang_limit, msecs_to_jiffies(timeout), ++ name); + } + + void lima_sched_pipe_fini(struct lima_sched_pipe *pipe) diff --git a/patch/kernel/rk322x-dev/01-linux-0022-drm-from-next.patch b/patch/kernel/rk322x-dev/01-linux-0022-drm-from-next.patch new file mode 100644 index 000000000..4cf8cdbe7 --- /dev/null +++ b/patch/kernel/rk322x-dev/01-linux-0022-drm-from-next.patch @@ -0,0 +1,1276 @@ +From 055013808487a12514bd6a10d5f1be4267d3cf4a Mon Sep 17 00:00:00 2001 +From: Neil Armstrong +Date: Thu, 23 Jul 2020 11:05:50 +0200 +Subject: [PATCH] drm/fourcc: fix Amlogic Video Framebuffer Compression macro + +Fix the Amlogic Video Framebuffer Compression modifier macro to +correctly add the layout options, a pair of parenthesis was missing. + +Fixes: d6528ec88309 ("drm/fourcc: Add modifier definitions for describing Amlogic Video Framebuffer Compression") +Signed-off-by: Neil Armstrong +Acked-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/20200723090551.27529-1-narmstrong@baylibre.com +(cherry picked from commit da3a9e9a6aa96ef589c153078f66e0646bf06b55) +--- + include/uapi/drm/drm_fourcc.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h +index 4bee7de5f306..82f327801267 100644 +--- a/include/uapi/drm/drm_fourcc.h ++++ b/include/uapi/drm/drm_fourcc.h +@@ -1004,7 +1004,7 @@ drm_fourcc_canonicalize_nvidia_format_mod(__u64 modifier) + #define DRM_FORMAT_MOD_AMLOGIC_FBC(__layout, __options) \ + fourcc_mod_code(AMLOGIC, \ + ((__layout) & __fourcc_mod_amlogic_layout_mask) | \ +- ((__options) & __fourcc_mod_amlogic_options_mask \ ++ (((__options) & __fourcc_mod_amlogic_options_mask) \ + << __fourcc_mod_amlogic_options_shift)) + + /* Amlogic FBC Layouts */ + +From 9df4c74d07ec7d3141b2a243b49de48f3e36932b Mon Sep 17 00:00:00 2001 +From: Tomeu Vizoso +Date: Thu, 11 Jun 2020 10:58:43 +0200 +Subject: [PATCH] drm/panfrost: Make sure GPU is powered on when reading + GPU_LATEST_FLUSH_ID + +Bifrost devices do support the flush reduction feature, so on first job +submit we were trying to read the register while still powered off. + +If the GPU is powered off, the feature doesn't bring any benefit, so +don't try to read. + +Tested-by: Heiko Stuebner +Reviewed-by: Steven Price +Signed-off-by: Tomeu Vizoso +Signed-off-by: Rob Herring +Link: https://patchwork.freedesktop.org/patch/msgid/20200611085900.49740-1-tomeu.vizoso@collabora.com +(cherry picked from commit 3a74265c54f883c847ed8554129baefb3e04f135) +--- + drivers/gpu/drm/panfrost/panfrost_gpu.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/panfrost/panfrost_gpu.c b/drivers/gpu/drm/panfrost/panfrost_gpu.c +index f2c1ddc41a9b..e0f190e43813 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_gpu.c ++++ b/drivers/gpu/drm/panfrost/panfrost_gpu.c +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + + #include "panfrost_device.h" + #include "panfrost_features.h" +@@ -368,7 +369,16 @@ void panfrost_gpu_fini(struct panfrost_device *pfdev) + + u32 panfrost_gpu_get_latest_flush_id(struct panfrost_device *pfdev) + { +- if (panfrost_has_hw_feature(pfdev, HW_FEATURE_FLUSH_REDUCTION)) +- return gpu_read(pfdev, GPU_LATEST_FLUSH_ID); ++ u32 flush_id; ++ ++ if (panfrost_has_hw_feature(pfdev, HW_FEATURE_FLUSH_REDUCTION)) { ++ /* Flush reduction only makes sense when the GPU is kept powered on between jobs */ ++ if (pm_runtime_get_if_in_use(pfdev->dev)) { ++ flush_id = gpu_read(pfdev, GPU_LATEST_FLUSH_ID); ++ pm_runtime_put(pfdev->dev); ++ return flush_id; ++ } ++ } ++ + return 0; + } + +From 956be03f3fc751937bbb07a4e4201a2a73aa87f1 Mon Sep 17 00:00:00 2001 +From: Tomeu Vizoso +Date: Thu, 11 Jun 2020 10:58:44 +0200 +Subject: [PATCH] drm/panfrost: Add compatible string for bifrost + +Mesa now supports some Bifrost devices, so enable it. + +Tested-by: Heiko Stuebner +Reviewed-by: Steven Price +Reviewed-by: Heiko Stuebner +Signed-off-by: Tomeu Vizoso +Signed-off-by: Rob Herring +Link: https://patchwork.freedesktop.org/patch/msgid/20200611085900.49740-2-tomeu.vizoso@collabora.com +(cherry picked from commit 72ef7fe96fd20d3d0e538e165b393819f99870ad) +--- + drivers/gpu/drm/panfrost/panfrost_drv.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c +index 882fecc33fdb..8ff8e140f91e 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_drv.c ++++ b/drivers/gpu/drm/panfrost/panfrost_drv.c +@@ -677,6 +677,7 @@ static const struct of_device_id dt_match[] = { + { .compatible = "arm,mali-t830", .data = &default_data, }, + { .compatible = "arm,mali-t860", .data = &default_data, }, + { .compatible = "arm,mali-t880", .data = &default_data, }, ++ { .compatible = "arm,mali-bifrost", .data = &default_data, }, + {} + }; + MODULE_DEVICE_TABLE(of, dt_match); + +From 1404f107a58a28fb71227550469c4785fa58081c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= +Date: Fri, 10 Jul 2020 11:53:56 +0200 +Subject: [PATCH] drm/panfrost: avoid static declaration +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This declaration can be avoided so change it. + +Reviewed-by: Steven Price +Reviewed-by: Alyssa Rosenzweig +Signed-off-by: Clément Péron +Signed-off-by: Rob Herring +Link: https://patchwork.freedesktop.org/patch/msgid/20200710095409.407087-2-peron.clem@gmail.com +(cherry picked from commit 862cc626210e34501b4d7a7795c41a67785987e5) +--- + drivers/gpu/drm/panfrost/panfrost_devfreq.c | 38 ++++++++++----------- + 1 file changed, 18 insertions(+), 20 deletions(-) + +diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.c b/drivers/gpu/drm/panfrost/panfrost_devfreq.c +index 413987038fbf..1b560b903ea6 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_devfreq.c ++++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.c +@@ -14,7 +14,24 @@ + #include "panfrost_gpu.h" + #include "panfrost_regs.h" + +-static void panfrost_devfreq_update_utilization(struct panfrost_device *pfdev); ++static void panfrost_devfreq_update_utilization(struct panfrost_device *pfdev) ++{ ++ ktime_t now; ++ ktime_t last; ++ ++ if (!pfdev->devfreq.devfreq) ++ return; ++ ++ now = ktime_get(); ++ last = pfdev->devfreq.time_last_update; ++ ++ if (atomic_read(&pfdev->devfreq.busy_count) > 0) ++ pfdev->devfreq.busy_time += ktime_sub(now, last); ++ else ++ pfdev->devfreq.idle_time += ktime_sub(now, last); ++ ++ pfdev->devfreq.time_last_update = now; ++} + + static int panfrost_devfreq_target(struct device *dev, unsigned long *freq, + u32 flags) +@@ -139,25 +156,6 @@ void panfrost_devfreq_suspend(struct panfrost_device *pfdev) + devfreq_suspend_device(pfdev->devfreq.devfreq); + } + +-static void panfrost_devfreq_update_utilization(struct panfrost_device *pfdev) +-{ +- ktime_t now; +- ktime_t last; +- +- if (!pfdev->devfreq.devfreq) +- return; +- +- now = ktime_get(); +- last = pfdev->devfreq.time_last_update; +- +- if (atomic_read(&pfdev->devfreq.busy_count) > 0) +- pfdev->devfreq.busy_time += ktime_sub(now, last); +- else +- pfdev->devfreq.idle_time += ktime_sub(now, last); +- +- pfdev->devfreq.time_last_update = now; +-} +- + void panfrost_devfreq_record_busy(struct panfrost_device *pfdev) + { + panfrost_devfreq_update_utilization(pfdev); + +From 42e45c3c4195d8e7ebe5bf970c7da55fc9c0d157 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= +Date: Fri, 10 Jul 2020 11:53:57 +0200 +Subject: [PATCH] drm/panfrost: clean headers in devfreq +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Don't include not required headers and sort them. + +Reviewed-by: Steven Price +Reviewed-by: Alyssa Rosenzweig +Signed-off-by: Clément Péron +Signed-off-by: Rob Herring +Link: https://patchwork.freedesktop.org/patch/msgid/20200710095409.407087-3-peron.clem@gmail.com +(cherry picked from commit 9713e942a539c55b5e0bc64ba83b736bda1087fe) +--- + drivers/gpu/drm/panfrost/panfrost_devfreq.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.c b/drivers/gpu/drm/panfrost/panfrost_devfreq.c +index 1b560b903ea6..df7b71da9a84 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_devfreq.c ++++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.c +@@ -1,18 +1,14 @@ + // SPDX-License-Identifier: GPL-2.0 + /* Copyright 2019 Collabora ltd. */ ++ ++#include + #include + #include + #include + #include +-#include +-#include + + #include "panfrost_device.h" + #include "panfrost_devfreq.h" +-#include "panfrost_features.h" +-#include "panfrost_issues.h" +-#include "panfrost_gpu.h" +-#include "panfrost_regs.h" + + static void panfrost_devfreq_update_utilization(struct panfrost_device *pfdev) + { + +From 99fda3d26b30e5f30d45fc6197da6335a2806e73 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= +Date: Fri, 10 Jul 2020 11:53:58 +0200 +Subject: [PATCH] drm/panfrost: don't use pfdevfreq.busy_count to know if hw is + idle +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This use devfreq variable that will be lock with spinlock in future +patches. We should either introduce a function to access this one +but as devfreq is optional let's just remove it. + +Reviewed-by: Steven Price +Reviewed-by: Alyssa Rosenzweig +Signed-off-by: Clément Péron +Signed-off-by: Rob Herring +Link: https://patchwork.freedesktop.org/patch/msgid/20200710095409.407087-4-peron.clem@gmail.com +(cherry picked from commit eb9dd67249b55fd1fa3d7359be387ea2079247a6) +--- + drivers/gpu/drm/panfrost/panfrost_job.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c b/drivers/gpu/drm/panfrost/panfrost_job.c +index c6242fe34840..aec05be1ba7a 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_job.c ++++ b/drivers/gpu/drm/panfrost/panfrost_job.c +@@ -581,10 +581,6 @@ int panfrost_job_is_idle(struct panfrost_device *pfdev) + struct panfrost_job_slot *js = pfdev->js; + int i; + +- /* Check whether the hardware is idle */ +- if (atomic_read(&pfdev->devfreq.busy_count)) +- return false; +- + for (i = 0; i < NUM_JOB_SLOTS; i++) { + /* If there are any jobs in the HW queue, we're not idle */ + if (atomic_read(&js->queue[i].sched.hw_rq_count)) + +From ca3fb7080e5fbaf5894bed7e119e8f4e49545449 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= +Date: Fri, 10 Jul 2020 11:53:59 +0200 +Subject: [PATCH] drm/panfrost: introduce panfrost_devfreq struct +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Introduce a proper panfrost_devfreq to deal with devfreq variables. + +Reviewed-by: Steven Price +Reviewed-by: Alyssa Rosenzweig +Signed-off-by: Clément Péron +Signed-off-by: Rob Herring +Link: https://patchwork.freedesktop.org/patch/msgid/20200710095409.407087-5-peron.clem@gmail.com +(cherry picked from commit 9bfacfc82f903b066b0b63460d5b7943705048a4) +--- + drivers/gpu/drm/panfrost/panfrost_devfreq.c | 76 ++++++++++++--------- + drivers/gpu/drm/panfrost/panfrost_devfreq.h | 20 +++++- + drivers/gpu/drm/panfrost/panfrost_device.h | 11 +-- + drivers/gpu/drm/panfrost/panfrost_job.c | 6 +- + 4 files changed, 66 insertions(+), 47 deletions(-) + +diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.c b/drivers/gpu/drm/panfrost/panfrost_devfreq.c +index df7b71da9a84..962550363391 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_devfreq.c ++++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.c +@@ -10,23 +10,23 @@ + #include "panfrost_device.h" + #include "panfrost_devfreq.h" + +-static void panfrost_devfreq_update_utilization(struct panfrost_device *pfdev) ++static void panfrost_devfreq_update_utilization(struct panfrost_devfreq *pfdevfreq) + { + ktime_t now; + ktime_t last; + +- if (!pfdev->devfreq.devfreq) ++ if (!pfdevfreq->devfreq) + return; + + now = ktime_get(); +- last = pfdev->devfreq.time_last_update; ++ last = pfdevfreq->time_last_update; + +- if (atomic_read(&pfdev->devfreq.busy_count) > 0) +- pfdev->devfreq.busy_time += ktime_sub(now, last); ++ if (atomic_read(&pfdevfreq->busy_count) > 0) ++ pfdevfreq->busy_time += ktime_sub(now, last); + else +- pfdev->devfreq.idle_time += ktime_sub(now, last); ++ pfdevfreq->idle_time += ktime_sub(now, last); + +- pfdev->devfreq.time_last_update = now; ++ pfdevfreq->time_last_update = now; + } + + static int panfrost_devfreq_target(struct device *dev, unsigned long *freq, +@@ -47,30 +47,31 @@ static int panfrost_devfreq_target(struct device *dev, unsigned long *freq, + return 0; + } + +-static void panfrost_devfreq_reset(struct panfrost_device *pfdev) ++static void panfrost_devfreq_reset(struct panfrost_devfreq *pfdevfreq) + { +- pfdev->devfreq.busy_time = 0; +- pfdev->devfreq.idle_time = 0; +- pfdev->devfreq.time_last_update = ktime_get(); ++ pfdevfreq->busy_time = 0; ++ pfdevfreq->idle_time = 0; ++ pfdevfreq->time_last_update = ktime_get(); + } + + static int panfrost_devfreq_get_dev_status(struct device *dev, + struct devfreq_dev_status *status) + { + struct panfrost_device *pfdev = dev_get_drvdata(dev); ++ struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq; + +- panfrost_devfreq_update_utilization(pfdev); ++ panfrost_devfreq_update_utilization(pfdevfreq); + + status->current_frequency = clk_get_rate(pfdev->clock); +- status->total_time = ktime_to_ns(ktime_add(pfdev->devfreq.busy_time, +- pfdev->devfreq.idle_time)); ++ status->total_time = ktime_to_ns(ktime_add(pfdevfreq->busy_time, ++ pfdevfreq->idle_time)); + +- status->busy_time = ktime_to_ns(pfdev->devfreq.busy_time); ++ status->busy_time = ktime_to_ns(pfdevfreq->busy_time); + +- panfrost_devfreq_reset(pfdev); ++ panfrost_devfreq_reset(pfdevfreq); + +- dev_dbg(pfdev->dev, "busy %lu total %lu %lu %% freq %lu MHz\n", status->busy_time, +- status->total_time, ++ dev_dbg(pfdev->dev, "busy %lu total %lu %lu %% freq %lu MHz\n", ++ status->busy_time, status->total_time, + status->busy_time / (status->total_time / 100), + status->current_frequency / 1000 / 1000); + +@@ -91,6 +92,7 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) + struct device *dev = &pfdev->pdev->dev; + struct devfreq *devfreq; + struct thermal_cooling_device *cooling; ++ struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq; + + ret = dev_pm_opp_of_add_table(dev); + if (ret == -ENODEV) /* Optional, continue without devfreq */ +@@ -98,7 +100,7 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) + else if (ret) + return ret; + +- panfrost_devfreq_reset(pfdev); ++ panfrost_devfreq_reset(pfdevfreq); + + cur_freq = clk_get_rate(pfdev->clock); + +@@ -116,53 +118,59 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) + dev_pm_opp_of_remove_table(dev); + return PTR_ERR(devfreq); + } +- pfdev->devfreq.devfreq = devfreq; ++ pfdevfreq->devfreq = devfreq; + + cooling = of_devfreq_cooling_register(dev->of_node, devfreq); + if (IS_ERR(cooling)) + DRM_DEV_INFO(dev, "Failed to register cooling device\n"); + else +- pfdev->devfreq.cooling = cooling; ++ pfdevfreq->cooling = cooling; + + return 0; + } + + void panfrost_devfreq_fini(struct panfrost_device *pfdev) + { +- if (pfdev->devfreq.cooling) +- devfreq_cooling_unregister(pfdev->devfreq.cooling); ++ struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq; ++ ++ if (pfdevfreq->cooling) ++ devfreq_cooling_unregister(pfdevfreq->cooling); + dev_pm_opp_of_remove_table(&pfdev->pdev->dev); + } + + void panfrost_devfreq_resume(struct panfrost_device *pfdev) + { +- if (!pfdev->devfreq.devfreq) ++ struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq; ++ ++ if (!pfdevfreq->devfreq) + return; + +- panfrost_devfreq_reset(pfdev); ++ panfrost_devfreq_reset(pfdevfreq); + +- devfreq_resume_device(pfdev->devfreq.devfreq); ++ devfreq_resume_device(pfdevfreq->devfreq); + } + + void panfrost_devfreq_suspend(struct panfrost_device *pfdev) + { +- if (!pfdev->devfreq.devfreq) ++ struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq; ++ ++ if (!pfdevfreq->devfreq) + return; + +- devfreq_suspend_device(pfdev->devfreq.devfreq); ++ devfreq_suspend_device(pfdevfreq->devfreq); + } + +-void panfrost_devfreq_record_busy(struct panfrost_device *pfdev) ++void panfrost_devfreq_record_busy(struct panfrost_devfreq *pfdevfreq) + { +- panfrost_devfreq_update_utilization(pfdev); +- atomic_inc(&pfdev->devfreq.busy_count); ++ panfrost_devfreq_update_utilization(pfdevfreq); ++ atomic_inc(&pfdevfreq->busy_count); + } + +-void panfrost_devfreq_record_idle(struct panfrost_device *pfdev) ++void panfrost_devfreq_record_idle(struct panfrost_devfreq *pfdevfreq) + { + int count; + +- panfrost_devfreq_update_utilization(pfdev); +- count = atomic_dec_if_positive(&pfdev->devfreq.busy_count); ++ panfrost_devfreq_update_utilization(pfdevfreq); ++ count = atomic_dec_if_positive(&pfdevfreq->busy_count); + WARN_ON(count < 0); + } +diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.h b/drivers/gpu/drm/panfrost/panfrost_devfreq.h +index 0611beffc8d0..0697f8d5aa34 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_devfreq.h ++++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.h +@@ -4,13 +4,29 @@ + #ifndef __PANFROST_DEVFREQ_H__ + #define __PANFROST_DEVFREQ_H__ + ++#include ++ ++struct devfreq; ++struct thermal_cooling_device; ++ ++struct panfrost_device; ++ ++struct panfrost_devfreq { ++ struct devfreq *devfreq; ++ struct thermal_cooling_device *cooling; ++ ktime_t busy_time; ++ ktime_t idle_time; ++ ktime_t time_last_update; ++ atomic_t busy_count; ++}; ++ + int panfrost_devfreq_init(struct panfrost_device *pfdev); + void panfrost_devfreq_fini(struct panfrost_device *pfdev); + + void panfrost_devfreq_resume(struct panfrost_device *pfdev); + void panfrost_devfreq_suspend(struct panfrost_device *pfdev); + +-void panfrost_devfreq_record_busy(struct panfrost_device *pfdev); +-void panfrost_devfreq_record_idle(struct panfrost_device *pfdev); ++void panfrost_devfreq_record_busy(struct panfrost_devfreq *devfreq); ++void panfrost_devfreq_record_idle(struct panfrost_devfreq *devfreq); + + #endif /* __PANFROST_DEVFREQ_H__ */ +diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h +index c30c719a8059..2efa59c9d1c5 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_device.h ++++ b/drivers/gpu/drm/panfrost/panfrost_device.h +@@ -13,6 +13,8 @@ + #include + #include + ++#include "panfrost_devfreq.h" ++ + struct panfrost_device; + struct panfrost_mmu; + struct panfrost_job_slot; +@@ -107,14 +109,7 @@ struct panfrost_device { + struct list_head shrinker_list; + struct shrinker shrinker; + +- struct { +- struct devfreq *devfreq; +- struct thermal_cooling_device *cooling; +- ktime_t busy_time; +- ktime_t idle_time; +- ktime_t time_last_update; +- atomic_t busy_count; +- } devfreq; ++ struct panfrost_devfreq pfdevfreq; + }; + + struct panfrost_mmu { +diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c b/drivers/gpu/drm/panfrost/panfrost_job.c +index aec05be1ba7a..2f297d962e64 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_job.c ++++ b/drivers/gpu/drm/panfrost/panfrost_job.c +@@ -145,7 +145,7 @@ static void panfrost_job_hw_submit(struct panfrost_job *job, int js) + u64 jc_head = job->jc; + int ret; + +- panfrost_devfreq_record_busy(pfdev); ++ panfrost_devfreq_record_busy(&pfdev->pfdevfreq); + + ret = pm_runtime_get_sync(pfdev->dev); + if (ret < 0) +@@ -410,7 +410,7 @@ static void panfrost_job_timedout(struct drm_sched_job *sched_job) + for (i = 0; i < NUM_JOB_SLOTS; i++) { + if (pfdev->jobs[i]) { + pm_runtime_put_noidle(pfdev->dev); +- panfrost_devfreq_record_idle(pfdev); ++ panfrost_devfreq_record_idle(&pfdev->pfdevfreq); + pfdev->jobs[i] = NULL; + } + } +@@ -478,7 +478,7 @@ static irqreturn_t panfrost_job_irq_handler(int irq, void *data) + pfdev->jobs[j] = NULL; + + panfrost_mmu_as_put(pfdev, &job->file_priv->mmu); +- panfrost_devfreq_record_idle(pfdev); ++ panfrost_devfreq_record_idle(&pfdev->pfdevfreq); + + dma_fence_signal_locked(job->done_fence); + pm_runtime_put_autosuspend(pfdev->dev); + +From 950ed8f4f8c6ab02e5f1c7b107e5af9a896c90dc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= +Date: Fri, 10 Jul 2020 11:54:00 +0200 +Subject: [PATCH] drm/panfrost: use spinlock instead of atomic +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Convert busy_count to a simple int protected by spinlock. + +Reviewed-by: Steven Price +Reviewed-by: Alyssa Rosenzweig +Signed-off-by: Clément Péron +Signed-off-by: Rob Herring +Link: https://patchwork.freedesktop.org/patch/msgid/20200710095409.407087-6-peron.clem@gmail.com +(cherry picked from commit ed85df3f60740bb4be23fbc2db283d59b361a834) +--- + drivers/gpu/drm/panfrost/panfrost_devfreq.c | 43 +++++++++++++++------ + drivers/gpu/drm/panfrost/panfrost_devfreq.h | 9 ++++- + 2 files changed, 40 insertions(+), 12 deletions(-) + +diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.c b/drivers/gpu/drm/panfrost/panfrost_devfreq.c +index 962550363391..78753cfb59fb 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_devfreq.c ++++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.c +@@ -12,16 +12,12 @@ + + static void panfrost_devfreq_update_utilization(struct panfrost_devfreq *pfdevfreq) + { +- ktime_t now; +- ktime_t last; +- +- if (!pfdevfreq->devfreq) +- return; ++ ktime_t now, last; + + now = ktime_get(); + last = pfdevfreq->time_last_update; + +- if (atomic_read(&pfdevfreq->busy_count) > 0) ++ if (pfdevfreq->busy_count > 0) + pfdevfreq->busy_time += ktime_sub(now, last); + else + pfdevfreq->idle_time += ktime_sub(now, last); +@@ -59,10 +55,14 @@ static int panfrost_devfreq_get_dev_status(struct device *dev, + { + struct panfrost_device *pfdev = dev_get_drvdata(dev); + struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq; ++ unsigned long irqflags; ++ ++ status->current_frequency = clk_get_rate(pfdev->clock); ++ ++ spin_lock_irqsave(&pfdevfreq->lock, irqflags); + + panfrost_devfreq_update_utilization(pfdevfreq); + +- status->current_frequency = clk_get_rate(pfdev->clock); + status->total_time = ktime_to_ns(ktime_add(pfdevfreq->busy_time, + pfdevfreq->idle_time)); + +@@ -70,6 +70,8 @@ static int panfrost_devfreq_get_dev_status(struct device *dev, + + panfrost_devfreq_reset(pfdevfreq); + ++ spin_unlock_irqrestore(&pfdevfreq->lock, irqflags); ++ + dev_dbg(pfdev->dev, "busy %lu total %lu %lu %% freq %lu MHz\n", + status->busy_time, status->total_time, + status->busy_time / (status->total_time / 100), +@@ -100,6 +102,8 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) + else if (ret) + return ret; + ++ spin_lock_init(&pfdevfreq->lock); ++ + panfrost_devfreq_reset(pfdevfreq); + + cur_freq = clk_get_rate(pfdev->clock); +@@ -162,15 +166,32 @@ void panfrost_devfreq_suspend(struct panfrost_device *pfdev) + + void panfrost_devfreq_record_busy(struct panfrost_devfreq *pfdevfreq) + { ++ unsigned long irqflags; ++ ++ if (!pfdevfreq->devfreq) ++ return; ++ ++ spin_lock_irqsave(&pfdevfreq->lock, irqflags); ++ + panfrost_devfreq_update_utilization(pfdevfreq); +- atomic_inc(&pfdevfreq->busy_count); ++ ++ pfdevfreq->busy_count++; ++ ++ spin_unlock_irqrestore(&pfdevfreq->lock, irqflags); + } + + void panfrost_devfreq_record_idle(struct panfrost_devfreq *pfdevfreq) + { +- int count; ++ unsigned long irqflags; ++ ++ if (!pfdevfreq->devfreq) ++ return; ++ ++ spin_lock_irqsave(&pfdevfreq->lock, irqflags); + + panfrost_devfreq_update_utilization(pfdevfreq); +- count = atomic_dec_if_positive(&pfdevfreq->busy_count); +- WARN_ON(count < 0); ++ ++ WARN_ON(--pfdevfreq->busy_count < 0); ++ ++ spin_unlock_irqrestore(&pfdevfreq->lock, irqflags); + } +diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.h b/drivers/gpu/drm/panfrost/panfrost_devfreq.h +index 0697f8d5aa34..3392df1020be 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_devfreq.h ++++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.h +@@ -4,6 +4,7 @@ + #ifndef __PANFROST_DEVFREQ_H__ + #define __PANFROST_DEVFREQ_H__ + ++#include + #include + + struct devfreq; +@@ -14,10 +15,16 @@ struct panfrost_device; + struct panfrost_devfreq { + struct devfreq *devfreq; + struct thermal_cooling_device *cooling; ++ + ktime_t busy_time; + ktime_t idle_time; + ktime_t time_last_update; +- atomic_t busy_count; ++ int busy_count; ++ /* ++ * Protect busy_time, idle_time, time_last_update and busy_count ++ * because these can be updated concurrently between multiple jobs. ++ */ ++ spinlock_t lock; + }; + + int panfrost_devfreq_init(struct panfrost_device *pfdev); + +From ac548872c7b7887d34b549efa3b8334b2cc862ed Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= +Date: Fri, 10 Jul 2020 11:54:01 +0200 +Subject: [PATCH] drm/panfrost: properly handle error in probe +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Introduce a boolean to know if opp table has been added. + +With this, we can call panfrost_devfreq_fini() in case of error +and release what has been initialised. + +Reviewed-by: Steven Price +Reviewed-by: Alyssa Rosenzweig +Signed-off-by: Clément Péron +Signed-off-by: Rob Herring +Link: https://patchwork.freedesktop.org/patch/msgid/20200710095409.407087-7-peron.clem@gmail.com +(cherry picked from commit 81f2fbe62cb54b6cf3d91078c4d49451ba7b9877) +--- + drivers/gpu/drm/panfrost/panfrost_devfreq.c | 25 ++++++++++++++++----- + drivers/gpu/drm/panfrost/panfrost_devfreq.h | 1 + + 2 files changed, 20 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.c b/drivers/gpu/drm/panfrost/panfrost_devfreq.c +index 78753cfb59fb..d9007f44b772 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_devfreq.c ++++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.c +@@ -101,6 +101,7 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) + return 0; + else if (ret) + return ret; ++ pfdevfreq->opp_of_table_added = true; + + spin_lock_init(&pfdevfreq->lock); + +@@ -109,8 +110,10 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) + cur_freq = clk_get_rate(pfdev->clock); + + opp = devfreq_recommended_opp(dev, &cur_freq, 0); +- if (IS_ERR(opp)) +- return PTR_ERR(opp); ++ if (IS_ERR(opp)) { ++ ret = PTR_ERR(opp); ++ goto err_fini; ++ } + + panfrost_devfreq_profile.initial_freq = cur_freq; + dev_pm_opp_put(opp); +@@ -119,8 +122,8 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) + DEVFREQ_GOV_SIMPLE_ONDEMAND, NULL); + if (IS_ERR(devfreq)) { + DRM_DEV_ERROR(dev, "Couldn't initialize GPU devfreq\n"); +- dev_pm_opp_of_remove_table(dev); +- return PTR_ERR(devfreq); ++ ret = PTR_ERR(devfreq); ++ goto err_fini; + } + pfdevfreq->devfreq = devfreq; + +@@ -131,15 +134,25 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) + pfdevfreq->cooling = cooling; + + return 0; ++ ++err_fini: ++ panfrost_devfreq_fini(pfdev); ++ return ret; + } + + void panfrost_devfreq_fini(struct panfrost_device *pfdev) + { + struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq; + +- if (pfdevfreq->cooling) ++ if (pfdevfreq->cooling) { + devfreq_cooling_unregister(pfdevfreq->cooling); +- dev_pm_opp_of_remove_table(&pfdev->pdev->dev); ++ pfdevfreq->cooling = NULL; ++ } ++ ++ if (pfdevfreq->opp_of_table_added) { ++ dev_pm_opp_of_remove_table(&pfdev->pdev->dev); ++ pfdevfreq->opp_of_table_added = false; ++ } + } + + void panfrost_devfreq_resume(struct panfrost_device *pfdev) +diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.h b/drivers/gpu/drm/panfrost/panfrost_devfreq.h +index 3392df1020be..210269944687 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_devfreq.h ++++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.h +@@ -15,6 +15,7 @@ struct panfrost_device; + struct panfrost_devfreq { + struct devfreq *devfreq; + struct thermal_cooling_device *cooling; ++ bool opp_of_table_added; + + ktime_t busy_time; + ktime_t idle_time; + +From 96a752deaead8b45cd188cde09cb873fd8dfd4b6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= +Date: Fri, 10 Jul 2020 11:54:02 +0200 +Subject: [PATCH] drm/panfrost: rename error labels in device_init +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Rename goto labels in device_init it will be easier to maintain. + +Reviewed-by: Alyssa Rosenzweig +Reviewed-by: Steven Price +Signed-off-by: Clément Péron +Signed-off-by: Rob Herring +Link: https://patchwork.freedesktop.org/patch/msgid/20200710095409.407087-8-peron.clem@gmail.com +(cherry picked from commit d3c335da0200be9287cdf5755d19f62ce1670a8d) +--- + drivers/gpu/drm/panfrost/panfrost_device.c | 30 +++++++++++----------- + 1 file changed, 15 insertions(+), 15 deletions(-) + +diff --git a/drivers/gpu/drm/panfrost/panfrost_device.c b/drivers/gpu/drm/panfrost/panfrost_device.c +index b172087eee6a..9f89984f652a 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_device.c ++++ b/drivers/gpu/drm/panfrost/panfrost_device.c +@@ -216,56 +216,56 @@ int panfrost_device_init(struct panfrost_device *pfdev) + + err = panfrost_regulator_init(pfdev); + if (err) +- goto err_out0; ++ goto out_clk; + + err = panfrost_reset_init(pfdev); + if (err) { + dev_err(pfdev->dev, "reset init failed %d\n", err); +- goto err_out1; ++ goto out_regulator; + } + + err = panfrost_pm_domain_init(pfdev); + if (err) +- goto err_out2; ++ goto out_reset; + + res = platform_get_resource(pfdev->pdev, IORESOURCE_MEM, 0); + pfdev->iomem = devm_ioremap_resource(pfdev->dev, res); + if (IS_ERR(pfdev->iomem)) { + dev_err(pfdev->dev, "failed to ioremap iomem\n"); + err = PTR_ERR(pfdev->iomem); +- goto err_out3; ++ goto out_pm_domain; + } + + err = panfrost_gpu_init(pfdev); + if (err) +- goto err_out3; ++ goto out_pm_domain; + + err = panfrost_mmu_init(pfdev); + if (err) +- goto err_out4; ++ goto out_gpu; + + err = panfrost_job_init(pfdev); + if (err) +- goto err_out5; ++ goto out_mmu; + + err = panfrost_perfcnt_init(pfdev); + if (err) +- goto err_out6; ++ goto out_job; + + return 0; +-err_out6: ++out_job: + panfrost_job_fini(pfdev); +-err_out5: ++out_mmu: + panfrost_mmu_fini(pfdev); +-err_out4: ++out_gpu: + panfrost_gpu_fini(pfdev); +-err_out3: ++out_pm_domain: + panfrost_pm_domain_fini(pfdev); +-err_out2: ++out_reset: + panfrost_reset_fini(pfdev); +-err_out1: ++out_regulator: + panfrost_regulator_fini(pfdev); +-err_out0: ++out_clk: + panfrost_clk_fini(pfdev); + return err; + } + +From 9c803e01258f241d49e1162ca6db5b29a98ba57d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= +Date: Fri, 10 Jul 2020 11:54:03 +0200 +Subject: [PATCH] drm/panfrost: move devfreq_init()/fini() in device +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Later we will introduce devfreq probing regulator if they +are present. As regulator should be probe only one time we +need to get this logic in the device_init(). + +panfrost_device is already taking care of devfreq_resume() +and devfreq_suspend(), so it's not totally illogic to move +the devfreq_init() and devfreq_fini() here. + +Reviewed-by: Alyssa Rosenzweig +Reviewed-by: Steven Price +Signed-off-by: Clément Péron +Signed-off-by: Rob Herring +Link: https://patchwork.freedesktop.org/patch/msgid/20200710095409.407087-9-peron.clem@gmail.com +(cherry picked from commit 25e247bbf85af3ad721dfeb2e2caf405f43b7e66) +--- + drivers/gpu/drm/panfrost/panfrost_device.c | 12 +++++++++++- + drivers/gpu/drm/panfrost/panfrost_drv.c | 15 ++------------- + 2 files changed, 13 insertions(+), 14 deletions(-) + +diff --git a/drivers/gpu/drm/panfrost/panfrost_device.c b/drivers/gpu/drm/panfrost/panfrost_device.c +index 9f89984f652a..36b5c8fea3eb 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_device.c ++++ b/drivers/gpu/drm/panfrost/panfrost_device.c +@@ -214,9 +214,16 @@ int panfrost_device_init(struct panfrost_device *pfdev) + return err; + } + ++ err = panfrost_devfreq_init(pfdev); ++ if (err) { ++ if (err != -EPROBE_DEFER) ++ dev_err(pfdev->dev, "devfreq init failed %d\n", err); ++ goto out_clk; ++ } ++ + err = panfrost_regulator_init(pfdev); + if (err) +- goto out_clk; ++ goto out_devfreq; + + err = panfrost_reset_init(pfdev); + if (err) { +@@ -265,6 +272,8 @@ int panfrost_device_init(struct panfrost_device *pfdev) + panfrost_reset_fini(pfdev); + out_regulator: + panfrost_regulator_fini(pfdev); ++out_devfreq: ++ panfrost_devfreq_fini(pfdev); + out_clk: + panfrost_clk_fini(pfdev); + return err; +@@ -278,6 +287,7 @@ void panfrost_device_fini(struct panfrost_device *pfdev) + panfrost_gpu_fini(pfdev); + panfrost_pm_domain_fini(pfdev); + panfrost_reset_fini(pfdev); ++ panfrost_devfreq_fini(pfdev); + panfrost_regulator_fini(pfdev); + panfrost_clk_fini(pfdev); + } +diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c +index 8ff8e140f91e..ed8bcdd6b211 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_drv.c ++++ b/drivers/gpu/drm/panfrost/panfrost_drv.c +@@ -14,7 +14,6 @@ + #include + + #include "panfrost_device.h" +-#include "panfrost_devfreq.h" + #include "panfrost_gem.h" + #include "panfrost_mmu.h" + #include "panfrost_job.h" +@@ -606,13 +605,6 @@ static int panfrost_probe(struct platform_device *pdev) + goto err_out0; + } + +- err = panfrost_devfreq_init(pfdev); +- if (err) { +- if (err != -EPROBE_DEFER) +- dev_err(&pdev->dev, "Fatal error during devfreq init\n"); +- goto err_out1; +- } +- + pm_runtime_set_active(pfdev->dev); + pm_runtime_mark_last_busy(pfdev->dev); + pm_runtime_enable(pfdev->dev); +@@ -625,16 +617,14 @@ static int panfrost_probe(struct platform_device *pdev) + */ + err = drm_dev_register(ddev, 0); + if (err < 0) +- goto err_out2; ++ goto err_out1; + + panfrost_gem_shrinker_init(ddev); + + return 0; + +-err_out2: +- pm_runtime_disable(pfdev->dev); +- panfrost_devfreq_fini(pfdev); + err_out1: ++ pm_runtime_disable(pfdev->dev); + panfrost_device_fini(pfdev); + err_out0: + drm_dev_put(ddev); +@@ -650,7 +640,6 @@ static int panfrost_remove(struct platform_device *pdev) + panfrost_gem_shrinker_cleanup(ddev); + + pm_runtime_get_sync(pfdev->dev); +- panfrost_devfreq_fini(pfdev); + panfrost_device_fini(pfdev); + pm_runtime_put_sync_suspend(pfdev->dev); + pm_runtime_disable(pfdev->dev); + +From d858649520907e147d85147efb8cfdb280ee5852 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= +Date: Fri, 10 Jul 2020 11:54:04 +0200 +Subject: [PATCH] drm/panfrost: dynamically alloc regulators +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We will later introduce regulators managed by OPP. + +Only alloc regulators when it's needed. This also help use +to release the regulators only when they are allocated. + +Reviewed-by: Steven Price +Reviewed-by: Alyssa Rosenzweig +Signed-off-by: Clément Péron +Signed-off-by: Rob Herring +Link: https://patchwork.freedesktop.org/patch/msgid/20200710095409.407087-10-peron.clem@gmail.com +(cherry picked from commit 512f21227fd3d2dbe7aad57a995b9732229c9b56) +--- + drivers/gpu/drm/panfrost/panfrost_device.c | 14 +++++++++----- + drivers/gpu/drm/panfrost/panfrost_device.h | 3 +-- + 2 files changed, 10 insertions(+), 7 deletions(-) + +diff --git a/drivers/gpu/drm/panfrost/panfrost_device.c b/drivers/gpu/drm/panfrost/panfrost_device.c +index 36b5c8fea3eb..f1474b961def 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_device.c ++++ b/drivers/gpu/drm/panfrost/panfrost_device.c +@@ -90,9 +90,11 @@ static int panfrost_regulator_init(struct panfrost_device *pfdev) + { + int ret, i; + +- if (WARN(pfdev->comp->num_supplies > ARRAY_SIZE(pfdev->regulators), +- "Too many supplies in compatible structure.\n")) +- return -EINVAL; ++ pfdev->regulators = devm_kcalloc(pfdev->dev, pfdev->comp->num_supplies, ++ sizeof(*pfdev->regulators), ++ GFP_KERNEL); ++ if (!pfdev->regulators) ++ return -ENOMEM; + + for (i = 0; i < pfdev->comp->num_supplies; i++) + pfdev->regulators[i].supply = pfdev->comp->supply_names[i]; +@@ -119,8 +121,10 @@ static int panfrost_regulator_init(struct panfrost_device *pfdev) + + static void panfrost_regulator_fini(struct panfrost_device *pfdev) + { +- regulator_bulk_disable(pfdev->comp->num_supplies, +- pfdev->regulators); ++ if (!pfdev->regulators) ++ return; ++ ++ regulator_bulk_disable(pfdev->comp->num_supplies, pfdev->regulators); + } + + static void panfrost_pm_domain_fini(struct panfrost_device *pfdev) +diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h +index 2efa59c9d1c5..953f7536a773 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_device.h ++++ b/drivers/gpu/drm/panfrost/panfrost_device.h +@@ -22,7 +22,6 @@ struct panfrost_job; + struct panfrost_perfcnt; + + #define NUM_JOB_SLOTS 3 +-#define MAX_REGULATORS 2 + #define MAX_PM_DOMAINS 3 + + struct panfrost_features { +@@ -81,7 +80,7 @@ struct panfrost_device { + void __iomem *iomem; + struct clk *clock; + struct clk *bus_clock; +- struct regulator_bulk_data regulators[MAX_REGULATORS]; ++ struct regulator_bulk_data *regulators; + struct reset_control *rstc; + /* pm_domains for devices with more than one. */ + struct device *pm_domain_devs[MAX_PM_DOMAINS]; + +From 1ee7aed7c3c6736b33828d488a6d29bd8f0e0e84 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= +Date: Fri, 10 Jul 2020 11:54:05 +0200 +Subject: [PATCH] drm/panfrost: add regulators to devfreq +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Some OPP tables specify voltage for each frequency. Devfreq can +handle these regulators but they should be get only 1 time to avoid +issue and know who is in charge. + +If OPP table is probe don't init regulator. + +Reviewed-by: Steven Price +Reviewed-by: Alyssa Rosenzweig +Signed-off-by: Clément Péron +Signed-off-by: Rob Herring +Link: https://patchwork.freedesktop.org/patch/msgid/20200710095409.407087-11-peron.clem@gmail.com +(cherry picked from commit fd587ff01d59554144e2fd20f4113638a45c7c4e) +--- + drivers/gpu/drm/panfrost/panfrost_devfreq.c | 29 ++++++++++++++++++--- + drivers/gpu/drm/panfrost/panfrost_devfreq.h | 2 ++ + drivers/gpu/drm/panfrost/panfrost_device.c | 9 ++++--- + 3 files changed, 33 insertions(+), 7 deletions(-) + +diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.c b/drivers/gpu/drm/panfrost/panfrost_devfreq.c +index d9007f44b772..8ab025d0035f 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_devfreq.c ++++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.c +@@ -93,14 +93,30 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) + unsigned long cur_freq; + struct device *dev = &pfdev->pdev->dev; + struct devfreq *devfreq; ++ struct opp_table *opp_table; + struct thermal_cooling_device *cooling; + struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq; + ++ opp_table = dev_pm_opp_set_regulators(dev, pfdev->comp->supply_names, ++ pfdev->comp->num_supplies); ++ if (IS_ERR(opp_table)) { ++ ret = PTR_ERR(opp_table); ++ /* Continue if the optional regulator is missing */ ++ if (ret != -ENODEV) { ++ DRM_DEV_ERROR(dev, "Couldn't set OPP regulators\n"); ++ goto err_fini; ++ } ++ } else { ++ pfdevfreq->regulators_opp_table = opp_table; ++ } ++ + ret = dev_pm_opp_of_add_table(dev); +- if (ret == -ENODEV) /* Optional, continue without devfreq */ +- return 0; +- else if (ret) +- return ret; ++ if (ret) { ++ /* Optional, continue without devfreq */ ++ if (ret == -ENODEV) ++ ret = 0; ++ goto err_fini; ++ } + pfdevfreq->opp_of_table_added = true; + + spin_lock_init(&pfdevfreq->lock); +@@ -153,6 +169,11 @@ void panfrost_devfreq_fini(struct panfrost_device *pfdev) + dev_pm_opp_of_remove_table(&pfdev->pdev->dev); + pfdevfreq->opp_of_table_added = false; + } ++ ++ if (pfdevfreq->regulators_opp_table) { ++ dev_pm_opp_put_regulators(pfdevfreq->regulators_opp_table); ++ pfdevfreq->regulators_opp_table = NULL; ++ } + } + + void panfrost_devfreq_resume(struct panfrost_device *pfdev) +diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.h b/drivers/gpu/drm/panfrost/panfrost_devfreq.h +index 210269944687..db6ea48e21f9 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_devfreq.h ++++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.h +@@ -8,12 +8,14 @@ + #include + + struct devfreq; ++struct opp_table; + struct thermal_cooling_device; + + struct panfrost_device; + + struct panfrost_devfreq { + struct devfreq *devfreq; ++ struct opp_table *regulators_opp_table; + struct thermal_cooling_device *cooling; + bool opp_of_table_added; + +diff --git a/drivers/gpu/drm/panfrost/panfrost_device.c b/drivers/gpu/drm/panfrost/panfrost_device.c +index f1474b961def..e6896733838a 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_device.c ++++ b/drivers/gpu/drm/panfrost/panfrost_device.c +@@ -225,9 +225,12 @@ int panfrost_device_init(struct panfrost_device *pfdev) + goto out_clk; + } + +- err = panfrost_regulator_init(pfdev); +- if (err) +- goto out_devfreq; ++ /* OPP will handle regulators */ ++ if (!pfdev->pfdevfreq.opp_of_table_added) { ++ err = panfrost_regulator_init(pfdev); ++ if (err) ++ goto out_devfreq; ++ } + + err = panfrost_reset_init(pfdev); + if (err) { + +From 94b3398f3b4d5e963f284bd39515bfdf84530c6c Mon Sep 17 00:00:00 2001 +From: Navid Emamdoost +Date: Sun, 14 Jun 2020 01:36:19 -0500 +Subject: [PATCH] drm/panfrost: perfcnt: fix ref count leak in + panfrost_perfcnt_enable_locked + +in panfrost_perfcnt_enable_locked, pm_runtime_get_sync is called which +increments the counter even in case of failure, leading to incorrect +ref count. In case of failure, decrement the ref count before returning. + +Acked-by: Alyssa Rosenzweig +Signed-off-by: Navid Emamdoost +Signed-off-by: Rob Herring +Link: https://patchwork.freedesktop.org/patch/msgid/20200614063619.44944-1-navid.emamdoost@gmail.com +(cherry picked from commit 9df0e0c1889677175037445d5ad1654d54176369) +--- + drivers/gpu/drm/panfrost/panfrost_perfcnt.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/panfrost/panfrost_perfcnt.c b/drivers/gpu/drm/panfrost/panfrost_perfcnt.c +index 6913578d5aa7..6169644d4469 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_perfcnt.c ++++ b/drivers/gpu/drm/panfrost/panfrost_perfcnt.c +@@ -83,11 +83,13 @@ static int panfrost_perfcnt_enable_locked(struct panfrost_device *pfdev, + + ret = pm_runtime_get_sync(pfdev->dev); + if (ret < 0) +- return ret; ++ goto err_put_pm; + + bo = drm_gem_shmem_create(pfdev->ddev, perfcnt->bosize); +- if (IS_ERR(bo)) +- return PTR_ERR(bo); ++ if (IS_ERR(bo)) { ++ ret = PTR_ERR(bo); ++ goto err_put_pm; ++ } + + /* Map the perfcnt buf in the address space attached to file_priv. */ + ret = panfrost_gem_open(&bo->base, file_priv); +@@ -168,6 +170,8 @@ static int panfrost_perfcnt_enable_locked(struct panfrost_device *pfdev, + panfrost_gem_close(&bo->base, file_priv); + err_put_bo: + drm_gem_object_put_unlocked(&bo->base); ++err_put_pm: ++ pm_runtime_put(pfdev->dev); + return ret; + } + diff --git a/patch/kernel/rk322x-dev/01-linux-1000-clk-rockchip-rk3228-fixup.patch b/patch/kernel/rk322x-dev/01-linux-1000-clk-rockchip-rk3228-fixup.patch deleted file mode 100644 index 21826f856..000000000 --- a/patch/kernel/rk322x-dev/01-linux-1000-clk-rockchip-rk3228-fixup.patch +++ /dev/null @@ -1,98 +0,0 @@ -diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c -index 0127d702720c..6ef71ec239ae 100644 ---- a/drivers/clk/rockchip/clk-rk3228.c -+++ b/drivers/clk/rockchip/clk-rk3228.c -@@ -353,7 +353,7 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { - RK2928_CLKGATE_CON(10), 12, GFLAGS), - - COMPOSITE(SCLK_WIFI, "sclk_wifi", mux_pll_src_cpll_gpll_usb480m_p, 0, -- RK2928_CLKSEL_CON(23), 5, 2, MFLAGS, 0, 6, DFLAGS, -+ RK2928_CLKSEL_CON(23), 5, 2, MFLAGS, 0, 5, DFLAGS, - RK2928_CLKGATE_CON(2), 15, GFLAGS), - - COMPOSITE(SCLK_SDMMC, "sclk_sdmmc", mux_mmc_src_p, 0, --- -2.17.1 - - -From 3acbbe5eb438e8b1061a803881579030d3c2b424 Mon Sep 17 00:00:00 2001 -From: Chen Lei -Date: Tue, 25 Dec 2018 18:29:04 +0800 -Subject: [PATCH] clk: rockchip: rk322x: fix wrong mmc phase shift for rk3228 - -mmc sample shift should be 1 for rk3228, or it will fail -if we enable mmc tuning for rk3228. - -Change-Id: I301c2a7d33de8d519d7c288aef03a82531016373 -Signed-off-by: Chen Lei ---- - drivers/clk/rockchip/clk-rk3228.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c -index 6ef71ec239ae..27adfca1a095 100644 ---- a/drivers/clk/rockchip/clk-rk3228.c -+++ b/drivers/clk/rockchip/clk-rk3228.c -@@ -610,13 +610,13 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { - - /* PD_MMC */ - MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "sclk_sdmmc", RK3228_SDMMC_CON0, 1), -- MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK3228_SDMMC_CON1, 0), -+ MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK3228_SDMMC_CON1, 1), - - MMC(SCLK_SDIO_DRV, "sdio_drv", "sclk_sdio", RK3228_SDIO_CON0, 1), -- MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "sclk_sdio", RK3228_SDIO_CON1, 0), -+ MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "sclk_sdio", RK3228_SDIO_CON1, 1), - - MMC(SCLK_EMMC_DRV, "emmc_drv", "sclk_emmc", RK3228_EMMC_CON0, 1), -- MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RK3228_EMMC_CON1, 0), -+ MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RK3228_EMMC_CON1, 1), - }; - - static const char *const rk3228_critical_clocks[] __initconst = { --- -2.17.1 - - -From a692001c1249473bdfe975ef53d2bdb8a4df736d Mon Sep 17 00:00:00 2001 -From: Finley Xiao -Date: Mon, 5 Feb 2018 10:04:15 +0800 -Subject: [PATCH] clk: rockchip: rk3228: Fix armclk parent - -Change-Id: I09830d96b37cca600f1782b9013b25e043467f97 -Signed-off-by: Finley Xiao ---- - drivers/clk/rockchip/clk-rk3228.c | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c -index 58292f80ad66..fba513de94eb 100644 ---- a/drivers/clk/rockchip/clk-rk3228.c -+++ b/drivers/clk/rockchip/clk-rk3228.c -@@ -170,7 +170,7 @@ static struct rockchip_pll_clock rk3228_pll_clks[] __initdata = { - [cpll] = PLL(pll_rk3036, PLL_CPLL, "cpll", mux_pll_p, 0, RK2928_PLL_CON(6), - RK2928_MODE_CON, 8, 8, 0, NULL), - [gpll] = PLL(pll_rk3036, PLL_GPLL, "gpll", mux_pll_p, 0, RK2928_PLL_CON(9), -- RK2928_MODE_CON, 12, 9, ROCKCHIP_PLL_SYNC_RATE, rk3228_pll_rates), -+ RK2928_MODE_CON, 12, 9, 0, rk3228_pll_rates), - }; - - #define MFLAGS CLK_MUX_HIWORD_MASK --- -2.17.1 - - -From f57d5061e7357a8f7a181517530658a223ba415b Mon Sep 17 00:00:00 2001 -From: Finley Xiao -Date: Thu, 22 Jun 2017 19:53:46 +0800 -Subject: [PATCH] clk: rockchip: rk3228: fix gpu gate-register - -Fix a typo making the aclk_gpu and aclk_gpu_noc access a wrong register to -handle its gate. - -Change-Id: Ie0bac8014363af7c0409b8a56eacf2e858818843 -Signed-off-by: Finley Xiao ---- - drivers/clk/rockchip/clk-rk3228.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - diff --git a/patch/kernel/rk322x-dev/01-linux-1000-export-mm_trace_rss_stat.patch b/patch/kernel/rk322x-dev/01-linux-1000-export-mm_trace_rss_stat.patch new file mode 100644 index 000000000..03be01030 --- /dev/null +++ b/patch/kernel/rk322x-dev/01-linux-1000-export-mm_trace_rss_stat.patch @@ -0,0 +1,12 @@ +diff --git a/mm/memory.c b/mm/memory.c +index 606da18..8429abc 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -158,6 +158,7 @@ + { + trace_rss_stat(mm, member, count); + } ++EXPORT_SYMBOL(mm_trace_rss_stat); + + #if defined(SPLIT_RSS_COUNTING) + diff --git a/patch/kernel/rk322x-dev/01-linux-1001-clk-rockchip-rk3228-more-fixes.patch b/patch/kernel/rk322x-dev/01-linux-1001-clk-rockchip-rk3228-more-fixes.patch deleted file mode 100644 index 024940cd3..000000000 --- a/patch/kernel/rk322x-dev/01-linux-1001-clk-rockchip-rk3228-more-fixes.patch +++ /dev/null @@ -1,219 +0,0 @@ -diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c -index 448b202bf4f3..828d0003a18e 100644 ---- a/drivers/clk/rockchip/clk-rk3228.c -+++ b/drivers/clk/rockchip/clk-rk3228.c -@@ -510,12 +510,12 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { - - /* PD_VOP */ - GATE(ACLK_RGA, "aclk_rga", "aclk_rga_pre", 0, RK2928_CLKGATE_CON(13), 0, GFLAGS), -- GATE(0, "aclk_rga_noc", "aclk_rga_pre", 0, RK2928_CLKGATE_CON(13), 11, GFLAGS), -+ GATE(0, "aclk_rga_noc", "aclk_rga_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(13), 11, GFLAGS), - GATE(ACLK_IEP, "aclk_iep", "aclk_iep_pre", 0, RK2928_CLKGATE_CON(13), 2, GFLAGS), -- GATE(0, "aclk_iep_noc", "aclk_iep_pre", 0, RK2928_CLKGATE_CON(13), 9, GFLAGS), -+ GATE(0, "aclk_iep_noc", "aclk_iep_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(13), 9, GFLAGS), - - GATE(ACLK_VOP, "aclk_vop", "aclk_vop_pre", 0, RK2928_CLKGATE_CON(13), 5, GFLAGS), -- GATE(0, "aclk_vop_noc", "aclk_vop_pre", 0, RK2928_CLKGATE_CON(13), 12, GFLAGS), -+ GATE(0, "aclk_vop_noc", "aclk_vop_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(13), 12, GFLAGS), - - GATE(ACLK_HDCP, "aclk_hdcp", "aclk_hdcp_pre", 0, RK2928_CLKGATE_CON(14), 10, GFLAGS), - GATE(0, "aclk_hdcp_noc", "aclk_hdcp_pre", 0, RK2928_CLKGATE_CON(13), 10, GFLAGS), -@@ -523,13 +523,13 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { - GATE(HCLK_RGA, "hclk_rga", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 1, GFLAGS), - GATE(HCLK_IEP, "hclk_iep", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 3, GFLAGS), - GATE(HCLK_VOP, "hclk_vop", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 6, GFLAGS), -- GATE(0, "hclk_vio_ahb_arbi", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 7, GFLAGS), -- GATE(0, "hclk_vio_noc", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 8, GFLAGS), -- GATE(0, "hclk_vop_noc", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 13, GFLAGS), -- GATE(HCLK_VIO_H2P, "hclk_vio_h2p", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 7, GFLAGS), -+ GATE(0, "hclk_vio_ahb_arbi", "hclk_vio_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(13), 7, GFLAGS), -+ GATE(0, "hclk_vio_noc", "hclk_vio_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(13), 8, GFLAGS), -+ GATE(0, "hclk_vop_noc", "hclk_vio_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(13), 13, GFLAGS), -+ GATE(HCLK_VIO_H2P, "hclk_vio_h2p", "hclk_vio_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(14), 7, GFLAGS), - GATE(HCLK_HDCP_MMU, "hclk_hdcp_mmu", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 12, GFLAGS), - GATE(PCLK_HDMI_CTRL, "pclk_hdmi_ctrl", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 6, GFLAGS), -- GATE(PCLK_VIO_H2P, "pclk_vio_h2p", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 8, GFLAGS), -+ GATE(PCLK_VIO_H2P, "pclk_vio_h2p", "hclk_vio_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(14), 8, GFLAGS), - GATE(PCLK_HDCP, "pclk_hdcp", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 11, GFLAGS), - - /* PD_PERI */ -@@ -541,13 +541,13 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { - GATE(HCLK_EMMC, "hclk_emmc", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 2, GFLAGS), - GATE(HCLK_NANDC, "hclk_nandc", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 3, GFLAGS), - GATE(HCLK_HOST0, "hclk_host0", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 6, GFLAGS), -- GATE(0, "hclk_host0_arb", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 7, GFLAGS), -+ GATE(0, "hclk_host0_arb", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(11), 7, GFLAGS), - GATE(HCLK_HOST1, "hclk_host1", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 8, GFLAGS), -- GATE(0, "hclk_host1_arb", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 9, GFLAGS), -+ GATE(0, "hclk_host1_arb", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(11), 9, GFLAGS), - GATE(HCLK_HOST2, "hclk_host2", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 10, GFLAGS), - GATE(HCLK_OTG, "hclk_otg", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 12, GFLAGS), -- GATE(0, "hclk_otg_pmu", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 13, GFLAGS), -- GATE(0, "hclk_host2_arb", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 14, GFLAGS), -+ GATE(0, "hclk_otg_pmu", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(11), 13, GFLAGS), -+ GATE(0, "hclk_host2_arb", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(11), 14, GFLAGS), - GATE(0, "hclk_peri_noc", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(12), 1, GFLAGS), - - GATE(PCLK_GMAC, "pclk_gmac", "pclk_peri", 0, RK2928_CLKGATE_CON(11), 5, GFLAGS), -@@ -555,15 +555,15 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { - - /* PD_GPU */ - GATE(ACLK_GPU, "aclk_gpu", "aclk_gpu_pre", 0, RK2928_CLKGATE_CON(7), 14, GFLAGS), -- GATE(0, "aclk_gpu_noc", "aclk_gpu_pre", 0, RK2928_CLKGATE_CON(7), 15, GFLAGS), -+ GATE(0, "aclk_gpu_noc", "aclk_gpu_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(7), 15, GFLAGS), - - /* PD_BUS */ -- GATE(0, "sclk_initmem_mbist", "aclk_cpu", 0, RK2928_CLKGATE_CON(8), 1, GFLAGS), -- GATE(0, "aclk_initmem", "aclk_cpu", 0, RK2928_CLKGATE_CON(8), 0, GFLAGS), -+ GATE(0, "sclk_initmem_mbist", "aclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(8), 1, GFLAGS), -+ GATE(0, "aclk_initmem", "aclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(8), 0, GFLAGS), - GATE(ACLK_DMAC, "aclk_dmac_bus", "aclk_cpu", 0, RK2928_CLKGATE_CON(8), 2, GFLAGS), - GATE(0, "aclk_bus_noc", "aclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 1, GFLAGS), - -- GATE(0, "hclk_rom", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 3, GFLAGS), -+ GATE(0, "hclk_rom", "hclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(8), 3, GFLAGS), - GATE(HCLK_I2S0_8CH, "hclk_i2s0_8ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 7, GFLAGS), - GATE(HCLK_I2S1_8CH, "hclk_i2s1_8ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 8, GFLAGS), - GATE(HCLK_I2S2_2CH, "hclk_i2s2_2ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 9, GFLAGS), -@@ -572,9 +572,9 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { - GATE(HCLK_M_CRYPTO, "hclk_crypto_mst", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 11, GFLAGS), - GATE(HCLK_S_CRYPTO, "hclk_crypto_slv", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 12, GFLAGS), - -- GATE(0, "pclk_ddrupctl", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(8), 4, GFLAGS), -- GATE(0, "pclk_ddrmon", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(8), 6, GFLAGS), -- GATE(0, "pclk_msch_noc", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(10), 2, GFLAGS), -+ GATE(0, "pclk_ddrupctl", "pclk_ddr_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(8), 4, GFLAGS), -+ GATE(0, "pclk_ddrmon", "pclk_ddr_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(8), 6, GFLAGS), -+ GATE(0, "pclk_msch_noc", "pclk_ddr_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 2, GFLAGS), - - GATE(PCLK_EFUSE_1024, "pclk_efuse_1024", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 13, GFLAGS), - GATE(PCLK_EFUSE_256, "pclk_efuse_256", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 14, GFLAGS), -@@ -583,7 +583,7 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { - GATE(PCLK_I2C2, "pclk_i2c2", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 1, GFLAGS), - GATE(PCLK_I2C3, "pclk_i2c3", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 2, GFLAGS), - GATE(PCLK_TIMER, "pclk_timer0", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 4, GFLAGS), -- GATE(0, "pclk_stimer", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 5, GFLAGS), -+ GATE(0, "pclk_stimer", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 5, GFLAGS), - GATE(PCLK_SPI0, "pclk_spi0", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 6, GFLAGS), - GATE(PCLK_PWM, "pclk_rk_pwm", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 7, GFLAGS), - GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 8, GFLAGS), -@@ -597,22 +597,22 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { - GATE(PCLK_GRF, "pclk_grf", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 0, GFLAGS), - GATE(0, "pclk_cru", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 1, GFLAGS), - GATE(0, "pclk_sgrf", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 2, GFLAGS), -- GATE(0, "pclk_sim", "pclk_cpu", 0, RK2928_CLKGATE_CON(10), 3, GFLAGS), -+ GATE(0, "pclk_sim", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 3, GFLAGS), - -- GATE(0, "pclk_ddrphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 3, GFLAGS), -- GATE(0, "pclk_acodecphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 5, GFLAGS), -+ GATE(0, "pclk_ddrphy", "pclk_phy_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 3, GFLAGS), -+ GATE(PCLK_ACODECPHY, "pclk_acodecphy", "pclk_phy_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 5, GFLAGS), - GATE(PCLK_HDMI_PHY, "pclk_hdmiphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 7, GFLAGS), -- GATE(0, "pclk_vdacphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 8, GFLAGS), -- GATE(0, "pclk_phy_noc", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 9, GFLAGS), -+ GATE(0, "pclk_vdacphy", "pclk_phy_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 8, GFLAGS), -+ GATE(0, "pclk_phy_noc", "pclk_phy_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 9, GFLAGS), - - GATE(ACLK_VPU, "aclk_vpu", "aclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 0, GFLAGS), -- GATE(0, "aclk_vpu_noc", "aclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 4, GFLAGS), -+ GATE(0, "aclk_vpu_noc", "aclk_vpu_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(15), 4, GFLAGS), - GATE(ACLK_RKVDEC, "aclk_rkvdec", "aclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 2, GFLAGS), -- GATE(0, "aclk_rkvdec_noc", "aclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 6, GFLAGS), -+ GATE(0, "aclk_rkvdec_noc", "aclk_rkvdec_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(15), 6, GFLAGS), - GATE(HCLK_VPU, "hclk_vpu", "hclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 1, GFLAGS), -- GATE(0, "hclk_vpu_noc", "hclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 5, GFLAGS), -+ GATE(0, "hclk_vpu_noc", "hclk_vpu_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(15), 5, GFLAGS), - GATE(HCLK_RKVDEC, "hclk_rkvdec", "hclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 3, GFLAGS), -- GATE(0, "hclk_rkvdec_noc", "hclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 7, GFLAGS), -+ GATE(0, "hclk_rkvdec_noc", "hclk_rkvdec_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(15), 7, GFLAGS), - - /* PD_MMC */ - MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "sclk_sdmmc", RK3228_SDMMC_CON0, 1), -@@ -656,25 +656,34 @@ static const char *const rk3228_critical_clocks[] __initconst = { - "pclk_phy_noc", - "aclk_vpu_noc", - "aclk_rkvdec_noc", -+ "aclk_rkvdec", - "hclk_vpu_noc", - "hclk_rkvdec_noc", -+ "hclk_rkvdec", - }; - -+static void __iomem *rk3228_cru_base; -+ -+static void rk3228_clk_shutdown(void) -+{ -+ writel_relaxed(0x11010000, rk3228_cru_base + RK3228_MODE_CON); -+} -+ - static void __init rk3228_clk_init(struct device_node *np) - { - struct rockchip_clk_provider *ctx; -- void __iomem *reg_base; - -- reg_base = of_iomap(np, 0); -- if (!reg_base) { -+ rk3228_cru_base = of_iomap(np, 0); -+ -+ if (!rk3228_cru_base) { - pr_err("%s: could not map cru region\n", __func__); - return; - } - -- ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS); -+ ctx = rockchip_clk_init(np, rk3228_cru_base, CLK_NR_CLKS); - if (IS_ERR(ctx)) { - pr_err("%s: rockchip clk init failed\n", __func__); -- iounmap(reg_base); -+ iounmap(rk3228_cru_base); - return; - } - -@@ -691,10 +700,10 @@ static void __init rk3228_clk_init(struct device_node *np) - &rk3228_cpuclk_data, rk3228_cpuclk_rates, - ARRAY_SIZE(rk3228_cpuclk_rates)); - -- rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0), -+ rockchip_register_softrst(np, 9, rk3228_cru_base + RK2928_SOFTRST_CON(0), - ROCKCHIP_SOFTRST_HIWORD_MASK); - -- rockchip_register_restart_notifier(ctx, RK3228_GLB_SRST_FST, NULL); -+ rockchip_register_restart_notifier(ctx, RK3228_GLB_SRST_FST, rk3228_clk_shutdown); - - rockchip_clk_of_add_provider(np, ctx); - } -diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h -index 2271a84124b0..f2f80f224f30 100644 ---- a/drivers/clk/rockchip/clk.h -+++ b/drivers/clk/rockchip/clk.h -@@ -134,6 +134,7 @@ struct clk; - #define RK3308_EMMC_CON0 0x490 - #define RK3308_EMMC_CON1 0x494 - -+#define RK3228_MODE_CON 0x40 - #define RK3328_PLL_CON(x) RK2928_PLL_CON(x) - #define RK3328_CLKSEL_CON(x) ((x) * 0x4 + 0x100) - #define RK3328_CLKGATE_CON(x) ((x) * 0x4 + 0x200) -diff --git a/include/dt-bindings/clock/rk3228-cru.h b/include/dt-bindings/clock/rk3228-cru.h -index de550ea56eeb..16e1feae5ce4 100644 ---- a/include/dt-bindings/clock/rk3228-cru.h -+++ b/include/dt-bindings/clock/rk3228-cru.h -@@ -65,6 +65,7 @@ - #define SCLK_OTGPHY0 142 - #define SCLK_OTGPHY1 143 - #define SCLK_HDMI_PHY 144 -+#define SCLK_DDRC 145 - - /* dclk gates */ - #define DCLK_VOP 190 -@@ -115,6 +116,7 @@ - #define PCLK_HDMI_CTRL 364 - #define PCLK_HDMI_PHY 365 - #define PCLK_GMAC 367 -+#define PCLK_ACODECPHY 368 - - /* hclk gates */ - #define HCLK_I2S0_8CH 442 --- -2.17.1 - diff --git a/patch/kernel/rk322x-dev/01-linux-1002-arm-dts-rk322x-dts.patch b/patch/kernel/rk322x-dev/01-linux-1002-arm-dts-rk322x-dts.patch deleted file mode 100644 index 50ae37df8..000000000 --- a/patch/kernel/rk322x-dev/01-linux-1002-arm-dts-rk322x-dts.patch +++ /dev/null @@ -1,1586 +0,0 @@ -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index e8dd99201..02d9d3ae7 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -952,6 +952,12 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \ - rk3188-px3-evb.dtb \ - rk3188-radxarock.dtb \ - rk3228-evb.dtb \ -+ rk3228a-box.dtb \ -+ rk3228a-box-h96mini.dtb \ -+ rk3228a-box-nand.dtb \ -+ rk3229-box.dtb \ -+ rk3229-box-a95xr1.dtb \ -+ rk3229-box-nand.dtb \ - rk3229-evb.dtb \ - rk3229-xms6.dtb \ - rk3288-evb-act8846.dtb \ -diff --git a/arch/arm/boot/dts/rk3228a-box-h96mini.dts b/arch/arm/boot/dts/rk3228a-box-h96mini.dts -new file mode 100644 -index 000000000..c624500d1 ---- /dev/null -+++ b/arch/arm/boot/dts/rk3228a-box-h96mini.dts -@@ -0,0 +1,106 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+ -+/dts-v1/; -+#include -+#include -+#include "rk3228a-box.dtsi" -+ -+/ { -+ compatible = "eledvb,h96mini", "rockchip,rk3228a-box", "rockchip,rk3229"; -+ model = "Rockchip RK3228A Box H96 mini"; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ led_green { -+ gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>; -+ default-state = "on"; -+ }; -+ -+ led_red { -+ gpios = <&gpio0 RK_PB0 GPIO_ACTIVE_HIGH>; -+ default-state = "off"; -+ }; -+ }; -+ -+}; -+ -+&emmc { -+ mmc-hs200-1_8v; -+ status = "okay"; -+}; -+ -+&gmac { -+ tx_delay = <0x26>; -+ rx_delay = <0x11>; -+}; -+ -+&ir_receiver { -+ status = "okay"; -+}; -+ -+&pinctrl { -+ wifi { -+ wifi_host_wake_l: wifi-host-wake-l { -+ rockchip,pins = <0 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+ -+ bt { -+ bt_host_wake_l: bt-host-wake-l { -+ rockchip,pins = <3 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ -+ bt_reg_on_h: bt-reg-on-h { -+ rockchip,pins = <2 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ -+ bt_wake_l: bt-wake-l { -+ rockchip,pins = <3 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+}; -+ -+&power_key { -+ status = "okay"; -+}; -+ -+&sdio { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ brcmf: wifi@1 { -+ compatible = "brcm,bcm4329-fmac"; -+ reg = <1>; -+ interrupt-parent = <&gpio0>; -+ interrupts = ; -+ interrupt-names = "host-wake"; -+ brcm,drive-strength = <5>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&wifi_host_wake_l>; -+ }; -+}; -+ -+&sdmmc { -+ disable-wp; -+ status = "okay"; -+}; -+ -+&uart1 { -+ status = "okay"; -+ -+ bluetooth { -+ compatible = "brcm,bcm4330-bt"; -+ host-wakeup-gpios = <&gpio3 RK_PD2 GPIO_ACTIVE_HIGH>; -+ device-wakeup-gpios = <&gpio3 RK_PD3 GPIO_ACTIVE_HIGH>; -+ shutdown-gpios = <&gpio2 RK_PD5 GPIO_ACTIVE_HIGH>; -+ max-speed = <4000000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&bt_reg_on_h &bt_host_wake_l &bt_wake_l>; -+ }; -+}; -+ -+&usb_otg { -+ dr_mode = "host"; -+}; -diff --git a/arch/arm/boot/dts/rk3228a-box-nand.dts b/arch/arm/boot/dts/rk3228a-box-nand.dts -new file mode 100644 -index 000000000..f3e5ab894 ---- /dev/null -+++ b/arch/arm/boot/dts/rk3228a-box-nand.dts -@@ -0,0 +1,57 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+ -+/dts-v1/; -+#include "rk3228a-box.dtsi" -+ -+/ { -+ model = "Rockchip RK3228A Box"; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ led_blue { -+ gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>; -+ default-state = "on"; -+ }; -+ -+ led_red { -+ gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_HIGH>; -+ default-state = "off"; -+ }; -+ }; -+ -+}; -+ -+&ir_receiver { -+ status = "okay"; -+}; -+ -+&nfc { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ nand@0 { -+ reg = <0>; -+ nand-ecc-mode = "hw"; -+ nand-ecc-strength = <60>; -+ nand-ecc-step-size = <1024>; -+ nand-bus-width = <8>; -+ }; -+}; -+ -+&sdio { -+ status = "okay"; -+}; -+ -+&sdmmc { -+ status = "okay"; -+}; -+ -+&uart1 { -+ status = "okay"; -+}; -+ -+&usb_otg { -+ dr_mode = "host"; -+}; -diff --git a/arch/arm/boot/dts/rk3228a-box.dts b/arch/arm/boot/dts/rk3228a-box.dts -new file mode 100644 -index 000000000..e68ef44b9 ---- /dev/null -+++ b/arch/arm/boot/dts/rk3228a-box.dts -@@ -0,0 +1,47 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+ -+/dts-v1/; -+#include "rk3228a-box.dtsi" -+ -+/ { -+ model = "Rockchip RK3228A Box"; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ led_blue { -+ gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>; -+ default-state = "on"; -+ }; -+ -+ led_red { -+ gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_HIGH>; -+ default-state = "off"; -+ }; -+ }; -+ -+}; -+ -+&emmc { -+ status = "okay"; -+}; -+ -+&ir_receiver { -+ status = "okay"; -+}; -+ -+&sdio { -+ status = "okay"; -+}; -+ -+&sdmmc { -+ status = "okay"; -+}; -+ -+&uart1 { -+ status = "okay"; -+}; -+ -+&usb_otg { -+ dr_mode = "host"; -+}; -diff --git a/arch/arm/boot/dts/rk3228a-box.dtsi b/arch/arm/boot/dts/rk3228a-box.dtsi -new file mode 100644 -index 000000000..dbd5c5dc4 ---- /dev/null -+++ b/arch/arm/boot/dts/rk3228a-box.dtsi -@@ -0,0 +1,12 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+ -+/dts-v1/; -+ -+#include "rk322x-box.dtsi" -+ -+/ { -+ -+ model = "Rockchip RK3228A Box"; -+ compatible = "rockchip,rk3228a-box", "rockchip,rk3229"; -+ -+}; -diff --git a/arch/arm/boot/dts/rk3229-box-a95xr1.dts b/arch/arm/boot/dts/rk3229-box-a95xr1.dts -new file mode 100644 -index 000000000..b3695fb0b ---- /dev/null -+++ b/arch/arm/boot/dts/rk3229-box-a95xr1.dts -@@ -0,0 +1,57 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+ -+/dts-v1/; -+#include -+#include -+#include "rk3229-box.dtsi" -+ -+/ { -+ model = "Rockchip RK3229 Box A95X-R1"; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ led_blue { -+ gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>; -+ default-state = "on"; -+ }; -+ -+ led_red { -+ gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_HIGH>; -+ default-state = "off"; -+ linux,default-trigger = "rc-feedback"; -+ }; -+ }; -+ -+}; -+ -+&emmc { -+ mmc-hs200-1_8v; -+ status = "okay"; -+}; -+ -+&gmac { -+ tx_delay = <0x26>; -+ rx_delay = <0x11>; -+}; -+ -+&ir_receiver { -+ status = "okay"; -+}; -+ -+&power_key { -+ status = "okay"; -+}; -+ -+&sdio { -+ status = "okay"; -+}; -+ -+&sdmmc { -+ disable-wp; -+ status = "okay"; -+}; -+ -+&usb_otg { -+ dr_mode = "host"; -+}; -diff --git a/arch/arm/boot/dts/rk3229-box-nand.dts b/arch/arm/boot/dts/rk3229-box-nand.dts -new file mode 100644 -index 000000000..5eca0f335 ---- /dev/null -+++ b/arch/arm/boot/dts/rk3229-box-nand.dts -@@ -0,0 +1,60 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+ -+/dts-v1/; -+#include "rk3229-box.dtsi" -+ -+/ { -+ model = "Rockchip RK3229 Box"; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ led_green { -+ gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>; -+ default-state = "on"; -+ }; -+ -+ led_red { -+ gpios = <&gpio0 RK_PB0 GPIO_ACTIVE_HIGH>; -+ default-state = "off"; -+ }; -+ }; -+}; -+ -+&ir_receiver { -+ status = "okay"; -+}; -+ -+&nfc { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ nand@0 { -+ reg = <0>; -+ nand-ecc-mode = "hw"; -+ nand-ecc-strength = <60>; -+ nand-ecc-step-size = <1024>; -+ nand-bus-width = <8>; -+ }; -+}; -+ -+&power_key { -+ status = "okay"; -+}; -+ -+&sdio { -+ status = "okay"; -+}; -+ -+&sdmmc { -+ status = "okay"; -+}; -+ -+&uart1 { -+ status = "okay"; -+}; -+ -+&usb_otg { -+ dr_mode = "host"; -+}; -diff --git a/arch/arm/boot/dts/rk3229-box.dts b/arch/arm/boot/dts/rk3229-box.dts -new file mode 100644 -index 000000000..b63e61cda ---- /dev/null -+++ b/arch/arm/boot/dts/rk3229-box.dts -@@ -0,0 +1,50 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+ -+/dts-v1/; -+#include "rk3229-box.dtsi" -+ -+/ { -+ model = "Rockchip RK3229 Box"; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ led_green { -+ gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>; -+ default-state = "on"; -+ }; -+ -+ led_red { -+ gpios = <&gpio0 RK_PB0 GPIO_ACTIVE_HIGH>; -+ default-state = "off"; -+ }; -+ }; -+}; -+ -+&emmc { -+ status = "okay"; -+}; -+ -+&ir_receiver { -+ status = "okay"; -+}; -+ -+&power_key { -+ status = "okay"; -+}; -+ -+&sdio { -+ status = "okay"; -+}; -+ -+&sdmmc { -+ status = "okay"; -+}; -+ -+&uart1 { -+ status = "okay"; -+}; -+ -+&usb_otg { -+ dr_mode = "host"; -+}; -diff --git a/arch/arm/boot/dts/rk3229-box.dtsi b/arch/arm/boot/dts/rk3229-box.dtsi -new file mode 100644 -index 000000000..79e2524e0 ---- /dev/null -+++ b/arch/arm/boot/dts/rk3229-box.dtsi -@@ -0,0 +1,21 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+ -+/dts-v1/; -+ -+#include "rk322x-box.dtsi" -+#include "rk3229-cpu-opp.dtsi" -+ -+/ { -+ -+ model = "Rockchip RK3229 Box"; -+ compatible = "rockchip,rk3229-box", "rockchip,rk3229"; -+ -+}; -+ -+&cpu0_opp_table { -+ -+ opp-1464000000 { -+ status = "disabled"; -+ }; -+ -+}; -diff --git a/arch/arm/boot/dts/rk3229-cpu-opp.dtsi b/arch/arm/boot/dts/rk3229-cpu-opp.dtsi -new file mode 100644 -index 000000000..c1c7613ba ---- /dev/null -+++ b/arch/arm/boot/dts/rk3229-cpu-opp.dtsi -@@ -0,0 +1,50 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd -+ */ -+ -+/ { -+ compatible = "rockchip,rk3229"; -+ -+ /delete-node/ opp-table0; -+ -+ cpu0_opp_table: opp_table0 { -+ compatible = "operating-points-v2"; -+ opp-shared; -+ -+ opp-408000000 { -+ opp-hz = /bits/ 64 <408000000>; -+ opp-microvolt = <950000 950000 1400000>; -+ clock-latency-ns = <40000>; -+ opp-suspend; -+ }; -+ opp-600000000 { -+ opp-hz = /bits/ 64 <600000000>; -+ opp-microvolt = <975000 975000 1400000>; -+ }; -+ opp-816000000 { -+ opp-hz = /bits/ 64 <816000000>; -+ opp-microvolt = <1000000 1000000 1400000>; -+ }; -+ opp-1008000000 { -+ opp-hz = /bits/ 64 <1008000000>; -+ opp-microvolt = <1175000 1175000 1400000>; -+ }; -+ opp-1200000000 { -+ opp-hz = /bits/ 64 <1200000000>; -+ opp-microvolt = <1275000 1275000 1400000>; -+ }; -+ opp-1296000000 { -+ opp-hz = /bits/ 64 <1296000000>; -+ opp-microvolt = <1325000 1325000 1400000>; -+ }; -+ opp-1392000000 { -+ opp-hz = /bits/ 64 <1392000000>; -+ opp-microvolt = <1350000 1350000 1400000>; -+ }; -+ opp-1464000000 { -+ opp-hz = /bits/ 64 <1464000000>; -+ opp-microvolt = <1400000 1400000 1400000>; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/rk322x-box.dtsi b/arch/arm/boot/dts/rk322x-box.dtsi -new file mode 100644 -index 000000000..44fb2f4ea ---- /dev/null -+++ b/arch/arm/boot/dts/rk322x-box.dtsi -@@ -0,0 +1,250 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+ -+/dts-v1/; -+ -+#include -+#include -+#include -+#include -+#include "rk322x-dcdc.dtsi" -+ -+/ { -+ model = "Rockchip RK322x Box"; -+ compatible = "rockchip,rk3229"; -+ -+ chosen { -+ bootargs = "earlyprintk=uart8250,mmio32,0x11030000"; -+ }; -+ -+ gpio_keys { -+ compatible = "gpio-keys"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ autorepeat; -+ -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pwr_key>; -+ -+ power_key: power-key { -+ label = "GPIO Key Power"; -+ gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_LOW>; -+ linux,code = ; -+ debounce-interval = <100>; -+ wakeup-source; -+ status = "disabled"; -+ }; -+ }; -+ -+ ir_receiver: ir-receiver { -+ compatible = "gpio-ir-receiver"; -+ gpios = <&gpio1 RK_PB3 GPIO_ACTIVE_LOW>; -+ pinctrl-0 = <&ir_int>; -+ pinctrl-names = "default"; -+ status = "disabled"; -+ }; -+ -+ memory@60000000 { -+ device_type = "memory"; -+ reg = <0x60000000 0x40000000>; -+ }; -+ -+ reserved-memory { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ -+ trust_reserved: trust@68400000 { -+ reg = <0x68400000 0xe00000>; -+ no-map; -+ }; -+ }; -+ -+ sdio_pwrseq: sdio-pwrseq { -+ compatible = "mmc-pwrseq-simple"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&wifi_enable_h>; -+ reset-gpios = <&gpio2 RK_PD2 GPIO_ACTIVE_LOW>; -+ }; -+ -+ timer { -+ arm,cpu-registers-not-fw-configured; -+ }; -+}; -+ -+&cpu_alert1 { -+ temperature = <105000>; -+}; -+ -+&cpu_crit { -+ temperature = <115000>; -+}; -+ -+&cpu_thermal { -+ cooling-maps { -+ /delete-node/ map0; -+ }; -+}; -+ -+&emmc { -+ cap-mmc-highspeed; -+ keep-power-in-suspend; -+ non-removable; -+}; -+ -+&gmac { -+ assigned-clocks = <&cru SCLK_MAC_SRC>; -+ assigned-clock-rates = <50000000>; -+ clock_in_out = "output"; -+ phy-handle = <&phy>; -+ phy-mode = "rmii"; -+ status = "okay"; -+ -+ mdio { -+ compatible = "snps,dwmac-mdio"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ phy: phy@0 { -+ compatible = "ethernet-phy-id1234.d400", -+ "ethernet-phy-ieee802.3-c22"; -+ reg = <0>; -+ clocks = <&cru SCLK_MAC_PHY>; -+ phy-is-integrated; -+ resets = <&cru SRST_MACPHY>; -+ }; -+ }; -+}; -+ -+&hdmi { -+ status = "okay"; -+}; -+ -+&hdmi_sound { -+ status = "okay"; -+}; -+ -+&hdmi_phy { -+ status = "okay"; -+}; -+ -+&i2s0 { -+ status = "okay"; -+}; -+ -+&pinctrl { -+ -+ ir { -+ ir_int: ir-int { -+ rockchip,pins = <1 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+ -+ keys { -+ pwr_key: pwr-key { -+ rockchip,pins = <3 RK_PC7 RK_FUNC_GPIO &pcfg_pull_up>; -+ }; -+ }; -+ -+ sdio-pwrseq { -+ wifi_enable_h: wifi-enable-h { -+ rockchip,pins = <2 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+ -+}; -+ -+&rga { -+ status = "okay"; -+}; -+ -+&sdio { -+ mmc-pwrseq = <&sdio_pwrseq>; -+ cap-sd-highspeed; -+ cap-sdio-irq; -+ keep-power-in-suspend; -+ non-removable; -+ no-sd; -+}; -+ -+&sdmmc { -+ cap-sd-highspeed; -+ keep-power-in-suspend; -+ no-sdio; -+}; -+ -+&spdif { -+ status = "okay"; -+}; -+ -+&spdif_out { -+ status = "okay"; -+}; -+ -+&spdif_sound { -+ status = "okay"; -+}; -+ -+&tsadc { -+ rockchip,hw-tshut-mode = <0>; -+ rockchip,hw-tshut-polarity = <1>; -+ status = "okay"; -+}; -+ -+&u2phy0 { -+ status = "okay"; -+}; -+ -+&u2phy1 { -+ status = "okay"; -+}; -+ -+&uart1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&uart11_xfer &uart11_rts &uart11_cts>; -+}; -+ -+&uart2 { -+ status = "okay"; -+}; -+ -+&usb_host0_ehci { -+ status = "okay"; -+}; -+ -+&usb_host0_ohci { -+ status = "okay"; -+}; -+ -+&usb_host1_ehci { -+ status = "okay"; -+}; -+ -+&usb_host1_ohci { -+ status = "okay"; -+}; -+ -+&usb_host2_ehci { -+ status = "okay"; -+}; -+ -+&usb_host2_ohci { -+ status = "okay"; -+}; -+ -+&usb_otg { -+ status = "okay"; -+}; -+ -+&vop { -+ assigned-clocks = <&cru DCLK_VOP>; -+ assigned-clock-parents = <&cru SCLK_HDMI_PHY>; -+ status = "okay"; -+}; -+ -+&vop_mmu { -+ status = "okay"; -+}; -+ -+&wdt { -+ status = "okay"; -+}; -diff --git a/arch/arm/boot/dts/rk322x-dcdc.dtsi b/arch/arm/boot/dts/rk322x-dcdc.dtsi -new file mode 100644 -index 000000000..6076cb1d0 ---- /dev/null -+++ b/arch/arm/boot/dts/rk322x-dcdc.dtsi -@@ -0,0 +1,164 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+ -+/dts-v1/; -+ -+#include -+#include -+#include "rk322x.dtsi" -+ -+/ { -+ -+ vcc_host: vcc-host-regulator { -+ compatible = "regulator-fixed"; -+ enable-active-high; -+ gpio = <&gpio3 RK_PC4 GPIO_ACTIVE_HIGH>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&host_vbus_drv>; -+ regulator-name = "vcc_host"; -+ regulator-always-on; -+ regulator-boot-on; -+ vin-supply = <&vcc_sys>; -+ }; -+ -+ vccio_1v8: vccio-1v8-regulator { -+ compatible = "regulator-fixed"; -+ regulator-name = "vccio_1v8"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-always-on; -+ vin-supply = <&vcc_sys>; -+ }; -+ -+ vccio_3v3: vccio-3v3-regulator { -+ compatible = "regulator-fixed"; -+ regulator-name = "vccio_3v3"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ vin-supply = <&vcc_sys>; -+ }; -+ -+ -+ vcc_otg: vcc-otg-regulator { -+ compatible = "regulator-fixed"; -+ enable-active-high; -+ gpio = <&gpio3 RK_PC6 GPIO_ACTIVE_HIGH>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&otg_vbus_drv>; -+ regulator-name = "vcc_otg_vbus"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ regulator-always-on; -+ regulator-boot-on; -+ vin-supply = <&vcc_sys>; -+ }; -+ -+ vcc_phy: vcc-phy-regulator { -+ compatible = "regulator-fixed"; -+ enable-active-high; -+ regulator-name = "vcc_phy"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-always-on; -+ regulator-boot-on; -+ vin-supply = <&vccio_1v8>; -+ }; -+ -+ vcc_sys: vcc-sys-regulator { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc_sys"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ }; -+ -+ vdd_arm: vdd-arm-regulator { -+ compatible = "pwm-regulator"; -+ pwms = <&pwm1 0 5000 1>; -+ pwm-supply = <&vcc_sys>; -+ regulator-name = "vdd_arm"; -+ regulator-min-microvolt = <950000>; -+ regulator-max-microvolt = <1400000>; -+ regulator-ramp-delay = <12500>; -+ regulator-settling-time-up-us = <250>; -+ regulator-always-on; -+ regulator-boot-on; -+ }; -+ -+ vdd_log: vdd-log-regulator { -+ compatible = "pwm-regulator"; -+ pwms = <&pwm2 0 5000 1>; -+ pwm-supply = <&vcc_sys>; -+ regulator-name = "vdd_log"; -+ regulator-min-microvolt = <1000000>; -+ regulator-max-microvolt = <1300000>; -+ regulator-ramp-delay = <12500>; -+ regulator-settling-time-up-us = <250>; -+ regulator-always-on; -+ regulator-boot-on; -+ }; -+ -+}; -+ -+ -+&cpu0 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&cpu1 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&cpu2 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&cpu3 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&io_domains { -+ vccio1-supply = <&vccio_3v3>; -+ vccio2-supply = <&vccio_1v8>; -+ vccio4-supply = <&vccio_3v3>; -+ status = "okay"; -+}; -+ -+&gmac { -+ phy-supply = <&vcc_phy>; -+}; -+ -+&gpu { -+ mali-supply = <&vdd_log>; -+}; -+ -+&pwm1 { -+ pinctrl-0 = <&pwm1_pin_pull_down>; -+ status = "okay"; -+}; -+ -+&pwm2 { -+ pinctrl-0 = <&pwm2_pin_pull_up>; -+ status = "okay"; -+}; -+ -+&u2phy0 { -+ u2phy0_host: host-port { -+ phy-supply = <&vcc_host>; -+ }; -+ -+ u2phy0_otg: otg-port { -+ phy-supply = <&vcc_otg>; -+ }; -+}; -+ -+&u2phy1 { -+ u2phy1_host: host-port { -+ phy-supply = <&vcc_host>; -+ }; -+ -+ u2phy1_otg: otg-port { -+ phy-supply = <&vcc_otg>; -+ }; -+}; -diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi -index 5485a9918..c3ca67301 100644 ---- a/arch/arm/boot/dts/rk322x.dtsi -+++ b/arch/arm/boot/dts/rk322x.dtsi -@@ -5,6 +5,8 @@ - #include - #include - #include -+#include -+#include - #include - - / { -@@ -14,6 +16,7 @@ / { - interrupt-parent = <&gic>; - - aliases { -+ ethernet0 = &gmac; - serial0 = &uart0; - serial1 = &uart1; - serial2 = &uart2; -@@ -73,25 +76,25 @@ cpu0_opp_table: opp_table0 { - - opp-408000000 { - opp-hz = /bits/ 64 <408000000>; -- opp-microvolt = <950000>; -+ opp-microvolt = <950000 950000 1275000>; - clock-latency-ns = <40000>; - opp-suspend; - }; - opp-600000000 { - opp-hz = /bits/ 64 <600000000>; -- opp-microvolt = <975000>; -+ opp-microvolt = <975000 975000 1275000>; - }; - opp-816000000 { - opp-hz = /bits/ 64 <816000000>; -- opp-microvolt = <1000000>; -+ opp-microvolt = <1000000 1000000 1275000>; - }; - opp-1008000000 { - opp-hz = /bits/ 64 <1008000000>; -- opp-microvolt = <1175000>; -+ opp-microvolt = <1175000 1175000 1275000>; - }; - opp-1200000000 { - opp-hz = /bits/ 64 <1200000000>; -- opp-microvolt = <1275000>; -+ opp-microvolt = <1275000 1275000 1275000>; - }; - }; - -@@ -121,11 +124,52 @@ arm-pmu { - interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>; - }; - -+ display_subsystem: display-subsystem { -+ compatible = "rockchip,display-subsystem"; -+ ports = <&vop_out>; -+ }; -+ -+ hdmi_sound: hdmi-sound { -+ compatible = "simple-audio-card"; -+ simple-audio-card,name = "HDMI"; -+ simple-audio-card,format = "i2s"; -+ simple-audio-card,mclk-fs = <128>; -+ status = "disabled"; -+ -+ simple-audio-card,cpu { -+ sound-dai = <&i2s0>; -+ }; -+ -+ simple-audio-card,codec { -+ sound-dai = <&hdmi>; -+ }; -+ }; -+ - psci { - compatible = "arm,psci-1.0", "arm,psci-0.2"; - method = "smc"; - }; - -+ spdif_out: spdif-out { -+ compatible = "linux,spdif-dit"; -+ #sound-dai-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ spdif_sound: spdif-sound { -+ compatible = "simple-audio-card"; -+ simple-audio-card,name = "SPDIF"; -+ status = "disabled"; -+ -+ simple-audio-card,cpu { -+ sound-dai = <&spdif>; -+ }; -+ -+ simple-audio-card,codec { -+ sound-dai = <&spdif_out>; -+ }; -+ }; -+ - timer { - compatible = "arm,armv7-timer"; - arm,cpu-registers-not-fw-configured; -@@ -143,15 +187,13 @@ xin24m: oscillator { - #clock-cells = <0>; - }; - -- display_subsystem: display-subsystem { -- compatible = "rockchip,display-subsystem"; -- ports = <&vop_out>; -- }; -- - i2s1: i2s1@100b0000 { - compatible = "rockchip,rk3228-i2s", "rockchip,rk3066-i2s"; - reg = <0x100b0000 0x4000>; - interrupts = ; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ #sound-dai-cells = <0>; - clock-names = "i2s_clk", "i2s_hclk"; - clocks = <&cru SCLK_I2S1>, <&cru HCLK_I2S1_8CH>; - dmas = <&pdma 14>, <&pdma 15>; -@@ -165,6 +207,9 @@ i2s0: i2s0@100c0000 { - compatible = "rockchip,rk3228-i2s", "rockchip,rk3066-i2s"; - reg = <0x100c0000 0x4000>; - interrupts = ; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ #sound-dai-cells = <0>; - clock-names = "i2s_clk", "i2s_hclk"; - clocks = <&cru SCLK_I2S0>, <&cru HCLK_I2S0_8CH>; - dmas = <&pdma 11>, <&pdma 12>; -@@ -182,6 +227,7 @@ spdif: spdif@100d0000 { - dma-names = "tx"; - pinctrl-names = "default"; - pinctrl-0 = <&spdif_tx>; -+ #sound-dai-cells = <0>; - status = "disabled"; - }; - -@@ -189,6 +235,9 @@ i2s2: i2s2@100e0000 { - compatible = "rockchip,rk3228-i2s", "rockchip,rk3066-i2s"; - reg = <0x100e0000 0x4000>; - interrupts = ; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ #sound-dai-cells = <0>; - clock-names = "i2s_clk", "i2s_hclk"; - clocks = <&cru SCLK_I2S2>, <&cru HCLK_I2S2_2CH>; - dmas = <&pdma 0>, <&pdma 1>; -@@ -207,6 +256,43 @@ io_domains: io-domains { - status = "disabled"; - }; - -+ power: power-controller { -+ compatible = "rockchip,rk3228-power-controller"; -+ #power-domain-cells = <1>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ pd_gpu@RK3228_PD_GPU { -+ reg = ; -+ clocks = <&cru ACLK_GPU>; -+ pm_qos = <&qos_gpu>; -+ }; -+ -+ pd_vpu@RK3228_PD_VPU { -+ reg = ; -+ clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; -+ pm_qos = <&qos_vpu>; -+ }; -+ -+ pd_rkvdec@RK3228_PD_RKVDEC { -+ reg = ; -+ clocks = <&cru ACLK_RKVDEC>, -+ <&cru HCLK_RKVDEC>, -+ <&cru SCLK_VDEC_CABAC>, -+ <&cru SCLK_VDEC_CORE>; -+ pm_qos = <&qos_rkvdec_r>, <&qos_rkvdec_w>; -+ }; -+ }; -+ -+ reboot_mode: reboot-mode { -+ compatible = "syscon-reboot-mode"; -+ offset = <0x5c8>; -+ mode-normal = ; -+ mode-recovery = ; -+ mode-bootloader = ; -+ mode-loader = ; -+ }; -+ - u2phy0: usb2-phy@760 { - compatible = "rockchip,rk3228-usb2phy"; - reg = <0x0760 0x0c>; -@@ -257,6 +343,7 @@ u2phy1_host: host-port { - status = "disabled"; - }; - }; -+ - }; - - uart0: serial@11010000 { -@@ -295,7 +382,7 @@ uart2: serial@11030000 { - clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>; - clock-names = "baudclk", "apb_pclk"; - pinctrl-names = "default"; -- pinctrl-0 = <&uart2_xfer>; -+ pinctrl-0 = <&uart21_xfer>; - reg-shift = <2>; - reg-io-width = <4>; - status = "disabled"; -@@ -454,13 +541,13 @@ cru: clock-controller@110e0000 { - <&cru PLL_CPLL>, <&cru ACLK_PERI>, - <&cru HCLK_PERI>, <&cru PCLK_PERI>, - <&cru ACLK_CPU>, <&cru HCLK_CPU>, -- <&cru PCLK_CPU>; -+ <&cru PCLK_CPU>, <&cru ACLK_VOP>; - assigned-clock-rates = -- <594000000>, <816000000>, -+ <1200000000>, <816000000>, - <500000000>, <150000000>, - <150000000>, <75000000>, - <150000000>, <150000000>, -- <75000000>; -+ <75000000>, <400000000>; - }; - - thermal-zones { -@@ -505,6 +592,12 @@ map1 { - <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; -+ -+ map2 { -+ trip = <&cpu_alert1>; -+ cooling-device = -+ <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; -+ }; - }; - }; - }; -@@ -523,8 +616,9 @@ tsadc: tsadc@11150000 { - pinctrl-0 = <&otp_gpio>; - pinctrl-1 = <&otp_out>; - pinctrl-2 = <&otp_gpio>; -+ rockchip,grf = <&grf>; -+ rockchip,hw-tshut-temp = <120000>; - #thermal-sensor-cells = <0>; -- rockchip,hw-tshut-temp = <95000>; - status = "disabled"; - }; - -@@ -554,10 +648,33 @@ gpu: gpu@20000000 { - "ppmmu0", - "pp1", - "ppmmu1"; -+ assigned-clocks = <&cru ACLK_GPU>; -+ assigned-clock-rates = <300000000>; - clocks = <&cru ACLK_GPU>, <&cru ACLK_GPU>; - clock-names = "bus", "core"; -+ operating-points-v2 = <&gpu_opp_table>; -+ #cooling-cells = <2>; /* min followed by max */ -+ power-domains = <&power RK3228_PD_GPU>; - resets = <&cru SRST_GPU_A>; -- status = "disabled"; -+ }; -+ -+ gpu_opp_table: opp-table2 { -+ compatible = "operating-points-v2"; -+ -+ opp-200000000 { -+ opp-hz = /bits/ 64 <200000000>; -+ opp-microvolt = <1050000>; -+ }; -+ -+ opp-300000000 { -+ opp-hz = /bits/ 64 <300000000>; -+ opp-microvolt = <1050000>; -+ }; -+ -+ opp-500000000 { -+ opp-hz = /bits/ 64 <500000000>; -+ opp-microvolt = <1150000>; -+ }; - }; - - vpu_mmu: iommu@20020800 { -@@ -567,8 +684,8 @@ vpu_mmu: iommu@20020800 { - interrupt-names = "vpu_mmu"; - clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; - clock-names = "aclk", "iface"; -- iommu-cells = <0>; -- status = "disabled"; -+ power-domains = <&power RK3228_PD_VPU>; -+ #iommu-cells = <0>; - }; - - vdec_mmu: iommu@20030480 { -@@ -578,8 +695,8 @@ vdec_mmu: iommu@20030480 { - interrupt-names = "vdec_mmu"; - clocks = <&cru ACLK_RKVDEC>, <&cru HCLK_RKVDEC>; - clock-names = "aclk", "iface"; -- iommu-cells = <0>; -- status = "disabled"; -+ power-domains = <&power RK3228_PD_RKVDEC>; -+ #iommu-cells = <0>; - }; - - vop: vop@20050000 { -@@ -622,7 +739,7 @@ iep_mmu: iommu@20070800 { - interrupt-names = "iep_mmu"; - clocks = <&cru ACLK_IEP>, <&cru HCLK_IEP>; - clock-names = "aclk", "iface"; -- iommu-cells = <0>; -+ #iommu-cells = <0>; - status = "disabled"; - }; - -@@ -642,6 +759,7 @@ hdmi: hdmi@200a0000 { - phys = <&hdmi_phy>; - phy-names = "hdmi"; - rockchip,grf = <&grf>; -+ #sound-dai-cells = <0>; - status = "disabled"; - - ports { -@@ -663,9 +781,13 @@ sdmmc: mmc@30000000 { - clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>, - <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>; - clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; -+ bus-width = <4>; - fifo-depth = <0x100>; -+ max-frequency = <150000000>; - pinctrl-names = "default"; -- pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_bus4>; -+ pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_bus4 &sdmmc_pwr>; -+ resets = <&cru SRST_SDMMC>; -+ reset-names = "reset"; - status = "disabled"; - }; - -@@ -675,10 +797,14 @@ sdio: mmc@30010000 { - interrupts = ; - clocks = <&cru HCLK_SDIO>, <&cru SCLK_SDIO>, - <&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>; -+ bus-width = <4>; - clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; - fifo-depth = <0x100>; -+ max-frequency = <150000000>; - pinctrl-names = "default"; - pinctrl-0 = <&sdio_clk &sdio_cmd &sdio_bus4>; -+ resets = <&cru SRST_SDIO>; -+ reset-names = "reset"; - status = "disabled"; - }; - -@@ -686,8 +812,7 @@ emmc: mmc@30020000 { - compatible = "rockchip,rk3228-dw-mshc", "rockchip,rk3288-dw-mshc"; - reg = <0x30020000 0x4000>; - interrupts = ; -- clock-frequency = <37500000>; -- max-frequency = <37500000>; -+ max-frequency = <150000000>; - clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>, - <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>; - clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; -@@ -701,6 +826,22 @@ emmc: mmc@30020000 { - status = "disabled"; - }; - -+ nfc: nand-controller@ff4b0000 { -+ compatible = "rockchip,rk3228_nfc"; -+ reg = <0x30030000 0x4000>; -+ interrupts = ; -+ clocks = <&cru SCLK_NANDC>, <&cru HCLK_NANDC>; -+ clock-names = "nfc", "ahb"; -+ assigned-clocks = <&cru SCLK_NANDC>; -+ assigned-clock-rates = <150000000>; -+ -+ pinctrl-names = "default"; -+ pinctrl-0 = <&flash_cs0 &flash_rdy &flash_ale &flash_cle -+ &flash_wrn &flash_rdn &flash_bus8>; -+ status = "disabled"; -+ -+ }; -+ - usb_otg: usb@30040000 { - compatible = "rockchip,rk3228-usb", "rockchip,rk3066-usb", - "snps,dwc2"; -@@ -796,6 +937,26 @@ gmac: ethernet@30200000 { - status = "disabled"; - }; - -+ qos_vpu: qos@31040000 { -+ compatible = "syscon"; -+ reg = <0x31040000 0x20>; -+ }; -+ -+ qos_gpu: qos@31050000 { -+ compatible = "syscon"; -+ reg = <0x31050000 0x20>; -+ }; -+ -+ qos_rkvdec_r: qos@31070000 { -+ compatible = "syscon"; -+ reg = <0x31070000 0x20>; -+ }; -+ -+ qos_rkvdec_w: qos@31070080 { -+ compatible = "syscon"; -+ reg = <0x31070080 0x20>; -+ }; -+ - gic: interrupt-controller@32010000 { - compatible = "arm,gic-400"; - interrupt-controller; -@@ -884,6 +1045,11 @@ pcfg_pull_none_drv_12ma: pcfg-pull-none-drv-12ma { - drive-strength = <12>; - }; - -+ pcfg_pull_up_12ma: pcfg-pull-up-12ma { -+ bias-pull-up; -+ drive-strength = <12>; -+ }; -+ - sdmmc { - sdmmc_clk: sdmmc-clk { - rockchip,pins = <1 RK_PC0 1 &pcfg_pull_none_drv_12ma>; -@@ -899,6 +1065,10 @@ sdmmc_bus4: sdmmc-bus4 { - <1 RK_PC4 1 &pcfg_pull_none_drv_12ma>, - <1 RK_PC5 1 &pcfg_pull_none_drv_12ma>; - }; -+ -+ sdmmc_pwr: sdmmc-pwr { -+ rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; - }; - - sdio { -@@ -939,6 +1109,55 @@ emmc_bus8: emmc-bus8 { - }; - }; - -+ flash { -+ -+ flash_cs0: flash-cs0 { -+ rockchip,pins = -+ <2 RK_PA6 1 &pcfg_pull_none>; -+ }; -+ -+ flash_cs1: flash-cs1 { -+ rockchip,pins = -+ <0 RK_PC7 1 &pcfg_pull_none>; -+ }; -+ -+ flash_rdy: flash-rdy { -+ rockchip,pins = -+ <2 RK_PA4 1 &pcfg_pull_none>; -+ }; -+ -+ flash_ale: flash-ale { -+ rockchip,pins = -+ <2 RK_PA0 1 &pcfg_pull_none>; -+ }; -+ -+ flash_cle: flash-cle { -+ rockchip,pins = -+ <2 RK_PA1 1 &pcfg_pull_none>; -+ }; -+ -+ flash_wrn: flash-wrn { -+ rockchip,pins = -+ <2 RK_PA2 1 &pcfg_pull_none>; -+ }; -+ -+ flash_rdn: flash-rdn { -+ rockchip,pins = -+ <2 RK_PA3 1 &pcfg_pull_none>; -+ }; -+ -+ flash_bus8: flash-bus8 { -+ rockchip,pins = <1 RK_PD0 1 &pcfg_pull_none>, -+ <1 RK_PD1 1 &pcfg_pull_none>, -+ <1 RK_PD2 1 &pcfg_pull_none>, -+ <1 RK_PD3 1 &pcfg_pull_none>, -+ <1 RK_PD4 1 &pcfg_pull_none>, -+ <1 RK_PD5 1 &pcfg_pull_none>, -+ <1 RK_PD6 1 &pcfg_pull_none>, -+ <1 RK_PD7 1 &pcfg_pull_none>; -+ }; -+ }; -+ - gmac { - rgmii_pins: rgmii-pins { - rockchip,pins = <2 RK_PB6 1 &pcfg_pull_none>, -@@ -1080,12 +1299,20 @@ pwm1 { - pwm1_pin: pwm1-pin { - rockchip,pins = <0 RK_PD6 2 &pcfg_pull_none>; - }; -+ -+ pwm1_pin_pull_down: pwm1-pin-pull-down { -+ rockchip,pins = <0 RK_PD6 2 &pcfg_pull_down>; -+ }; - }; - - pwm2 { - pwm2_pin: pwm2-pin { - rockchip,pins = <1 RK_PB4 2 &pcfg_pull_none>; - }; -+ -+ pwm2_pin_pull_up: pwm2-pin-pull-up { -+ rockchip,pins = <1 RK_PB4 2 &pcfg_pull_up>; -+ }; - }; - - pwm3 { -@@ -1140,16 +1367,31 @@ uart1_rts: uart1-rts { - }; - }; - -+ uart1-1 { -+ uart11_xfer: uart11-xfer { -+ rockchip,pins = <3 RK_PB6 1 &pcfg_pull_up>, -+ <3 RK_PB5 1 &pcfg_pull_none>; -+ }; -+ -+ uart11_cts: uart11-cts { -+ rockchip,pins = <3 RK_PA7 1 &pcfg_pull_none>; -+ }; -+ -+ uart11_rts: uart11-rts { -+ rockchip,pins = <3 RK_PA6 1 &pcfg_pull_none>; -+ }; -+ -+ uart11_rts_gpio: uart11-rts-gpio { -+ rockchip,pins = <3 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+ - uart2 { - uart2_xfer: uart2-xfer { - rockchip,pins = <1 RK_PC2 2 &pcfg_pull_up>, - <1 RK_PC3 2 &pcfg_pull_none>; - }; - -- uart21_xfer: uart21-xfer { -- rockchip,pins = <1 RK_PB2 2 &pcfg_pull_up>, -- <1 RK_PB1 2 &pcfg_pull_none>; -- }; - - uart2_cts: uart2-cts { - rockchip,pins = <0 RK_PD1 1 &pcfg_pull_none>; -@@ -1159,5 +1401,23 @@ uart2_rts: uart2-rts { - rockchip,pins = <0 RK_PD0 1 &pcfg_pull_none>; - }; - }; -+ -+ uart2-1 { -+ uart21_xfer: uart21-xfer { -+ rockchip,pins = <1 RK_PB2 2 &pcfg_pull_up>, -+ <1 RK_PB1 2 &pcfg_pull_none>; -+ }; -+ }; -+ -+ usb { -+ host_vbus_drv: host-vbus-drv { -+ rockchip,pins = <3 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ -+ otg_vbus_drv: otg-vbus-drv { -+ rockchip,pins = <3 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+ - }; - }; -diff --git a/arch/arm/boot/dts/rk322x.dtsi.rej b/arch/arm/boot/dts/rk322x.dtsi.rej -new file mode 100644 -index 000000000..cc36be3e9 ---- /dev/null -+++ b/arch/arm/boot/dts/rk322x.dtsi.rej -@@ -0,0 +1,45 @@ -+--- arch/arm/boot/dts/rk322x.dtsi -++++ arch/arm/boot/dts/rk322x.dtsi -+@@ -187,17 +231,13 @@ -+ #clock-cells = <0>; -+ }; -+ -+- display_subsystem: display-subsystem { -+- compatible = "rockchip,display-subsystem"; -+- ports = <&vop_out>; -+- }; -+- -+ i2s1: i2s1@100b0000 { -+ compatible = "rockchip,rk3228-i2s", "rockchip,rk3066-i2s"; -+ reg = <0x100b0000 0x4000>; -+ interrupts = ; -+ #address-cells = <1>; -+ #size-cells = <0>; -++ #sound-dai-cells = <0>; -+ clock-names = "i2s_clk", "i2s_hclk"; -+ clocks = <&cru SCLK_I2S1>, <&cru HCLK_I2S1_8CH>; -+ dmas = <&pdma 14>, <&pdma 15>; -+@@ -213,6 +253,7 @@ -+ interrupts = ; -+ #address-cells = <1>; -+ #size-cells = <0>; -++ #sound-dai-cells = <0>; -+ clock-names = "i2s_clk", "i2s_hclk"; -+ clocks = <&cru SCLK_I2S0>, <&cru HCLK_I2S0_8CH>; -+ dmas = <&pdma 11>, <&pdma 12>; -+@@ -825,14 +944,13 @@ -+ compatible = "rockchip,rk3228-dw-mshc", "rockchip,rk3288-dw-mshc"; -+ reg = <0x30020000 0x4000>; -+ interrupts = ; -+- clock-frequency = <37500000>; -+- max-frequency = <37500000>; -+ clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>, -+ <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>; -+ clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; -+ bus-width = <8>; -+ default-sample-phase = <158>; -+ fifo-depth = <0x100>; -++ max-frequency = <150000000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; -+ resets = <&cru SRST_EMMC>; diff --git a/patch/kernel/rk322x-dev/01-linux-1003-rk322x-hantro.patch b/patch/kernel/rk322x-dev/01-linux-1003-rk322x-hantro.patch deleted file mode 100644 index e63bce853..000000000 --- a/patch/kernel/rk322x-dev/01-linux-1003-rk322x-hantro.patch +++ /dev/null @@ -1,98 +0,0 @@ -diff --git a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml -index a0c45e05cf03..a20cfaa8973e 100644 ---- a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml -+++ b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml -@@ -16,6 +16,7 @@ description: - properties: - compatible: - enum: -+ - rockchip,rk322x-vpu - - rockchip,rk3288-vpu - - rockchip,rk3328-vpu - - rockchip,rk3399-vpu -diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi -index f7a50b903a7d..2ed8aa7ae520 100644 ---- a/arch/arm/boot/dts/rk322x.dtsi -+++ b/arch/arm/boot/dts/rk322x.dtsi -@@ -676,6 +676,18 @@ - }; - }; - -+ vpu: video-codec@20020000 { -+ compatible = "rockchip,rk322x-vpu"; -+ reg = <0x20020000 0x800>; -+ interrupts = , -+ ; -+ interrupt-names = "vepu", "vdpu"; -+ clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; -+ clock-names = "aclk", "hclk"; -+ iommus = <&vpu_mmu>; -+ power-domains = <&power RK3228_PD_VPU>; -+ }; -+ - vpu_mmu: iommu@20020800 { - compatible = "rockchip,iommu"; - reg = <0x20020800 0x100>; -diff --git a/drivers/staging/media/hantro/Kconfig b/drivers/staging/media/hantro/Kconfig -index de77fe6554e7..9f99d1c9f453 100644 ---- a/drivers/staging/media/hantro/Kconfig -+++ b/drivers/staging/media/hantro/Kconfig -@@ -20,4 +20,4 @@ config VIDEO_HANTRO_ROCKCHIP - depends on ARCH_ROCKCHIP || COMPILE_TEST - default y - help -- Enable support for RK3288, RK3328, and RK3399 SoCs. -+ Enable support for RK322x, RK3288, RK3328, and RK3399 SoCs. -diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c -index a732beeb3bb6..fae9555a349b 100644 ---- a/drivers/staging/media/hantro/hantro_drv.c -+++ b/drivers/staging/media/hantro/hantro_drv.c -@@ -469,6 +469,7 @@ static const struct of_device_id of_hantro_match[] = { - { .compatible = "rockchip,rk3399-vpu", .data = &rk3399_vpu_variant, }, - { .compatible = "rockchip,rk3328-vpu", .data = &rk3328_vpu_variant, }, - { .compatible = "rockchip,rk3288-vpu", .data = &rk3288_vpu_variant, }, -+ { .compatible = "rockchip,rk322x-vpu", .data = &rk322x_vpu_variant, }, - #endif - { /* sentinel */ } - }; -diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h -index 33c1ce169203..e64369e01a21 100644 ---- a/drivers/staging/media/hantro/hantro_hw.h -+++ b/drivers/staging/media/hantro/hantro_hw.h -@@ -157,6 +157,7 @@ enum hantro_enc_fmt { - extern const struct hantro_variant rk3399_vpu_variant; - extern const struct hantro_variant rk3328_vpu_variant; - extern const struct hantro_variant rk3288_vpu_variant; -+extern const struct hantro_variant rk322x_vpu_variant; - extern const struct hantro_variant imx8mq_vpu_variant; - - extern const struct hantro_postproc_regs hantro_g1_postproc_regs; - -diff --git a/drivers/staging/media/hantro/rk3399_vpu_hw.c b/drivers/staging/media/hantro/rk3399_vpu_hw.c -index 78f878ca01ff..0a6c021c2332 100644 ---- a/drivers/staging/media/hantro/rk3399_vpu_hw.c -+++ b/drivers/staging/media/hantro/rk3399_vpu_hw.c -@@ -241,3 +241,20 @@ const struct hantro_variant rk3328_vpu_variant = { - .clk_names = rk3399_clk_names, - .num_clocks = ARRAY_SIZE(rk3399_clk_names), - }; -+ -+const struct hantro_variant rk322x_vpu_variant = { -+ .enc_offset = 0x0, -+ .enc_fmts = rk3399_vpu_enc_fmts, -+ .num_enc_fmts = ARRAY_SIZE(rk3399_vpu_enc_fmts), -+ .dec_offset = 0x400, -+ .dec_fmts = rk3399_vpu_dec_fmts, -+ .num_dec_fmts = ARRAY_SIZE(rk3399_vpu_dec_fmts), -+ .codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER | -+ HANTRO_H264_DECODER, -+ .codec_ops = rk3399_vpu_codec_ops, -+ .irqs = rk3399_irqs, -+ .num_irqs = ARRAY_SIZE(rk3399_irqs), -+ .init = rk3399_vpu_hw_init, -+ .clk_names = rk3399_clk_names, -+ .num_clocks = ARRAY_SIZE(rk3399_clk_names) -+}; --- -2.17.1 - diff --git a/patch/kernel/rk322x-dev/01-linux-1004-rockchip-rk322x-enhancements-and-fixes.patch b/patch/kernel/rk322x-dev/01-linux-1004-rockchip-rk322x-enhancements-and-fixes.patch deleted file mode 100644 index aa5a48973..000000000 --- a/patch/kernel/rk322x-dev/01-linux-1004-rockchip-rk322x-enhancements-and-fixes.patch +++ /dev/null @@ -1,383 +0,0 @@ -diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c -index 54eb6cfc5d5b..c6b33f7c43df 100644 ---- a/drivers/soc/rockchip/pm_domains.c -+++ b/drivers/soc/rockchip/pm_domains.c -@@ -71,6 +71,7 @@ struct rockchip_pm_domain { - struct regmap **qos_regmap; - u32 *qos_save_regs[MAX_QOS_REGS_NUM]; - int num_clks; -+ bool is_ignore_pwr; - struct clk_bulk_data *clks; - }; - -@@ -330,6 +331,9 @@ static int rockchip_pd_power_on(struct generic_pm_domain *domain) - { - struct rockchip_pm_domain *pd = to_rockchip_pd(domain); - -+ if (pd->is_ignore_pwr) -+ return 0; -+ - return rockchip_pd_power(pd, true); - } - -@@ -337,6 +341,9 @@ static int rockchip_pd_power_off(struct generic_pm_domain *domain) - { - struct rockchip_pm_domain *pd = to_rockchip_pd(domain); - -+ if (pd->is_ignore_pwr) -+ return 0; -+ - return rockchip_pd_power(pd, false); - } - -@@ -416,6 +423,9 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, - pd->info = pd_info; - pd->pmu = pmu; - -+ if (!pd_info->pwr_mask) -+ pd->is_ignore_pwr = true; -+ - pd->num_clks = of_clk_get_parent_count(node); - if (pd->num_clks > 0) { - pd->clks = devm_kcalloc(pmu->dev, pd->num_clks, -@@ -566,6 +576,7 @@ static int rockchip_pm_add_subdomain(struct rockchip_pmu *pmu, - { - struct device_node *np; - struct generic_pm_domain *child_domain, *parent_domain; -+ struct rockchip_pm_domain *child_pd, *parent_pd; - int error; - - for_each_child_of_node(parent, np) { -@@ -606,6 +617,18 @@ static int rockchip_pm_add_subdomain(struct rockchip_pmu *pmu, - parent_domain->name, child_domain->name); - } - -+ /* -+ * If child_pd doesn't do idle request or power on/off, -+ * parent_pd may fail to do power on/off, so if parent_pd -+ * need to power on/off, child_pd can't ignore to do idle -+ * request and power on/off. -+ */ -+ child_pd = to_rockchip_pd(child_domain); -+ parent_pd = to_rockchip_pd(parent_domain); -+ if (!parent_pd->is_ignore_pwr) -+ child_pd->is_ignore_pwr = false; -+ -+ - rockchip_pm_add_subdomain(pmu, np); - } - --- -2.17.1 - -From c94b1272290bafced10d79b7da1525466e8c843b Mon Sep 17 00:00:00 2001 -From: "Huang, Tao" -Date: Thu, 28 Jul 2016 10:59:22 +0800 -Subject: [PATCH] power: reset: reboot-mode: fix normal mode setup - -If cmd is empty in get_reboot_mode_magic, we should return normal magic. - -Change-Id: I10931adc49e33f72ae73d9471159f82cc02ff0c0 -Signed-off-by: Huang, Tao ---- - drivers/power/reset/reboot-mode.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/power/reset/reboot-mode.c b/drivers/power/reset/reboot-mode.c -index b4076b10b893..47f9a162807d 100644 ---- a/drivers/power/reset/reboot-mode.c -+++ b/drivers/power/reset/reboot-mode.c -@@ -26,7 +26,7 @@ static unsigned int get_reboot_mode_magic(struct reboot_mode_driver *reboot, - int magic = 0; - struct mode_info *info; - -- if (!cmd) -+ if (!cmd || !cmd[0]) - cmd = normal; - - list_for_each_entry(info, &reboot->head, list) { --- -2.17.1 - - -From be9674f270c97399f9f6b1facb11e93eced6ec34 Mon Sep 17 00:00:00 2001 -From: Andy Yan -Date: Thu, 8 Dec 2016 16:58:07 +0800 -Subject: [PATCH] power: reset: reboot-mode: treat unrecognized reboot mode as - normal mode - -Some bootloader will check the reboot mode to take different action, so -we treat unrecognized reboot mode as normal mode to prevent the system -run into abnormal case. - -Change-Id: I88063a5b41e4e645443229fa490b2b55db5ccf27 -Signed-off-by: Andy Yan ---- - drivers/power/reset/reboot-mode.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/drivers/power/reset/reboot-mode.c b/drivers/power/reset/reboot-mode.c -index 47f9a162807d..99bf938404e3 100644 ---- a/drivers/power/reset/reboot-mode.c -+++ b/drivers/power/reset/reboot-mode.c -@@ -47,6 +47,8 @@ static int reboot_mode_notify(struct notifier_block *this, - - reboot = container_of(this, struct reboot_mode_driver, reboot_notifier); - magic = get_reboot_mode_magic(reboot, cmd); -+ if (!magic) -+ magic = get_reboot_mode_magic(reboot, NULL); - if (magic) - reboot->write(reboot, magic); - --- -2.17.1 - -From 7c097120eb21a9bd15ab63c0ac60ffd5cba902b2 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Fri, 24 Apr 2020 13:01:07 +0200 -Subject: [PATCH] sound: soc: rockchip: use rouned rate for i2s - ---- - sound/soc/rockchip/rockchip_i2s.c | 9 +++++++-- - 1 file changed, 7 insertions(+), 2 deletions(-) - -diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c -index 61c984f10d8e..efca853eba6b 100644 ---- a/sound/soc/rockchip/rockchip_i2s.c -+++ b/sound/soc/rockchip/rockchip_i2s.c -@@ -279,10 +279,13 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, - if (i2s->is_master_mode) { - mclk_rate = clk_get_rate(i2s->mclk); - bclk_rate = 2 * 32 * params_rate(params); -- if (bclk_rate && mclk_rate % bclk_rate) -+ if (!bclk_rate) { -+ dev_err(i2s->dev, "invalid bclk_rate: %d\n", -+ bclk_rate); - return -EINVAL; -+ } - -- div_bclk = mclk_rate / bclk_rate; -+ div_bclk = DIV_ROUND_CLOSEST(mclk_rate, bclk_rate); - div_lrck = bclk_rate / params_rate(params); - regmap_update_bits(i2s->regmap, I2S_CKR, - I2S_CKR_MDIV_MASK, -@@ -312,6 +315,8 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, - val |= I2S_TXCR_VDW(32); - break; - default: -+ dev_err(i2s->dev, "invalid format: %d\n", -+ params_format(params)); - return -EINVAL; - } - --- -2.17.1 - - -From 4102c5b07d8610c729d577612c1df52737fb9a0f Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Fri, 24 Apr 2020 09:08:44 +0200 -Subject: [PATCH] phy: rockchip: hdmi: readout hdmi phy flag for RK3228 HDMI - phys - -Some RK3228 HDMI phys only get a stable pll on frequencies higher 337,5 MHz. -This is defined in a flag in efuse of those devices. ---- - arch/arm/boot/dts/rk322x.dtsi | 7 ++++ - drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 38 ++++++++++++++++++- - 2 files changed, 43 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi -index 2ed8aa7ae520..8c50dcb0e9f1 100644 ---- a/arch/arm/boot/dts/rk322x.dtsi -+++ b/arch/arm/boot/dts/rk322x.dtsi -@@ -402,6 +402,11 @@ - cpu_leakage: cpu_leakage@17 { - reg = <0x17 0x1>; - }; -+ -+ hdmi_phy_flag: hdmi-phy-flag@1d { -+ reg = <0x1d 0x1>; -+ bits = <1 1>; -+ }; - }; - - i2c0: i2c@11050000 { -@@ -628,6 +633,8 @@ - clock-names = "sysclk", "refoclk", "refpclk"; - #clock-cells = <0>; - clock-output-names = "hdmiphy_phy"; -+ nvmem-cells = <&hdmi_phy_flag>; -+ nvmem-cell-names = "hdmi-phy-flag"; - #phy-cells = <0>; - status = "disabled"; - }; -diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c -index bb8bdf5e3301..0c7a97352714 100644 ---- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c -+++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c -@@ -237,6 +237,9 @@ struct inno_hdmi_phy { - struct clk *refoclk; - struct clk *refpclk; - -+ /* phy_flag flag */ -+ bool phy_flag; -+ - /* platform data */ - const struct inno_hdmi_phy_drv_data *plat_data; - int chip_version; -@@ -347,6 +350,7 @@ static const struct pre_pll_config pre_pll_cfg_table[] = { - static const struct post_pll_config post_pll_cfg_table[] = { - {33750000, 1, 40, 8, 1}, - {33750000, 1, 80, 8, 2}, -+ {33750000, 1, 10, 2, 4}, - {74250000, 1, 40, 8, 1}, - {74250000, 18, 80, 8, 2}, - {148500000, 2, 40, 4, 3}, -@@ -497,8 +501,11 @@ static int inno_hdmi_phy_power_on(struct phy *phy) - return -EINVAL; - - for (; cfg->tmdsclock != 0; cfg++) -- if (tmdsclock <= cfg->tmdsclock && -- cfg->version & inno->chip_version) -+ if (((!inno->phy_flag || tmdsclock > 33750000) -+ && tmdsclock <= cfg->tmdsclock -+ && cfg->version & inno->chip_version) || -+ (inno->phy_flag && tmdsclock <= 33750000 -+ && cfg->version & 4)) - break; - - for (; phy_cfg->tmdsclock != 0; phy_cfg++) -@@ -909,6 +916,10 @@ static int inno_hdmi_phy_clk_register(struct inno_hdmi_phy *inno) - - static int inno_hdmi_phy_rk3228_init(struct inno_hdmi_phy *inno) - { -+ struct nvmem_cell *cell; -+ unsigned char *efuse_buf; -+ size_t len; -+ - /* - * Use phy internal register control - * rxsense/poweron/pllpd/pdataen signal. -@@ -923,7 +934,28 @@ static int inno_hdmi_phy_rk3228_init(struct inno_hdmi_phy *inno) - inno_update_bits(inno, 0xaa, RK3228_POST_PLL_CTRL_MANUAL, - RK3228_POST_PLL_CTRL_MANUAL); - -+ - inno->chip_version = 1; -+ inno->phy_flag = false; -+ -+ cell = nvmem_cell_get(inno->dev, "hdmi-phy-flag"); -+ if (IS_ERR(cell)) { -+ if (PTR_ERR(cell) == -EPROBE_DEFER) -+ return -EPROBE_DEFER; -+ -+ return 0; -+ } -+ -+ efuse_buf = nvmem_cell_read(cell, &len); -+ nvmem_cell_put(cell); -+ -+ if (IS_ERR(efuse_buf)) -+ return 0; -+ if (len == 1) -+ inno->phy_flag = (efuse_buf[0] & BIT(1)) ? true : false; -+ kfree(efuse_buf); -+ -+ dev_info(inno->dev, "phy_flag is: %d\n", inno->phy_flag); - - return 0; - } -@@ -1023,6 +1055,8 @@ static int inno_hdmi_phy_rk3328_init(struct inno_hdmi_phy *inno) - - /* try to read the chip-version */ - inno->chip_version = 1; -+ inno->phy_flag = false; -+ - cell = nvmem_cell_get(inno->dev, "cpu-version"); - if (IS_ERR(cell)) { - if (PTR_ERR(cell) == -EPROBE_DEFER) --- -2.17.1 - - -From fe30b024a7a7d6261dff0b87c2aec270ad530c39 Mon Sep 17 00:00:00 2001 -From: Alex Bee -Date: Fri, 24 Apr 2020 14:23:38 +0200 -Subject: [PATCH] drm: rockchip: Use 2nd RK3228 plane as an overlay - -As per datasheet the second plane of RK3228 vop is an overlay window. For -the missing implementation of hardware cursor it is missued as such (as -already pointed in comment for RK3288). Furthermore the overlay window -does not support YUV modes with the current implementation - so it -supports only RGB modes for now. ---- - drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 44 +++++++++++++++++++-- - 1 file changed, 41 insertions(+), 3 deletions(-) - -diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -index 73d24c6bbf05..d4ac6e161ef2 100644 ---- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -@@ -614,6 +614,44 @@ static const struct vop_common rk3288_common = { - .dsp_background = VOP_REG(RK3288_DSP_BG, 0xffffffff, 0), - }; - -+static const struct vop_win_phy rk3228_win0_data = { -+ .scl = &rk3288_win_full_scl, -+ .data_formats = formats_win_full, -+ .nformats = ARRAY_SIZE(formats_win_full), -+ .enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0), -+ .format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1), -+ .rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12), -+ .act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0), -+ .dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0), -+ .dsp_st = VOP_REG(RK3288_WIN0_DSP_ST, 0x1fff1fff, 0), -+ .yrgb_mst = VOP_REG(RK3288_WIN0_YRGB_MST, 0xffffffff, 0), -+ .uv_mst = VOP_REG(RK3288_WIN0_CBR_MST, 0xffffffff, 0), -+ .yrgb_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 0), -+ .uv_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 16), -+ .src_alpha_ctl = VOP_REG(RK3288_WIN0_SRC_ALPHA_CTRL, 0xff, 0), -+ .dst_alpha_ctl = VOP_REG(RK3288_WIN0_DST_ALPHA_CTRL, 0xff, 0), -+ .channel = VOP_REG(RK3288_WIN0_CTRL2, 0xff, 0), -+}; -+ -+static const struct vop_win_phy rk3228_win1_data = { -+ .scl = &rk3288_win_full_scl, -+ .data_formats = formats_win_lite, -+ .nformats = ARRAY_SIZE(formats_win_lite), -+ .enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0), -+ .format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1), -+ .rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12), -+ .act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0), -+ .dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0), -+ .dsp_st = VOP_REG(RK3288_WIN0_DSP_ST, 0x1fff1fff, 0), -+ .yrgb_mst = VOP_REG(RK3288_WIN0_YRGB_MST, 0xffffffff, 0), -+ .uv_mst = VOP_REG(RK3288_WIN0_CBR_MST, 0xffffffff, 0), -+ .yrgb_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 0), -+ .uv_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 16), -+ .src_alpha_ctl = VOP_REG(RK3288_WIN0_SRC_ALPHA_CTRL, 0xff, 0), -+ .dst_alpha_ctl = VOP_REG(RK3288_WIN0_DST_ALPHA_CTRL, 0xff, 0), -+ .channel = VOP_REG(RK3288_WIN0_CTRL2, 0xff, 0), -+}; -+ - /* - * Note: rk3288 has a dedicated 'cursor' window, however, that window requires - * special support to get alpha blending working. For now, just use overlay -@@ -864,10 +902,10 @@ static const struct vop_data rk3399_vop_lit = { - }; - - static const struct vop_win_data rk3228_vop_win_data[] = { -- { .base = 0x00, .phy = &rk3288_win01_data, -+ { .base = 0x00, .phy = &rk3228_win0_data, - .type = DRM_PLANE_TYPE_PRIMARY }, -- { .base = 0x40, .phy = &rk3288_win01_data, -- .type = DRM_PLANE_TYPE_CURSOR }, -+ { .base = 0x40, .phy = &rk3228_win1_data, -+ .type = DRM_PLANE_TYPE_OVERLAY }, - }; - - static const struct vop_data rk3228_vop = { --- -2.17.1 - diff --git a/patch/kernel/rk322x-dev/01-linux-2000-rockchip-drm-wip.patch b/patch/kernel/rk322x-dev/01-linux-2000-rockchip-drm-wip.patch new file mode 100644 index 000000000..454c77a33 --- /dev/null +++ b/patch/kernel/rk322x-dev/01-linux-2000-rockchip-drm-wip.patch @@ -0,0 +1,5333 @@ +From 4fe70563eb6f08f737ecc7091b8c4806e18a2479 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 8 Jan 2020 21:07:47 +0000 +Subject: [PATCH] phy/rockchip: inno-hdmi: use correct vco_div_5 macro on + rk3328 + +inno_hdmi_phy_rk3328_clk_set_rate() is using the RK3228 macro +when configuring vco_div_5 on RK3328. + +Fix this by using correct vco_div_5 macro for RK3328. + +Fixes: 53706a116863 ("phy: add Rockchip Innosilicon hdmi phy") +Signed-off-by: Jonas Karlman +--- + drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c +index 9ca20c947283..b0ac1d3ee390 100644 +--- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c +@@ -790,8 +790,8 @@ static int inno_hdmi_phy_rk3328_clk_set_rate(struct clk_hw *hw, + RK3328_PRE_PLL_POWER_DOWN); + + /* Configure pre-pll */ +- inno_update_bits(inno, 0xa0, RK3228_PCLK_VCO_DIV_5_MASK, +- RK3228_PCLK_VCO_DIV_5(cfg->vco_div_5_en)); ++ inno_update_bits(inno, 0xa0, RK3328_PCLK_VCO_DIV_5_MASK, ++ RK3328_PCLK_VCO_DIV_5(cfg->vco_div_5_en)); + inno_write(inno, 0xa1, RK3328_PRE_PLL_PRE_DIV(cfg->prediv)); + + val = RK3328_SPREAD_SPECTRUM_MOD_DISABLE; + +From 619967c6bc6f6c81a3dabf8b2d4c0f5f3b3afc78 Mon Sep 17 00:00:00 2001 +From: Zheng Yang +Date: Wed, 8 Jan 2020 21:07:48 +0000 +Subject: [PATCH] phy/rockchip: inno-hdmi: round fractal pixclock in rk3328 + recalc_rate + +inno_hdmi_phy_rk3328_clk_recalc_rate() is returning a rate not found +in the pre pll config table when the fractal divider is used. +This can prevent proper power_on because a tmdsclock for the new rate +is not found in the pre pll config table. + +Fix this by saving and returning a rounded pixel rate that exist +in the pre pll config table. + +Fixes: 53706a116863 ("phy: add Rockchip Innosilicon hdmi phy") +Signed-off-by: Zheng Yang +Signed-off-by: Jonas Karlman +--- + drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c +index b0ac1d3ee390..093d2334e8cd 100644 +--- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c +@@ -745,10 +745,12 @@ unsigned long inno_hdmi_phy_rk3328_clk_recalc_rate(struct clk_hw *hw, + do_div(vco, (nd * (no_a == 1 ? no_b : no_a) * no_d * 2)); + } + +- inno->pixclock = vco; +- dev_dbg(inno->dev, "%s rate %lu\n", __func__, inno->pixclock); ++ inno->pixclock = DIV_ROUND_CLOSEST((unsigned long)vco, 1000) * 1000; + +- return vco; ++ dev_dbg(inno->dev, "%s rate %lu vco %llu\n", ++ __func__, inno->pixclock, vco); ++ ++ return inno->pixclock; + } + + static long inno_hdmi_phy_rk3328_clk_round_rate(struct clk_hw *hw, + +From 8fe477a61c44d9df65a1f3a7bd9a0d7b4be7760b Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 8 Jan 2020 21:07:48 +0000 +Subject: [PATCH] phy/rockchip: inno-hdmi: remove unused no_c from rk3328 + recalc_rate + +no_c is not used in any calculation, lets remove it. + +Signed-off-by: Jonas Karlman +--- + drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c +index 093d2334e8cd..06db69c8373e 100644 +--- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c +@@ -714,7 +714,7 @@ unsigned long inno_hdmi_phy_rk3328_clk_recalc_rate(struct clk_hw *hw, + { + struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw); + unsigned long frac; +- u8 nd, no_a, no_b, no_c, no_d; ++ u8 nd, no_a, no_b, no_d; + u64 vco; + u16 nf; + +@@ -737,9 +737,6 @@ unsigned long inno_hdmi_phy_rk3328_clk_recalc_rate(struct clk_hw *hw, + no_b = inno_read(inno, 0xa5) & RK3328_PRE_PLL_PCLK_DIV_B_MASK; + no_b >>= RK3328_PRE_PLL_PCLK_DIV_B_SHIFT; + no_b += 2; +- no_c = inno_read(inno, 0xa6) & RK3328_PRE_PLL_PCLK_DIV_C_MASK; +- no_c >>= RK3328_PRE_PLL_PCLK_DIV_C_SHIFT; +- no_c = 1 << no_c; + no_d = inno_read(inno, 0xa6) & RK3328_PRE_PLL_PCLK_DIV_D_MASK; + + do_div(vco, (nd * (no_a == 1 ? no_b : no_a) * no_d * 2)); + +From 428d1129cfacf119ed86954e6b21c938510ef2b2 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 8 Jan 2020 21:07:48 +0000 +Subject: [PATCH] phy/rockchip: inno-hdmi: do not power on rk3328 post pll on + reg write + +inno_write is used to configure 0xaa reg, that also hold the +POST_PLL_POWER_DOWN bit. +When POST_PLL_REFCLK_SEL_TMDS is configured the power down bit is not +taken into consideration. + +Fix this by keeping the power down bit until configuration is complete. +Also reorder the reg write order for consistency. + +Fixes: 53706a116863 ("phy: add Rockchip Innosilicon hdmi phy") +Signed-off-by: Jonas Karlman +--- + drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c +index 06db69c8373e..3a59a6da0440 100644 +--- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c +@@ -1020,9 +1020,10 @@ inno_hdmi_phy_rk3328_power_on(struct inno_hdmi_phy *inno, + + inno_write(inno, 0xac, RK3328_POST_PLL_FB_DIV_7_0(cfg->fbdiv)); + if (cfg->postdiv == 1) { +- inno_write(inno, 0xaa, RK3328_POST_PLL_REFCLK_SEL_TMDS); + inno_write(inno, 0xab, RK3328_POST_PLL_FB_DIV_8(cfg->fbdiv) | + RK3328_POST_PLL_PRE_DIV(cfg->prediv)); ++ inno_write(inno, 0xaa, RK3328_POST_PLL_REFCLK_SEL_TMDS | ++ RK3328_POST_PLL_POWER_DOWN); + } else { + v = (cfg->postdiv / 2) - 1; + v &= RK3328_POST_PLL_POST_DIV_MASK; +@@ -1030,7 +1031,8 @@ inno_hdmi_phy_rk3328_power_on(struct inno_hdmi_phy *inno, + inno_write(inno, 0xab, RK3328_POST_PLL_FB_DIV_8(cfg->fbdiv) | + RK3328_POST_PLL_PRE_DIV(cfg->prediv)); + inno_write(inno, 0xaa, RK3328_POST_PLL_POST_DIV_ENABLE | +- RK3328_POST_PLL_REFCLK_SEL_TMDS); ++ RK3328_POST_PLL_REFCLK_SEL_TMDS | ++ RK3328_POST_PLL_POWER_DOWN); + } + + for (v = 0; v < 14; v++) + +From 335bf9964e953ca56351df1c35ed4249740f548d Mon Sep 17 00:00:00 2001 +From: Huicong Xu +Date: Wed, 8 Jan 2020 21:07:49 +0000 +Subject: [PATCH] phy/rockchip: inno-hdmi: force set_rate on power_on + +Regular 8-bit and Deep Color video formats mainly differ in TMDS rate and +not in pixel clock rate. +When the hdmiphy clock is configured with the same pixel clock rate using +clk_set_rate() the clock framework do not signal the hdmi phy driver +to set_rate when switching between 8-bit and Deep Color. +This result in pre/post pll not being re-configured when switching between +regular 8-bit and Deep Color video formats. + +Fix this by calling set_rate in power_on to force pre pll re-configuration. + +Signed-off-by: Huicong Xu +Signed-off-by: Jonas Karlman +--- + drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c +index 3a59a6da0440..3719309ad0d0 100644 +--- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c +@@ -245,6 +245,7 @@ struct inno_hdmi_phy { + struct clk_hw hw; + struct clk *phyclk; + unsigned long pixclock; ++ unsigned long tmdsclock; + }; + + struct pre_pll_config { +@@ -485,6 +486,8 @@ static int inno_hdmi_phy_power_on(struct phy *phy) + + dev_dbg(inno->dev, "Inno HDMI PHY Power On\n"); + ++ inno->plat_data->clk_ops->set_rate(&inno->hw, inno->pixclock, 24000000); ++ + ret = clk_prepare_enable(inno->phyclk); + if (ret) + return ret; +@@ -509,6 +512,8 @@ static int inno_hdmi_phy_power_off(struct phy *phy) + + clk_disable_unprepare(inno->phyclk); + ++ inno->tmdsclock = 0; ++ + dev_dbg(inno->dev, "Inno HDMI PHY Power Off\n"); + + return 0; +@@ -628,6 +633,9 @@ static int inno_hdmi_phy_rk3228_clk_set_rate(struct clk_hw *hw, + dev_dbg(inno->dev, "%s rate %lu tmdsclk %lu\n", + __func__, rate, tmdsclock); + ++ if (inno->pixclock == rate && inno->tmdsclock == tmdsclock) ++ return 0; ++ + cfg = inno_hdmi_phy_get_pre_pll_cfg(inno, rate); + if (IS_ERR(cfg)) + return PTR_ERR(cfg); +@@ -670,6 +678,7 @@ static int inno_hdmi_phy_rk3228_clk_set_rate(struct clk_hw *hw, + } + + inno->pixclock = rate; ++ inno->tmdsclock = tmdsclock; + + return 0; + } +@@ -781,6 +790,9 @@ static int inno_hdmi_phy_rk3328_clk_set_rate(struct clk_hw *hw, + dev_dbg(inno->dev, "%s rate %lu tmdsclk %lu\n", + __func__, rate, tmdsclock); + ++ if (inno->pixclock == rate && inno->tmdsclock == tmdsclock) ++ return 0; ++ + cfg = inno_hdmi_phy_get_pre_pll_cfg(inno, rate); + if (IS_ERR(cfg)) + return PTR_ERR(cfg); +@@ -820,6 +832,7 @@ static int inno_hdmi_phy_rk3328_clk_set_rate(struct clk_hw *hw, + } + + inno->pixclock = rate; ++ inno->tmdsclock = tmdsclock; + + return 0; + } + +From b4a0c66750a98eea4b1ab65026cd46a4364512cb Mon Sep 17 00:00:00 2001 +From: Algea Cao +Date: Wed, 8 Jan 2020 21:07:53 +0000 +Subject: [PATCH] phy/rockchip: inno-hdmi: Support more pre-pll configuration + +Adding the following freq cfg in 8-bit and 10-bit color depth: + +{ + 40000000, 65000000, 71000000, 83500000, 85750000, + 88750000, 108000000, 119000000, 162000000 +} + +New freq has been validated by quantumdata 980. + +For some freq which can't be got by only using integer freq div, +frac freq div is needed, Such as 88.75Mhz 10-bit. But The actual +freq is different from the target freq, We must try to narrow +the gap between them. RK322X only support integer freq div. + +The VCO of pre-PLL must be more than 2Ghz, otherwise PLL may be +unlocked. + +Signed-off-by: Algea Cao +Signed-off-by: Jonas Karlman +Acked-by: Heiko Stuebner +--- + drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 74 ++++++++++++------- + 1 file changed, 49 insertions(+), 25 deletions(-) + +diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c +index 3719309ad0d0..bb8bdf5e3301 100644 +--- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c +@@ -291,32 +291,56 @@ struct inno_hdmi_phy_drv_data { + const struct phy_config *phy_cfg_table; + }; + ++/* ++ * If only using integer freq div can't get frequency we want, frac ++ * freq div is needed. For example, pclk 88.75 Mhz and tmdsclk ++ * 110.9375 Mhz must use frac div 0xF00000. The actual frequency is different ++ * from the target frequency. Such as the tmds clock 110.9375 Mhz, ++ * the actual tmds clock we get is 110.93719 Mhz. It is important ++ * to note that RK322X platforms do not support frac div. ++ */ + static const struct pre_pll_config pre_pll_cfg_table[] = { +- { 27000000, 27000000, 1, 90, 3, 2, 2, 10, 3, 3, 4, 0, 0}, +- { 27000000, 33750000, 1, 90, 1, 3, 3, 10, 3, 3, 4, 0, 0}, +- { 40000000, 40000000, 1, 80, 2, 2, 2, 12, 2, 2, 2, 0, 0}, +- { 59341000, 59341000, 1, 98, 3, 1, 2, 1, 3, 3, 4, 0, 0xE6AE6B}, +- { 59400000, 59400000, 1, 99, 3, 1, 1, 1, 3, 3, 4, 0, 0}, +- { 59341000, 74176250, 1, 98, 0, 3, 3, 1, 3, 3, 4, 0, 0xE6AE6B}, +- { 59400000, 74250000, 1, 99, 1, 2, 2, 1, 3, 3, 4, 0, 0}, +- { 74176000, 74176000, 1, 98, 1, 2, 2, 1, 2, 3, 4, 0, 0xE6AE6B}, +- { 74250000, 74250000, 1, 99, 1, 2, 2, 1, 2, 3, 4, 0, 0}, +- { 74176000, 92720000, 4, 494, 1, 2, 2, 1, 3, 3, 4, 0, 0x816817}, +- { 74250000, 92812500, 4, 495, 1, 2, 2, 1, 3, 3, 4, 0, 0}, +- {148352000, 148352000, 1, 98, 1, 1, 1, 1, 2, 2, 2, 0, 0xE6AE6B}, +- {148500000, 148500000, 1, 99, 1, 1, 1, 1, 2, 2, 2, 0, 0}, +- {148352000, 185440000, 4, 494, 0, 2, 2, 1, 3, 2, 2, 0, 0x816817}, +- {148500000, 185625000, 4, 495, 0, 2, 2, 1, 3, 2, 2, 0, 0}, +- {296703000, 296703000, 1, 98, 0, 1, 1, 1, 0, 2, 2, 0, 0xE6AE6B}, +- {297000000, 297000000, 1, 99, 0, 1, 1, 1, 0, 2, 2, 0, 0}, +- {296703000, 370878750, 4, 494, 1, 2, 0, 1, 3, 1, 1, 0, 0x816817}, +- {297000000, 371250000, 4, 495, 1, 2, 0, 1, 3, 1, 1, 0, 0}, +- {593407000, 296703500, 1, 98, 0, 1, 1, 1, 0, 2, 1, 0, 0xE6AE6B}, +- {594000000, 297000000, 1, 99, 0, 1, 1, 1, 0, 2, 1, 0, 0}, +- {593407000, 370879375, 4, 494, 1, 2, 0, 1, 3, 1, 1, 1, 0x816817}, +- {594000000, 371250000, 4, 495, 1, 2, 0, 1, 3, 1, 1, 1, 0}, +- {593407000, 593407000, 1, 98, 0, 2, 0, 1, 0, 1, 1, 0, 0xE6AE6B}, +- {594000000, 594000000, 1, 99, 0, 2, 0, 1, 0, 1, 1, 0, 0}, ++ { 27000000, 27000000, 1, 90, 3, 2, 2, 10, 3, 3, 4, 0, 0}, ++ { 27000000, 33750000, 1, 90, 1, 3, 3, 10, 3, 3, 4, 0, 0}, ++ { 40000000, 40000000, 1, 80, 2, 2, 2, 12, 2, 2, 2, 0, 0}, ++ { 40000000, 50000000, 1, 100, 2, 2, 2, 1, 0, 0, 15, 0, 0}, ++ { 59341000, 59341000, 1, 98, 3, 1, 2, 1, 3, 3, 4, 0, 0xE6AE6B}, ++ { 59400000, 59400000, 1, 99, 3, 1, 1, 1, 3, 3, 4, 0, 0}, ++ { 59341000, 74176250, 1, 98, 0, 3, 3, 1, 3, 3, 4, 0, 0xE6AE6B}, ++ { 59400000, 74250000, 1, 99, 1, 2, 2, 1, 3, 3, 4, 0, 0}, ++ { 65000000, 65000000, 1, 130, 2, 2, 2, 1, 0, 0, 12, 0, 0}, ++ { 65000000, 81250000, 3, 325, 0, 3, 3, 1, 0, 0, 10, 0, 0}, ++ { 71000000, 71000000, 3, 284, 0, 3, 3, 1, 0, 0, 8, 0, 0}, ++ { 71000000, 88750000, 3, 355, 0, 3, 3, 1, 0, 0, 10, 0, 0}, ++ { 74176000, 74176000, 1, 98, 1, 2, 2, 1, 2, 3, 4, 0, 0xE6AE6B}, ++ { 74250000, 74250000, 1, 99, 1, 2, 2, 1, 2, 3, 4, 0, 0}, ++ { 74176000, 92720000, 4, 494, 1, 2, 2, 1, 3, 3, 4, 0, 0x816817}, ++ { 74250000, 92812500, 4, 495, 1, 2, 2, 1, 3, 3, 4, 0, 0}, ++ { 83500000, 83500000, 2, 167, 2, 1, 1, 1, 0, 0, 6, 0, 0}, ++ { 83500000, 104375000, 1, 104, 2, 1, 1, 1, 1, 0, 5, 0, 0x600000}, ++ { 85750000, 85750000, 3, 343, 0, 3, 3, 1, 0, 0, 8, 0, 0}, ++ { 88750000, 88750000, 3, 355, 0, 3, 3, 1, 0, 0, 8, 0, 0}, ++ { 88750000, 110937500, 1, 110, 2, 1, 1, 1, 1, 0, 5, 0, 0xF00000}, ++ {108000000, 108000000, 1, 90, 3, 0, 0, 1, 0, 0, 5, 0, 0}, ++ {108000000, 135000000, 1, 90, 0, 2, 2, 1, 0, 0, 5, 0, 0}, ++ {119000000, 119000000, 1, 119, 2, 1, 1, 1, 0, 0, 6, 0, 0}, ++ {119000000, 148750000, 1, 99, 0, 2, 2, 1, 0, 0, 5, 0, 0x2AAAAA}, ++ {148352000, 148352000, 1, 98, 1, 1, 1, 1, 2, 2, 2, 0, 0xE6AE6B}, ++ {148500000, 148500000, 1, 99, 1, 1, 1, 1, 2, 2, 2, 0, 0}, ++ {148352000, 185440000, 4, 494, 0, 2, 2, 1, 3, 2, 2, 0, 0x816817}, ++ {148500000, 185625000, 4, 495, 0, 2, 2, 1, 3, 2, 2, 0, 0}, ++ {162000000, 162000000, 1, 108, 0, 2, 2, 1, 0, 0, 4, 0, 0}, ++ {162000000, 202500000, 1, 135, 0, 2, 2, 1, 0, 0, 5, 0, 0}, ++ {296703000, 296703000, 1, 98, 0, 1, 1, 1, 0, 2, 2, 0, 0xE6AE6B}, ++ {297000000, 297000000, 1, 99, 0, 1, 1, 1, 0, 2, 2, 0, 0}, ++ {296703000, 370878750, 4, 494, 1, 2, 0, 1, 3, 1, 1, 0, 0x816817}, ++ {297000000, 371250000, 4, 495, 1, 2, 0, 1, 3, 1, 1, 0, 0}, ++ {593407000, 296703500, 1, 98, 0, 1, 1, 1, 0, 2, 1, 0, 0xE6AE6B}, ++ {594000000, 297000000, 1, 99, 0, 1, 1, 1, 0, 2, 1, 0, 0}, ++ {593407000, 370879375, 4, 494, 1, 2, 0, 1, 3, 1, 1, 1, 0x816817}, ++ {594000000, 371250000, 4, 495, 1, 2, 0, 1, 3, 1, 1, 1, 0}, ++ {593407000, 593407000, 1, 98, 0, 2, 0, 1, 0, 1, 1, 0, 0xE6AE6B}, ++ {594000000, 594000000, 1, 99, 0, 2, 0, 1, 0, 1, 1, 0, 0}, + { /* sentinel */ } + }; + + +From ddc63db13e520a56bf1afbe6c5ebd3d9935f282f Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 3 May 2020 16:51:31 +0000 +Subject: [PATCH] drm/rockchip: vop: filter modes outside 0.5% pixel clock + tolerance + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 33 +++++++++++++++++++++ + 1 file changed, 33 insertions(+) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +index c80f7d9fd13f..6cbdb4672a4b 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +@@ -1142,6 +1142,38 @@ static void vop_crtc_disable_vblank(struct drm_crtc *crtc) + spin_unlock_irqrestore(&vop->irq_lock, flags); + } + ++/* ++ * The VESA DMT standard specifies a 0.5% pixel clock frequency tolerance. ++ * The CVT spec reuses that tolerance in its examples. ++ */ ++#define CLOCK_TOLERANCE_PER_MILLE 5 ++ ++static enum drm_mode_status vop_crtc_mode_valid(struct drm_crtc *crtc, ++ const struct drm_display_mode *mode) ++{ ++ struct vop *vop = to_vop(crtc); ++ struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state); ++ long rounded_rate; ++ long lowest, highest; ++ ++ if (s->output_type != DRM_MODE_CONNECTOR_HDMIA) ++ return MODE_OK; ++ ++ rounded_rate = clk_round_rate(vop->dclk, mode->clock * 1000 + 999); ++ if (rounded_rate < 0) ++ return MODE_NOCLOCK; ++ ++ lowest = mode->clock * (1000 - CLOCK_TOLERANCE_PER_MILLE); ++ if (rounded_rate < lowest) ++ return MODE_CLOCK_LOW; ++ ++ highest = mode->clock * (1000 + CLOCK_TOLERANCE_PER_MILLE); ++ if (rounded_rate > highest) ++ return MODE_CLOCK_HIGH; ++ ++ return MODE_OK; ++} ++ + static bool vop_crtc_mode_fixup(struct drm_crtc *crtc, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +@@ -1512,6 +1544,7 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc, + } + + static const struct drm_crtc_helper_funcs vop_crtc_helper_funcs = { ++ .mode_valid = vop_crtc_mode_valid, + .mode_fixup = vop_crtc_mode_fixup, + .atomic_check = vop_crtc_atomic_check, + .atomic_begin = vop_crtc_atomic_begin, + +From 204bb448d3adbe5597d94ddf15ab7fa927931685 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 20 Jul 2020 11:46:16 +0000 +Subject: [PATCH] WIP: drm/rockchip: vop: max_output + +--- + drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 5 +++++ + drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 6 ++++++ + drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 7 +++++++ + 3 files changed, 18 insertions(+) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +index 6cbdb4672a4b..106b38ea12df 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +@@ -1152,6 +1152,7 @@ static enum drm_mode_status vop_crtc_mode_valid(struct drm_crtc *crtc, + const struct drm_display_mode *mode) + { + struct vop *vop = to_vop(crtc); ++ const struct vop_rect *max_output = &vop->data->max_output; + struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state); + long rounded_rate; + long lowest, highest; +@@ -1171,6 +1172,10 @@ static enum drm_mode_status vop_crtc_mode_valid(struct drm_crtc *crtc, + if (rounded_rate > highest) + return MODE_CLOCK_HIGH; + ++ if (max_output->width && max_output->height) ++ return drm_mode_validate_size(mode, max_output->width, ++ max_output->height); ++ + return MODE_OK; + } + +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +index 4a2099cb582e..1516231bbf93 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +@@ -185,6 +185,11 @@ struct vop_win_data { + enum drm_plane_type type; + }; + ++struct vop_rect { ++ int width; ++ int height; ++}; ++ + struct vop_data { + uint32_t version; + const struct vop_intr *intr; +@@ -197,6 +202,7 @@ struct vop_data { + const struct vop_win_data *win; + unsigned int win_size; + unsigned int lut_size; ++ struct vop_rect max_output; + + #define VOP_FEATURE_OUTPUT_RGB10 BIT(0) + #define VOP_FEATURE_INTERNAL_RGB BIT(1) +diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +index 80053d91a301..57c36e9207c1 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c ++++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +@@ -682,6 +682,7 @@ static const struct vop_intr rk3288_vop_intr = { + static const struct vop_data rk3288_vop = { + .version = VOP_VERSION(3, 1), + .feature = VOP_FEATURE_OUTPUT_RGB10, ++ .max_output = { 3840, 2160 }, + .intr = &rk3288_vop_intr, + .common = &rk3288_common, + .modeset = &rk3288_modeset, +@@ -782,6 +783,7 @@ static const struct vop_misc rk3368_misc = { + + static const struct vop_data rk3368_vop = { + .version = VOP_VERSION(3, 2), ++ .max_output = { 4096, 2160 }, + .intr = &rk3368_vop_intr, + .common = &rk3288_common, + .modeset = &rk3288_modeset, +@@ -803,6 +805,7 @@ static const struct vop_intr rk3366_vop_intr = { + + static const struct vop_data rk3366_vop = { + .version = VOP_VERSION(3, 4), ++ .max_output = { 4096, 2160 }, + .intr = &rk3366_vop_intr, + .common = &rk3288_common, + .modeset = &rk3288_modeset, +@@ -909,6 +912,7 @@ static const struct vop_afbc rk3399_vop_afbc = { + static const struct vop_data rk3399_vop_big = { + .version = VOP_VERSION(3, 5), + .feature = VOP_FEATURE_OUTPUT_RGB10, ++ .max_output = { 4096, 2160 }, + .intr = &rk3366_vop_intr, + .common = &rk3288_common, + .modeset = &rk3288_modeset, +@@ -935,6 +939,7 @@ static const struct vop_win_yuv2yuv_data rk3399_vop_lit_win_yuv2yuv_data[] = { + + static const struct vop_data rk3399_vop_lit = { + .version = VOP_VERSION(3, 6), ++ .max_output = { 2560, 1600 }, + .intr = &rk3366_vop_intr, + .common = &rk3288_common, + .modeset = &rk3288_modeset, +@@ -955,6 +960,7 @@ static const struct vop_win_data rk3228_vop_win_data[] = { + static const struct vop_data rk3228_vop = { + .version = VOP_VERSION(3, 7), + .feature = VOP_FEATURE_OUTPUT_RGB10, ++ .max_output = { 4096, 2160 }, + .intr = &rk3366_vop_intr, + .common = &rk3288_common, + .modeset = &rk3288_modeset, +@@ -1026,6 +1032,7 @@ static const struct vop_win_data rk3328_vop_win_data[] = { + static const struct vop_data rk3328_vop = { + .version = VOP_VERSION(3, 8), + .feature = VOP_FEATURE_OUTPUT_RGB10, ++ .max_output = { 4096, 2160 }, + .intr = &rk3328_vop_intr, + .common = &rk3328_common, + .modeset = &rk3328_modeset, + +From 77dae737d6b7ab099707e746311bf683729b662b Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 8 Jan 2020 21:07:51 +0000 +Subject: [PATCH] arm64: dts: rockchip: increase vop clock rate on rk3328 + +The VOP on RK3328 needs to run at higher rate in order to +produce a proper 3840x2160 signal. + +Signed-off-by: Jonas Karlman +--- + arch/arm64/boot/dts/rockchip/rk3328.dtsi | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +index bbdb19a3e85d..6547e2b4b617 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +@@ -802,8 +802,8 @@ cru: clock-controller@ff440000 { + <0>, <24000000>, + <24000000>, <24000000>, + <15000000>, <15000000>, +- <100000000>, <100000000>, +- <100000000>, <100000000>, ++ <300000000>, <100000000>, ++ <400000000>, <100000000>, + <50000000>, <100000000>, + <100000000>, <100000000>, + <50000000>, <50000000>, + +From 8312c58922e497f6d26c0845597bd23dbeba95d7 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 8 Jan 2020 21:07:49 +0000 +Subject: [PATCH] drm/rockchip: dw-hdmi: allow high tmds bit rates + +Prepare support for High TMDS Bit Rates used by HDMI2.0 display modes. + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index 23de359a1dec..cdf953850873 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -317,6 +317,8 @@ static int dw_hdmi_rockchip_genphy_init(struct dw_hdmi *dw_hdmi, void *data, + { + struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; + ++ dw_hdmi_set_high_tmds_clock_ratio(dw_hdmi, display); ++ + return phy_power_on(hdmi->phy); + } + + +From 1638ed24fb959926267f59a590e61b04c1050b96 Mon Sep 17 00:00:00 2001 +From: Yakir Yang +Date: Mon, 11 Jul 2016 19:05:39 +0800 +Subject: [PATCH] drm/rockchip: dw_hdmi: adjust cklvl & txlvl for RF/EMI + +Dut to the high HDMI signal voltage driver, Mickey have meet +a serious RF/EMI problem, so we decided to reduce HDMI signal +voltage to a proper value. + +The default params for phy is cklvl = 20 & txlvl = 13 (RF/EMI failed) + ck: lvl = 13, term=100, vlo = 2.71, vhi=3.14, vswing = 0.43 + tx: lvl = 20, term=100, vlo = 2.81, vhi=3.16, vswing = 0.35 + +1. We decided to reduce voltage value to lower, but VSwing still +keep high, RF/EMI have been improved but still failed. + ck: lvl = 6, term=100, vlo = 2.61, vhi=3.11, vswing = 0.50 + tx: lvl = 6, term=100, vlo = 2.61, vhi=3.11, vswing = 0.50 + +2. We try to keep voltage value and vswing both lower, then RF/EMI +test all passed ;) + ck: lvl = 11, term= 66, vlo = 2.68, vhi=3.09, vswing = 0.40 + tx: lvl = 11, term= 66, vlo = 2.68, vhi=3.09, vswing = 0.40 +When we back to run HDMI different test and single-end test, we see +different test passed, but signle-end test failed. The oscilloscope +show that simgle-end clock's VL value is 1.78v (which remind LowLimit +should not lower then 2.6v). + +3. That's to say there are some different between PHY document and +measure value. And according to experiment 2 results, we need to +higher clock voltage and lower data voltage, then we can keep RF/EMI +satisfied and single-end & differen test passed. + ck: lvl = 9, term=100, vlo = 2.65, vhi=3.12, vswing = 0.47 + tx: lvl = 16, term=100, vlo = 2.75, vhi=3.15, vswing = 0.39 + +Signed-off-by: Yakir Yang +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index cdf953850873..4652c0e0dcd6 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -181,7 +181,7 @@ static const struct dw_hdmi_curr_ctrl rockchip_cur_ctr[] = { + static const struct dw_hdmi_phy_config rockchip_phy_config[] = { + /*pixelclk symbol term vlev*/ + { 74250000, 0x8009, 0x0004, 0x0272}, +- { 148500000, 0x802b, 0x0004, 0x028d}, ++ { 165000000, 0x802b, 0x0004, 0x0209}, + { 297000000, 0x8039, 0x0005, 0x028d}, + { ~0UL, 0x0000, 0x0000, 0x0000} + }; + +From f60a4b188ee2e3bfcc44dd8d1fa3b5fa19f90720 Mon Sep 17 00:00:00 2001 +From: Nickey Yang +Date: Mon, 13 Feb 2017 15:40:29 +0800 +Subject: [PATCH] drm/rockchip: dw_hdmi: add phy_config for 594Mhz pixel clock + +Add phy_config for 594Mhz pixel clock used for 4K@60hz + +Signed-off-by: Nickey Yang +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index 4652c0e0dcd6..10c3dc521cbd 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -183,6 +183,7 @@ static const struct dw_hdmi_phy_config rockchip_phy_config[] = { + { 74250000, 0x8009, 0x0004, 0x0272}, + { 165000000, 0x802b, 0x0004, 0x0209}, + { 297000000, 0x8039, 0x0005, 0x028d}, ++ { 594000000, 0x8039, 0x0000, 0x019d}, + { ~0UL, 0x0000, 0x0000, 0x0000} + }; + + +From 6835093bddcc3634ba0ebd98deb72ab59d916f9c Mon Sep 17 00:00:00 2001 +From: Douglas Anderson +Date: Mon, 11 Jul 2016 19:05:36 +0800 +Subject: [PATCH] drm/rockchip: dw_hdmi: Set cur_ctr to 0 always + +Jitter was improved by lowering the MPLL bandwidth to account for high +frequency noise in the rk3288 PLL. In each case MPLL bandwidth was +lowered only enough to get us a comfortable margin. We believe that +lowering the bandwidth like this is safe given sufficient testing. + +Signed-off-by: Douglas Anderson +Signed-off-by: Yakir Yang +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 16 ++-------------- + 1 file changed, 2 insertions(+), 14 deletions(-) + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index 10c3dc521cbd..cc7675638e4f 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -160,20 +160,8 @@ static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = { + static const struct dw_hdmi_curr_ctrl rockchip_cur_ctr[] = { + /* pixelclk bpp8 bpp10 bpp12 */ + { +- 40000000, { 0x0018, 0x0018, 0x0018 }, +- }, { +- 65000000, { 0x0028, 0x0028, 0x0028 }, +- }, { +- 66000000, { 0x0038, 0x0038, 0x0038 }, +- }, { +- 74250000, { 0x0028, 0x0038, 0x0038 }, +- }, { +- 83500000, { 0x0028, 0x0038, 0x0038 }, +- }, { +- 146250000, { 0x0038, 0x0038, 0x0038 }, +- }, { +- 148500000, { 0x0000, 0x0038, 0x0038 }, +- }, { ++ 600000000, { 0x0000, 0x0000, 0x0000 }, ++ }, { + ~0UL, { 0x0000, 0x0000, 0x0000}, + } + }; + +From da024b1ee785c2443d32a955321dbae7e5b280d3 Mon Sep 17 00:00:00 2001 +From: Douglas Anderson +Date: Mon, 11 Jul 2016 19:05:42 +0800 +Subject: [PATCH] drm/rockchip: dw_hdmi: Use auto-generated tables + +The previous tables for mpll_cfg and curr_ctrl were created using the +20-pages of example settings provided by the PHY vendor. Those +example settings weren't particularly dense, so there were places +where we were guessing what the settings would be for 10-bit and +12-bit (not that we use those anyway). It was also always a lot of +extra work every time we wanted to add a new clock rate since we had +to cross-reference several tables. + +In I've gone through the work to figure +out how to generate this table automatically. Let's now use the +automatically generated table and then we'll never need to look at it +again. + +We only support 8-bit mode right now and only support a small number +of clock rates and and I've verified that the only 8-bit rate that was +affected was 148.5. That mode appears to have been wrong in the old +table. + +Signed-off-by: Douglas Anderson +Signed-off-by: Yakir Yang +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 130 +++++++++++--------- + 1 file changed, 69 insertions(+), 61 deletions(-) + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index cc7675638e4f..c4c158106ca4 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -79,80 +79,88 @@ struct rockchip_hdmi { + + static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = { + { +- 27000000, { +- { 0x00b3, 0x0000}, +- { 0x2153, 0x0000}, +- { 0x40f3, 0x0000} ++ 30666000, { ++ { 0x00b3, 0x0000 }, ++ { 0x2153, 0x0000 }, ++ { 0x40f3, 0x0000 }, + }, +- }, { +- 36000000, { +- { 0x00b3, 0x0000}, +- { 0x2153, 0x0000}, +- { 0x40f3, 0x0000} ++ }, { ++ 36800000, { ++ { 0x00b3, 0x0000 }, ++ { 0x2153, 0x0000 }, ++ { 0x40a2, 0x0001 }, + }, +- }, { +- 40000000, { +- { 0x00b3, 0x0000}, +- { 0x2153, 0x0000}, +- { 0x40f3, 0x0000} ++ }, { ++ 46000000, { ++ { 0x00b3, 0x0000 }, ++ { 0x2142, 0x0001 }, ++ { 0x40a2, 0x0001 }, + }, +- }, { +- 54000000, { +- { 0x0072, 0x0001}, +- { 0x2142, 0x0001}, +- { 0x40a2, 0x0001}, ++ }, { ++ 61333000, { ++ { 0x0072, 0x0001 }, ++ { 0x2142, 0x0001 }, ++ { 0x40a2, 0x0001 }, + }, +- }, { +- 65000000, { +- { 0x0072, 0x0001}, +- { 0x2142, 0x0001}, +- { 0x40a2, 0x0001}, ++ }, { ++ 73600000, { ++ { 0x0072, 0x0001 }, ++ { 0x2142, 0x0001 }, ++ { 0x4061, 0x0002 }, + }, +- }, { +- 66000000, { +- { 0x013e, 0x0003}, +- { 0x217e, 0x0002}, +- { 0x4061, 0x0002} ++ }, { ++ 92000000, { ++ { 0x0072, 0x0001 }, ++ { 0x2145, 0x0002 }, ++ { 0x4061, 0x0002 }, ++ }, ++ }, { ++ 122666000, { ++ { 0x0051, 0x0002 }, ++ { 0x2145, 0x0002 }, ++ { 0x4061, 0x0002 }, + }, +- }, { +- 74250000, { +- { 0x0072, 0x0001}, +- { 0x2145, 0x0002}, +- { 0x4061, 0x0002} ++ }, { ++ 147200000, { ++ { 0x0051, 0x0002 }, ++ { 0x2145, 0x0002 }, ++ { 0x4064, 0x0003 }, + }, +- }, { +- 83500000, { +- { 0x0072, 0x0001}, ++ }, { ++ 184000000, { ++ { 0x0051, 0x0002 }, ++ { 0x214c, 0x0003 }, ++ { 0x4064, 0x0003 }, + }, +- }, { +- 108000000, { +- { 0x0051, 0x0002}, +- { 0x2145, 0x0002}, +- { 0x4061, 0x0002} ++ }, { ++ 226666000, { ++ { 0x0040, 0x0003 }, ++ { 0x214c, 0x0003 }, ++ { 0x4064, 0x0003 }, + }, +- }, { +- 106500000, { +- { 0x0051, 0x0002}, +- { 0x2145, 0x0002}, +- { 0x4061, 0x0002} ++ }, { ++ 272000000, { ++ { 0x0040, 0x0003 }, ++ { 0x214c, 0x0003 }, ++ { 0x5a64, 0x0003 }, + }, +- }, { +- 146250000, { +- { 0x0051, 0x0002}, +- { 0x2145, 0x0002}, +- { 0x4061, 0x0002} ++ }, { ++ 340000000, { ++ { 0x0040, 0x0003 }, ++ { 0x3b4c, 0x0003 }, ++ { 0x5a64, 0x0003 }, + }, +- }, { +- 148500000, { +- { 0x0051, 0x0003}, +- { 0x214c, 0x0003}, +- { 0x4064, 0x0003} ++ }, { ++ 600000000, { ++ { 0x1a40, 0x0003 }, ++ { 0x3b4c, 0x0003 }, ++ { 0x5a64, 0x0003 }, + }, +- }, { ++ }, { + ~0UL, { +- { 0x00a0, 0x000a }, +- { 0x2001, 0x000f }, +- { 0x4002, 0x000f }, ++ { 0x0000, 0x0000 }, ++ { 0x0000, 0x0000 }, ++ { 0x0000, 0x0000 }, + }, + } + }; + +From 45e1a78887ebd640f8518afc1cfd5b2f2beb3ba4 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 8 Jan 2020 21:07:52 +0000 +Subject: [PATCH] drm/rockchip: dw-hdmi: limit tmds to 340mhz + +RK3228/RK3328 does not provide a stable hdmi signal at TMDS rates +above 371.25MHz (340MHz pixel clock). + +Limit the pixel clock rate to 340MHz to provide a stable signal. +Also limit the pixel clock to the display reported max tmds clock. + +This also enables use of pixel clocks up to 340MHz on RK3288/RK3399. + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 16 ++++------------ + 1 file changed, 4 insertions(+), 12 deletions(-) + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index c4c158106ca4..b62d8f4fc9a8 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -221,19 +221,11 @@ dw_hdmi_rockchip_mode_valid(struct dw_hdmi *hdmi, void *data, + const struct drm_display_info *info, + const struct drm_display_mode *mode) + { +- const struct dw_hdmi_mpll_config *mpll_cfg = rockchip_mpll_cfg; +- int pclk = mode->clock * 1000; +- bool valid = false; +- int i; +- +- for (i = 0; mpll_cfg[i].mpixelclock != (~0UL); i++) { +- if (pclk == mpll_cfg[i].mpixelclock) { +- valid = true; +- break; +- } +- } ++ if (mode->clock > 340000 || ++ (info->max_tmds_clock && mode->clock > info->max_tmds_clock)) ++ return MODE_CLOCK_HIGH; + +- return (valid) ? MODE_OK : MODE_BAD; ++ return MODE_OK; + } + + static void dw_hdmi_rockchip_encoder_disable(struct drm_encoder *encoder) + +From 13fdba7d97013c909f5574dea1d006ae8380de82 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 3 May 2020 22:36:23 +0000 +Subject: [PATCH] drm/rockchip: dw-hdmi: limit resolution to 3840x2160 + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index b62d8f4fc9a8..6f7641fbe6cc 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -225,7 +225,7 @@ dw_hdmi_rockchip_mode_valid(struct dw_hdmi *hdmi, void *data, + (info->max_tmds_clock && mode->clock > info->max_tmds_clock)) + return MODE_CLOCK_HIGH; + +- return MODE_OK; ++ return drm_mode_validate_size(mode, 3840, 2160); + } + + static void dw_hdmi_rockchip_encoder_disable(struct drm_encoder *encoder) + +From af4d3cc6fbed0adca1b20bf25929b37c980c8b96 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 8 Jan 2020 21:07:52 +0000 +Subject: [PATCH] drm/rockchip: dw-hdmi: remove unused plat_data on + rk3228/rk3328 + +mpll_cfg/cur_ctr/phy_config is not used when phy_force_vendor is true, +lets remove them. + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index 6f7641fbe6cc..cc20a83fa9b8 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -396,9 +396,6 @@ static struct rockchip_hdmi_chip_data rk3228_chip_data = { + + static const struct dw_hdmi_plat_data rk3228_hdmi_drv_data = { + .mode_valid = dw_hdmi_rockchip_mode_valid, +- .mpll_cfg = rockchip_mpll_cfg, +- .cur_ctr = rockchip_cur_ctr, +- .phy_config = rockchip_phy_config, + .phy_data = &rk3228_chip_data, + .phy_ops = &rk3228_hdmi_phy_ops, + .phy_name = "inno_dw_hdmi_phy2", +@@ -433,9 +430,6 @@ static struct rockchip_hdmi_chip_data rk3328_chip_data = { + + static const struct dw_hdmi_plat_data rk3328_hdmi_drv_data = { + .mode_valid = dw_hdmi_rockchip_mode_valid, +- .mpll_cfg = rockchip_mpll_cfg, +- .cur_ctr = rockchip_cur_ctr, +- .phy_config = rockchip_phy_config, + .phy_data = &rk3328_chip_data, + .phy_ops = &rk3328_hdmi_phy_ops, + .phy_name = "inno_dw_hdmi_phy2", + +From 8b696168a0ff4acd7b1add7ea689a51f9259f294 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 8 Jan 2020 21:07:50 +0000 +Subject: [PATCH] clk: rockchip: set parent rate for DCLK_VOP clock on rk3228 + +Signed-off-by: Jonas Karlman +--- + drivers/clk/rockchip/clk-rk3228.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c +index d7243c09cc84..dd414c8255e3 100644 +--- a/drivers/clk/rockchip/clk-rk3228.c ++++ b/drivers/clk/rockchip/clk-rk3228.c +@@ -408,7 +408,7 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + RK2928_CLKSEL_CON(29), 0, 3, DFLAGS), + DIV(0, "sclk_vop_pre", "sclk_vop_src", 0, + RK2928_CLKSEL_CON(27), 8, 8, DFLAGS), +- MUX(DCLK_VOP, "dclk_vop", mux_dclk_vop_p, 0, ++ MUX(DCLK_VOP, "dclk_vop", mux_dclk_vop_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + RK2928_CLKSEL_CON(27), 1, 1, MFLAGS), + + FACTOR(0, "xin12m", "xin24m", 0, 1, 2), + +From 41fdeaa849dcebfd9a9c9e5d3d48fc146dc1e789 Mon Sep 17 00:00:00 2001 +From: Nickey Yang +Date: Mon, 17 Jul 2017 16:35:34 +0800 +Subject: [PATCH] HACK: clk: rockchip: rk3288: dedicate npll for vopb and hdmi + use + +MINIARM: set npll be used for hdmi only + +Signed-off-by: Nickey Yang +Signed-off-by: Jonas Karlman +--- + arch/arm/boot/dts/rk3288.dtsi | 2 ++ + drivers/clk/rockchip/clk-rk3288.c | 4 ++-- + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi +index 68d5a58cfe88..a376dea3bb1b 100644 +--- a/arch/arm/boot/dts/rk3288.dtsi ++++ b/arch/arm/boot/dts/rk3288.dtsi +@@ -1046,6 +1046,8 @@ vopb: vop@ff930000 { + resets = <&cru SRST_LCDC0_AXI>, <&cru SRST_LCDC0_AHB>, <&cru SRST_LCDC0_DCLK>; + reset-names = "axi", "ahb", "dclk"; + iommus = <&vopb_mmu>; ++ assigned-clocks = <&cru DCLK_VOP0>; ++ assigned-clock-parents = <&cru PLL_NPLL>; + status = "disabled"; + + vopb_out: port { +diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c +index 93c794695c46..db6c8bbb35f4 100644 +--- a/drivers/clk/rockchip/clk-rk3288.c ++++ b/drivers/clk/rockchip/clk-rk3288.c +@@ -231,7 +231,7 @@ static struct rockchip_pll_clock rk3288_pll_clks[] __initdata = { + [gpll] = PLL(pll_rk3066, PLL_GPLL, "gpll", mux_pll_p, 0, RK3288_PLL_CON(12), + RK3288_MODE_CON, 12, 8, ROCKCHIP_PLL_SYNC_RATE, rk3288_pll_rates), + [npll] = PLL(pll_rk3066, PLL_NPLL, "npll", mux_pll_p, 0, RK3288_PLL_CON(16), +- RK3288_MODE_CON, 14, 9, ROCKCHIP_PLL_SYNC_RATE, rk3288_pll_rates), ++ RK3288_MODE_CON, 14, 9, 0, rk3288_pll_rates), + }; + + static struct clk_div_table div_hclk_cpu_t[] = { +@@ -441,7 +441,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { + RK3288_CLKSEL_CON(30), 14, 2, MFLAGS, 8, 5, DFLAGS, + RK3288_CLKGATE_CON(3), 4, GFLAGS), + +- COMPOSITE(DCLK_VOP0, "dclk_vop0", mux_pll_src_cpll_gpll_npll_p, 0, ++ COMPOSITE(DCLK_VOP0, "dclk_vop0", mux_pll_src_cpll_gpll_npll_p, CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT, + RK3288_CLKSEL_CON(27), 0, 2, MFLAGS, 8, 8, DFLAGS, + RK3288_CLKGATE_CON(3), 1, GFLAGS), + COMPOSITE(DCLK_VOP1, "dclk_vop1", mux_pll_src_cpll_gpll_npll_p, 0, + +From 0a33b20a1a890158d704b8a2cc759036952a09e2 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 4 Aug 2018 14:51:14 +0200 +Subject: [PATCH] HACK: clk: rockchip: rk3288: use npll table to to improve + HDMI compatibility + +Based on https://github.com/TinkerBoard/debian_kernel/commit/3d90870530b8a2901681f7b7fa598ee7381e49f3 + +Signed-off-by: Jonas Karlman +--- + drivers/clk/rockchip/clk-rk3288.c | 23 ++++++++++++++++++++++- + 1 file changed, 22 insertions(+), 1 deletion(-) + +diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c +index db6c8bbb35f4..426309f5dd44 100644 +--- a/drivers/clk/rockchip/clk-rk3288.c ++++ b/drivers/clk/rockchip/clk-rk3288.c +@@ -121,6 +121,27 @@ static struct rockchip_pll_rate_table rk3288_pll_rates[] = { + { /* sentinel */ }, + }; + ++static struct rockchip_pll_rate_table rk3288_npll_rates[] = { ++ RK3066_PLL_RATE_NB(594000000, 1, 99, 4, 32), ++ RK3066_PLL_RATE_NB(585000000, 6, 585, 4, 32), ++ RK3066_PLL_RATE_NB(432000000, 3, 216, 4, 32), ++ RK3066_PLL_RATE_NB(426000000, 3, 213, 4, 32), ++ RK3066_PLL_RATE_NB(400000000, 1, 100, 6, 32), ++ RK3066_PLL_RATE_NB(342000000, 3, 171, 4, 32), ++ RK3066_PLL_RATE_NB(297000000, 2, 198, 8, 16), ++ RK3066_PLL_RATE_NB(270000000, 1, 135, 12, 32), ++ RK3066_PLL_RATE_NB(260000000, 1, 130, 12, 32), ++ RK3066_PLL_RATE_NB(148500000, 1, 99, 16, 32), ++ RK3066_PLL_RATE(148352000, 13, 1125, 14), ++ RK3066_PLL_RATE_NB(146250000, 6, 585, 16, 32), ++ RK3066_PLL_RATE_NB(108000000, 1, 54, 12, 32), ++ RK3066_PLL_RATE_NB(106500000, 4, 213, 12, 32), ++ RK3066_PLL_RATE_NB(85500000, 4, 171, 12, 32), ++ RK3066_PLL_RATE_NB(74250000, 4, 198, 16, 32), ++ RK3066_PLL_RATE(74176000, 26, 1125, 14), ++ { /* sentinel */ }, ++}; ++ + #define RK3288_DIV_ACLK_CORE_M0_MASK 0xf + #define RK3288_DIV_ACLK_CORE_M0_SHIFT 0 + #define RK3288_DIV_ACLK_CORE_MP_MASK 0xf +@@ -231,7 +252,7 @@ static struct rockchip_pll_clock rk3288_pll_clks[] __initdata = { + [gpll] = PLL(pll_rk3066, PLL_GPLL, "gpll", mux_pll_p, 0, RK3288_PLL_CON(12), + RK3288_MODE_CON, 12, 8, ROCKCHIP_PLL_SYNC_RATE, rk3288_pll_rates), + [npll] = PLL(pll_rk3066, PLL_NPLL, "npll", mux_pll_p, 0, RK3288_PLL_CON(16), +- RK3288_MODE_CON, 14, 9, 0, rk3288_pll_rates), ++ RK3288_MODE_CON, 14, 9, 0, rk3288_npll_rates), + }; + + static struct clk_div_table div_hclk_cpu_t[] = { + +From 5c8dac1f946b2a4f2ec3e605a221d5cba56ee59f Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 28 Oct 2018 21:43:01 +0100 +Subject: [PATCH] HACK: clk: rockchip: rk3288: add more npll clocks + +Fixes 2560x1440@60Hz, 1600x1200@60Hz, 1920x1200@60Hz, 1680x1050@60Hz and 1440x900@60Hz modes on my monitor + +Signed-off-by: Jonas Karlman +--- + drivers/clk/rockchip/clk-rk3288.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c +index 426309f5dd44..b3247a3a7290 100644 +--- a/drivers/clk/rockchip/clk-rk3288.c ++++ b/drivers/clk/rockchip/clk-rk3288.c +@@ -127,18 +127,34 @@ static struct rockchip_pll_rate_table rk3288_npll_rates[] = { + RK3066_PLL_RATE_NB(432000000, 3, 216, 4, 32), + RK3066_PLL_RATE_NB(426000000, 3, 213, 4, 32), + RK3066_PLL_RATE_NB(400000000, 1, 100, 6, 32), ++ RK3066_PLL_RATE(348500000, 8, 697, 6), + RK3066_PLL_RATE_NB(342000000, 3, 171, 4, 32), + RK3066_PLL_RATE_NB(297000000, 2, 198, 8, 16), + RK3066_PLL_RATE_NB(270000000, 1, 135, 12, 32), + RK3066_PLL_RATE_NB(260000000, 1, 130, 12, 32), ++ RK3066_PLL_RATE(241500000, 2, 161, 8), ++ RK3066_PLL_RATE(162000000, 1, 81, 12), ++ RK3066_PLL_RATE(154000000, 6, 539, 14), + RK3066_PLL_RATE_NB(148500000, 1, 99, 16, 32), + RK3066_PLL_RATE(148352000, 13, 1125, 14), + RK3066_PLL_RATE_NB(146250000, 6, 585, 16, 32), ++ RK3066_PLL_RATE(121750000, 6, 487, 16), ++ RK3066_PLL_RATE(119000000, 3, 238, 16), + RK3066_PLL_RATE_NB(108000000, 1, 54, 12, 32), + RK3066_PLL_RATE_NB(106500000, 4, 213, 12, 32), ++ RK3066_PLL_RATE(101000000, 3, 202, 16), ++ RK3066_PLL_RATE(88750000, 6, 355, 16), + RK3066_PLL_RATE_NB(85500000, 4, 171, 12, 32), ++ RK3066_PLL_RATE(83500000, 3, 167, 16), ++ RK3066_PLL_RATE(79500000, 1, 53, 16), + RK3066_PLL_RATE_NB(74250000, 4, 198, 16, 32), + RK3066_PLL_RATE(74176000, 26, 1125, 14), ++ RK3066_PLL_RATE(72000000, 1, 48, 16), ++ RK3066_PLL_RATE(71000000, 3, 142, 16), ++ RK3066_PLL_RATE(68250000, 2, 91, 16), ++ RK3066_PLL_RATE(65000000, 3, 130, 16), ++ RK3066_PLL_RATE(40000000, 3, 80, 16), ++ RK3066_PLL_RATE(33750000, 2, 45, 16), + { /* sentinel */ }, + }; + + +From bcdd0b34aa22e3bf3d5750d003267cc072fed5db Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 25 May 2020 20:36:45 +0000 +Subject: [PATCH] HACK: clk: rockchip: rk3399: dedicate vpll for vopb and hdmi + use + +Signed-off-by: Jonas Karlman +--- + drivers/clk/rockchip/clk-rk3399.c | 32 +++++++++++++++++++++++++------ + 1 file changed, 26 insertions(+), 6 deletions(-) + +diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c +index ce1d2446f142..f75df0afa2bd 100644 +--- a/drivers/clk/rockchip/clk-rk3399.c ++++ b/drivers/clk/rockchip/clk-rk3399.c +@@ -103,6 +103,25 @@ static struct rockchip_pll_rate_table rk3399_pll_rates[] = { + { /* sentinel */ }, + }; + ++static struct rockchip_pll_rate_table rk3399_vpll_rates[] = { ++ /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */ ++ RK3036_PLL_RATE( 594000000, 1, 123, 5, 1, 0, 12582912), /* vco = 2970000000 */ ++ RK3036_PLL_RATE( 593406592, 1, 123, 5, 1, 0, 10508804), /* vco = 2967032965 */ ++ RK3036_PLL_RATE( 297000000, 1, 123, 5, 2, 0, 12582912), /* vco = 2970000000 */ ++ RK3036_PLL_RATE( 296703296, 1, 123, 5, 2, 0, 10508807), /* vco = 2967032970 */ ++ RK3036_PLL_RATE( 148500000, 1, 129, 7, 3, 0, 15728640), /* vco = 3118500000 */ ++ RK3036_PLL_RATE( 148351648, 1, 123, 5, 4, 0, 10508800), /* vco = 2967032960 */ ++ RK3036_PLL_RATE( 106500000, 1, 124, 7, 4, 0, 4194304), /* vco = 2982000000 */ ++ RK3036_PLL_RATE( 74250000, 1, 129, 7, 6, 0, 15728640), /* vco = 3118500000 */ ++ RK3036_PLL_RATE( 74175824, 1, 129, 7, 6, 0, 13550823), /* vco = 3115384608 */ ++ RK3036_PLL_RATE( 65000000, 1, 113, 7, 6, 0, 12582912), /* vco = 2730000000 */ ++ RK3036_PLL_RATE( 59340659, 1, 121, 7, 7, 0, 2581098), /* vco = 2907692291 */ ++ RK3036_PLL_RATE( 54000000, 1, 110, 7, 7, 0, 4194304), /* vco = 2646000000 */ ++ RK3036_PLL_RATE( 27000000, 1, 55, 7, 7, 0, 2097152), /* vco = 1323000000 */ ++ RK3036_PLL_RATE( 26973026, 1, 55, 7, 7, 0, 1173232), /* vco = 1321678323 */ ++ { /* sentinel */ }, ++}; ++ + /* CRU parents */ + PNAME(mux_pll_p) = { "xin24m", "xin32k" }; + +@@ -121,7 +140,7 @@ PNAME(mux_ddrclk_p) = { "clk_ddrc_lpll_src", + PNAME(mux_aclk_cci_p) = { "cpll_aclk_cci_src", + "gpll_aclk_cci_src", + "npll_aclk_cci_src", +- "vpll_aclk_cci_src" }; ++ "prevent:vpll" }; + PNAME(mux_cci_trace_p) = { "cpll_cci_trace", + "gpll_cci_trace" }; + PNAME(mux_cs_p) = { "cpll_cs", "gpll_cs", +@@ -148,9 +167,10 @@ PNAME(mux_pll_src_cpll_gpll_npll_ppll_upll_24m_p) = { "cpll", "gpll", "npll", + "ppll", "upll", "xin24m" }; + + PNAME(mux_pll_src_vpll_cpll_gpll_p) = { "vpll", "cpll", "gpll" }; +-PNAME(mux_pll_src_vpll_cpll_gpll_npll_p) = { "vpll", "cpll", "gpll", ++ ++PNAME(mux_pll_src_vpll_cpll_gpll_npll_p) = { "prevent:vpll", "cpll", "gpll", + "npll" }; +-PNAME(mux_pll_src_vpll_cpll_gpll_24m_p) = { "vpll", "cpll", "gpll", ++PNAME(mux_pll_src_vpll_cpll_gpll_24m_p) = { "prevent:vpll", "cpll", "gpll", + "xin24m" }; + + PNAME(mux_dclk_vop0_p) = { "dclk_vop0_div", +@@ -227,7 +247,7 @@ static struct rockchip_pll_clock rk3399_pll_clks[] __initdata = { + [npll] = PLL(pll_rk3399, PLL_NPLL, "npll", mux_pll_p, 0, RK3399_PLL_CON(40), + RK3399_PLL_CON(43), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk3399_pll_rates), + [vpll] = PLL(pll_rk3399, PLL_VPLL, "vpll", mux_pll_p, 0, RK3399_PLL_CON(48), +- RK3399_PLL_CON(51), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk3399_pll_rates), ++ RK3399_PLL_CON(51), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk3399_vpll_rates), + }; + + static struct rockchip_pll_clock rk3399_pmu_pll_clks[] __initdata = { +@@ -277,7 +297,7 @@ static struct rockchip_clk_branch rk3399_uart4_pmu_fracmux __initdata = + RK3399_PMU_CLKSEL_CON(5), 8, 2, MFLAGS); + + static struct rockchip_clk_branch rk3399_dclk_vop0_fracmux __initdata = +- MUX(DCLK_VOP0, "dclk_vop0", mux_dclk_vop0_p, CLK_SET_RATE_PARENT, ++ MUX(DCLK_VOP0, "dclk_vop0", mux_dclk_vop0_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + RK3399_CLKSEL_CON(49), 11, 1, MFLAGS); + + static struct rockchip_clk_branch rk3399_dclk_vop1_fracmux __initdata = +@@ -1158,7 +1178,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { + GATE(HCLK_VOP0_NOC, "hclk_vop0_noc", "hclk_vop0_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(28), 0, GFLAGS), + +- COMPOSITE(DCLK_VOP0_DIV, "dclk_vop0_div", mux_pll_src_vpll_cpll_gpll_p, 0, ++ COMPOSITE(DCLK_VOP0_DIV, "dclk_vop0_div", mux_pll_src_vpll_cpll_gpll_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + RK3399_CLKSEL_CON(49), 8, 2, MFLAGS, 0, 8, DFLAGS, + RK3399_CLKGATE_CON(10), 12, GFLAGS), + + +From 1178026ac93b4a05b643d9e68b7c98d0434b8b0e Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 19 Jul 2020 16:35:11 +0000 +Subject: [PATCH] HACK: dts: rockchip: do not use vopl for hdmi + +--- + arch/arm/boot/dts/rk3288.dtsi | 9 --------- + arch/arm64/boot/dts/rockchip/rk3399.dtsi | 9 --------- + 2 files changed, 18 deletions(-) + +diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi +index a376dea3bb1b..9757976d6e8a 100644 +--- a/arch/arm/boot/dts/rk3288.dtsi ++++ b/arch/arm/boot/dts/rk3288.dtsi +@@ -1104,11 +1104,6 @@ vopl_out: port { + #address-cells = <1>; + #size-cells = <0>; + +- vopl_out_hdmi: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&hdmi_in_vopl>; +- }; +- + vopl_out_edp: endpoint@1 { + reg = <1>; + remote-endpoint = <&edp_in_vopl>; +@@ -1249,10 +1244,6 @@ hdmi_in_vopb: endpoint@0 { + reg = <0>; + remote-endpoint = <&vopb_out_hdmi>; + }; +- hdmi_in_vopl: endpoint@1 { +- reg = <1>; +- remote-endpoint = <&vopl_out_hdmi>; +- }; + }; + }; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi +index ada724b12f01..8973bf68d652 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi +@@ -1637,11 +1637,6 @@ vopl_out_edp: endpoint@1 { + remote-endpoint = <&edp_in_vopl>; + }; + +- vopl_out_hdmi: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&hdmi_in_vopl>; +- }; +- + vopl_out_mipi1: endpoint@3 { + reg = <3>; + remote-endpoint = <&mipi1_in_vopl>; +@@ -1787,10 +1782,6 @@ hdmi_in_vopb: endpoint@0 { + reg = <0>; + remote-endpoint = <&vopb_out_hdmi>; + }; +- hdmi_in_vopl: endpoint@1 { +- reg = <1>; +- remote-endpoint = <&vopl_out_hdmi>; +- }; + }; + }; + }; + +From df6bdd1b82221a3d03736963bdc1845222ff3b5c Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Tue, 26 Feb 2019 20:45:14 +0000 +Subject: [PATCH] WIP: dw-hdmi-cec: sleep 100ms on error + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c | 19 +++++++++++++++++-- + 1 file changed, 17 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c +index 70ab4fbdc23e..f6a85f73b90d 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c +@@ -4,6 +4,7 @@ + * + * Copyright (C) 2015-2017 Russell King. + */ ++#include + #include + #include + #include +@@ -129,8 +130,16 @@ static irqreturn_t dw_hdmi_cec_hardirq(int irq, void *data) + + dw_hdmi_write(cec, stat, HDMI_IH_CEC_STAT0); + +- if (stat & CEC_STAT_ERROR_INIT) { +- cec->tx_status = CEC_TX_STATUS_ERROR; ++ /* ++ * Status with both done and error_initiator bits have been seen ++ * on Rockchip RK3328 devices, transmit attempt seems to have failed ++ * when this happens, report as low drive and block cec-framework ++ * 100ms before core retransmits the failed message, this seems to ++ * mitigate the issue with failed transmit attempts. ++ */ ++ if ((stat & (CEC_STAT_DONE|CEC_STAT_ERROR_INIT)) == (CEC_STAT_DONE|CEC_STAT_ERROR_INIT)) { ++ pr_info("dw_hdmi_cec_hardirq: stat=%02x LOW_DRIVE\n", stat); ++ cec->tx_status = CEC_TX_STATUS_LOW_DRIVE; + cec->tx_done = true; + ret = IRQ_WAKE_THREAD; + } else if (stat & CEC_STAT_DONE) { +@@ -141,6 +150,10 @@ static irqreturn_t dw_hdmi_cec_hardirq(int irq, void *data) + cec->tx_status = CEC_TX_STATUS_NACK; + cec->tx_done = true; + ret = IRQ_WAKE_THREAD; ++ } else if (stat & CEC_STAT_ERROR_INIT) { ++ cec->tx_status = CEC_TX_STATUS_ERROR; ++ cec->tx_done = true; ++ ret = IRQ_WAKE_THREAD; + } + + if (stat & CEC_STAT_EOM) { +@@ -173,6 +186,8 @@ static irqreturn_t dw_hdmi_cec_thread(int irq, void *data) + + if (cec->tx_done) { + cec->tx_done = false; ++ if (cec->tx_status == CEC_TX_STATUS_LOW_DRIVE) ++ msleep(100); + cec_transmit_attempt_done(adap, cec->tx_status); + } + if (cec->rx_done) { + +From f482feeeeedc41f34892a05a0594d23924a0571a Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 18 Jul 2020 20:54:38 +0000 +Subject: [PATCH] asdf + +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c | 36 +++++++++++++++---- + drivers/media/cec/core/cec-adap.c | 2 +- + 2 files changed, 30 insertions(+), 8 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c +index f6a85f73b90d..e6953219beee 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c +@@ -58,6 +58,7 @@ struct dw_hdmi_cec { + u32 addresses; + struct cec_adapter *adap; + struct cec_msg rx_msg; ++ unsigned int tx_attempts; + unsigned int tx_status; + bool tx_done; + bool rx_done; +@@ -96,6 +97,8 @@ static int dw_hdmi_cec_transmit(struct cec_adapter *adap, u8 attempts, + struct dw_hdmi_cec *cec = cec_get_drvdata(adap); + unsigned int i, ctrl; + ++ pr_info("%s: attempts=%u signal_free_time=%u msg=%*ph (sequence: %u)\n", __func__, attempts, signal_free_time, msg->len, msg->msg, msg->sequence); ++ + switch (signal_free_time) { + case CEC_SIGNAL_FREE_TIME_RETRY: + ctrl = CEC_CTRL_RETRY; +@@ -131,26 +134,35 @@ static irqreturn_t dw_hdmi_cec_hardirq(int irq, void *data) + dw_hdmi_write(cec, stat, HDMI_IH_CEC_STAT0); + + /* +- * Status with both done and error_initiator bits have been seen +- * on Rockchip RK3328 devices, transmit attempt seems to have failed +- * when this happens, report as low drive and block cec-framework ++ * Status with both done and error_initiator bits have been observed ++ * on Rockchip RK3328/RK3399 devices, transmit attempt seems to have ++ * failed when this happens, report as low drive and block cec-framework + * 100ms before core retransmits the failed message, this seems to + * mitigate the issue with failed transmit attempts. + */ + if ((stat & (CEC_STAT_DONE|CEC_STAT_ERROR_INIT)) == (CEC_STAT_DONE|CEC_STAT_ERROR_INIT)) { +- pr_info("dw_hdmi_cec_hardirq: stat=%02x LOW_DRIVE\n", stat); ++ if (!cec->tx_attempts) ++ cec->tx_attempts = 2; + cec->tx_status = CEC_TX_STATUS_LOW_DRIVE; + cec->tx_done = true; + ret = IRQ_WAKE_THREAD; ++ } else if (stat & CEC_STAT_ARBLOST) { ++ cec->tx_attempts = 0; ++ cec->tx_status = CEC_TX_STATUS_ARB_LOST; ++ cec->tx_done = true; ++ ret = IRQ_WAKE_THREAD; + } else if (stat & CEC_STAT_DONE) { ++ cec->tx_attempts = 0; + cec->tx_status = CEC_TX_STATUS_OK; + cec->tx_done = true; + ret = IRQ_WAKE_THREAD; + } else if (stat & CEC_STAT_NACK) { ++ cec->tx_attempts = 0; + cec->tx_status = CEC_TX_STATUS_NACK; + cec->tx_done = true; + ret = IRQ_WAKE_THREAD; + } else if (stat & CEC_STAT_ERROR_INIT) { ++ cec->tx_attempts = 0; + cec->tx_status = CEC_TX_STATUS_ERROR; + cec->tx_done = true; + ret = IRQ_WAKE_THREAD; +@@ -176,6 +188,8 @@ static irqreturn_t dw_hdmi_cec_hardirq(int irq, void *data) + ret = IRQ_WAKE_THREAD; + } + ++ pr_info("%s: stat=%x ret=%x tx_done=%d rx_done=%d tx_status=%u tx_attempts=%u\n", __func__, stat, ret, cec->tx_done, cec->rx_done, cec->tx_status, cec->tx_attempts); ++ + return ret; + } + +@@ -184,11 +198,19 @@ static irqreturn_t dw_hdmi_cec_thread(int irq, void *data) + struct cec_adapter *adap = data; + struct dw_hdmi_cec *cec = cec_get_drvdata(adap); + ++ //pr_info("%s: tx_done=%d rx_done=%d tx_status=%u tx_attempts=%u\n", __func__, cec->tx_done, cec->rx_done, cec->tx_status, cec->tx_attempts); ++ + if (cec->tx_done) { + cec->tx_done = false; + if (cec->tx_status == CEC_TX_STATUS_LOW_DRIVE) + msleep(100); +- cec_transmit_attempt_done(adap, cec->tx_status); ++ if (cec->tx_attempts > 1) { ++ cec->tx_attempts--; ++ dw_hdmi_write(cec, CEC_CTRL_RETRY | CEC_CTRL_START, HDMI_CEC_CTRL); ++ } else { ++ cec->tx_attempts = 0; ++ cec_transmit_attempt_done(adap, cec->tx_status); ++ } + } + if (cec->rx_done) { + cec->rx_done = false; +@@ -219,8 +241,8 @@ static int dw_hdmi_cec_enable(struct cec_adapter *adap, bool enable) + + cec->ops->enable(cec->hdmi); + +- irqs = CEC_STAT_ERROR_INIT | CEC_STAT_NACK | CEC_STAT_EOM | +- CEC_STAT_DONE; ++ irqs = CEC_STAT_ERROR_INIT | CEC_STAT_ARBLOST | CEC_STAT_NACK | ++ CEC_STAT_EOM | CEC_STAT_DONE; + dw_hdmi_write(cec, irqs, HDMI_CEC_POLARITY); + dw_hdmi_write(cec, ~irqs, HDMI_CEC_MASK); + dw_hdmi_write(cec, ~irqs, HDMI_IH_MUTE_CEC_STAT0); +diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c +index 6a04d19a96b2..3d12f9d30bd0 100644 +--- a/drivers/media/cec/core/cec-adap.c ++++ b/drivers/media/cec/core/cec-adap.c +@@ -599,7 +599,6 @@ void cec_transmit_done_ts(struct cec_adapter *adap, u8 status, + unsigned int attempts_made = arb_lost_cnt + nack_cnt + + low_drive_cnt + error_cnt; + +- dprintk(2, "%s: status 0x%02x\n", __func__, status); + if (attempts_made < 1) + attempts_made = 1; + +@@ -620,6 +619,7 @@ void cec_transmit_done_ts(struct cec_adapter *adap, u8 status, + adap->transmit_in_progress = false; + + msg = &data->msg; ++ dprintk(2, "%s: %*ph (sequence: %u, attempts: %d, status: %02x)\n", __func__, msg->len, msg->msg, msg->sequence, attempts_made, status); + + /* Drivers must fill in the status! */ + WARN_ON(status == 0); + +From 7abf7a462dd2e503dd816277628ed09a46dc8c55 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 20 Jul 2020 11:44:01 +0000 +Subject: [PATCH] cec dprintk revert + +--- + drivers/media/cec/core/cec-adap.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c +index 3d12f9d30bd0..6a04d19a96b2 100644 +--- a/drivers/media/cec/core/cec-adap.c ++++ b/drivers/media/cec/core/cec-adap.c +@@ -599,6 +599,7 @@ void cec_transmit_done_ts(struct cec_adapter *adap, u8 status, + unsigned int attempts_made = arb_lost_cnt + nack_cnt + + low_drive_cnt + error_cnt; + ++ dprintk(2, "%s: status 0x%02x\n", __func__, status); + if (attempts_made < 1) + attempts_made = 1; + +@@ -619,7 +620,6 @@ void cec_transmit_done_ts(struct cec_adapter *adap, u8 status, + adap->transmit_in_progress = false; + + msg = &data->msg; +- dprintk(2, "%s: %*ph (sequence: %u, attempts: %d, status: %02x)\n", __func__, msg->len, msg->msg, msg->sequence, attempts_made, status); + + /* Drivers must fill in the status! */ + WARN_ON(status == 0); + +From 8ca2d36b31a5921a9f7e0e1deba847915eac55bf Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 20 Jul 2020 12:33:01 +0000 +Subject: [PATCH] Revert "fixup! WIP: drm/rockchip: vop: max_output" + +This reverts commit c69612ca6820500cd1a0a3e4f8eb8c6f7b971cda. +--- + drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +index 106b38ea12df..138f449924f8 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +@@ -1184,8 +1184,19 @@ static bool vop_crtc_mode_fixup(struct drm_crtc *crtc, + struct drm_display_mode *adjusted_mode) + { + struct vop *vop = to_vop(crtc); ++ const struct vop_rect *max_output = &vop->data->max_output; + unsigned long rate; + ++ if (max_output->width && max_output->height) { ++ enum drm_mode_status status; ++ ++ status = drm_mode_validate_size(adjusted_mode, ++ max_output->width, ++ max_output->height); ++ if (status != MODE_OK) ++ return false; ++ } ++ + /* + * Clock craziness. + * + +From fff7adceb4d87d2fa0b4f108dbcd39748dfd0689 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 15 Jul 2020 15:24:47 +0000 +Subject: [PATCH] drm/rockchip: vop: fix crtc duplicate state + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +index 138f449924f8..0a25de483515 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +@@ -1578,7 +1578,11 @@ static struct drm_crtc_state *vop_crtc_duplicate_state(struct drm_crtc *crtc) + { + struct rockchip_crtc_state *rockchip_state; + +- rockchip_state = kzalloc(sizeof(*rockchip_state), GFP_KERNEL); ++ if (WARN_ON(!crtc->state)) ++ return NULL; ++ ++ rockchip_state = kmemdup(to_rockchip_crtc_state(crtc->state), ++ sizeof(*rockchip_state), GFP_KERNEL); + if (!rockchip_state) + return NULL; + + +From 36a518702d98bb3c22276352f648ee1d206db475 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 20 Jul 2020 15:15:50 +0000 +Subject: [PATCH] WIP: drm/rockchip: vop: filter interlaced modes + +--- + drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +index 0a25de483515..5ab1412173a7 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +@@ -1160,6 +1160,9 @@ static enum drm_mode_status vop_crtc_mode_valid(struct drm_crtc *crtc, + if (s->output_type != DRM_MODE_CONNECTOR_HDMIA) + return MODE_OK; + ++ if (mode->flags & DRM_MODE_FLAG_INTERLACE) ++ return MODE_NO_INTERLACE; ++ + rounded_rate = clk_round_rate(vop->dclk, mode->clock * 1000 + 999); + if (rounded_rate < 0) + return MODE_NOCLOCK; + +From 14ba7a75af03d8e3fd7274cfe8a21dd867b23ce5 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Fri, 20 Dec 2019 08:12:42 +0000 +Subject: [PATCH] drm/rockchip: dw-hdmi: add bridge and switch to + drm_bridge_funcs + +Switch the dw-hdmi driver to drm_bridge_funcs by implementing +a new local bridge, connecting it to the dw-hdmi bridge. + +Also enable bridge format negotiation by implementing +atomic_get_input_bus_fmts and support for 8-bit RGB 4:4:4. + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 138 ++++++++++++++------ + 1 file changed, 95 insertions(+), 43 deletions(-) + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index cc20a83fa9b8..745fd1c13cef 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -68,6 +68,7 @@ struct rockchip_hdmi { + struct device *dev; + struct regmap *regmap; + struct drm_encoder encoder; ++ struct drm_bridge bridge; + const struct rockchip_hdmi_chip_data *chip_data; + struct clk *vpll_clk; + struct clk *grf_clk; +@@ -228,30 +229,20 @@ dw_hdmi_rockchip_mode_valid(struct dw_hdmi *hdmi, void *data, + return drm_mode_validate_size(mode, 3840, 2160); + } + +-static void dw_hdmi_rockchip_encoder_disable(struct drm_encoder *encoder) ++static void ++dw_hdmi_rockchip_bridge_mode_set(struct drm_bridge *bridge, ++ const struct drm_display_mode *mode, ++ const struct drm_display_mode *adjusted_mode) + { +-} ++ struct rockchip_hdmi *hdmi = to_rockchip_hdmi(bridge); + +-static bool +-dw_hdmi_rockchip_encoder_mode_fixup(struct drm_encoder *encoder, +- const struct drm_display_mode *mode, +- struct drm_display_mode *adj_mode) +-{ +- return true; ++ clk_set_rate(hdmi->vpll_clk, adjusted_mode->clock * 1000); + } + +-static void dw_hdmi_rockchip_encoder_mode_set(struct drm_encoder *encoder, +- struct drm_display_mode *mode, +- struct drm_display_mode *adj_mode) ++static void dw_hdmi_rockchip_bridge_enable(struct drm_bridge *bridge) + { +- struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); +- +- clk_set_rate(hdmi->vpll_clk, adj_mode->clock * 1000); +-} +- +-static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder) +-{ +- struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); ++ struct rockchip_hdmi *hdmi = to_rockchip_hdmi(bridge); ++ struct drm_encoder *encoder = bridge->encoder; + u32 val; + int ret; + +@@ -279,10 +270,21 @@ static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder) + ret ? "LIT" : "BIG"); + } + ++static bool is_rgb(u32 format) ++{ ++ switch (format) { ++ case MEDIA_BUS_FMT_RGB888_1X24: ++ return true; ++ default: ++ return false; ++ } ++} ++ + static int +-dw_hdmi_rockchip_encoder_atomic_check(struct drm_encoder *encoder, +- struct drm_crtc_state *crtc_state, +- struct drm_connector_state *conn_state) ++dw_hdmi_rockchip_bridge_atomic_check(struct drm_bridge *bridge, ++ struct drm_bridge_state *bridge_state, ++ struct drm_crtc_state *crtc_state, ++ struct drm_connector_state *conn_state) + { + struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); + +@@ -292,12 +294,38 @@ dw_hdmi_rockchip_encoder_atomic_check(struct drm_encoder *encoder, + return 0; + } + +-static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_funcs = { +- .mode_fixup = dw_hdmi_rockchip_encoder_mode_fixup, +- .mode_set = dw_hdmi_rockchip_encoder_mode_set, +- .enable = dw_hdmi_rockchip_encoder_enable, +- .disable = dw_hdmi_rockchip_encoder_disable, +- .atomic_check = dw_hdmi_rockchip_encoder_atomic_check, ++static u32 *dw_hdmi_rockchip_get_input_bus_fmts(struct drm_bridge *bridge, ++ struct drm_bridge_state *bridge_state, ++ struct drm_crtc_state *crtc_state, ++ struct drm_connector_state *conn_state, ++ u32 output_fmt, ++ unsigned int *num_input_fmts) ++{ ++ u32 *input_fmt; ++ ++ *num_input_fmts = 0; ++ ++ if (!is_rgb(output_fmt)) ++ return NULL; ++ ++ input_fmt = kzalloc(sizeof(*input_fmt), GFP_KERNEL); ++ if (!input_fmt) ++ return NULL; ++ ++ *num_input_fmts = 1; ++ *input_fmt = output_fmt; ++ ++ return input_fmt; ++} ++ ++static const struct drm_bridge_funcs dw_hdmi_rockchip_bridge_funcs = { ++ .mode_set = dw_hdmi_rockchip_bridge_mode_set, ++ .enable = dw_hdmi_rockchip_bridge_enable, ++ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, ++ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, ++ .atomic_get_input_bus_fmts = dw_hdmi_rockchip_get_input_bus_fmts, ++ .atomic_check = dw_hdmi_rockchip_bridge_atomic_check, ++ .atomic_reset = drm_atomic_helper_bridge_reset, + }; + + static int dw_hdmi_rockchip_genphy_init(struct dw_hdmi *dw_hdmi, void *data, +@@ -476,6 +504,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, + struct dw_hdmi_plat_data *plat_data; + const struct of_device_id *match; + struct drm_device *drm = data; ++ struct drm_bridge *next_bridge; + struct drm_encoder *encoder; + struct rockchip_hdmi *hdmi; + int ret; +@@ -516,8 +545,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, + + ret = clk_prepare_enable(hdmi->vpll_clk); + if (ret) { +- DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI vpll: %d\n", +- ret); ++ DRM_DEV_ERROR(hdmi->dev, "Failed to enable vpll: %d\n", ret); + return ret; + } + +@@ -525,27 +553,51 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, + if (IS_ERR(hdmi->phy)) { + ret = PTR_ERR(hdmi->phy); + if (ret != -EPROBE_DEFER) +- DRM_DEV_ERROR(hdmi->dev, "failed to get phy\n"); +- return ret; ++ DRM_DEV_ERROR(hdmi->dev, "Failed to get phy: %d\n", ret); ++ goto err_disable_clk; + } + +- drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs); +- drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); ++ ret = drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); ++ if (ret) { ++ DRM_DEV_ERROR(hdmi->dev, "Failed to init encoder: %d\n", ret); ++ goto err_disable_clk; ++ } + +- platform_set_drvdata(pdev, hdmi); ++ hdmi->bridge.funcs = &dw_hdmi_rockchip_bridge_funcs; ++ drm_bridge_attach(encoder, &hdmi->bridge, NULL, 0); + +- hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data); ++ platform_set_drvdata(pdev, hdmi); + +- /* +- * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(), +- * which would have called the encoder cleanup. Do it manually. +- */ ++ hdmi->hdmi = dw_hdmi_probe(pdev, plat_data); + if (IS_ERR(hdmi->hdmi)) { + ret = PTR_ERR(hdmi->hdmi); +- drm_encoder_cleanup(encoder); +- clk_disable_unprepare(hdmi->vpll_clk); ++ if (ret != -EPROBE_DEFER) ++ DRM_DEV_ERROR(hdmi->dev, "Failed to init dw-hdmi bridge: %d\n", ret); ++ goto err_encoder_cleanup; ++ } ++ ++ next_bridge = of_drm_find_bridge(pdev->dev.of_node); ++ if (!next_bridge) { ++ ret = -EPROBE_DEFER; ++ goto err_dw_hdmi_remove; ++ } ++ ++ ret = drm_bridge_attach(encoder, next_bridge, &hdmi->bridge, 0); ++ if (ret) { ++ if (ret != -EPROBE_DEFER) ++ DRM_DEV_ERROR(hdmi->dev, "Failed to attach dw-hdmi bridge: %d\n", ret); ++ goto err_dw_hdmi_remove; + } + ++ return 0; ++ ++err_dw_hdmi_remove: ++ dw_hdmi_remove(hdmi->hdmi); ++err_encoder_cleanup: ++ drm_encoder_cleanup(encoder); ++err_disable_clk: ++ clk_disable_unprepare(hdmi->vpll_clk); ++ + return ret; + } + +@@ -554,7 +606,7 @@ static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master, + { + struct rockchip_hdmi *hdmi = dev_get_drvdata(dev); + +- dw_hdmi_unbind(hdmi->hdmi); ++ dw_hdmi_remove(hdmi->hdmi); + clk_disable_unprepare(hdmi->vpll_clk); + } + + +From ffded51c4e7a79cca7d97b4fe0d98ee4b0b74e34 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 20 Jul 2020 18:00:44 +0000 +Subject: [PATCH] drm/bridge: dw-hdmi: add mtmdsclock parameter to phy + configure ops + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 10 ++++++---- + drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c | 3 ++- + include/drm/bridge/dw_hdmi.h | 3 ++- + 3 files changed, 10 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 748df1cacd2b..c25d5ac7bb07 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -137,7 +137,8 @@ struct dw_hdmi_phy_data { + bool has_svsret; + int (*configure)(struct dw_hdmi *hdmi, + const struct dw_hdmi_plat_data *pdata, +- unsigned long mpixelclock); ++ unsigned long mpixelclock, ++ unsigned long mtmdsclock); + }; + + struct dw_hdmi { +@@ -1441,7 +1442,8 @@ static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi) + */ + static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi, + const struct dw_hdmi_plat_data *pdata, +- unsigned long mpixelclock) ++ unsigned long mpixelclock, ++ unsigned long mtmdsclock) + { + const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg; + const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr; +@@ -1516,9 +1518,9 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, + + /* Write to the PHY as configured by the platform */ + if (pdata->configure_phy) +- ret = pdata->configure_phy(hdmi, pdata->priv_data, mpixelclock); ++ ret = pdata->configure_phy(hdmi, pdata->priv_data, mpixelclock, mtmdsclock); + else +- ret = phy->configure(hdmi, pdata, mpixelclock); ++ ret = phy->configure(hdmi, pdata, mpixelclock, mtmdsclock); + if (ret) { + dev_err(hdmi->dev, "PHY configuration failed (clock %lu)\n", + mpixelclock); +diff --git a/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c b/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c +index 7b8ec8310699..539d86131fd4 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c ++++ b/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c +@@ -53,7 +53,8 @@ rcar_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, + } + + static int rcar_hdmi_phy_configure(struct dw_hdmi *hdmi, void *data, +- unsigned long mpixelclock) ++ unsigned long mpixelclock, ++ unsigned long mtmdsclock) + { + const struct rcar_hdmi_phy_params *params = rcar_hdmi_phy_params; + +diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h +index ea34ca146b82..4f61ede6486d 100644 +--- a/include/drm/bridge/dw_hdmi.h ++++ b/include/drm/bridge/dw_hdmi.h +@@ -152,7 +152,8 @@ struct dw_hdmi_plat_data { + const struct dw_hdmi_curr_ctrl *cur_ctr; + const struct dw_hdmi_phy_config *phy_config; + int (*configure_phy)(struct dw_hdmi *hdmi, void *data, +- unsigned long mpixelclock); ++ unsigned long mpixelclock, ++ unsigned long mtmdsclock); + }; + + struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev, + +From e3c32df45f5d84f541586a6c382008be538528ba Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 20 Jul 2020 21:34:48 +0000 +Subject: [PATCH] drm/bridge: dw-hdmi: support configuring phy for deep color + +Q: Should we rename dw_hdmi_curr_ctrl and dw_hdmi_phy_config mpixelclock to mtmdsclock ? + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index c25d5ac7bb07..bcdd823907c2 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -1448,6 +1448,7 @@ static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi, + const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg; + const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr; + const struct dw_hdmi_phy_config *phy_config = pdata->phy_config; ++ int depth; + + /* TOFIX Will need 420 specific PHY configuration tables */ + +@@ -1457,11 +1458,11 @@ static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi, + break; + + for (; curr_ctrl->mpixelclock != ~0UL; curr_ctrl++) +- if (mpixelclock <= curr_ctrl->mpixelclock) ++ if (mtmdsclock <= curr_ctrl->mpixelclock) + break; + + for (; phy_config->mpixelclock != ~0UL; phy_config++) +- if (mpixelclock <= phy_config->mpixelclock) ++ if (mtmdsclock <= phy_config->mpixelclock) + break; + + if (mpll_config->mpixelclock == ~0UL || +@@ -1469,11 +1470,17 @@ static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi, + phy_config->mpixelclock == ~0UL) + return -EINVAL; + +- dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].cpce, ++ depth = hdmi_bus_fmt_color_depth(hdmi->hdmi_data.enc_out_bus_format); ++ if (depth > 8 && mpixelclock != mtmdsclock) ++ depth = fls(depth - 8) - 1; ++ else ++ depth = 0; ++ ++ dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[depth].cpce, + HDMI_3D_TX_PHY_CPCE_CTRL); +- dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].gmp, ++ dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[depth].gmp, + HDMI_3D_TX_PHY_GMPCTRL); +- dw_hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[0], ++ dw_hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[depth], + HDMI_3D_TX_PHY_CURRCTRL); + + dw_hdmi_phy_i2c_write(hdmi, 0, HDMI_3D_TX_PHY_PLLPHBYCTRL); + +From d391dfb202b03bad6d52efe7d0aa46225febe3c5 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 20 Jul 2020 22:25:15 +0000 +Subject: [PATCH] drm/bridge: dw-hdmi: add mpll_cfg_420 for ycbcr420 mode + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 4 +++- + include/drm/bridge/dw_hdmi.h | 1 + + 2 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index bcdd823907c2..f5d048adf649 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -1450,7 +1450,9 @@ static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi, + const struct dw_hdmi_phy_config *phy_config = pdata->phy_config; + int depth; + +- /* TOFIX Will need 420 specific PHY configuration tables */ ++ if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format) && ++ pdata->mpll_cfg_420) ++ mpll_config = pdata->mpll_cfg_420; + + /* PLL/MPLL Cfg - always match on final entry */ + for (; mpll_config->mpixelclock != ~0UL; mpll_config++) +diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h +index 4f61ede6486d..0ebe01835d2a 100644 +--- a/include/drm/bridge/dw_hdmi.h ++++ b/include/drm/bridge/dw_hdmi.h +@@ -149,6 +149,7 @@ struct dw_hdmi_plat_data { + + /* Synopsys PHY support */ + const struct dw_hdmi_mpll_config *mpll_cfg; ++ const struct dw_hdmi_mpll_config *mpll_cfg_420; + const struct dw_hdmi_curr_ctrl *cur_ctr; + const struct dw_hdmi_phy_config *phy_config; + int (*configure_phy)(struct dw_hdmi *hdmi, void *data, + +From 08b2f123efe8bb641671ad038dd0dc37f877794d Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 15 Jul 2020 09:49:21 +0000 +Subject: [PATCH] drm/rockchip: dw-hdmi: mode_valid: allow 420 clock rate + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index 745fd1c13cef..9784111ea746 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -222,8 +222,15 @@ dw_hdmi_rockchip_mode_valid(struct dw_hdmi *hdmi, void *data, + const struct drm_display_info *info, + const struct drm_display_mode *mode) + { +- if (mode->clock > 340000 || +- (info->max_tmds_clock && mode->clock > info->max_tmds_clock)) ++ struct dw_hdmi_plat_data *pdata = (struct dw_hdmi_plat_data *)data; ++ int clock = mode->clock; ++ ++ if (pdata->ycbcr_420_allowed && drm_mode_is_420(info, mode) && ++ (info->color_formats & DRM_COLOR_FORMAT_YCRCB420)) ++ clock /= 2; ++ ++ if (clock > 340000 || ++ (info->max_tmds_clock && clock > info->max_tmds_clock)) + return MODE_CLOCK_HIGH; + + return drm_mode_validate_size(mode, 3840, 2160); +@@ -524,6 +531,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, + + hdmi->dev = &pdev->dev; + hdmi->chip_data = plat_data->phy_data; ++ plat_data->priv_data = plat_data; + plat_data->phy_data = hdmi; + encoder = &hdmi->encoder; + + +From e8f87de2fef5c2be3110fcd23fa1b09325bbd041 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 20 Jul 2020 22:26:19 +0000 +Subject: [PATCH] drm/rockchip: dw-hdmi: rk3399: add mpll_cfg_420 + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 41 +++++++++++++++++++++ + 1 file changed, 41 insertions(+) + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index 9784111ea746..e7fbeb9132fb 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -166,6 +166,46 @@ static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = { + } + }; + ++static const struct dw_hdmi_mpll_config rockchip_mpll_cfg_420[] = { ++ { ++ 30666000, { ++ { 0x00b7, 0x0000 }, ++ { 0x2157, 0x0000 }, ++ { 0x40f7, 0x0000 }, ++ }, ++ }, { ++ 92000000, { ++ { 0x00b7, 0x0000 }, ++ { 0x2143, 0x0001 }, ++ { 0x40a3, 0x0001 }, ++ }, ++ }, { ++ 184000000, { ++ { 0x0073, 0x0001 }, ++ { 0x2146, 0x0002 }, ++ { 0x4062, 0x0002 }, ++ }, ++ }, { ++ 340000000, { ++ { 0x0052, 0x0003 }, ++ { 0x214d, 0x0003 }, ++ { 0x4065, 0x0003 }, ++ }, ++ }, { ++ 600000000, { ++ { 0x0041, 0x0003 }, ++ { 0x3b4d, 0x0003 }, ++ { 0x5a65, 0x0003 }, ++ }, ++ }, { ++ ~0UL, { ++ { 0x0000, 0x0000 }, ++ { 0x0000, 0x0000 }, ++ { 0x0000, 0x0000 }, ++ }, ++ } ++}; ++ + static const struct dw_hdmi_curr_ctrl rockchip_cur_ctr[] = { + /* pixelclk bpp8 bpp10 bpp12 */ + { +@@ -481,6 +521,7 @@ static struct rockchip_hdmi_chip_data rk3399_chip_data = { + static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = { + .mode_valid = dw_hdmi_rockchip_mode_valid, + .mpll_cfg = rockchip_mpll_cfg, ++ .mpll_cfg_420 = rockchip_mpll_cfg_420, + .cur_ctr = rockchip_cur_ctr, + .phy_config = rockchip_phy_config, + .phy_data = &rk3399_chip_data, + +From 90cd0a2b9a02f11488bddcc9fe7dad15c04a8d36 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Fri, 20 Dec 2019 08:12:43 +0000 +Subject: [PATCH] WIP: drm/bridge: dw-hdmi: limit mode and bus format to + max_tmds_clock + +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 120 ++++++++++++++-------- + 1 file changed, 76 insertions(+), 44 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index f5d048adf649..26c64cf2d00a 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -1859,6 +1859,21 @@ static void hdmi_config_drm_infoframe(struct dw_hdmi *hdmi, + HDMI_FC_PACKET_TX_EN_DRM_MASK, HDMI_FC_PACKET_TX_EN); + } + ++static unsigned int ++hdmi_get_tmdsclock(unsigned int bus_format, unsigned int pixelclock) ++{ ++ int color_depth = hdmi_bus_fmt_color_depth(bus_format); ++ unsigned int tmdsclock = pixelclock; ++ ++ if (!hdmi_bus_fmt_is_yuv422(bus_format) && color_depth > 8) ++ tmdsclock = (u64)pixelclock * color_depth / 8; ++ ++ if (hdmi_bus_fmt_is_yuv420(bus_format)) ++ tmdsclock /= 2; ++ ++ return tmdsclock; ++} ++ + static void hdmi_av_composer(struct dw_hdmi *hdmi, + const struct drm_display_info *display, + const struct drm_display_mode *mode) +@@ -1870,29 +1885,11 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi, + unsigned int vdisplay, hdisplay; + + vmode->mpixelclock = mode->clock * 1000; ++ vmode->mtmdsclock = ++ hdmi_get_tmdsclock(hdmi->hdmi_data.enc_out_bus_format, ++ vmode->mpixelclock); + + dev_dbg(hdmi->dev, "final pixclk = %d\n", vmode->mpixelclock); +- +- vmode->mtmdsclock = vmode->mpixelclock; +- +- if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format)) { +- switch (hdmi_bus_fmt_color_depth( +- hdmi->hdmi_data.enc_out_bus_format)) { +- case 16: +- vmode->mtmdsclock = vmode->mpixelclock * 2; +- break; +- case 12: +- vmode->mtmdsclock = vmode->mpixelclock * 3 / 2; +- break; +- case 10: +- vmode->mtmdsclock = vmode->mpixelclock * 5 / 4; +- break; +- } +- } +- +- if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format)) +- vmode->mtmdsclock /= 2; +- + dev_dbg(hdmi->dev, "final tmdsclock = %d\n", vmode->mtmdsclock); + + /* Set up HDMI_FC_INVIDCONF */ +@@ -2550,8 +2547,21 @@ static int dw_hdmi_connector_create(struct dw_hdmi *hdmi) + * - MEDIA_BUS_FMT_RGB888_1X24, + */ + +-/* Can return a maximum of 11 possible output formats for a mode/connector */ +-#define MAX_OUTPUT_SEL_FORMATS 11 ++/* Can return a maximum of 15 possible output formats for a mode/connector */ ++#define MAX_OUTPUT_SEL_FORMATS 15 ++ ++static bool is_tmds_allowed(struct drm_display_info *info, ++ struct drm_display_mode *mode, ++ u32 bus_format) ++{ ++ unsigned long tmdsclock = hdmi_get_tmdsclock(bus_format, mode->clock); ++ int max_tmds_clock = info->max_tmds_clock ? info->max_tmds_clock : 340000; ++ ++ if (max_tmds_clock >= tmdsclock) ++ return true; ++ ++ return false; ++} + + static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, +@@ -2563,8 +2573,6 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, + struct drm_display_info *info = &conn->display_info; + struct drm_display_mode *mode = &crtc_state->mode; + u8 max_bpc = conn_state->max_requested_bpc; +- bool is_hdmi2_sink = info->hdmi.scdc.supported || +- (info->color_formats & DRM_COLOR_FORMAT_YCRCB420); + u32 *output_fmts; + unsigned int i = 0; + +@@ -2587,29 +2595,33 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, + * If the current mode enforces 4:2:0, force the output but format + * to 4:2:0 and do not add the YUV422/444/RGB formats + */ +- if (conn->ycbcr_420_allowed && +- (drm_mode_is_420_only(info, mode) || +- (is_hdmi2_sink && drm_mode_is_420_also(info, mode)))) { ++ if (conn->ycbcr_420_allowed && drm_mode_is_420(info, mode) && ++ (info->color_formats & DRM_COLOR_FORMAT_YCRCB420)) { + + /* Order bus formats from 16bit to 8bit if supported */ + if (max_bpc >= 16 && info->bpc == 16 && +- (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_48)) ++ (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_48) && ++ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYYVYY16_0_5X48)) + output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY16_0_5X48; + + if (max_bpc >= 12 && info->bpc >= 12 && +- (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_36)) ++ (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_36) && ++ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYYVYY12_0_5X36)) + output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY12_0_5X36; + + if (max_bpc >= 10 && info->bpc >= 10 && +- (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30)) ++ (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30) && ++ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYYVYY10_0_5X30)) + output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY10_0_5X30; + + /* Default 8bit fallback */ +- output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY8_0_5X24; ++ if (is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYYVYY8_0_5X24)) ++ output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY8_0_5X24; + + *num_output_fmts = i; + +- return output_fmts; ++ if (drm_mode_is_420_only(info, mode)) ++ return output_fmts; + } + + /* +@@ -2618,40 +2630,51 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, + */ + + if (max_bpc >= 16 && info->bpc == 16) { +- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444) ++ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB444) && ++ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_YUV16_1X48)) + output_fmts[i++] = MEDIA_BUS_FMT_YUV16_1X48; + +- output_fmts[i++] = MEDIA_BUS_FMT_RGB161616_1X48; ++ if (is_tmds_allowed(info, mode, MEDIA_BUS_FMT_RGB161616_1X48)) ++ output_fmts[i++] = MEDIA_BUS_FMT_RGB161616_1X48; + } + + if (max_bpc >= 12 && info->bpc >= 12) { +- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422) ++ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB422) && ++ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYVY12_1X24)) + output_fmts[i++] = MEDIA_BUS_FMT_UYVY12_1X24; + +- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444) ++ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB444) && ++ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_YUV12_1X36)) + output_fmts[i++] = MEDIA_BUS_FMT_YUV12_1X36; + +- output_fmts[i++] = MEDIA_BUS_FMT_RGB121212_1X36; ++ if (is_tmds_allowed(info, mode, MEDIA_BUS_FMT_RGB121212_1X36)) ++ output_fmts[i++] = MEDIA_BUS_FMT_RGB121212_1X36; + } + + if (max_bpc >= 10 && info->bpc >= 10) { +- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422) ++ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB422) && ++ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYVY10_1X20)) + output_fmts[i++] = MEDIA_BUS_FMT_UYVY10_1X20; + +- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444) ++ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB444) && ++ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_YUV10_1X30)) + output_fmts[i++] = MEDIA_BUS_FMT_YUV10_1X30; + +- output_fmts[i++] = MEDIA_BUS_FMT_RGB101010_1X30; ++ if (is_tmds_allowed(info, mode, MEDIA_BUS_FMT_RGB101010_1X30)) ++ output_fmts[i++] = MEDIA_BUS_FMT_RGB101010_1X30; + } + +- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422) ++ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB422) && ++ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYVY8_1X16)) + output_fmts[i++] = MEDIA_BUS_FMT_UYVY8_1X16; + +- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444) ++ if ((info->color_formats & DRM_COLOR_FORMAT_YCRCB444) && ++ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_YUV8_1X24)) + output_fmts[i++] = MEDIA_BUS_FMT_YUV8_1X24; + + /* Default 8bit RGB fallback */ +- output_fmts[i++] = MEDIA_BUS_FMT_RGB888_1X24; ++ if (is_tmds_allowed(info, mode, MEDIA_BUS_FMT_RGB888_1X24)) ++ output_fmts[i++] = MEDIA_BUS_FMT_RGB888_1X24; + + *num_output_fmts = i; + +@@ -2831,11 +2854,20 @@ dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge, + struct dw_hdmi *hdmi = bridge->driver_private; + const struct dw_hdmi_plat_data *pdata = hdmi->plat_data; + enum drm_mode_status mode_status = MODE_OK; ++ int max_tmds_clock = info->max_tmds_clock ? info->max_tmds_clock : 340000; ++ int clock = mode->clock; + + /* We don't support double-clocked modes */ + if (mode->flags & DRM_MODE_FLAG_DBLCLK) + return MODE_BAD; + ++ if (pdata->ycbcr_420_allowed && drm_mode_is_420(info, mode) && ++ (info->color_formats & DRM_COLOR_FORMAT_YCRCB420)) ++ clock /= 2; ++ ++ if (clock > max_tmds_clock) ++ return MODE_CLOCK_HIGH; ++ + if (pdata->mode_valid) + mode_status = pdata->mode_valid(hdmi, pdata->priv_data, info, + mode); + +From 2960613151591dd65e3b7dac4bc760ad0cddd4b6 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Fri, 20 Dec 2019 08:12:42 +0000 +Subject: [PATCH] WIP: drm/rockchip: dw_hdmi: add 10-bit rgb bus format + +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 41 +++++++++++++++++++++ + drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 2 + + 2 files changed, 43 insertions(+) + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index e7fbeb9132fb..cd87ee8a65c3 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -77,6 +77,7 @@ struct rockchip_hdmi { + }; + + #define to_rockchip_hdmi(x) container_of(x, struct rockchip_hdmi, x) ++#define to_crtc_state(x) container_of(x, struct drm_crtc_state, x) + + static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = { + { +@@ -282,6 +283,11 @@ dw_hdmi_rockchip_bridge_mode_set(struct drm_bridge *bridge, + const struct drm_display_mode *adjusted_mode) + { + struct rockchip_hdmi *hdmi = to_rockchip_hdmi(bridge); ++ struct drm_crtc_state *crtc_state = to_crtc_state(adjusted_mode); ++ struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); ++ ++ if (hdmi->phy) ++ phy_set_bus_width(hdmi->phy, s->bus_width); + + clk_set_rate(hdmi->vpll_clk, adjusted_mode->clock * 1000); + } +@@ -320,6 +326,7 @@ static void dw_hdmi_rockchip_bridge_enable(struct drm_bridge *bridge) + static bool is_rgb(u32 format) + { + switch (format) { ++ case MEDIA_BUS_FMT_RGB101010_1X30: + case MEDIA_BUS_FMT_RGB888_1X24: + return true; + default: +@@ -327,6 +334,16 @@ static bool is_rgb(u32 format) + } + } + ++static bool is_10bit(u32 format) ++{ ++ switch (format) { ++ case MEDIA_BUS_FMT_RGB101010_1X30: ++ return true; ++ default: ++ return false; ++ } ++} ++ + static int + dw_hdmi_rockchip_bridge_atomic_check(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, +@@ -334,9 +351,24 @@ dw_hdmi_rockchip_bridge_atomic_check(struct drm_bridge *bridge, + struct drm_connector_state *conn_state) + { + struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); ++ struct drm_atomic_state *state = bridge_state->base.state; ++ struct drm_crtc_state *old_crtc_state; ++ struct rockchip_crtc_state *old_state; ++ u32 format = bridge_state->output_bus_cfg.format; + + s->output_mode = ROCKCHIP_OUT_MODE_AAAA; + s->output_type = DRM_MODE_CONNECTOR_HDMIA; ++ s->output_bpc = 10; ++ s->bus_format = format; ++ s->bus_width = is_10bit(format) ? 10 : 8; ++ ++ old_crtc_state = drm_atomic_get_old_crtc_state(state, conn_state->crtc); ++ if (old_crtc_state && !crtc_state->mode_changed) { ++ old_state = to_rockchip_crtc_state(old_crtc_state); ++ if (s->bus_format != old_state->bus_format || ++ s->bus_width != old_state->bus_width) ++ crtc_state->mode_changed = true; ++ } + + return 0; + } +@@ -348,10 +380,19 @@ static u32 *dw_hdmi_rockchip_get_input_bus_fmts(struct drm_bridge *bridge, + u32 output_fmt, + unsigned int *num_input_fmts) + { ++ struct rockchip_hdmi *hdmi = to_rockchip_hdmi(bridge); ++ struct drm_encoder *encoder = bridge->encoder; + u32 *input_fmt; ++ bool has_10bit = true; + + *num_input_fmts = 0; + ++ if (drm_of_encoder_active_endpoint_id(hdmi->dev->of_node, encoder)) ++ has_10bit = false; ++ ++ if (!has_10bit && is_10bit(output_fmt)) ++ return NULL; ++ + if (!is_rgb(output_fmt)) + return NULL; + +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +index e33c2dcd0d4b..03944e08b6c7 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +@@ -31,6 +31,8 @@ struct rockchip_crtc_state { + int output_bpc; + int output_flags; + bool enable_afbc; ++ u32 bus_format; ++ int bus_width; + }; + #define to_rockchip_crtc_state(s) \ + container_of(s, struct rockchip_crtc_state, base) + +From 7eda226a69e0c2b4fd8ab41b51ddff08da682073 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 8 Dec 2019 23:42:44 +0000 +Subject: [PATCH] WIP: drm: dw-hdmi: add content type connector property + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 26c64cf2d00a..ffb72e6874c8 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -1646,6 +1646,7 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, + const struct drm_connector *connector, + const struct drm_display_mode *mode) + { ++ const struct drm_connector_state *conn_state = connector->state; + struct hdmi_avi_infoframe frame; + u8 val; + +@@ -1703,6 +1704,8 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, + HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; + } + ++ drm_hdmi_avi_infoframe_content_type(&frame, conn_state); ++ + /* + * The Designware IP uses a different byte format from standard + * AVI info frames, though generally the bits are in the correct +@@ -2437,7 +2440,8 @@ static int dw_hdmi_connector_atomic_check(struct drm_connector *connector, + if (!crtc) + return 0; + +- if (!hdr_metadata_equal(old_state, new_state)) { ++ if (!hdr_metadata_equal(old_state, new_state) || ++ old_state->content_type != new_state->content_type) { + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (IS_ERR(crtc_state)) + return PTR_ERR(crtc_state); +@@ -2505,6 +2509,8 @@ static int dw_hdmi_connector_create(struct dw_hdmi *hdmi) + + drm_connector_attach_max_bpc_property(connector, 8, 16); + ++ drm_connector_attach_content_type_property(connector); ++ + if (hdmi->version >= 0x200a && hdmi->plat_data->use_drm_infoframe) + drm_object_attach_property(&connector->base, + connector->dev->mode_config.hdr_output_metadata_property, 0); + +From 8e94faae53df05c7466387b65edc808218f15277 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Fri, 20 Dec 2019 08:12:43 +0000 +Subject: [PATCH] WIP: drm/rockchip: add yuv444 support + +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 30 ++++++++++++++++++++- + drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 29 ++++++++++++++++++++ + drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 6 +++++ + drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 14 ++++++++++ + 4 files changed, 78 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index cd87ee8a65c3..436a9223e5e4 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -62,6 +62,7 @@ struct rockchip_hdmi_chip_data { + int lcdsel_grf_reg; + u32 lcdsel_big; + u32 lcdsel_lit; ++ bool ycbcr_444_allowed; + }; + + struct rockchip_hdmi { +@@ -334,10 +335,22 @@ static bool is_rgb(u32 format) + } + } + ++static bool is_yuv444(u32 format) ++{ ++ switch (format) { ++ case MEDIA_BUS_FMT_YUV10_1X30: ++ case MEDIA_BUS_FMT_YUV8_1X24: ++ return true; ++ default: ++ return false; ++ } ++} ++ + static bool is_10bit(u32 format) + { + switch (format) { + case MEDIA_BUS_FMT_RGB101010_1X30: ++ case MEDIA_BUS_FMT_YUV10_1X30: + return true; + default: + return false; +@@ -354,12 +367,22 @@ dw_hdmi_rockchip_bridge_atomic_check(struct drm_bridge *bridge, + struct drm_atomic_state *state = bridge_state->base.state; + struct drm_crtc_state *old_crtc_state; + struct rockchip_crtc_state *old_state; ++ struct drm_bridge *next_bridge; ++ struct drm_bridge_state *next_bridge_state; + u32 format = bridge_state->output_bus_cfg.format; + + s->output_mode = ROCKCHIP_OUT_MODE_AAAA; + s->output_type = DRM_MODE_CONNECTOR_HDMIA; + s->output_bpc = 10; + s->bus_format = format; ++ ++ next_bridge = drm_bridge_get_next_bridge(bridge); ++ if (next_bridge) { ++ next_bridge_state = drm_atomic_get_new_bridge_state(state, ++ next_bridge); ++ format = next_bridge_state->output_bus_cfg.format; ++ } ++ + s->bus_width = is_10bit(format) ? 10 : 8; + + old_crtc_state = drm_atomic_get_old_crtc_state(state, conn_state->crtc); +@@ -393,7 +416,10 @@ static u32 *dw_hdmi_rockchip_get_input_bus_fmts(struct drm_bridge *bridge, + if (!has_10bit && is_10bit(output_fmt)) + return NULL; + +- if (!is_rgb(output_fmt)) ++ if (is_yuv444(output_fmt)) { ++ if (!hdmi->chip_data->ycbcr_444_allowed) ++ return NULL; ++ } else if (!is_rgb(output_fmt)) + return NULL; + + input_fmt = kzalloc(sizeof(*input_fmt), GFP_KERNEL); +@@ -542,6 +568,7 @@ static const struct dw_hdmi_phy_ops rk3328_hdmi_phy_ops = { + + static struct rockchip_hdmi_chip_data rk3328_chip_data = { + .lcdsel_grf_reg = -1, ++ .ycbcr_444_allowed = true, + }; + + static const struct dw_hdmi_plat_data rk3328_hdmi_drv_data = { +@@ -557,6 +584,7 @@ static struct rockchip_hdmi_chip_data rk3399_chip_data = { + .lcdsel_grf_reg = RK3399_GRF_SOC_CON20, + .lcdsel_big = HIWORD_UPDATE(0, RK3399_HDMI_LCDC_SEL), + .lcdsel_lit = HIWORD_UPDATE(RK3399_HDMI_LCDC_SEL, RK3399_HDMI_LCDC_SEL), ++ .ycbcr_444_allowed = true, + }; + + static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = { +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +index 5ab1412173a7..a17bd4e90ba7 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +@@ -310,6 +310,17 @@ static int vop_convert_afbc_format(uint32_t format) + return -EINVAL; + } + ++static bool is_yuv_output(uint32_t bus_format) ++{ ++ switch (bus_format) { ++ case MEDIA_BUS_FMT_YUV8_1X24: ++ case MEDIA_BUS_FMT_YUV10_1X30: ++ return true; ++ default: ++ return false; ++ } ++} ++ + static uint16_t scl_vop_cal_scale(enum scale_mode mode, uint32_t src, + uint32_t dst, bool is_horizontal, + int vsu_mode, int *vskiplines) +@@ -1329,6 +1340,7 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, + u16 vact_end = vact_st + vdisplay; + uint32_t pin_pol, val; + int dither_bpc = s->output_bpc ? s->output_bpc : 10; ++ bool yuv_output = is_yuv_output(s->bus_format); + int ret; + + if (old_state && old_state->self_refresh_active) { +@@ -1402,6 +1414,8 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, + !(vop_data->feature & VOP_FEATURE_OUTPUT_RGB10)) + s->output_mode = ROCKCHIP_OUT_MODE_P888; + ++ VOP_REG_SET(vop, common, dsp_data_swap, yuv_output ? 2 : 0); ++ + if (s->output_mode == ROCKCHIP_OUT_MODE_AAAA && dither_bpc <= 8) + VOP_REG_SET(vop, common, pre_dither_down, 1); + else +@@ -1417,6 +1431,21 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, + + VOP_REG_SET(vop, common, out_mode, s->output_mode); + ++ VOP_REG_SET(vop, common, overlay_mode, yuv_output); ++ VOP_REG_SET(vop, common, dsp_out_yuv, yuv_output); ++ ++ /* ++ * Background color is 10bit depth if vop version >= 3.5 ++ */ ++ if (!yuv_output) ++ val = 0; ++ else if (VOP_MAJOR(vop_data->version) == 3 && ++ VOP_MINOR(vop_data->version) >= 5) ++ val = 0x20010200; ++ else ++ val = 0x801080; ++ VOP_REG_SET(vop, common, dsp_background, val); ++ + VOP_REG_SET(vop, modeset, htotal_pw, (htotal << 16) | hsync_len); + val = hact_st << 16; + val |= hact_end; +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +index 1516231bbf93..b820ad3fa091 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +@@ -92,10 +92,16 @@ struct vop_common { + struct vop_reg mmu_en; + struct vop_reg out_mode; + struct vop_reg standby; ++ ++ struct vop_reg overlay_mode; ++ struct vop_reg dsp_data_swap; ++ struct vop_reg dsp_out_yuv; ++ struct vop_reg dsp_background; + }; + + struct vop_misc { + struct vop_reg global_regdone_en; ++ struct vop_reg win_channel[4]; + }; + + struct vop_intr { +diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +index 57c36e9207c1..800b9341dd42 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c ++++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +@@ -644,6 +644,11 @@ static const struct vop_common rk3288_common = { + .dsp_blank = VOP_REG(RK3288_DSP_CTRL0, 0x3, 18), + .out_mode = VOP_REG(RK3288_DSP_CTRL0, 0xf, 0), + .cfg_done = VOP_REG_SYNC(RK3288_REG_CFG_DONE, 0x1, 0), ++ ++ .overlay_mode = VOP_REG(RK3288_SYS_CTRL, 0x1, 16), ++ .dsp_data_swap = VOP_REG(RK3288_DSP_CTRL0, 0x1f, 12), ++ .dsp_out_yuv = VOP_REG(RK3288_POST_SCL_CTRL, 0x1, 2), ++ .dsp_background = VOP_REG(RK3288_DSP_BG, 0xffffffff, 0), + }; + + /* +@@ -996,6 +1001,10 @@ static const struct vop_output rk3328_output = { + + static const struct vop_misc rk3328_misc = { + .global_regdone_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 11), ++ ++ .win_channel[0] = VOP_REG(RK3328_WIN0_CTRL2, 0xff, 0), ++ .win_channel[1] = VOP_REG(RK3328_WIN1_CTRL2, 0xff, 0), ++ .win_channel[2] = VOP_REG(RK3328_WIN2_CTRL2, 0xff, 0), + }; + + static const struct vop_common rk3328_common = { +@@ -1008,6 +1017,11 @@ static const struct vop_common rk3328_common = { + .dsp_blank = VOP_REG(RK3328_DSP_CTRL0, 0x3, 18), + .out_mode = VOP_REG(RK3328_DSP_CTRL0, 0xf, 0), + .cfg_done = VOP_REG_SYNC(RK3328_REG_CFG_DONE, 0x1, 0), ++ ++ .overlay_mode = VOP_REG(RK3328_SYS_CTRL, 0x1, 16), ++ .dsp_data_swap = VOP_REG(RK3328_DSP_CTRL0, 0x1f, 12), ++ .dsp_out_yuv = VOP_REG(RK3328_POST_SCL_CTRL, 0x1, 2), ++ .dsp_background = VOP_REG(RK3328_DSP_BG, 0xffffffff, 0), + }; + + static const struct vop_intr rk3328_vop_intr = { + +From d5563c9163f1a691e73c1b027d39c78672ff3e17 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Fri, 20 Dec 2019 08:12:43 +0000 +Subject: [PATCH] WIP: drm/rockchip: add yuv420 support + +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 23 +++++++++++++++++++++ + drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 18 +++++++++++++++- + drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 10 +++++---- + drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 2 ++ + 4 files changed, 48 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index 436a9223e5e4..1abc46a023a4 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -346,9 +346,21 @@ static bool is_yuv444(u32 format) + } + } + ++static bool is_yuv420(u32 format) ++{ ++ switch (format) { ++ case MEDIA_BUS_FMT_UYYVYY10_0_5X30: ++ case MEDIA_BUS_FMT_UYYVYY8_0_5X24: ++ return true; ++ default: ++ return false; ++ } ++} ++ + static bool is_10bit(u32 format) + { + switch (format) { ++ case MEDIA_BUS_FMT_UYYVYY10_0_5X30: + case MEDIA_BUS_FMT_RGB101010_1X30: + case MEDIA_BUS_FMT_YUV10_1X30: + return true; +@@ -385,6 +397,11 @@ dw_hdmi_rockchip_bridge_atomic_check(struct drm_bridge *bridge, + + s->bus_width = is_10bit(format) ? 10 : 8; + ++ if (is_yuv420(format)) { ++ s->output_mode = ROCKCHIP_OUT_MODE_YUV420; ++ s->bus_width /= 2; ++ } ++ + old_crtc_state = drm_atomic_get_old_crtc_state(state, conn_state->crtc); + if (old_crtc_state && !crtc_state->mode_changed) { + old_state = to_rockchip_crtc_state(old_crtc_state); +@@ -405,6 +422,7 @@ static u32 *dw_hdmi_rockchip_get_input_bus_fmts(struct drm_bridge *bridge, + { + struct rockchip_hdmi *hdmi = to_rockchip_hdmi(bridge); + struct drm_encoder *encoder = bridge->encoder; ++ struct drm_connector *connector = conn_state->connector; + u32 *input_fmt; + bool has_10bit = true; + +@@ -419,6 +437,9 @@ static u32 *dw_hdmi_rockchip_get_input_bus_fmts(struct drm_bridge *bridge, + if (is_yuv444(output_fmt)) { + if (!hdmi->chip_data->ycbcr_444_allowed) + return NULL; ++ } else if (is_yuv420(output_fmt)) { ++ if (!connector->ycbcr_420_allowed) ++ return NULL; + } else if (!is_rgb(output_fmt)) + return NULL; + +@@ -578,6 +599,7 @@ static const struct dw_hdmi_plat_data rk3328_hdmi_drv_data = { + .phy_name = "inno_dw_hdmi_phy2", + .phy_force_vendor = true, + .use_drm_infoframe = true, ++ .ycbcr_420_allowed = true, + }; + + static struct rockchip_hdmi_chip_data rk3399_chip_data = { +@@ -595,6 +617,7 @@ static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = { + .phy_config = rockchip_phy_config, + .phy_data = &rk3399_chip_data, + .use_drm_infoframe = true, ++ .ycbcr_420_allowed = true, + }; + + static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = { +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +index a17bd4e90ba7..5ea8031eb0f7 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +@@ -311,6 +311,19 @@ static int vop_convert_afbc_format(uint32_t format) + } + + static bool is_yuv_output(uint32_t bus_format) ++{ ++ switch (bus_format) { ++ case MEDIA_BUS_FMT_YUV8_1X24: ++ case MEDIA_BUS_FMT_YUV10_1X30: ++ case MEDIA_BUS_FMT_UYYVYY8_0_5X24: ++ case MEDIA_BUS_FMT_UYYVYY10_0_5X30: ++ return true; ++ default: ++ return false; ++ } ++} ++ ++static bool has_uv_swapped(uint32_t bus_format) + { + switch (bus_format) { + case MEDIA_BUS_FMT_YUV8_1X24: +@@ -1414,7 +1427,7 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, + !(vop_data->feature & VOP_FEATURE_OUTPUT_RGB10)) + s->output_mode = ROCKCHIP_OUT_MODE_P888; + +- VOP_REG_SET(vop, common, dsp_data_swap, yuv_output ? 2 : 0); ++ VOP_REG_SET(vop, common, dsp_data_swap, has_uv_swapped(s->bus_format) ? 2 : 0); + + if (s->output_mode == ROCKCHIP_OUT_MODE_AAAA && dither_bpc <= 8) + VOP_REG_SET(vop, common, pre_dither_down, 1); +@@ -1431,6 +1444,9 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, + + VOP_REG_SET(vop, common, out_mode, s->output_mode); + ++ VOP_REG_SET(vop, common, dclk_ddr, ++ s->output_mode == ROCKCHIP_OUT_MODE_YUV420 ? 1 : 0); ++ + VOP_REG_SET(vop, common, overlay_mode, yuv_output); + VOP_REG_SET(vop, common, dsp_out_yuv, yuv_output); + +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +index b820ad3fa091..8e6e999e5163 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +@@ -94,6 +94,7 @@ struct vop_common { + struct vop_reg standby; + + struct vop_reg overlay_mode; ++ struct vop_reg dclk_ddr; + struct vop_reg dsp_data_swap; + struct vop_reg dsp_out_yuv; + struct vop_reg dsp_background; +@@ -257,11 +258,12 @@ struct vop_data { + /* + * display output interface supported by rockchip lcdc + */ +-#define ROCKCHIP_OUT_MODE_P888 0 +-#define ROCKCHIP_OUT_MODE_P666 1 +-#define ROCKCHIP_OUT_MODE_P565 2 ++#define ROCKCHIP_OUT_MODE_P888 0 ++#define ROCKCHIP_OUT_MODE_P666 1 ++#define ROCKCHIP_OUT_MODE_P565 2 ++#define ROCKCHIP_OUT_MODE_YUV420 14 + /* for use special outface */ +-#define ROCKCHIP_OUT_MODE_AAAA 15 ++#define ROCKCHIP_OUT_MODE_AAAA 15 + + /* output flags */ + #define ROCKCHIP_OUTPUT_DSI_DUAL BIT(0) +diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +index 800b9341dd42..dd4546f9f410 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c ++++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +@@ -646,6 +646,7 @@ static const struct vop_common rk3288_common = { + .cfg_done = VOP_REG_SYNC(RK3288_REG_CFG_DONE, 0x1, 0), + + .overlay_mode = VOP_REG(RK3288_SYS_CTRL, 0x1, 16), ++ .dclk_ddr = VOP_REG(RK3288_DSP_CTRL0, 0x1, 8), + .dsp_data_swap = VOP_REG(RK3288_DSP_CTRL0, 0x1f, 12), + .dsp_out_yuv = VOP_REG(RK3288_POST_SCL_CTRL, 0x1, 2), + .dsp_background = VOP_REG(RK3288_DSP_BG, 0xffffffff, 0), +@@ -1019,6 +1020,7 @@ static const struct vop_common rk3328_common = { + .cfg_done = VOP_REG_SYNC(RK3328_REG_CFG_DONE, 0x1, 0), + + .overlay_mode = VOP_REG(RK3328_SYS_CTRL, 0x1, 16), ++ .dclk_ddr = VOP_REG(RK3328_DSP_CTRL0, 0x1, 8), + .dsp_data_swap = VOP_REG(RK3328_DSP_CTRL0, 0x1f, 12), + .dsp_out_yuv = VOP_REG(RK3328_POST_SCL_CTRL, 0x1, 2), + .dsp_background = VOP_REG(RK3328_DSP_BG, 0xffffffff, 0), + +From 1b47a0a13f295cff2a50f6b4af272b7ee1f01534 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 7 Jun 2020 20:25:25 +0000 +Subject: [PATCH] drm: drm_fourcc: add NV20 and NV30 YUV formats + +DRM_FORMAT_NV20 and DRM_FORMAT_NV30 formats is the 2x1 and non-subsampled +variant of NV15, a 10-bit 2-plane YUV format that has no padding between +components. Instead, luminance and chrominance samples are grouped into 4s +so that each group is packed into an integer number of bytes: + +YYYY = UVUV = 4 * 10 bits = 40 bits = 5 bytes + +The '20' and '30' suffix refers to the optimum effective bits per pixel +which is achieved when the total number of luminance samples is a multiple +of 4. + +V2: Added NV30 format + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/drm_fourcc.c | 8 ++++++++ + include/uapi/drm/drm_fourcc.h | 2 ++ + 2 files changed, 10 insertions(+) + +diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c +index 722c7ebe4e88..2daf8a304b53 100644 +--- a/drivers/gpu/drm/drm_fourcc.c ++++ b/drivers/gpu/drm/drm_fourcc.c +@@ -278,6 +278,14 @@ const struct drm_format_info *__drm_format_info(u32 format) + .num_planes = 2, .char_per_block = { 5, 5, 0 }, + .block_w = { 4, 2, 0 }, .block_h = { 1, 1, 0 }, .hsub = 2, + .vsub = 2, .is_yuv = true }, ++ { .format = DRM_FORMAT_NV20, .depth = 0, ++ .num_planes = 2, .char_per_block = { 5, 5, 0 }, ++ .block_w = { 4, 2, 0 }, .block_h = { 1, 1, 0 }, .hsub = 2, ++ .vsub = 1, .is_yuv = true }, ++ { .format = DRM_FORMAT_NV30, .depth = 0, ++ .num_planes = 2, .char_per_block = { 5, 5, 0 }, ++ .block_w = { 4, 2, 0 }, .block_h = { 1, 1, 0 }, .hsub = 1, ++ .vsub = 1, .is_yuv = true }, + { .format = DRM_FORMAT_Q410, .depth = 0, + .num_planes = 3, .char_per_block = { 2, 2, 2 }, + .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 }, .hsub = 0, +diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h +index 82f327801267..d8e6159213dc 100644 +--- a/include/uapi/drm/drm_fourcc.h ++++ b/include/uapi/drm/drm_fourcc.h +@@ -242,6 +242,8 @@ extern "C" { + * index 1 = Cr:Cb plane, [39:0] Cr1:Cb1:Cr0:Cb0 little endian + */ + #define DRM_FORMAT_NV15 fourcc_code('N', 'V', '1', '5') /* 2x2 subsampled Cr:Cb plane */ ++#define DRM_FORMAT_NV20 fourcc_code('N', 'V', '2', '0') /* 2x1 subsampled Cr:Cb plane */ ++#define DRM_FORMAT_NV30 fourcc_code('N', 'V', '3', '0') /* non-subsampled Cr:Cb plane */ + + /* + * 2 plane YCbCr MSB aligned + +From 6c52f23c9f8215a7a5a99d6ac299701baa85a8cb Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 7 Jun 2020 20:25:26 +0000 +Subject: [PATCH] drm: rockchip: add NV15, NV20 and NV30 support + +Add support for displaying 10-bit 4:2:0 and 4:2:2 formats produced by the +Rockchip Video Decoder on RK322X, RK3288, RK3328, RK3368 and RK3399. +Also add support for 10-bit 4:4:4 format while at it. + +V2: Added NV30 support + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 29 +++++++++++++++++-- + drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 1 + + drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 32 +++++++++++++++++---- + 3 files changed, 54 insertions(+), 8 deletions(-) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +index 5ea8031eb0f7..413534cf1a93 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +@@ -261,6 +261,18 @@ static bool has_rb_swapped(uint32_t format) + } + } + ++static bool is_fmt_10(uint32_t format) ++{ ++ switch (format) { ++ case DRM_FORMAT_NV15: ++ case DRM_FORMAT_NV20: ++ case DRM_FORMAT_NV30: ++ return true; ++ default: ++ return false; ++ } ++} ++ + static enum vop_data_format vop_convert_format(uint32_t format) + { + switch (format) { +@@ -276,10 +288,13 @@ static enum vop_data_format vop_convert_format(uint32_t format) + case DRM_FORMAT_BGR565: + return VOP_FMT_RGB565; + case DRM_FORMAT_NV12: ++ case DRM_FORMAT_NV15: + return VOP_FMT_YUV420SP; + case DRM_FORMAT_NV16: ++ case DRM_FORMAT_NV20: + return VOP_FMT_YUV422SP; + case DRM_FORMAT_NV24: ++ case DRM_FORMAT_NV30: + return VOP_FMT_YUV444SP; + default: + DRM_ERROR("unsupported format[%08x]\n", format); +@@ -946,7 +961,12 @@ static void vop_plane_atomic_update(struct drm_plane *plane, + dsp_sty = dest->y1 + crtc->mode.vtotal - crtc->mode.vsync_start; + dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff); + +- offset = (src->x1 >> 16) * fb->format->cpp[0]; ++ if (fb->format->block_w[0]) ++ offset = (src->x1 >> 16) * fb->format->char_per_block[0] / ++ fb->format->block_w[0]; ++ else ++ offset = (src->x1 >> 16) * fb->format->cpp[0]; ++ + offset += (src->y1 >> 16) * fb->pitches[0]; + dma_addr = rk_obj->dma_addr + offset + fb->offsets[0]; + +@@ -972,6 +992,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane, + } + + VOP_WIN_SET(vop, win, format, format); ++ VOP_WIN_SET(vop, win, fmt_10, is_fmt_10(fb->format->format)); + VOP_WIN_SET(vop, win, yrgb_vir, DIV_ROUND_UP(fb->pitches[0], 4)); + VOP_WIN_SET(vop, win, yrgb_mst, dma_addr); + VOP_WIN_YUV2YUV_SET(vop, win_yuv2yuv, y2r_en, is_yuv); +@@ -988,7 +1009,11 @@ static void vop_plane_atomic_update(struct drm_plane *plane, + uv_obj = fb->obj[1]; + rk_uv_obj = to_rockchip_obj(uv_obj); + +- offset = (src->x1 >> 16) * bpp / hsub; ++ if (fb->format->block_w[1]) ++ offset = (src->x1 >> 16) * bpp / ++ fb->format->block_w[1] / hsub; ++ else ++ offset = (src->x1 >> 16) * bpp / hsub; + offset += (src->y1 >> 16) * fb->pitches[1] / vsub; + + dma_addr = rk_uv_obj->dma_addr + offset + fb->offsets[1]; +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +index 8e6e999e5163..9f50e0e00127 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +@@ -161,6 +161,7 @@ struct vop_win_phy { + struct vop_reg enable; + struct vop_reg gate; + struct vop_reg format; ++ struct vop_reg fmt_10; + struct vop_reg rb_swap; + struct vop_reg act_info; + struct vop_reg dsp_info; +diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +index dd4546f9f410..7d5191421ddf 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c ++++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +@@ -50,6 +50,23 @@ static const uint32_t formats_win_full[] = { + DRM_FORMAT_NV24, + }; + ++static const uint32_t formats_win_full_10[] = { ++ DRM_FORMAT_XRGB8888, ++ DRM_FORMAT_ARGB8888, ++ DRM_FORMAT_XBGR8888, ++ DRM_FORMAT_ABGR8888, ++ DRM_FORMAT_RGB888, ++ DRM_FORMAT_BGR888, ++ DRM_FORMAT_RGB565, ++ DRM_FORMAT_BGR565, ++ DRM_FORMAT_NV12, ++ DRM_FORMAT_NV16, ++ DRM_FORMAT_NV24, ++ DRM_FORMAT_NV15, ++ DRM_FORMAT_NV20, ++ DRM_FORMAT_NV30, ++}; ++ + static const uint64_t format_modifiers_win_full[] = { + DRM_FORMAT_MOD_LINEAR, + DRM_FORMAT_MOD_INVALID, +@@ -579,11 +596,12 @@ static const struct vop_scl_regs rk3288_win_full_scl = { + + static const struct vop_win_phy rk3288_win01_data = { + .scl = &rk3288_win_full_scl, +- .data_formats = formats_win_full, +- .nformats = ARRAY_SIZE(formats_win_full), ++ .data_formats = formats_win_full_10, ++ .nformats = ARRAY_SIZE(formats_win_full_10), + .format_modifiers = format_modifiers_win_full, + .enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0), + .format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1), ++ .fmt_10 = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 4), + .rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12), + .act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0), + .dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0), +@@ -720,11 +738,12 @@ static const struct vop_intr rk3368_vop_intr = { + + static const struct vop_win_phy rk3368_win01_data = { + .scl = &rk3288_win_full_scl, +- .data_formats = formats_win_full, +- .nformats = ARRAY_SIZE(formats_win_full), ++ .data_formats = formats_win_full_10, ++ .nformats = ARRAY_SIZE(formats_win_full_10), + .format_modifiers = format_modifiers_win_full, + .enable = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 0), + .format = VOP_REG(RK3368_WIN0_CTRL0, 0x7, 1), ++ .fmt_10 = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 4), + .rb_swap = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 12), + .x_mir_en = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 21), + .y_mir_en = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 22), +@@ -871,11 +890,12 @@ static const struct vop_win_yuv2yuv_data rk3399_vop_big_win_yuv2yuv_data[] = { + + static const struct vop_win_phy rk3399_win01_data = { + .scl = &rk3288_win_full_scl, +- .data_formats = formats_win_full, +- .nformats = ARRAY_SIZE(formats_win_full), ++ .data_formats = formats_win_full_10, ++ .nformats = ARRAY_SIZE(formats_win_full_10), + .format_modifiers = format_modifiers_win_full_afbc, + .enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0), + .format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1), ++ .fmt_10 = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 4), + .rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12), + .y_mir_en = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 22), + .act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0), + +From 82b749d252ad0a50a36ad7ca93335e8d8e5416b7 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sat, 15 Aug 2020 21:11:08 +0200 +Subject: [PATCH] drm/rockchip: rk3368's vop does not support 10-bit formats - + neither as input nor as output + +--- + drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +index 7d5191421ddf..20c3e6248ec7 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c ++++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +@@ -738,8 +738,8 @@ static const struct vop_intr rk3368_vop_intr = { + + static const struct vop_win_phy rk3368_win01_data = { + .scl = &rk3288_win_full_scl, +- .data_formats = formats_win_full_10, +- .nformats = ARRAY_SIZE(formats_win_full_10), ++ .data_formats = formats_win_full, ++ .nformats = ARRAY_SIZE(formats_win_full), + .format_modifiers = format_modifiers_win_full, + .enable = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 0), + .format = VOP_REG(RK3368_WIN0_CTRL0, 0x7, 1), + +From 74b287a1526a234bd9450461087f7b3ae53ead5f Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sat, 15 Aug 2020 23:20:34 +0200 +Subject: [PATCH] drm/rockchip: enable ycbcr_420_allowed and ycbcr_444_allowed + for RK3228 + +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index 1abc46a023a4..64a79b33ff18 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -555,6 +555,7 @@ static const struct dw_hdmi_phy_ops rk3228_hdmi_phy_ops = { + + static struct rockchip_hdmi_chip_data rk3228_chip_data = { + .lcdsel_grf_reg = -1, ++ .ycbcr_444_allowed = true, + }; + + static const struct dw_hdmi_plat_data rk3228_hdmi_drv_data = { +@@ -563,6 +564,7 @@ static const struct dw_hdmi_plat_data rk3228_hdmi_drv_data = { + .phy_ops = &rk3228_hdmi_phy_ops, + .phy_name = "inno_dw_hdmi_phy2", + .phy_force_vendor = true, ++ .ycbcr_420_allowed = true, + }; + + static struct rockchip_hdmi_chip_data rk3288_chip_data = { + +From 93f930ae209a684210098a2612df72b19b8db88a Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Wed, 22 Jul 2020 20:13:28 +0200 +Subject: [PATCH] drm: rockchip: add scaling for RK3036 win1 + +Add the registers needed to make scaling work on RK3036's win1. + +Signed-off-by: Alex Bee +--- + drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +index 20c3e6248ec7..93a00b6ac295 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c ++++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +@@ -94,15 +94,20 @@ static const uint64_t format_modifiers_win_lite[] = { + DRM_FORMAT_MOD_INVALID, + }; + +-static const struct vop_scl_regs rk3036_win_scl = { ++static const struct vop_scl_regs rk3036_win0_scl = { + .scale_yrgb_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0), + .scale_yrgb_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 16), + .scale_cbcr_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0), + .scale_cbcr_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 16), + }; + ++static const struct vop_scl_regs rk3036_win1_scl = { ++ .scale_yrgb_x = VOP_REG(RK3036_WIN1_SCL_FACTOR_YRGB, 0xffff, 0x0), ++ .scale_yrgb_y = VOP_REG(RK3036_WIN1_SCL_FACTOR_YRGB, 0xffff, 16), ++}; ++ + static const struct vop_win_phy rk3036_win0_data = { +- .scl = &rk3036_win_scl, ++ .scl = &rk3036_win0_scl, + .data_formats = formats_win_full, + .nformats = ARRAY_SIZE(formats_win_full), + .format_modifiers = format_modifiers_win_full, +@@ -119,6 +124,7 @@ static const struct vop_win_phy rk3036_win0_data = { + }; + + static const struct vop_win_phy rk3036_win1_data = { ++ .scl = &rk3036_win1_scl, + .data_formats = formats_win_lite, + .nformats = ARRAY_SIZE(formats_win_lite), + .format_modifiers = format_modifiers_win_lite, + +From 5251b3cefd51bbf0c28da354b8e59e4f540d4b94 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Wed, 22 Jul 2020 20:13:29 +0200 +Subject: [PATCH] drm: rockchip: add missing registers for RK3188 + +Add dither_up, dsp_lut_en and data_blank registers to enable their +respective functionality for RK3188's VOP. + +Signed-off-by: Alex Bee +--- + drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +index 93a00b6ac295..2638d084f9ce 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c ++++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +@@ -529,6 +529,9 @@ static const struct vop_common rk3188_common = { + .dither_down_en = VOP_REG(RK3188_DSP_CTRL0, 0x1, 11), + .dither_down_mode = VOP_REG(RK3188_DSP_CTRL0, 0x1, 10), + .dsp_blank = VOP_REG(RK3188_DSP_CTRL1, 0x3, 24), ++ .dither_up = VOP_REG(RK3188_DSP_CTRL0, 0x1, 9), ++ .dsp_lut_en = VOP_REG(RK3188_SYS_CTRL, 0x1, 28), ++ .data_blank = VOP_REG(RK3188_DSP_CTRL1, 0x1, 25), + }; + + static const struct vop_win_data rk3188_vop_win_data[] = { + +From cb6d552767e2ce4b79be85cdb3a1526869d11ce4 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Wed, 22 Jul 2020 20:13:30 +0200 +Subject: [PATCH] drm: rockchip: add alpha support for RK3036, RK3066, RK3126 + and RK3188 + +With commit 2aae8ed1f390 +("drm/rockchip: Add per-pixel alpha support for the PX30 VOP") alpha +support was introduced for PX30's VOP. +RK3036, RK3066, RK3126 and RK3188 VOPs support alpha blending in the +same manner. +With the exception of RK3066 all of them support pre-multiplied alpha. + +Lets add these registers to make this work for those VOPs as well. + +Signed-off-by: Alex Bee +--- + drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 21 +++++++++++++++++++++ + drivers/gpu/drm/rockchip/rockchip_vop_reg.h | 1 + + 2 files changed, 22 insertions(+) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +index 2638d084f9ce..e1db4e57c51a 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c ++++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +@@ -121,6 +121,9 @@ static const struct vop_win_phy rk3036_win0_data = { + .uv_mst = VOP_REG(RK3036_WIN0_CBR_MST, 0xffffffff, 0), + .yrgb_vir = VOP_REG(RK3036_WIN0_VIR, 0xffff, 0), + .uv_vir = VOP_REG(RK3036_WIN0_VIR, 0x1fff, 16), ++ .alpha_mode = VOP_REG(RK3036_DSP_CTRL0, 0x1, 18), ++ .alpha_en = VOP_REG(RK3036_ALPHA_CTRL, 0x1, 0), ++ .alpha_pre_mul = VOP_REG(RK3036_DSP_CTRL0, 0x1, 29), + }; + + static const struct vop_win_phy rk3036_win1_data = { +@@ -136,6 +139,9 @@ static const struct vop_win_phy rk3036_win1_data = { + .dsp_st = VOP_REG(RK3036_WIN1_DSP_ST, 0x1fff1fff, 0), + .yrgb_mst = VOP_REG(RK3036_WIN1_MST, 0xffffffff, 0), + .yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0), ++ .alpha_mode = VOP_REG(RK3036_DSP_CTRL0, 0x1, 19), ++ .alpha_en = VOP_REG(RK3036_ALPHA_CTRL, 0x1, 1), ++ .alpha_pre_mul = VOP_REG(RK3036_DSP_CTRL0, 0x1, 29), + }; + + static const struct vop_win_data rk3036_vop_win_data[] = { +@@ -202,6 +208,9 @@ static const struct vop_win_phy rk3126_win1_data = { + .dsp_st = VOP_REG(RK3126_WIN1_DSP_ST, 0x1fff1fff, 0), + .yrgb_mst = VOP_REG(RK3126_WIN1_MST, 0xffffffff, 0), + .yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0), ++ .alpha_mode = VOP_REG(RK3036_DSP_CTRL0, 0x1, 19), ++ .alpha_en = VOP_REG(RK3036_ALPHA_CTRL, 0x1, 1), ++ .alpha_pre_mul = VOP_REG(RK3036_DSP_CTRL0, 0x1, 29), + }; + + static const struct vop_win_data rk3126_vop_win_data[] = { +@@ -381,6 +390,8 @@ static const struct vop_win_phy rk3066_win0_data = { + .uv_mst = VOP_REG(RK3066_WIN0_CBR_MST0, 0xffffffff, 0), + .yrgb_vir = VOP_REG(RK3066_WIN0_VIR, 0xffff, 0), + .uv_vir = VOP_REG(RK3066_WIN0_VIR, 0x1fff, 16), ++ .alpha_mode = VOP_REG(RK3066_DSP_CTRL0, 0x1, 21), ++ .alpha_en = VOP_REG(RK3066_BLEND_CTRL, 0x1, 0), + }; + + static const struct vop_win_phy rk3066_win1_data = { +@@ -398,6 +409,8 @@ static const struct vop_win_phy rk3066_win1_data = { + .uv_mst = VOP_REG(RK3066_WIN1_CBR_MST, 0xffffffff, 0), + .yrgb_vir = VOP_REG(RK3066_WIN1_VIR, 0xffff, 0), + .uv_vir = VOP_REG(RK3066_WIN1_VIR, 0x1fff, 16), ++ .alpha_mode = VOP_REG(RK3066_DSP_CTRL0, 0x1, 22), ++ .alpha_en = VOP_REG(RK3066_BLEND_CTRL, 0x1, 1), + }; + + static const struct vop_win_phy rk3066_win2_data = { +@@ -411,6 +424,8 @@ static const struct vop_win_phy rk3066_win2_data = { + .dsp_st = VOP_REG(RK3066_WIN2_DSP_ST, 0x1fff1fff, 0), + .yrgb_mst = VOP_REG(RK3066_WIN2_MST, 0xffffffff, 0), + .yrgb_vir = VOP_REG(RK3066_WIN2_VIR, 0xffff, 0), ++ .alpha_mode = VOP_REG(RK3066_DSP_CTRL0, 0x1, 23), ++ .alpha_en = VOP_REG(RK3066_BLEND_CTRL, 0x1, 2), + }; + + static const struct vop_modeset rk3066_modeset = { +@@ -493,6 +508,9 @@ static const struct vop_win_phy rk3188_win0_data = { + .yrgb_mst = VOP_REG(RK3188_WIN0_YRGB_MST0, 0xffffffff, 0), + .uv_mst = VOP_REG(RK3188_WIN0_CBR_MST0, 0xffffffff, 0), + .yrgb_vir = VOP_REG(RK3188_WIN_VIR, 0x1fff, 0), ++ .alpha_mode = VOP_REG(RK3188_DSP_CTRL0, 0x1, 18), ++ .alpha_en = VOP_REG(RK3188_ALPHA_CTRL, 0x1, 0), ++ .alpha_pre_mul = VOP_REG(RK3188_DSP_CTRL0, 0x1, 29), + }; + + static const struct vop_win_phy rk3188_win1_data = { +@@ -507,6 +525,9 @@ static const struct vop_win_phy rk3188_win1_data = { + .dsp_st = VOP_REG(RK3188_WIN1_DSP_ST, 0x0fff0fff, 0), + .yrgb_mst = VOP_REG(RK3188_WIN1_MST, 0xffffffff, 0), + .yrgb_vir = VOP_REG(RK3188_WIN_VIR, 0x1fff, 16), ++ .alpha_mode = VOP_REG(RK3188_DSP_CTRL0, 0x1, 19), ++ .alpha_en = VOP_REG(RK3188_ALPHA_CTRL, 0x1, 1), ++ .alpha_pre_mul = VOP_REG(RK3188_DSP_CTRL0, 0x1, 29), + }; + + static const struct vop_modeset rk3188_modeset = { +diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h +index 6e9fa5815d4d..0b3cd65ba5c1 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h ++++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h +@@ -955,6 +955,7 @@ + #define RK3188_DSP_CTRL0 0x04 + #define RK3188_DSP_CTRL1 0x08 + #define RK3188_INT_STATUS 0x10 ++#define RK3188_ALPHA_CTRL 0x14 + #define RK3188_WIN0_YRGB_MST0 0x20 + #define RK3188_WIN0_CBR_MST0 0x24 + #define RK3188_WIN0_YRGB_MST1 0x28 + +From 931fd5e26f3b2dd7a758124dc9c024e944eeedb4 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Wed, 22 Jul 2020 20:13:31 +0200 +Subject: [PATCH] drm: rockchip: set alpha_en to 0 if it is not used + +alpha_en should be set to 0 if it is not used, i.e. to disable alpha +blending if it was enabled before and should be disabled now. + +Fixes: 2aae8ed1f390 ("drm/rockchip: Add per-pixel alpha support for the PX30 VOP") + +Signed-off-by: Alex Bee +--- + drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +index 413534cf1a93..9b1cc0f413fc 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +@@ -1062,6 +1062,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane, + VOP_WIN_SET(vop, win, alpha_en, 1); + } else { + VOP_WIN_SET(vop, win, src_alpha_ctl, SRC_ALPHA_EN(0)); ++ VOP_WIN_SET(vop, win, alpha_en, 0); + } + + VOP_WIN_SET(vop, win, enable, 1); + +From 87f111b8511eb1236c53ea4369502cf4c6847303 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sat, 15 Aug 2020 23:38:05 +0200 +Subject: [PATCH] rockchip/drm: add dsp_data_swap register for RK3188 + +--- + drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +index e1db4e57c51a..e10cb2d33951 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c ++++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +@@ -553,6 +553,7 @@ static const struct vop_common rk3188_common = { + .dither_up = VOP_REG(RK3188_DSP_CTRL0, 0x1, 9), + .dsp_lut_en = VOP_REG(RK3188_SYS_CTRL, 0x1, 28), + .data_blank = VOP_REG(RK3188_DSP_CTRL1, 0x1, 25), ++ .dsp_data_swap = VOP_REG(RK3188_DSP_CTRL1, 0x1f, 26), + }; + + static const struct vop_win_data rk3188_vop_win_data[] = { + +From 75e43e951351c5f0d269d7b788a9469a1ccadb48 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sun, 16 Aug 2020 00:55:19 +0200 +Subject: [PATCH] drm/rockchip: inno hdmi - add audio support - add required + aclk - fix video timing - fix phy pre-emphasis + +--- + .../display/rockchip/inno_hdmi-rockchip.txt | 6 +- + arch/arm/boot/dts/rk3036.dtsi | 24 +- + drivers/gpu/drm/rockchip/inno_hdmi.c | 266 +++++++++++++++++- + drivers/gpu/drm/rockchip/inno_hdmi.h | 2 + + 4 files changed, 279 insertions(+), 19 deletions(-) + +diff --git a/Documentation/devicetree/bindings/display/rockchip/inno_hdmi-rockchip.txt b/Documentation/devicetree/bindings/display/rockchip/inno_hdmi-rockchip.txt +index cec21714f0e0..b022c931e186 100644 +--- a/Documentation/devicetree/bindings/display/rockchip/inno_hdmi-rockchip.txt ++++ b/Documentation/devicetree/bindings/display/rockchip/inno_hdmi-rockchip.txt +@@ -7,7 +7,7 @@ Required properties: + - reg: + Physical base address and length of the controller's registers. + - clocks, clock-names: +- Phandle to hdmi controller clock, name should be "pclk" ++ Phandle to hdmi controller clock, name should be "aclk" and "pclk". + - interrupts: + HDMI interrupt number + - ports: +@@ -21,8 +21,8 @@ hdmi: hdmi@20034000 { + compatible = "rockchip,rk3036-inno-hdmi"; + reg = <0x20034000 0x4000>; + interrupts = ; +- clocks = <&cru PCLK_HDMI>; +- clock-names = "pclk"; ++ clocks = <&cru ACLK_VIO>, <&cru PCLK_HDMI>; ++ clock-names = "aclk", "pclk"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmi_ctl>; + +diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi +index dda5a1f79aca..6be6d9d134fe 100644 +--- a/arch/arm/boot/dts/rk3036.dtsi ++++ b/arch/arm/boot/dts/rk3036.dtsi +@@ -344,11 +344,14 @@ hdmi: hdmi@20034000 { + compatible = "rockchip,rk3036-inno-hdmi"; + reg = <0x20034000 0x4000>; + interrupts = ; +- clocks = <&cru PCLK_HDMI>; +- clock-names = "pclk"; ++ clocks = <&cru ACLK_VIO>, <&cru PCLK_HDMI>; ++ clock-names = "aclk", "pclk"; + rockchip,grf = <&grf>; + pinctrl-names = "default"; + pinctrl-0 = <&hdmi_ctl>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ #sound-dai-cells = <0>; + status = "disabled"; + + hdmi_in: port { +@@ -361,6 +364,23 @@ hdmi_in_vop: endpoint@0 { + }; + }; + ++ hdmi_sound: hdmi-sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,name = "HDMI"; ++ status = "disabled"; ++ ++ simple-audio-card,dai-link { ++ format = "i2s"; ++ mclk-fs = <256>; ++ cpu { ++ sound-dai = <&i2s>; ++ }; ++ codec { ++ sound-dai = <&hdmi>; ++ }; ++ }; ++ }; ++ + timer: timer@20044000 { + compatible = "rockchip,rk3036-timer", "rockchip,rk3288-timer"; + reg = <0x20044000 0x20>; +diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c +index 7afdc54eb3ec..7e93208609a0 100644 +--- a/drivers/gpu/drm/rockchip/inno_hdmi.c ++++ b/drivers/gpu/drm/rockchip/inno_hdmi.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -21,6 +22,8 @@ + #include + #include + ++#include ++ + #include "rockchip_drm_drv.h" + #include "rockchip_drm_vop.h" + +@@ -28,6 +31,12 @@ + + #define to_inno_hdmi(x) container_of(x, struct inno_hdmi, x) + ++struct audio_info { ++ int sample_rate; ++ int channels; ++ int sample_width; ++}; ++ + struct hdmi_data_info { + int vic; + bool sink_is_hdmi; +@@ -52,8 +61,10 @@ struct inno_hdmi { + struct drm_device *drm_dev; + + int irq; ++ struct clk *aclk; + struct clk *pclk; + void __iomem *regs; ++ struct regmap *regmap; + + struct drm_connector connector; + struct drm_encoder encoder; +@@ -63,6 +74,9 @@ struct inno_hdmi { + + unsigned int tmds_rate; + ++ struct platform_device *audio_pdev; ++ bool audio_enable; ++ + struct hdmi_data_info hdmi_data; + struct drm_display_mode previous_mode; + }; +@@ -189,11 +203,17 @@ static void inno_hdmi_sys_power(struct inno_hdmi *hdmi, bool enable) + + static void inno_hdmi_set_pwr_mode(struct inno_hdmi *hdmi, int mode) + { ++ ++ u8 value; ++ + switch (mode) { + case NORMAL: + inno_hdmi_sys_power(hdmi, false); +- +- hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, 0x6f); ++ if (hdmi->tmds_rate > 140000000) ++ value = 0x6f; ++ else ++ value = 0x3f; ++ hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, value); + hdmi_writeb(hdmi, HDMI_PHY_DRIVER, 0xbb); + + hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15); +@@ -301,6 +321,21 @@ static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi, + return inno_hdmi_upload_frame(hdmi, rc, &frame, INFOFRAME_AVI, 0, 0, 0); + } + ++static int inno_hdmi_config_audio_aai(struct inno_hdmi *hdmi, ++ struct audio_info *audio) ++{ ++ struct hdmi_audio_infoframe *faudio; ++ union hdmi_infoframe frame; ++ int rc; ++ ++ rc = hdmi_audio_infoframe_init(&frame.audio); ++ faudio = (struct hdmi_audio_infoframe *)&frame; ++ ++ faudio->channels = audio->channels; ++ ++ return inno_hdmi_upload_frame(hdmi, rc, &frame, INFOFRAME_AAI, 0, 0, 0); ++} ++ + static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi) + { + struct hdmi_data_info *data = &hdmi->hdmi_data; +@@ -383,6 +418,11 @@ static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi, + { + int value; + ++ value = BIT(20) | BIT(21); ++ value |= mode->flags & DRM_MODE_FLAG_PHSYNC ? BIT(4) : 0; ++ value |= mode->flags & DRM_MODE_FLAG_PVSYNC ? BIT(5) : 0; ++ regmap_write(hdmi->regmap, 0x148, value); ++ + /* Set detail external video timing polarity and interlace mode */ + value = v_EXTERANL_VIDEO(1); + value |= mode->flags & DRM_MODE_FLAG_PHSYNC ? +@@ -402,7 +442,7 @@ static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi, + hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_L, value & 0xFF); + hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_H, (value >> 8) & 0xFF); + +- value = mode->hsync_start - mode->hdisplay; ++ value = mode->htotal - mode->hsync_start; + hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_L, value & 0xFF); + hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_H, (value >> 8) & 0xFF); + +@@ -417,7 +457,7 @@ static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi, + value = mode->vtotal - mode->vdisplay; + hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VBLANK, value & 0xFF); + +- value = mode->vsync_start - mode->vdisplay; ++ value = mode->vtotal - mode->vsync_start; + hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VDELAY, value & 0xFF); + + value = mode->vsync_end - mode->vsync_start; +@@ -473,8 +513,9 @@ static int inno_hdmi_setup(struct inno_hdmi *hdmi, + inno_hdmi_i2c_init(hdmi); + + /* Unmute video and audio output */ +- hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK, +- v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0)); ++ hdmi_modb(hdmi, HDMI_AV_MUTE, m_VIDEO_BLACK, v_VIDEO_MUTE(0)); ++ if (hdmi->audio_enable) ++ hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE, v_AUDIO_MUTE(0)); + + return 0; + } +@@ -521,6 +562,7 @@ inno_hdmi_encoder_atomic_check(struct drm_encoder *encoder, + + s->output_mode = ROCKCHIP_OUT_MODE_P888; + s->output_type = DRM_MODE_CONNECTOR_HDMIA; ++ s->bus_format = MEDIA_BUS_FMT_RGB888_1X24; + + return 0; + } +@@ -597,6 +639,175 @@ static struct drm_connector_helper_funcs inno_hdmi_connector_helper_funcs = { + .mode_valid = inno_hdmi_connector_mode_valid, + }; + ++int inno_hdmi_audio_config_set(struct inno_hdmi *hdmi, struct audio_info *audio) ++{ ++ int rate, N, channel; ++ ++ if (audio->channels < 3) ++ channel = I2S_CHANNEL_1_2; ++ else if (audio->channels < 5) ++ channel = I2S_CHANNEL_3_4; ++ else if (audio->channels < 7) ++ channel = I2S_CHANNEL_5_6; ++ else ++ channel = I2S_CHANNEL_7_8; ++ ++ switch (audio->sample_rate) { ++ case 32000: ++ rate = AUDIO_32K; ++ N = N_32K; ++ break; ++ case 44100: ++ rate = AUDIO_441K; ++ N = N_441K; ++ break; ++ case 48000: ++ rate = AUDIO_48K; ++ N = N_48K; ++ break; ++ case 88200: ++ rate = AUDIO_882K; ++ N = N_882K; ++ break; ++ case 96000: ++ rate = AUDIO_96K; ++ N = N_96K; ++ break; ++ case 176400: ++ rate = AUDIO_1764K; ++ N = N_1764K; ++ break; ++ case 192000: ++ rate = AUDIO_192K; ++ N = N_192K; ++ break; ++ default: ++ dev_err(hdmi->dev, "[%s] not support such sample rate %d\n", ++ __func__, audio->sample_rate); ++ return -ENOENT; ++ } ++ ++ /* set_audio source I2S */ ++ hdmi_writeb(hdmi, HDMI_AUDIO_CTRL1, 0x01); ++ hdmi_writeb(hdmi, AUDIO_SAMPLE_RATE, rate); ++ hdmi_writeb(hdmi, AUDIO_I2S_MODE, v_I2S_MODE(I2S_STANDARD) | ++ v_I2S_CHANNEL(channel)); ++ ++ hdmi_writeb(hdmi, AUDIO_I2S_MAP, 0x00); ++ hdmi_writeb(hdmi, AUDIO_I2S_SWAPS_SPDIF, 0); ++ ++ /* Set N value */ ++ hdmi_writeb(hdmi, AUDIO_N_H, (N >> 16) & 0x0F); ++ hdmi_writeb(hdmi, AUDIO_N_M, (N >> 8) & 0xFF); ++ hdmi_writeb(hdmi, AUDIO_N_L, N & 0xFF); ++ ++ /*Set hdmi nlpcm mode to support hdmi bitstream*/ ++ hdmi_writeb(hdmi, HDMI_AUDIO_CHANNEL_STATUS, v_AUDIO_STATUS_NLPCM(0)); ++ ++ return inno_hdmi_config_audio_aai(hdmi, audio); ++} ++ ++static int inno_hdmi_audio_hw_params(struct device *dev, void *data, ++ struct hdmi_codec_daifmt *daifmt, ++ struct hdmi_codec_params *params) ++{ ++ struct inno_hdmi *hdmi = dev_get_drvdata(dev); ++ struct audio_info audio = { ++ .sample_width = params->sample_width, ++ .sample_rate = params->sample_rate, ++ .channels = params->channels, ++ }; ++ ++ if (!hdmi->hdmi_data.sink_has_audio) { ++ dev_err(hdmi->dev, "Sink do not support audio!\n"); ++ return -ENODEV; ++ } ++ ++ if (!hdmi->encoder.crtc) ++ return -ENODEV; ++ ++ switch (daifmt->fmt) { ++ case HDMI_I2S: ++ break; ++ default: ++ dev_err(dev, "%s: Invalid format %d\n", __func__, daifmt->fmt); ++ return -EINVAL; ++ } ++ ++ return inno_hdmi_audio_config_set(hdmi, &audio); ++} ++ ++static void inno_hdmi_audio_shutdown(struct device *dev, void *data) ++{ ++ /* do nothing */ ++} ++ ++static int inno_hdmi_audio_digital_mute(struct device *dev, void *data, bool mute) ++{ ++ struct inno_hdmi *hdmi = dev_get_drvdata(dev); ++ ++ if (!hdmi->hdmi_data.sink_has_audio) { ++ dev_err(hdmi->dev, "Sink do not support audio!\n"); ++ return -ENODEV; ++ } ++ ++ hdmi->audio_enable = !mute; ++ ++ if (mute) ++ hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_AUDIO_PD, ++ v_AUDIO_MUTE(1) | v_AUDIO_PD(1)); ++ else ++ hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_AUDIO_PD, ++ v_AUDIO_MUTE(0) | v_AUDIO_PD(0)); ++ ++ return 0; ++} ++ ++static int inno_hdmi_audio_get_eld(struct device *dev, void *data, ++ uint8_t *buf, size_t len) ++{ ++ struct inno_hdmi *hdmi = dev_get_drvdata(dev); ++ struct drm_mode_config *config = &hdmi->encoder.dev->mode_config; ++ struct drm_connector *connector; ++ int ret = -ENODEV; ++ ++ mutex_lock(&config->mutex); ++ list_for_each_entry(connector, &config->connector_list, head) { ++ if (&hdmi->encoder == connector->encoder) { ++ memcpy(buf, connector->eld, ++ min(sizeof(connector->eld), len)); ++ ret = 0; ++ } ++ } ++ mutex_unlock(&config->mutex); ++ ++ return ret; ++} ++ ++static const struct hdmi_codec_ops audio_codec_ops = { ++ .hw_params = inno_hdmi_audio_hw_params, ++ .audio_shutdown = inno_hdmi_audio_shutdown, ++ .digital_mute = inno_hdmi_audio_digital_mute, ++ .get_eld = inno_hdmi_audio_get_eld, ++}; ++ ++static int inno_hdmi_audio_codec_init(struct inno_hdmi *hdmi, ++ struct device *dev) ++{ ++ struct hdmi_codec_pdata codec_data = { ++ .i2s = 1, ++ .ops = &audio_codec_ops, ++ .max_i2s_channels = 8, ++ }; ++ ++ hdmi->audio_enable = false; ++ hdmi->audio_pdev = platform_device_register_data( ++ dev, HDMI_CODEC_DRV_NAME, PLATFORM_DEVID_NONE, ++ &codec_data, sizeof(codec_data)); ++ ++ return PTR_ERR_OR_ZERO(hdmi->audio_pdev); ++} ++ + static int inno_hdmi_register(struct drm_device *drm, struct inno_hdmi *hdmi) + { + struct drm_encoder *encoder = &hdmi->encoder; +@@ -627,6 +838,8 @@ static int inno_hdmi_register(struct drm_device *drm, struct inno_hdmi *hdmi) + + drm_connector_attach_encoder(&hdmi->connector, encoder); + ++ inno_hdmi_audio_codec_init(hdmi, dev); ++ + return 0; + } + +@@ -826,23 +1039,44 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, + if (IS_ERR(hdmi->regs)) + return PTR_ERR(hdmi->regs); + ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) ++ return irq; ++ ++ hdmi->aclk = devm_clk_get(hdmi->dev, "aclk"); ++ if (IS_ERR(hdmi->aclk)) { ++ dev_err(hdmi->dev, "Unable to get HDMI aclk clk\n"); ++ return PTR_ERR(hdmi->aclk); ++ } ++ + hdmi->pclk = devm_clk_get(hdmi->dev, "pclk"); + if (IS_ERR(hdmi->pclk)) { + DRM_DEV_ERROR(hdmi->dev, "Unable to get HDMI pclk clk\n"); + return PTR_ERR(hdmi->pclk); + } + ++ ret = clk_prepare_enable(hdmi->aclk); ++ if (ret) { ++ DRM_DEV_ERROR(hdmi->dev, ++ "Cannot enable HDMI aclk clock: %d\n", ret); ++ return ret; ++ } ++ ++ + ret = clk_prepare_enable(hdmi->pclk); + if (ret) { + DRM_DEV_ERROR(hdmi->dev, + "Cannot enable HDMI pclk clock: %d\n", ret); +- return ret; ++ goto err_disable_aclk; + } + +- irq = platform_get_irq(pdev, 0); +- if (irq < 0) { +- ret = irq; +- goto err_disable_clk; ++ hdmi->regmap = ++ syscon_regmap_lookup_by_phandle(hdmi->dev->of_node, ++ "rockchip,grf"); ++ if (IS_ERR(hdmi->regmap)) { ++ dev_err(hdmi->dev, "Unable to get rockchip,grf\n"); ++ ret = PTR_ERR(hdmi->regmap); ++ goto err_disable_aclk; + } + + inno_hdmi_reset(hdmi); +@@ -851,7 +1085,7 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, + if (IS_ERR(hdmi->ddc)) { + ret = PTR_ERR(hdmi->ddc); + hdmi->ddc = NULL; +- goto err_disable_clk; ++ goto err_disable_pclk; + } + + /* +@@ -884,9 +1118,12 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, + hdmi->encoder.funcs->destroy(&hdmi->encoder); + err_put_adapter: + i2c_put_adapter(hdmi->ddc); +-err_disable_clk: ++err_disable_pclk: + clk_disable_unprepare(hdmi->pclk); +- return ret; ++err_disable_aclk: ++ clk_disable_unprepare(hdmi->aclk); ++ ++return ret; + } + + static void inno_hdmi_unbind(struct device *dev, struct device *master, +@@ -899,6 +1136,7 @@ static void inno_hdmi_unbind(struct device *dev, struct device *master, + + i2c_put_adapter(hdmi->ddc); + clk_disable_unprepare(hdmi->pclk); ++ clk_disable_unprepare(hdmi->aclk); + } + + static const struct component_ops inno_hdmi_ops = { +diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.h b/drivers/gpu/drm/rockchip/inno_hdmi.h +index 93245b55f967..b722afc4e41f 100644 +--- a/drivers/gpu/drm/rockchip/inno_hdmi.h ++++ b/drivers/gpu/drm/rockchip/inno_hdmi.h +@@ -96,11 +96,13 @@ enum { + #define HDMI_AV_MUTE 0x05 + #define m_AVMUTE_CLEAR (1 << 7) + #define m_AVMUTE_ENABLE (1 << 6) ++#define m_AUDIO_PD (1 << 2) + #define m_AUDIO_MUTE (1 << 1) + #define m_VIDEO_BLACK (1 << 0) + #define v_AVMUTE_CLEAR(n) (n << 7) + #define v_AVMUTE_ENABLE(n) (n << 6) + #define v_AUDIO_MUTE(n) (n << 1) ++#define v_AUDIO_PD(n) (n << 2) + #define v_VIDEO_MUTE(n) (n << 0) + + #define HDMI_VIDEO_TIMING_CTL 0x08 + +From fd3c78e6eec709b6a70af8a175c6965d0112f372 Mon Sep 17 00:00:00 2001 +From: Phong LE +Date: Wed, 11 Mar 2020 13:51:33 +0100 +Subject: [PATCH] dt-bindings: display: bridge: add it66121 bindings + +Add the ITE bridge HDMI it66121 bindings. + +Signed-off-by: Phong LE +--- + .../bindings/display/bridge/ite,it66121.yaml | 98 +++++++++++++++++++ + 1 file changed, 98 insertions(+) + create mode 100644 Documentation/devicetree/bindings/display/bridge/ite,it66121.yaml + +diff --git a/Documentation/devicetree/bindings/display/bridge/ite,it66121.yaml b/Documentation/devicetree/bindings/display/bridge/ite,it66121.yaml +new file mode 100644 +index 000000000000..1717e880d130 +--- /dev/null ++++ b/Documentation/devicetree/bindings/display/bridge/ite,it66121.yaml +@@ -0,0 +1,98 @@ ++# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/display/bridge/ite,it66121.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: ITE it66121 HDMI bridge Device Tree Bindings ++ ++maintainers: ++ - Phong LE ++ - Neil Armstrong ++ ++description: | ++ The IT66121 is a high-performance and low-power single channel HDMI ++ transmitter, fully compliant with HDMI 1.3a, HDCP 1.2 and backward compatible ++ to DVI 1.0 specifications. ++ ++properties: ++ compatible: ++ const: ite,it66121 ++ ++ reg: ++ maxItems: 1 ++ description: base I2C address of the device ++ ++ reset-gpios: ++ maxItems: 1 ++ description: GPIO connected to active low reset ++ ++ vrf12-supply: ++ maxItems: 1 ++ description: Regulator for 1.2V analog core power. ++ ++ vcn33-supply: ++ maxItems: 1 ++ description: Regulator for 3.3V digital core power. ++ ++ vcn18-supply: ++ maxItems: 1 ++ description: Regulator for 1.8V IO core power. ++ ++ interrupts: ++ maxItems: 1 ++ ++ pclk-dual-edge: ++ maxItems: 1 ++ description: enable pclk dual edge mode. ++ ++ port: ++ type: object ++ ++ properties: ++ endpoint: ++ type: object ++ description: | ++ Input endpoints of the bridge. ++ ++ required: ++ - endpoint ++ ++required: ++ - compatible ++ - reg ++ - reset-gpios ++ - vrf12-supply ++ - vcn33-supply ++ - vcn18-supply ++ - interrupts ++ - port ++ ++additionalProperties: false ++ ++examples: ++ - | ++ i2c6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ it66121hdmitx: it66121hdmitx@4c { ++ compatible = "ite,it66121"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&ite_pins_default>; ++ vcn33-supply = <&mt6358_vcn33_wifi_reg>; ++ vcn18-supply = <&mt6358_vcn18_reg>; ++ vrf12-supply = <&mt6358_vrf12_reg>; ++ reset-gpios = <&pio 160 1 /* GPIO_ACTIVE_LOW */>; ++ interrupt-parent = <&pio>; ++ interrupts = <4 8 /* IRQ_TYPE_LEVEL_LOW */>; ++ reg = <0x4c>; ++ pclk-dual-edge; ++ ++ port { ++ it66121_in: endpoint { ++ remote-endpoint = <&display_out>; ++ }; ++ }; ++ }; ++ }; + +From 28d8fb9319bee0252c3b756966298a065bfa16c5 Mon Sep 17 00:00:00 2001 +From: Phong LE +Date: Wed, 11 Mar 2020 13:51:34 +0100 +Subject: [PATCH] drm: bridge: add it66121 driver + +This commit is a simple driver for bridge HMDI it66121. +The input format is RBG and there is no color conversion. +Audio, HDCP and CEC are not supported yet. + +Signed-off-by: Phong LE +--- + drivers/gpu/drm/bridge/Kconfig | 8 + + drivers/gpu/drm/bridge/Makefile | 1 + + drivers/gpu/drm/bridge/ite-it66121.c | 997 +++++++++++++++++++++++++++ + 3 files changed, 1006 insertions(+) + create mode 100644 drivers/gpu/drm/bridge/ite-it66121.c + +diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig +index 43271c21d3fc..204246d65f44 100644 +--- a/drivers/gpu/drm/bridge/Kconfig ++++ b/drivers/gpu/drm/bridge/Kconfig +@@ -48,6 +48,14 @@ config DRM_DISPLAY_CONNECTOR + on ARM-based platforms. Saying Y here when this driver is not needed + will not cause any issue. + ++config DRM_ITE_IT66121 ++ tristate "ITE IT66121 HDMI bridge" ++ depends on OF ++ select DRM_KMS_HELPER ++ select REGMAP_I2C ++ help ++ Support for ITE IT66121 HDMI bridge. ++ + config DRM_LVDS_CODEC + tristate "Transparent LVDS encoders and decoders support" + depends on OF +diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile +index d63d4b7e4347..ffa91a5a6bda 100644 +--- a/drivers/gpu/drm/bridge/Makefile ++++ b/drivers/gpu/drm/bridge/Makefile +@@ -2,6 +2,7 @@ + obj-$(CONFIG_DRM_CDNS_DSI) += cdns-dsi.o + obj-$(CONFIG_DRM_CHRONTEL_CH7033) += chrontel-ch7033.o + obj-$(CONFIG_DRM_DISPLAY_CONNECTOR) += display-connector.o ++obj-$(CONFIG_DRM_ITE_IT66121) += ite-it66121.o + obj-$(CONFIG_DRM_LVDS_CODEC) += lvds-codec.o + obj-$(CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW) += megachips-stdpxxxx-ge-b850v3-fw.o + obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o +diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c +new file mode 100644 +index 000000000000..7e1a90319a6a +--- /dev/null ++++ b/drivers/gpu/drm/bridge/ite-it66121.c +@@ -0,0 +1,997 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2020 BayLibre, SAS ++ * Author: Phong LE ++ * Copyright (C) 2018-2019, Artem Mygaiev ++ * Copyright (C) 2017, Fresco Logic, Incorporated. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define IT66121_MASTER_SEL_REG 0x10 ++#define IT66121_MASTER_SEL_HOST BIT(0) ++ ++#define IT66121_AFE_DRV_REG 0x61 ++#define IT66121_AFE_DRV_RST BIT(4) ++#define IT66121_AFE_DRV_PWD BIT(5) ++ ++#define IT66121_INPUT_MODE_REG 0x70 ++#define IT66121_INPUT_MODE_RGB (0 << 6) ++#define IT66121_INPUT_MODE_YUV422 BIT(6) ++#define IT66121_INPUT_MODE_YUV444 (2 << 6) ++#define IT66121_INPUT_MODE_CCIR656 BIT(4) ++#define IT66121_INPUT_MODE_SYNCEMB BIT(3) ++#define IT66121_INPUT_MODE_DDR BIT(2) ++ ++#define IT66121_INPUT_CSC_REG 0x72 ++#define IT66121_INPUT_CSC_ENDITHER BIT(7) ++#define IT66121_INPUT_CSC_ENUDFILTER BIT(6) ++#define IT66121_INPUT_CSC_DNFREE_GO BIT(5) ++#define IT66121_INPUT_CSC_RGB_TO_YUV 0x02 ++#define IT66121_INPUT_CSC_YUV_TO_RGB 0x03 ++#define IT66121_INPUT_CSC_NO_CONV 0x00 ++ ++#define IT66121_AFE_XP_REG 0x62 ++#define IT66121_AFE_XP_GAINBIT BIT(7) ++#define IT66121_AFE_XP_PWDPLL BIT(6) ++#define IT66121_AFE_XP_ENI BIT(5) ++#define IT66121_AFE_XP_ENO BIT(4) ++#define IT66121_AFE_XP_RESETB BIT(3) ++#define IT66121_AFE_XP_PWDI BIT(2) ++ ++#define IT66121_AFE_IP_REG 0x64 ++#define IT66121_AFE_IP_GAINBIT BIT(7) ++#define IT66121_AFE_IP_PWDPLL BIT(6) ++#define IT66121_AFE_IP_CKSEL_05 (0 << 4) ++#define IT66121_AFE_IP_CKSEL_1 BIT(4) ++#define IT66121_AFE_IP_CKSEL_2 (2 << 4) ++#define IT66121_AFE_IP_CKSEL_2OR4 (3 << 4) ++#define IT66121_AFE_IP_ER0 BIT(3) ++#define IT66121_AFE_IP_RESETB BIT(2) ++#define IT66121_AFE_IP_ENC BIT(1) ++#define IT66121_AFE_IP_EC1 BIT(0) ++ ++#define IT66121_AFE_XP_EC1_REG 0x68 ++#define IT66121_AFE_XP_EC1_LOWCLK BIT(4) ++ ++#define IT66121_SW_RST_REG 0x04 ++#define IT66121_SW_RST_REF BIT(5) ++#define IT66121_SW_RST_AREF BIT(4) ++#define IT66121_SW_RST_VID BIT(3) ++#define IT66121_SW_RST_AUD BIT(2) ++#define IT66121_SW_RST_HDCP BIT(0) ++ ++#define IT66121_DDC_COMMAND_REG 0x15 ++#define IT66121_DDC_COMMAND_BURST_READ 0x0 ++#define IT66121_DDC_COMMAND_EDID_READ 0x3 ++#define IT66121_DDC_COMMAND_FIFO_CLR 0x9 ++#define IT66121_DDC_COMMAND_SCL_PULSE 0xA ++#define IT66121_DDC_COMMAND_ABORT 0xF ++ ++#define IT66121_HDCP_REG 0x20 ++#define IT66121_HDCP_CPDESIRED BIT(0) ++#define IT66121_HDCP_EN1P1FEAT BIT(1) ++ ++#define IT66121_INT_STATUS1_REG 0x06 ++#define IT66121_INT_STATUS1_AUD_OVF BIT(7) ++#define IT66121_INT_STATUS1_DDC_NOACK BIT(5) ++#define IT66121_INT_STATUS1_DDC_FIFOERR BIT(4) ++#define IT66121_INT_STATUS1_DDC_BUSHANG BIT(2) ++#define IT66121_INT_STATUS1_RX_SENS_STATUS BIT(1) ++#define IT66121_INT_STATUS1_HPD_STATUS BIT(0) ++ ++#define IT66121_DDC_HEADER_REG 0x11 ++#define IT66121_DDC_HEADER_HDCP 0x74 ++#define IT66121_DDC_HEADER_EDID 0xA0 ++ ++#define IT66121_DDC_OFFSET_REG 0x12 ++#define IT66121_DDC_BYTE_REG 0x13 ++#define IT66121_DDC_SEGMENT_REG 0x14 ++#define IT66121_DDC_RD_FIFO_REG 0x17 ++ ++#define IT66121_CLK_BANK_REG 0x0F ++#define IT66121_CLK_BANK_PWROFF_RCLK BIT(6) ++#define IT66121_CLK_BANK_PWROFF_ACLK BIT(5) ++#define IT66121_CLK_BANK_PWROFF_TXCLK BIT(4) ++#define IT66121_CLK_BANK_PWROFF_CRCLK BIT(3) ++#define IT66121_CLK_BANK_0 0 ++#define IT66121_CLK_BANK_1 1 ++ ++#define IT66121_INT_REG 0x05 ++#define IT66121_INT_ACTIVE_HIGH BIT(7) ++#define IT66121_INT_OPEN_DRAIN BIT(6) ++#define IT66121_INT_TX_CLK_OFF BIT(0) ++ ++#define IT66121_INT_MASK1_REG 0x09 ++#define IT66121_INT_MASK1_AUD_OVF BIT(7) ++#define IT66121_INT_MASK1_DDC_NOACK BIT(5) ++#define IT66121_INT_MASK1_DDC_FIFOERR BIT(4) ++#define IT66121_INT_MASK1_DDC_BUSHANG BIT(2) ++#define IT66121_INT_MASK1_RX_SENS BIT(1) ++#define IT66121_INT_MASK1_HPD BIT(0) ++ ++#define IT66121_INT_CLR1_REG 0x0C ++#define IT66121_INT_CLR1_PKTACP BIT(7) ++#define IT66121_INT_CLR1_PKTNULL BIT(6) ++#define IT66121_INT_CLR1_PKTGEN BIT(5) ++#define IT66121_INT_CLR1_KSVLISTCHK BIT(4) ++#define IT66121_INT_CLR1_AUTHDONE BIT(3) ++#define IT66121_INT_CLR1_AUTHFAIL BIT(2) ++#define IT66121_INT_CLR1_RX_SENS BIT(1) ++#define IT66121_INT_CLR1_HPD BIT(0) ++ ++#define IT66121_AV_MUTE_REG 0xC1 ++#define IT66121_AV_MUTE_ON BIT(0) ++#define IT66121_AV_MUTE_BLUESCR BIT(1) ++ ++#define IT66121_PKT_GEN_CTRL_REG 0xC6 ++#define IT66121_PKT_GEN_CTRL_ON BIT(0) ++#define IT66121_PKT_GEN_CTRL_RPT BIT(1) ++ ++#define IT66121_AVIINFO_DB1_REG 0x158 ++#define IT66121_AVIINFO_DB2_REG 0x159 ++#define IT66121_AVIINFO_DB3_REG 0x15A ++#define IT66121_AVIINFO_DB4_REG 0x15B ++#define IT66121_AVIINFO_DB5_REG 0x15C ++#define IT66121_AVIINFO_CSUM_REG 0x15D ++#define IT66121_AVIINFO_DB6_REG 0x15E ++#define IT66121_AVIINFO_DB7_REG 0x15F ++#define IT66121_AVIINFO_DB8_REG 0x160 ++#define IT66121_AVIINFO_DB9_REG 0x161 ++#define IT66121_AVIINFO_DB10_REG 0x162 ++#define IT66121_AVIINFO_DB11_REG 0x163 ++#define IT66121_AVIINFO_DB12_REG 0x164 ++#define IT66121_AVIINFO_DB13_REG 0x165 ++ ++#define IT66121_AVI_INFO_PKT_REG 0xCD ++#define IT66121_AVI_INFO_PKT_ON BIT(0) ++#define IT66121_AVI_INFO_PKT_RPT BIT(1) ++ ++#define IT66121_HDMI_MODE_REG 0xC0 ++#define IT66121_HDMI_MODE_HDMI BIT(0) ++ ++#define IT66121_SYS_STATUS_REG 0x0E ++#define IT66121_SYS_STATUS_ACTIVE_IRQ BIT(7) ++#define IT66121_SYS_STATUS_HPDETECT BIT(6) ++#define IT66121_SYS_STATUS_SENDECTECT BIT(5) ++#define IT66121_SYS_STATUS_VID_STABLE BIT(4) ++#define IT66121_SYS_STATUS_AUD_CTS_CLR BIT(1) ++#define IT66121_SYS_STATUS_CLEAR_IRQ BIT(0) ++ ++#define IT66121_DDC_STATUS_REG 0x16 ++#define IT66121_DDC_STATUS_TX_DONE BIT(7) ++#define IT66121_DDC_STATUS_ACTIVE BIT(6) ++#define IT66121_DDC_STATUS_NOACK BIT(5) ++#define IT66121_DDC_STATUS_WAIT_BUS BIT(4) ++#define IT66121_DDC_STATUS_ARBI_LOSE BIT(3) ++#define IT66121_DDC_STATUS_FIFO_FULL BIT(2) ++#define IT66121_DDC_STATUS_FIFO_EMPTY BIT(1) ++#define IT66121_DDC_STATUS_FIFO_VALID BIT(0) ++ ++#define IT66121_VENDOR_ID0 0x54 ++#define IT66121_VENDOR_ID1 0x49 ++#define IT66121_DEVICE_ID0 0x12 ++#define IT66121_DEVICE_ID1 0x06 ++#define IT66121_DEVICE_MASK 0x0F ++#define IT66121_EDID_SLEEP 20000 ++#define IT66121_EDID_TIMEOUT 200000 ++#define IT66121_EDID_FIFO_SIZE 32 ++#define IT66121_AFE_CLK_HIGH 80000 ++ ++struct it66121_conf { ++ unsigned int input_mode_reg; ++ unsigned int input_conversion_reg; ++}; ++ ++struct it66121_ctx { ++ struct regmap *regmap; ++ struct drm_bridge bridge; ++ struct drm_connector connector; ++ struct device *dev; ++ struct gpio_desc *gpio_reset; ++ struct i2c_client *client; ++ struct regulator_bulk_data supplies[3]; ++ bool dual_edge; ++ const struct it66121_conf *conf; ++ struct mutex lock; /* Protects fields below and device registers */ ++ struct edid *edid; ++ struct hdmi_avi_infoframe hdmi_avi_infoframe; ++}; ++ ++static const struct regmap_range_cfg it66121_regmap_banks[] = { ++ { ++ .name = "it66121", ++ .range_min = 0x00, ++ .range_max = 0x1FF, ++ .selector_reg = IT66121_CLK_BANK_REG, ++ .selector_mask = 0x1, ++ .selector_shift = 0, ++ .window_start = 0x00, ++ .window_len = 0x130, ++ }, ++}; ++ ++static const struct regmap_config it66121_regmap_config = { ++ .val_bits = 8, ++ .reg_bits = 8, ++ .max_register = 0x1FF, ++ .ranges = it66121_regmap_banks, ++ .num_ranges = ARRAY_SIZE(it66121_regmap_banks), ++}; ++ ++static const struct it66121_conf it66121_conf_simple = { ++ .input_mode_reg = IT66121_INPUT_MODE_RGB | IT66121_INPUT_MODE_DDR, ++ .input_conversion_reg = IT66121_INPUT_CSC_NO_CONV, ++}; ++ ++static void it66121_hw_reset(struct it66121_ctx *ctx) ++{ ++ gpiod_set_value(ctx->gpio_reset, 1); ++ msleep(20); ++ gpiod_set_value(ctx->gpio_reset, 0); ++} ++ ++static int ite66121_power_on(struct it66121_ctx *ctx) ++{ ++ return regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); ++} ++ ++static int ite66121_power_off(struct it66121_ctx *ctx) ++{ ++ return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); ++} ++ ++static int it66121_preamble_ddc(struct it66121_ctx *ctx) ++{ ++ return regmap_write(ctx->regmap, IT66121_MASTER_SEL_REG, ++ IT66121_MASTER_SEL_HOST); ++} ++ ++static int it66121_fire_afe(struct it66121_ctx *ctx) ++{ ++ return regmap_write(ctx->regmap, IT66121_AFE_DRV_REG, 0); ++} ++ ++static int it66121_configure_input(struct it66121_ctx *ctx) ++{ ++ int ret; ++ ++ ret = regmap_write(ctx->regmap, IT66121_INPUT_MODE_REG, ++ ctx->conf->input_mode_reg); ++ if (ret) ++ return ret; ++ ++ return regmap_write(ctx->regmap, IT66121_INPUT_CSC_REG, ++ ctx->conf->input_conversion_reg); ++} ++ ++/** ++ * it66121_configure_afe() - Configure the analog front end ++ * @ctx: it66121_ctx object ++ * ++ * RETURNS: ++ * zero if success, a negative error code otherwise. ++ */ ++static int it66121_configure_afe(struct it66121_ctx *ctx, ++ const struct drm_display_mode *mode) ++{ ++ int ret; ++ ++ ret = regmap_write(ctx->regmap, IT66121_AFE_DRV_REG, ++ IT66121_AFE_DRV_RST); ++ if (ret) ++ return ret; ++ ++ if (mode->clock > IT66121_AFE_CLK_HIGH) { ++ ret = regmap_write_bits(ctx->regmap, IT66121_AFE_XP_REG, ++ IT66121_AFE_XP_GAINBIT | ++ IT66121_AFE_XP_ENO, ++ IT66121_AFE_XP_GAINBIT); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write_bits(ctx->regmap, IT66121_AFE_IP_REG, ++ IT66121_AFE_IP_GAINBIT | ++ IT66121_AFE_IP_ER0 | ++ IT66121_AFE_IP_EC1, ++ IT66121_AFE_IP_GAINBIT); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write_bits(ctx->regmap, IT66121_AFE_XP_EC1_REG, ++ IT66121_AFE_XP_EC1_LOWCLK, 0x80); ++ if (ret) ++ return ret; ++ } else { ++ ret = regmap_write_bits(ctx->regmap, IT66121_AFE_XP_REG, ++ IT66121_AFE_XP_GAINBIT | ++ IT66121_AFE_XP_ENO, ++ IT66121_AFE_XP_ENO); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write_bits(ctx->regmap, IT66121_AFE_IP_REG, ++ IT66121_AFE_IP_GAINBIT | ++ IT66121_AFE_IP_ER0 | ++ IT66121_AFE_IP_EC1, IT66121_AFE_IP_ER0 | ++ IT66121_AFE_IP_EC1); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write_bits(ctx->regmap, IT66121_AFE_XP_EC1_REG, ++ IT66121_AFE_XP_EC1_LOWCLK, ++ IT66121_AFE_XP_EC1_LOWCLK); ++ if (ret) ++ return ret; ++ } ++ ++ /* Clear reset flags */ ++ ret = regmap_write_bits(ctx->regmap, IT66121_SW_RST_REG, ++ IT66121_SW_RST_REF | IT66121_SW_RST_VID, ++ ~(IT66121_SW_RST_REF | IT66121_SW_RST_VID) & ++ 0xFF); ++ if (ret) ++ return ret; ++ ++ return it66121_fire_afe(ctx); ++} ++ ++static inline int it66121_wait_ddc_ready(struct it66121_ctx *ctx) ++{ ++ int ret, val; ++ ++ ret = regmap_read_poll_timeout(ctx->regmap, IT66121_DDC_STATUS_REG, ++ val, true, ++ IT66121_EDID_SLEEP, ++ IT66121_EDID_TIMEOUT); ++ if (ret) ++ return ret; ++ ++ if (val & (IT66121_DDC_STATUS_NOACK | IT66121_DDC_STATUS_WAIT_BUS | ++ IT66121_DDC_STATUS_ARBI_LOSE)) ++ return -EAGAIN; ++ ++ return 0; ++} ++ ++static int it66121_clear_ddc_fifo(struct it66121_ctx *ctx) ++{ ++ int ret; ++ ++ ret = it66121_preamble_ddc(ctx); ++ if (ret) ++ return ret; ++ ++ return regmap_write(ctx->regmap, IT66121_DDC_COMMAND_REG, ++ IT66121_DDC_COMMAND_FIFO_CLR); ++} ++ ++static int it66121_abort_ddc_ops(struct it66121_ctx *ctx) ++{ ++ int ret; ++ unsigned int swreset, cpdesire; ++ ++ ret = regmap_read(ctx->regmap, IT66121_SW_RST_REG, &swreset); ++ if (ret) ++ return ret; ++ ++ ret = regmap_read(ctx->regmap, IT66121_HDCP_REG, &cpdesire); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write(ctx->regmap, IT66121_HDCP_REG, ++ cpdesire & (~IT66121_HDCP_CPDESIRED & 0xFF)); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write(ctx->regmap, IT66121_SW_RST_REG, ++ swreset | IT66121_SW_RST_HDCP); ++ if (ret) ++ return ret; ++ ++ ret = it66121_preamble_ddc(ctx); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write(ctx->regmap, IT66121_DDC_COMMAND_REG, ++ IT66121_DDC_COMMAND_ABORT); ++ if (ret) ++ return ret; ++ ++ return it66121_wait_ddc_ready(ctx); ++} ++ ++static int it66121_get_edid_block(void *context, u8 *buf, ++ unsigned int block, size_t len) ++{ ++ struct it66121_ctx *ctx = context; ++ unsigned int val; ++ int remain = len; ++ int offset = 0; ++ int ret, cnt; ++ ++ offset = (block % 2) * len; ++ block = block / 2; ++ ++ ret = regmap_read(ctx->regmap, IT66121_INT_STATUS1_REG, &val); ++ if (ret) ++ return ret; ++ ++ if (val & IT66121_INT_STATUS1_DDC_BUSHANG) { ++ ret = it66121_abort_ddc_ops(ctx); ++ if (ret) ++ return ret; ++ } ++ ++ ret = it66121_clear_ddc_fifo(ctx); ++ if (ret) ++ return ret; ++ ++ while (remain > 0) { ++ cnt = (remain > IT66121_EDID_FIFO_SIZE) ? ++ IT66121_EDID_FIFO_SIZE : remain; ++ ret = it66121_preamble_ddc(ctx); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write(ctx->regmap, IT66121_DDC_COMMAND_REG, ++ IT66121_DDC_COMMAND_FIFO_CLR); ++ if (ret) ++ return ret; ++ ++ ret = it66121_wait_ddc_ready(ctx); ++ if (ret) ++ return ret; ++ ++ ret = regmap_read(ctx->regmap, IT66121_INT_STATUS1_REG, &val); ++ if (ret) ++ return ret; ++ ++ if (val & IT66121_INT_STATUS1_DDC_BUSHANG) { ++ ret = it66121_abort_ddc_ops(ctx); ++ if (ret) ++ return ret; ++ } ++ ++ ret = it66121_preamble_ddc(ctx); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write(ctx->regmap, IT66121_DDC_HEADER_REG, ++ IT66121_DDC_HEADER_EDID); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write(ctx->regmap, IT66121_DDC_OFFSET_REG, offset); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write(ctx->regmap, IT66121_DDC_BYTE_REG, cnt); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write(ctx->regmap, IT66121_DDC_SEGMENT_REG, block); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write(ctx->regmap, IT66121_DDC_COMMAND_REG, ++ IT66121_DDC_COMMAND_EDID_READ); ++ if (ret) ++ return ret; ++ ++ offset += cnt; ++ remain -= cnt; ++ msleep(20); ++ ++ ret = it66121_wait_ddc_ready(ctx); ++ if (ret) ++ return ret; ++ ++ do { ++ ret = regmap_read(ctx->regmap, ++ IT66121_DDC_RD_FIFO_REG, &val); ++ if (ret) ++ return ret; ++ *(buf++) = val; ++ cnt--; ++ } while (cnt > 0); ++ } ++ ++ return 0; ++} ++ ++static int it66121_connector_get_modes(struct drm_connector *connector) ++{ ++ int ret, num_modes = 0; ++ struct it66121_ctx *ctx = container_of(connector, struct it66121_ctx, ++ connector); ++ ++ if (ctx->edid) ++ return drm_add_edid_modes(connector, ctx->edid); ++ ++ mutex_lock(&ctx->lock); ++ ++ ctx->edid = drm_do_get_edid(connector, it66121_get_edid_block, ctx); ++ if (!ctx->edid) { ++ DRM_ERROR("Failed to read EDID\n"); ++ goto unlock; ++ } ++ ++ ret = drm_connector_update_edid_property(connector, ++ ctx->edid); ++ if (ret) { ++ DRM_ERROR("Failed to update EDID property: %d\n", ret); ++ goto unlock; ++ } ++ ++ num_modes = drm_add_edid_modes(connector, ctx->edid); ++ ++unlock: ++ mutex_unlock(&ctx->lock); ++ ++ return num_modes; ++} ++ ++static bool it66121_is_hpd_detect(struct it66121_ctx *ctx) ++{ ++ int val; ++ ++ if (regmap_read(ctx->regmap, IT66121_SYS_STATUS_REG, &val)) ++ return false; ++ ++ return (val & IT66121_SYS_STATUS_HPDETECT); ++} ++ ++static int it66121_connector_detect_ctx(struct drm_connector *connector, ++ struct drm_modeset_acquire_ctx *c, ++ bool force) ++{ ++ struct it66121_ctx *ctx = container_of(connector, struct it66121_ctx, ++ connector); ++ ++ return (it66121_is_hpd_detect(ctx)) ? ++ connector_status_connected : connector_status_disconnected; ++} ++ ++static enum drm_mode_status ++it66121_connector_mode_valid(struct drm_connector *connector, ++ struct drm_display_mode *mode) ++{ ++ unsigned long max_clock; ++ struct it66121_ctx *ctx = container_of(connector, struct it66121_ctx, ++ connector); ++ ++ max_clock = ctx->dual_edge ? 74250 : 148500; ++ ++ if (mode->clock > max_clock) ++ return MODE_CLOCK_HIGH; ++ ++ if (mode->clock < 25000) ++ return MODE_CLOCK_LOW; ++ ++ return MODE_OK; ++} ++ ++static struct drm_connector_helper_funcs it66121_connector_helper_funcs = { ++ .get_modes = it66121_connector_get_modes, ++ .detect_ctx = it66121_connector_detect_ctx, ++ .mode_valid = it66121_connector_mode_valid, ++}; ++ ++static const struct drm_connector_funcs it66121_connector_funcs = { ++ .reset = drm_atomic_helper_connector_reset, ++ .fill_modes = drm_helper_probe_single_connector_modes, ++ .destroy = drm_connector_cleanup, ++ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, ++ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, ++}; ++ ++static int it66121_bridge_attach(struct drm_bridge *bridge, ++ enum drm_bridge_attach_flags flags) ++{ ++ int ret; ++ struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, ++ bridge); ++ ++ if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { ++ DRM_ERROR("Fix bridge driver to make connector optional!"); ++ return -EINVAL; ++ } ++ ++ if (!bridge->encoder) { ++ DRM_ERROR("Parent encoder object not found"); ++ return -ENODEV; ++ } ++ ++ ret = regmap_write_bits(ctx->regmap, IT66121_CLK_BANK_REG, ++ IT66121_CLK_BANK_PWROFF_RCLK, 0); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write_bits(ctx->regmap, IT66121_INT_REG, ++ IT66121_INT_TX_CLK_OFF, 0); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write_bits(ctx->regmap, IT66121_AFE_DRV_REG, ++ IT66121_AFE_DRV_PWD, 0); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write_bits(ctx->regmap, IT66121_AFE_XP_REG, ++ IT66121_AFE_XP_PWDI | IT66121_AFE_XP_PWDPLL, 0); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write_bits(ctx->regmap, IT66121_AFE_IP_REG, ++ IT66121_AFE_IP_PWDPLL, 0); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write_bits(ctx->regmap, IT66121_AFE_DRV_REG, ++ IT66121_AFE_DRV_RST, 0); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write_bits(ctx->regmap, IT66121_AFE_XP_REG, ++ IT66121_AFE_XP_RESETB, IT66121_AFE_XP_RESETB); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write_bits(ctx->regmap, IT66121_AFE_IP_REG, ++ IT66121_AFE_IP_RESETB, IT66121_AFE_IP_RESETB); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write_bits(ctx->regmap, IT66121_SW_RST_REG, ++ IT66121_SW_RST_REF, ++ IT66121_SW_RST_REF); ++ if (ret) ++ return ret; ++ ++ msleep(50); ++ ++ ret = drm_connector_init(bridge->dev, &ctx->connector, ++ &it66121_connector_funcs, ++ DRM_MODE_CONNECTOR_HDMIA); ++ if (ret) ++ return ret; ++ ++ ctx->connector.polled = DRM_CONNECTOR_POLL_HPD; ++ drm_connector_helper_add(&ctx->connector, ++ &it66121_connector_helper_funcs); ++ ++ ret = drm_connector_attach_encoder(&ctx->connector, bridge->encoder); ++ if (ret) ++ return ret; ++ ++ ret = drm_connector_register(&ctx->connector); ++ if (ret) ++ return ret; ++ ++ /* Start interrupts */ ++ return regmap_write_bits(ctx->regmap, IT66121_INT_MASK1_REG, ++ IT66121_INT_MASK1_DDC_NOACK | ++ IT66121_INT_MASK1_HPD | ++ IT66121_INT_MASK1_DDC_FIFOERR | ++ IT66121_INT_MASK1_DDC_BUSHANG, ++ ~(IT66121_INT_MASK1_DDC_NOACK | ++ IT66121_INT_MASK1_HPD | ++ IT66121_INT_MASK1_DDC_FIFOERR | ++ IT66121_INT_MASK1_DDC_BUSHANG) & 0xFF); ++} ++ ++static int it66121_set_mute(struct it66121_ctx *ctx, bool mute) ++{ ++ int ret; ++ unsigned int val; ++ ++ val = mute ? IT66121_AV_MUTE_ON : (~IT66121_AV_MUTE_ON & 0xFF); ++ ret = regmap_write_bits(ctx->regmap, IT66121_AV_MUTE_REG, ++ IT66121_AV_MUTE_ON, val); ++ if (ret) ++ return ret; ++ ++ return regmap_write(ctx->regmap, IT66121_PKT_GEN_CTRL_REG, ++ IT66121_PKT_GEN_CTRL_ON | ++ IT66121_PKT_GEN_CTRL_RPT); ++} ++ ++static void it66121_bridge_enable(struct drm_bridge *bridge) ++{ ++ struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, ++ bridge); ++ ++ it66121_set_mute(ctx, false); ++} ++ ++static void it66121_bridge_disable(struct drm_bridge *bridge) ++{ ++ struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, ++ bridge); ++ ++ it66121_set_mute(ctx, true); ++} ++ ++static ++void it66121_bridge_mode_set(struct drm_bridge *bridge, ++ const struct drm_display_mode *mode, ++ const struct drm_display_mode *adjusted_mode) ++{ ++ int ret, i; ++ u8 buf[HDMI_INFOFRAME_SIZE(AVI)]; ++ struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, ++ bridge); ++ const u16 aviinfo_reg[HDMI_AVI_INFOFRAME_SIZE] = { ++ IT66121_AVIINFO_DB1_REG, ++ IT66121_AVIINFO_DB2_REG, ++ IT66121_AVIINFO_DB3_REG, ++ IT66121_AVIINFO_DB4_REG, ++ IT66121_AVIINFO_DB5_REG, ++ IT66121_AVIINFO_DB6_REG, ++ IT66121_AVIINFO_DB7_REG, ++ IT66121_AVIINFO_DB8_REG, ++ IT66121_AVIINFO_DB9_REG, ++ IT66121_AVIINFO_DB10_REG, ++ IT66121_AVIINFO_DB11_REG, ++ IT66121_AVIINFO_DB12_REG, ++ IT66121_AVIINFO_DB13_REG ++ }; ++ ++ mutex_lock(&ctx->lock); ++ ++ hdmi_avi_infoframe_init(&ctx->hdmi_avi_infoframe); ++ ++ ret = drm_hdmi_avi_infoframe_from_display_mode(&ctx->hdmi_avi_infoframe, ++ &ctx->connector, ++ adjusted_mode); ++ if (ret) { ++ DRM_ERROR("Failed to setup AVI infoframe: %d\n", ret); ++ goto unlock; ++ } ++ ++ ret = hdmi_avi_infoframe_pack(&ctx->hdmi_avi_infoframe, buf, ++ sizeof(buf)); ++ if (ret < 0) { ++ DRM_ERROR("Failed to pack infoframe: %d\n", ret); ++ goto unlock; ++ } ++ ++ /* Write new AVI infoframe packet */ ++ for (i = 0; i < HDMI_AVI_INFOFRAME_SIZE; i++) { ++ if (regmap_write(ctx->regmap, aviinfo_reg[i], ++ buf[i + HDMI_INFOFRAME_HEADER_SIZE])) ++ goto unlock; ++ } ++ if (regmap_write(ctx->regmap, IT66121_AVIINFO_CSUM_REG, buf[3])) ++ goto unlock; ++ ++ /* Enable AVI infoframe */ ++ if (regmap_write(ctx->regmap, IT66121_AVI_INFO_PKT_REG, ++ IT66121_AVI_INFO_PKT_ON | ++ IT66121_AVI_INFO_PKT_RPT)) ++ goto unlock; ++ ++ /* Set TX mode to HDMI */ ++ if (regmap_write(ctx->regmap, IT66121_HDMI_MODE_REG, ++ IT66121_HDMI_MODE_HDMI)) ++ goto unlock; ++ ++ if (regmap_write_bits(ctx->regmap, IT66121_CLK_BANK_REG, ++ IT66121_CLK_BANK_PWROFF_TXCLK, ++ IT66121_CLK_BANK_PWROFF_TXCLK)) ++ goto unlock; ++ ++ if (it66121_configure_input(ctx)) ++ goto unlock; ++ ++ if (it66121_configure_afe(ctx, adjusted_mode)) ++ goto unlock; ++ ++ regmap_write_bits(ctx->regmap, IT66121_CLK_BANK_REG, ++ IT66121_CLK_BANK_PWROFF_TXCLK, ++ ~IT66121_CLK_BANK_PWROFF_TXCLK & 0xFF); ++ ++unlock: ++ mutex_unlock(&ctx->lock); ++} ++ ++static const struct drm_bridge_funcs it66121_bridge_funcs = { ++ .attach = it66121_bridge_attach, ++ .enable = it66121_bridge_enable, ++ .disable = it66121_bridge_disable, ++ .mode_set = it66121_bridge_mode_set, ++}; ++ ++static irqreturn_t it66121_irq_threaded_handler(int irq, void *dev_id) ++{ ++ int ret; ++ unsigned int val; ++ struct it66121_ctx *ctx = dev_id; ++ struct device *dev = ctx->dev; ++ bool event = false; ++ ++ mutex_lock(&ctx->lock); ++ ++ ret = regmap_read(ctx->regmap, IT66121_SYS_STATUS_REG, &val); ++ if (ret) ++ goto unlock; ++ ++ if (val & IT66121_SYS_STATUS_ACTIVE_IRQ) { ++ ret = regmap_read(ctx->regmap, IT66121_INT_STATUS1_REG, &val); ++ if (ret) { ++ dev_err(dev, "Cannot read STATUS1_REG %d\n", ret); ++ } else { ++ if (val & IT66121_INT_STATUS1_DDC_FIFOERR) ++ it66121_clear_ddc_fifo(ctx); ++ if (val & (IT66121_INT_STATUS1_DDC_BUSHANG | ++ IT66121_INT_STATUS1_DDC_NOACK)) ++ it66121_abort_ddc_ops(ctx); ++ if (val & IT66121_INT_STATUS1_HPD_STATUS) { ++ regmap_write_bits(ctx->regmap, ++ IT66121_INT_CLR1_REG, ++ IT66121_INT_CLR1_HPD, ++ IT66121_INT_CLR1_HPD); ++ ++ if (!it66121_is_hpd_detect(ctx)) { ++ kfree(ctx->edid); ++ ctx->edid = NULL; ++ } ++ event = true; ++ } ++ } ++ ++ regmap_write_bits(ctx->regmap, IT66121_SYS_STATUS_REG, ++ IT66121_SYS_STATUS_CLEAR_IRQ, ++ IT66121_SYS_STATUS_CLEAR_IRQ); ++ } ++ ++unlock: ++ mutex_unlock(&ctx->lock); ++ ++ if (event) ++ drm_helper_hpd_irq_event(ctx->bridge.dev); ++ ++ return IRQ_HANDLED; ++} ++ ++static int it66121_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ u8 ids[4]; ++ int i, ret; ++ struct it66121_ctx *ctx; ++ struct device *dev = &client->dev; ++ ++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { ++ dev_err(dev, "I2C check functionality failed.\n"); ++ return -ENXIO; ++ } ++ ++ ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); ++ if (!ctx) ++ return -ENOMEM; ++ ++ ctx->dev = dev; ++ ctx->client = client; ++ i2c_set_clientdata(client, ctx); ++ mutex_init(&ctx->lock); ++ ctx->conf = (struct it66121_conf *)of_device_get_match_data(dev); ++ if (!ctx->conf) ++ return -ENODEV; ++ ++ ctx->supplies[0].supply = "vcn33"; ++ ctx->supplies[1].supply = "vcn18"; ++ ctx->supplies[2].supply = "vrf12"; ++ ret = devm_regulator_bulk_get(ctx->dev, 3, ctx->supplies); ++ if (ret) { ++ dev_err(ctx->dev, "regulator_bulk failed\n"); ++ return ret; ++ } ++ ++ ctx->dual_edge = of_property_read_bool(dev->of_node, "pclk-dual-edge"); ++ ++ ret = ite66121_power_on(ctx); ++ if (ret) ++ return ret; ++ ++ it66121_hw_reset(ctx); ++ ++ ctx->regmap = devm_regmap_init_i2c(client, &it66121_regmap_config); ++ if (IS_ERR(ctx->regmap)) { ++ ite66121_power_off(ctx); ++ return PTR_ERR(ctx); ++ } ++ ++ for (i = 0; i < 4; i++) { ++ regmap_read(ctx->regmap, i, &ret); ++ ids[i] = ret; ++ } ++ ++ if (ids[0] != IT66121_VENDOR_ID0 || ++ ids[1] != IT66121_VENDOR_ID1 || ++ ids[2] != IT66121_DEVICE_ID0 || ++ ((ids[3] & IT66121_DEVICE_MASK) != IT66121_DEVICE_ID1)) { ++ ite66121_power_off(ctx); ++ return -ENODEV; ++ } ++ ++ ctx->bridge.funcs = &it66121_bridge_funcs; ++ ctx->bridge.of_node = dev->of_node; ++ ++ ret = devm_request_threaded_irq(dev, client->irq, NULL, ++ it66121_irq_threaded_handler, ++ IRQF_SHARED | IRQF_TRIGGER_LOW | ++ IRQF_ONESHOT, ++ dev_name(dev), ++ ctx); ++ if (ret < 0) { ++ dev_err(dev, "Failed to request irq %d:%d\n", client->irq, ret); ++ ite66121_power_off(ctx); ++ return ret; ++ } ++ ++ drm_bridge_add(&ctx->bridge); ++ ++ return 0; ++} ++ ++static int it66121_remove(struct i2c_client *client) ++{ ++ struct it66121_ctx *ctx = i2c_get_clientdata(client); ++ ++ ite66121_power_off(ctx); ++ drm_bridge_remove(&ctx->bridge); ++ kfree(ctx->edid); ++ mutex_destroy(&ctx->lock); ++ ++ return 0; ++} ++ ++static const struct of_device_id it66121_dt_match[] = { ++ { .compatible = "ite,it66121", ++ .data = &it66121_conf_simple, ++ }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, it66121_dt_match); ++ ++static const struct i2c_device_id it66121_id[] = { ++ { "it66121", 0 }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(i2c, it66121_id); ++ ++static struct i2c_driver it66121_driver = { ++ .driver = { ++ .name = "it66121", ++ .of_match_table = it66121_dt_match, ++ }, ++ .probe = it66121_probe, ++ .remove = it66121_remove, ++ .id_table = it66121_id, ++}; ++ ++module_i2c_driver(it66121_driver); ++ ++MODULE_AUTHOR("Phong LE"); ++MODULE_DESCRIPTION("IT66121 HDMI transmitter driver"); ++MODULE_LICENSE("GPL v2"); + +From ec5271e4d8d6d57545a284ee5bd365f17990fdc6 Mon Sep 17 00:00:00 2001 +From: Phong LE +Date: Wed, 11 Mar 2020 13:51:35 +0100 +Subject: [PATCH] MAINTAINERS: add it66121 HDMI bridge driver entry + +Add Neil Armstrong and myself as maintainers + +Signed-off-by: Phong LE +--- + MAINTAINERS | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/MAINTAINERS b/MAINTAINERS +index db98a799f409..5a34ca2f0e11 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -9193,6 +9193,14 @@ Q: http://patchwork.linuxtv.org/project/linux-media/list/ + T: git git://linuxtv.org/anttip/media_tree.git + F: drivers/media/tuners/it913x* + ++ITE IT66121 HDMI BRIDGE DRIVER ++M: Phong LE ++M: Neil Armstrong ++S: Maintained ++F: drivers/gpu/drm/bridge/ite-it66121.c ++T: git git://anongit.freedesktop.org/drm/drm-misc ++F: Documentation/devicetree/bindings/display/bridge/ite,it66121.yaml ++ + IVTV VIDEO4LINUX DRIVER + M: Andy Walls + L: linux-media@vger.kernel.org + +From b8f225a1145ac25cd5df830d557e5be6d212a798 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Tue, 26 May 2020 13:48:12 +0200 +Subject: [PATCH] drm: bridge: it66121: add IT66121FN variant + +--- + drivers/gpu/drm/bridge/ite-it66121.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c +index 7e1a90319a6a..68f7e50fdddd 100644 +--- a/drivers/gpu/drm/bridge/ite-it66121.c ++++ b/drivers/gpu/drm/bridge/ite-it66121.c +@@ -242,6 +242,11 @@ static const struct it66121_conf it66121_conf_simple = { + .input_conversion_reg = IT66121_INPUT_CSC_NO_CONV, + }; + ++static const struct it66121_conf it66121fn_conf_simple = { ++ .input_mode_reg = IT66121_INPUT_MODE_RGB, ++ .input_conversion_reg = IT66121_INPUT_CSC_NO_CONV, ++}; ++ + static void it66121_hw_reset(struct it66121_ctx *ctx) + { + gpiod_set_value(ctx->gpio_reset, 1); +@@ -970,6 +975,9 @@ static const struct of_device_id it66121_dt_match[] = { + { .compatible = "ite,it66121", + .data = &it66121_conf_simple, + }, ++ { .compatible = "ite,it66121fn", ++ .data = &it66121fn_conf_simple, ++ }, + { }, + }; + MODULE_DEVICE_TABLE(of, it66121_dt_match); + +From e7ebcc04f15308b5ece1b5f99689d8577be2625d Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sun, 16 Aug 2020 23:40:24 +0200 +Subject: [PATCH] WIP: ARM: dts: rockchip add vpll clock to RK322Xs hdmi node + +--- + arch/arm/boot/dts/rk322x.dtsi | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi +index 48e6e8d44a1a..b69b5be110c3 100644 +--- a/arch/arm/boot/dts/rk322x.dtsi ++++ b/arch/arm/boot/dts/rk322x.dtsi +@@ -644,8 +644,8 @@ hdmi: hdmi@200a0000 { + interrupts = ; + assigned-clocks = <&cru SCLK_HDMI_PHY>; + assigned-clock-parents = <&hdmi_phy>; +- clocks = <&cru SCLK_HDMI_HDCP>, <&cru PCLK_HDMI_CTRL>, <&cru SCLK_HDMI_CEC>; +- clock-names = "isfr", "iahb", "cec"; ++ clocks = <&cru SCLK_HDMI_HDCP>, <&cru PCLK_HDMI_CTRL>, <&hdmi_phy>, <&cru SCLK_HDMI_CEC>; ++ clock-names = "isfr", "iahb", "vpll", "cec"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmii2c_xfer &hdmi_hpd &hdmi_cec>; + resets = <&cru SRST_HDMI_P>; + +From e1dd22643e8fc82021c3ed8f5355bffa33899b9c Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Tue, 18 Aug 2020 11:19:53 +0200 +Subject: [PATCH] drm/bridge: !cleanup: remove pr_infos + +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c +index e6953219beee..2cfd5b418c05 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c +@@ -97,8 +97,6 @@ static int dw_hdmi_cec_transmit(struct cec_adapter *adap, u8 attempts, + struct dw_hdmi_cec *cec = cec_get_drvdata(adap); + unsigned int i, ctrl; + +- pr_info("%s: attempts=%u signal_free_time=%u msg=%*ph (sequence: %u)\n", __func__, attempts, signal_free_time, msg->len, msg->msg, msg->sequence); +- + switch (signal_free_time) { + case CEC_SIGNAL_FREE_TIME_RETRY: + ctrl = CEC_CTRL_RETRY; +@@ -188,8 +186,6 @@ static irqreturn_t dw_hdmi_cec_hardirq(int irq, void *data) + ret = IRQ_WAKE_THREAD; + } + +- pr_info("%s: stat=%x ret=%x tx_done=%d rx_done=%d tx_status=%u tx_attempts=%u\n", __func__, stat, ret, cec->tx_done, cec->rx_done, cec->tx_status, cec->tx_attempts); +- + return ret; + } + +@@ -198,8 +194,6 @@ static irqreturn_t dw_hdmi_cec_thread(int irq, void *data) + struct cec_adapter *adap = data; + struct dw_hdmi_cec *cec = cec_get_drvdata(adap); + +- //pr_info("%s: tx_done=%d rx_done=%d tx_status=%u tx_attempts=%u\n", __func__, cec->tx_done, cec->rx_done, cec->tx_status, cec->tx_attempts); +- + if (cec->tx_done) { + cec->tx_done = false; + if (cec->tx_status == CEC_TX_STATUS_LOW_DRIVE) diff --git a/patch/kernel/rk322x-dev/01-linux-3000-rockchip-v4l-wip.patch b/patch/kernel/rk322x-dev/01-linux-3000-rockchip-v4l-wip.patch new file mode 100644 index 000000000..e19954c6d --- /dev/null +++ b/patch/kernel/rk322x-dev/01-linux-3000-rockchip-v4l-wip.patch @@ -0,0 +1,4647 @@ +From d9d1bb6e72ad344280be5887718444f110aec86f Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Fri, 22 May 2020 20:42:11 +0000 +Subject: [PATCH] fixup! media: rkvdec: Fix .buf_prepare + +--- + drivers/staging/media/rkvdec/rkvdec.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index f0f28f6a68cf..9edaea98a483 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -599,13 +599,11 @@ static int rkvdec_buf_prepare(struct vb2_buffer *vb) + } + + /* +- * Buffer's bytesused is written by the driver for CAPTURE buffers, +- * or if the application passed zero bytesused on an OUTPUT buffer. ++ * Buffer's bytesused is written by the driver for CAPTURE buffers. + */ +- if (!V4L2_TYPE_IS_OUTPUT(vq->type) || +- (V4L2_TYPE_IS_OUTPUT(vq->type) && !vb2_get_plane_payload(vb, 0))) +- vb2_set_plane_payload(vb, 0, +- f->fmt.pix_mp.plane_fmt[0].sizeimage); ++ if (!V4L2_TYPE_IS_OUTPUT(vq->type)) ++ vb2_set_plane_payload(vb, 0, f->fmt.pix_mp.plane_fmt[0].sizeimage); ++ + return 0; + } + + +From e5c9031e74c1ff2c597654f172c9f1e856810544 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 15 Aug 2020 08:28:56 +0000 +Subject: [PATCH] fixup! media: rkvdec: Add the VP9 backend + +--- + drivers/staging/media/rkvdec/rkvdec.c | 5 ----- + 1 file changed, 5 deletions(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index 9edaea98a483..9accbe889040 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -161,24 +161,19 @@ static const u32 rkvdec_h264_decoded_fmts[] = { + + static const struct rkvdec_ctrl_desc rkvdec_vp9_ctrl_descs[] = { + { +- .per_request = true, + .mandatory = true, + .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_DECODE_PARAMS, + }, + { +- .mandatory = true, + .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(0), + }, + { +- .mandatory = true, + .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(1), + }, + { +- .mandatory = true, + .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(2), + }, + { +- .mandatory = true, + .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(3), + }, + { + +From 9a9b9efc39a879ef65d7f9bec29fd8f0b8ce89fc Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 23 May 2020 10:18:16 +0000 +Subject: [PATCH] WIP: media: rkvdec: continue to gate clock when decoding + finish + +Signed-off-by: Jonas Karlman +--- + drivers/staging/media/rkvdec/rkvdec.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index 9accbe889040..a282b7e6d6e8 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -1079,7 +1079,8 @@ static irqreturn_t rkvdec_irq_handler(int irq, void *priv) + state = (status & RKVDEC_RDY_STA) ? + VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR; + +- writel(0, rkvdec->regs + RKVDEC_REG_INTERRUPT); ++ writel(RKVDEC_CONFIG_DEC_CLK_GATE_E, ++ rkvdec->regs + RKVDEC_REG_INTERRUPT); + if (cancel_delayed_work(&rkvdec->watchdog_work)) { + struct rkvdec_ctx *ctx; + +@@ -1100,7 +1101,8 @@ static void rkvdec_watchdog_func(struct work_struct *work) + ctx = v4l2_m2m_get_curr_priv(rkvdec->m2m_dev); + if (ctx) { + dev_err(rkvdec->dev, "Frame processing timed out!\n"); +- writel(RKVDEC_IRQ_DIS, rkvdec->regs + RKVDEC_REG_INTERRUPT); ++ writel(RKVDEC_CONFIG_DEC_CLK_GATE_E | RKVDEC_IRQ_DIS, ++ rkvdec->regs + RKVDEC_REG_INTERRUPT); + writel(0, rkvdec->regs + RKVDEC_REG_SYSCTRL); + rkvdec_job_finish(ctx, VB2_BUF_STATE_ERROR); + } + +From 126fa7ad4de4368fe4938d59b327813a8649ff3b Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 23 May 2020 10:16:01 +0000 +Subject: [PATCH] WIP: media: rkvdec: pm runtime dont use autosuspend before + disable and cleanup + +Signed-off-by: Jonas Karlman +--- + drivers/staging/media/rkvdec/rkvdec.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index a282b7e6d6e8..658fb6028e72 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -1200,9 +1200,9 @@ static int rkvdec_remove(struct platform_device *pdev) + { + struct rkvdec_dev *rkvdec = platform_get_drvdata(pdev); + +- rkvdec_v4l2_cleanup(rkvdec); +- pm_runtime_disable(&pdev->dev); + pm_runtime_dont_use_autosuspend(&pdev->dev); ++ pm_runtime_disable(&pdev->dev); ++ rkvdec_v4l2_cleanup(rkvdec); + return 0; + } + + +From c7382800a8af054b62ff6edea7d62bc30a160b74 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 23 May 2020 11:23:04 +0000 +Subject: [PATCH] WIP: media: rkvdec: h264: return early when no reference + pictures + +NOTE: also change from a switch statement to access reflists from a pointer array, +should simplify once we add support for field reference list + +Signed-off-by: Jonas Karlman +--- + drivers/staging/media/rkvdec/rkvdec-h264.c | 18 +++++------------- + 1 file changed, 5 insertions(+), 13 deletions(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c +index afc695d32186..1716bfb596ae 100644 +--- a/drivers/staging/media/rkvdec/rkvdec-h264.c ++++ b/drivers/staging/media/rkvdec/rkvdec-h264.c +@@ -734,6 +734,7 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx, + const struct v4l2_ctrl_h264_sps *sps = run->sps; + struct rkvdec_h264_priv_tbl *priv_tbl = h264_ctx->priv_tbl.cpu; + u32 max_frame_num = 1 << (sps->log2_max_frame_num_minus4 + 4); ++ u8 *reflists[3] = { h264_ctx->reflists.p, h264_ctx->reflists.b0, h264_ctx->reflists.b1 }; + + u32 *hw_rps = priv_tbl->rps; + u32 i, j; +@@ -741,6 +742,9 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx, + + memset(hw_rps, 0, sizeof(priv_tbl->rps)); + ++ if (!h264_ctx->reflists.num_valid) ++ return; ++ + /* + * Assign an invalid pic_num if DPB entry at that position is inactive. + * If we assign 0 in that position hardware will treat that as a real +@@ -763,19 +767,7 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx, + for (j = 0; j < RKVDEC_NUM_REFLIST; j++) { + for (i = 0; i < h264_ctx->reflists.num_valid; i++) { + u8 dpb_valid = 0; +- u8 idx = 0; +- +- switch (j) { +- case 0: +- idx = h264_ctx->reflists.p[i]; +- break; +- case 1: +- idx = h264_ctx->reflists.b0[i]; +- break; +- case 2: +- idx = h264_ctx->reflists.b1[i]; +- break; +- } ++ u8 idx = reflists[j][i]; + + if (idx >= ARRAY_SIZE(dec_params->dpb)) + continue; + +From 70eb1d9dfa98bf6a6662280de58e01dffa347add Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 23 May 2020 14:42:27 +0000 +Subject: [PATCH] WIP: media: rkvdec: h264: add field decoding support + +Signed-off-by: Jonas Karlman +--- + drivers/staging/media/rkvdec/rkvdec-h264.c | 79 ++++++++++++++++++---- + 1 file changed, 64 insertions(+), 15 deletions(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c +index 1716bfb596ae..c388bf3da079 100644 +--- a/drivers/staging/media/rkvdec/rkvdec-h264.c ++++ b/drivers/staging/media/rkvdec/rkvdec-h264.c +@@ -737,7 +737,7 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx, + u8 *reflists[3] = { h264_ctx->reflists.p, h264_ctx->reflists.b0, h264_ctx->reflists.b1 }; + + u32 *hw_rps = priv_tbl->rps; +- u32 i, j; ++ u32 i, j, k; + u16 *p = (u16 *)hw_rps; + + memset(hw_rps, 0, sizeof(priv_tbl->rps)); +@@ -764,18 +764,71 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx, + p[i] = dpb[i].frame_num - max_frame_num; + } + +- for (j = 0; j < RKVDEC_NUM_REFLIST; j++) { +- for (i = 0; i < h264_ctx->reflists.num_valid; i++) { +- u8 dpb_valid = 0; +- u8 idx = reflists[j][i]; ++ if (!(dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC)) { ++ for (j = 0; j < RKVDEC_NUM_REFLIST; j++) { ++ for (i = 0; i < h264_ctx->reflists.num_valid; i++) { ++ u8 dpb_valid = 0; ++ u8 idx = reflists[j][i]; + +- if (idx >= ARRAY_SIZE(dec_params->dpb)) +- continue; +- dpb_valid = !!(dpb[idx].flags & +- V4L2_H264_DPB_ENTRY_FLAG_ACTIVE); ++ if (idx >= ARRAY_SIZE(dec_params->dpb)) ++ continue; ++ dpb_valid = !!(dpb[idx].flags & ++ V4L2_H264_DPB_ENTRY_FLAG_ACTIVE); + +- set_ps_field(hw_rps, DPB_INFO(i, j), +- idx | dpb_valid << 4); ++ set_ps_field(hw_rps, DPB_INFO(i, j), ++ idx | dpb_valid << 4); ++ } ++ } ++ return; ++ } ++ ++ for (j = 0; j < RKVDEC_NUM_REFLIST; j++) { ++ enum v4l2_h264_field_reference a_parity = ++ (dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD) ++ ? V4L2_H264_BOTTOM_FIELD_REF : V4L2_H264_TOP_FIELD_REF; ++ enum v4l2_h264_field_reference b_parity = ++ (dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD) ++ ? V4L2_H264_TOP_FIELD_REF : V4L2_H264_BOTTOM_FIELD_REF; ++ u32 flags = V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM; ++ i = 0; ++ ++ for (k = 0; k < 2; k++) { ++ u8 a = 0; ++ u8 b = 0; ++ u32 long_term = k ? V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM : 0; ++ ++ while (a < h264_ctx->reflists.num_valid || b < h264_ctx->reflists.num_valid) { ++ for (; a < h264_ctx->reflists.num_valid; a++) { ++ u8 idx = reflists[j][a]; ++ if (idx >= ARRAY_SIZE(dec_params->dpb)) ++ continue; ++ if ((dpb[idx].reference & a_parity) == a_parity && ++ (dpb[idx].flags & flags) == long_term) { ++ set_ps_field(hw_rps, DPB_INFO(i, j), ++ idx | (1 << 4)); ++ set_ps_field(hw_rps, BOTTOM_FLAG(i, j), ++ a_parity == V4L2_H264_BOTTOM_FIELD_REF); ++ i++; ++ a++; ++ break; ++ } ++ } ++ for (; b < h264_ctx->reflists.num_valid; b++) { ++ u8 idx = reflists[j][b]; ++ if (idx >= ARRAY_SIZE(dec_params->dpb)) ++ continue; ++ if ((dpb[idx].reference & b_parity) == b_parity && ++ (dpb[idx].flags & flags) == long_term) { ++ set_ps_field(hw_rps, DPB_INFO(i, j), ++ idx | (1 << 4)); ++ set_ps_field(hw_rps, BOTTOM_FLAG(i, j), ++ b_parity == V4L2_H264_BOTTOM_FIELD_REF); ++ i++; ++ b++; ++ break; ++ } ++ } ++ } + } + } + } +@@ -968,10 +1021,6 @@ static void config_registers(struct rkvdec_ctx *ctx, + rkvdec->regs + RKVDEC_REG_H264_BASE_REFER15); + } + +- /* +- * Since support frame mode only +- * top_field_order_cnt is the same as bottom_field_order_cnt +- */ + reg = RKVDEC_CUR_POC(dec_params->top_field_order_cnt); + writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_CUR_POC0); + + +From 7032b50b559ff869d47ae06ec94cf7b50f7a8eb1 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 26 Oct 2019 13:55:15 +0200 +Subject: [PATCH] media: uapi: hevc: Add scaling matrix control + +HEVC has a scaling matrix concept. Add support for it. + +Signed-off-by: Jernej Skrabec +--- + .../media/v4l/ext-ctrls-codec.rst | 41 +++++++++++++++++++ + .../media/v4l/pixfmt-compressed.rst | 1 + + drivers/media/v4l2-core/v4l2-ctrls.c | 10 +++++ + include/media/hevc-ctrls.h | 11 +++++ + 4 files changed, 63 insertions(+) + +diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +index ca13b141d8c2..578de53ff929 100644 +--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst ++++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +@@ -4777,6 +4777,47 @@ enum v4l2_mpeg_video_hevc_size_of_length_field - + - ``padding[6]`` + - Applications and drivers must set this to zero. + ++``V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX (struct)`` ++ Specifies the scaling matrix (as extracted from the bitstream) for ++ the associated HEVC slice data. The bitstream parameters are ++ defined according to :ref:`hevc`, section 7.4.5 "Scaling list ++ data semantics". For further documentation, refer to the above ++ specification, unless there is an explicit comment stating ++ otherwise. ++ ++ .. note:: ++ ++ This compound control is not yet part of the public kernel API and ++ it is expected to change. ++ ++.. c:type:: v4l2_ctrl_hevc_scaling_matrix ++ ++.. cssclass:: longtable ++ ++.. flat-table:: struct v4l2_ctrl_hevc_scaling_matrix ++ :header-rows: 0 ++ :stub-columns: 0 ++ :widths: 1 1 2 ++ ++ * - __u8 ++ - ``scaling_list_4x4[6][16]`` ++ - ++ * - __u8 ++ - ``scaling_list_8x8[6][64]`` ++ - ++ * - __u8 ++ - ``scaling_list_16x16[6][64]`` ++ - ++ * - __u8 ++ - ``scaling_list_32x32[2][64]`` ++ - ++ * - __u8 ++ - ``scaling_list_dc_coef_16x16[6]`` ++ - ++ * - __u8 ++ - ``scaling_list_dc_coef_32x32[2]`` ++ - ++ + ``V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE (enum)`` + Specifies the decoding mode to use. Currently exposes slice-based and + frame-based decoding but new modes might be added later on. +diff --git a/Documentation/userspace-api/media/v4l/pixfmt-compressed.rst b/Documentation/userspace-api/media/v4l/pixfmt-compressed.rst +index 3828bb79225d..a77560204c21 100644 +--- a/Documentation/userspace-api/media/v4l/pixfmt-compressed.rst ++++ b/Documentation/userspace-api/media/v4l/pixfmt-compressed.rst +@@ -207,6 +207,7 @@ Compressed Formats + * ``V4L2_CID_MPEG_VIDEO_HEVC_SPS`` + * ``V4L2_CID_MPEG_VIDEO_HEVC_PPS`` + * ``V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS`` ++ * ``V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX`` + See the :ref:`associated Codec Control IDs `. + Buffers associated with this pixel format must contain the appropriate + number of macroblocks to decode a full corresponding frame. +diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c +index 5913088cbc6f..6f7df51cb633 100644 +--- a/drivers/media/v4l2-core/v4l2-ctrls.c ++++ b/drivers/media/v4l2-core/v4l2-ctrls.c +@@ -995,6 +995,7 @@ const char *v4l2_ctrl_get_name(u32 id) + case V4L2_CID_MPEG_VIDEO_HEVC_SPS: return "HEVC Sequence Parameter Set"; + case V4L2_CID_MPEG_VIDEO_HEVC_PPS: return "HEVC Picture Parameter Set"; + case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS: return "HEVC Slice Parameters"; ++ case V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX: return "HEVC Scaling Matrix"; + case V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE: return "HEVC Decode Mode"; + case V4L2_CID_MPEG_VIDEO_HEVC_START_CODE: return "HEVC Start Code"; + +@@ -1442,6 +1443,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, + case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS: + *type = V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS; + break; ++ case V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX: ++ *type = V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX; ++ break; + case V4L2_CID_UNIT_CELL_SIZE: + *type = V4L2_CTRL_TYPE_AREA; + *flags |= V4L2_CTRL_FLAG_READ_ONLY; +@@ -2134,6 +2138,9 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, + zero_padding(*p_hevc_slice_params); + break; + ++ case V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX: ++ break; ++ + case V4L2_CTRL_TYPE_AREA: + area = p; + if (!area->width || !area->height) +@@ -2832,6 +2839,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, + case V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS: + elem_size = sizeof(struct v4l2_ctrl_hevc_slice_params); + break; ++ case V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX: ++ elem_size = sizeof(struct v4l2_ctrl_hevc_scaling_matrix); ++ break; + case V4L2_CTRL_TYPE_AREA: + elem_size = sizeof(struct v4l2_area); + break; +diff --git a/include/media/hevc-ctrls.h b/include/media/hevc-ctrls.h +index 1009cf0891cc..1592e52c3614 100644 +--- a/include/media/hevc-ctrls.h ++++ b/include/media/hevc-ctrls.h +@@ -19,6 +19,7 @@ + #define V4L2_CID_MPEG_VIDEO_HEVC_SPS (V4L2_CID_MPEG_BASE + 1008) + #define V4L2_CID_MPEG_VIDEO_HEVC_PPS (V4L2_CID_MPEG_BASE + 1009) + #define V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS (V4L2_CID_MPEG_BASE + 1010) ++#define V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX (V4L2_CID_MPEG_BASE + 1011) + #define V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE (V4L2_CID_MPEG_BASE + 1015) + #define V4L2_CID_MPEG_VIDEO_HEVC_START_CODE (V4L2_CID_MPEG_BASE + 1016) + +@@ -26,6 +27,7 @@ + #define V4L2_CTRL_TYPE_HEVC_SPS 0x0120 + #define V4L2_CTRL_TYPE_HEVC_PPS 0x0121 + #define V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS 0x0122 ++#define V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX 0x0123 + + enum v4l2_mpeg_video_hevc_decode_mode { + V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED, +@@ -209,4 +211,13 @@ struct v4l2_ctrl_hevc_slice_params { + __u64 flags; + }; + ++struct v4l2_ctrl_hevc_scaling_matrix { ++ __u8 scaling_list_4x4[6][16]; ++ __u8 scaling_list_8x8[6][64]; ++ __u8 scaling_list_16x16[6][64]; ++ __u8 scaling_list_32x32[2][64]; ++ __u8 scaling_list_dc_coef_16x16[6]; ++ __u8 scaling_list_dc_coef_32x32[2]; ++}; ++ + #endif + +From e8b0441e3d60b0e936b975f2467d1604158a1d6c Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 26 Oct 2019 15:42:28 +0200 +Subject: [PATCH] media: uapi: hevc: Add segment address field + +If HEVC frame consists of multiple slices, segment address has to be +known in order to properly decode it. + +Add segment address field to slice parameters. + +Signed-off-by: Jernej Skrabec +--- + Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst | 5 ++++- + include/media/hevc-ctrls.h | 5 ++++- + 2 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +index 578de53ff929..bca71e38b85d 100644 +--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst ++++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +@@ -4572,6 +4572,9 @@ enum v4l2_mpeg_video_hevc_size_of_length_field - + * - __u32 + - ``data_bit_offset`` + - Offset (in bits) to the video data in the current slice data. ++ * - __u32 ++ - ``slice_segment_addr`` ++ - + * - __u8 + - ``nal_unit_type`` + - +@@ -4649,7 +4652,7 @@ enum v4l2_mpeg_video_hevc_size_of_length_field - + - ``num_rps_poc_lt_curr`` + - The number of reference pictures in the long-term set. + * - __u8 +- - ``padding[7]`` ++ - ``padding[5]`` + - Applications and drivers must set this to zero. + * - struct :c:type:`v4l2_hevc_dpb_entry` + - ``dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]`` +diff --git a/include/media/hevc-ctrls.h b/include/media/hevc-ctrls.h +index 1592e52c3614..3e2e32098312 100644 +--- a/include/media/hevc-ctrls.h ++++ b/include/media/hevc-ctrls.h +@@ -167,6 +167,9 @@ struct v4l2_ctrl_hevc_slice_params { + __u32 bit_size; + __u32 data_bit_offset; + ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ ++ __u32 slice_segment_addr; ++ + /* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */ + __u8 nal_unit_type; + __u8 nuh_temporal_id_plus1; +@@ -200,7 +203,7 @@ struct v4l2_ctrl_hevc_slice_params { + __u8 num_rps_poc_st_curr_after; + __u8 num_rps_poc_lt_curr; + +- __u8 padding; ++ __u8 padding[5]; + + /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ + struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; + +From 180280b4b2e59865227ac90235ae902ce8088369 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 23 May 2020 15:03:46 +0000 +Subject: [PATCH] WIP: media: uapi: hevc: add fields needed for rkvdec + +NOTE: these fields are used by rkvdec hevc backend + +Signed-off-by: Jonas Karlman +--- + include/media/hevc-ctrls.h | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/include/media/hevc-ctrls.h b/include/media/hevc-ctrls.h +index 3e2e32098312..3cc3b47e1417 100644 +--- a/include/media/hevc-ctrls.h ++++ b/include/media/hevc-ctrls.h +@@ -56,6 +56,9 @@ enum v4l2_mpeg_video_hevc_start_code { + /* The controls are not stable at the moment and will likely be reworked. */ + struct v4l2_ctrl_hevc_sps { + /* ISO/IEC 23008-2, ITU-T Rec. H.265: Sequence parameter set */ ++ __u8 video_parameter_set_id; ++ __u8 seq_parameter_set_id; ++ __u8 chroma_format_idc; + __u16 pic_width_in_luma_samples; + __u16 pic_height_in_luma_samples; + __u8 bit_depth_luma_minus8; +@@ -76,9 +79,8 @@ struct v4l2_ctrl_hevc_sps { + __u8 log2_diff_max_min_pcm_luma_coding_block_size; + __u8 num_short_term_ref_pic_sets; + __u8 num_long_term_ref_pics_sps; +- __u8 chroma_format_idc; + +- __u8 padding; ++ __u8 padding[7]; + + __u64 flags; + }; +@@ -105,7 +107,10 @@ struct v4l2_ctrl_hevc_sps { + + struct v4l2_ctrl_hevc_pps { + /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture parameter set */ ++ __u8 pic_parameter_set_id; + __u8 num_extra_slice_header_bits; ++ __u8 num_ref_idx_l0_default_active_minus1; ++ __u8 num_ref_idx_l1_default_active_minus1; + __s8 init_qp_minus26; + __u8 diff_cu_qp_delta_depth; + __s8 pps_cb_qp_offset; +@@ -118,7 +123,7 @@ struct v4l2_ctrl_hevc_pps { + __s8 pps_tc_offset_div2; + __u8 log2_parallel_merge_level_minus2; + +- __u8 padding[4]; ++ __u8 padding; + __u64 flags; + }; + +@@ -203,7 +208,10 @@ struct v4l2_ctrl_hevc_slice_params { + __u8 num_rps_poc_st_curr_after; + __u8 num_rps_poc_lt_curr; + +- __u8 padding[5]; ++ __u16 short_term_ref_pic_set_size; ++ __u16 long_term_ref_pic_set_size; ++ ++ __u8 padding; + + /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ + struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; + +From 80ec0ecb1f7555aae1daa174cde084b3d9f42459 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 23 May 2020 15:07:15 +0000 +Subject: [PATCH] HACK: media: uapi: hevc: tiles and num_slices + +--- + include/media/hevc-ctrls.h | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/include/media/hevc-ctrls.h b/include/media/hevc-ctrls.h +index 3cc3b47e1417..b33e1a8141e1 100644 +--- a/include/media/hevc-ctrls.h ++++ b/include/media/hevc-ctrls.h +@@ -80,7 +80,8 @@ struct v4l2_ctrl_hevc_sps { + __u8 num_short_term_ref_pic_sets; + __u8 num_long_term_ref_pics_sps; + +- __u8 padding[7]; ++ __u8 num_slices; ++ __u8 padding[6]; + + __u64 flags; + }; +@@ -174,6 +175,7 @@ struct v4l2_ctrl_hevc_slice_params { + + /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ + __u32 slice_segment_addr; ++ __u32 num_entry_point_offsets; + + /* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */ + __u8 nal_unit_type; +@@ -211,7 +213,9 @@ struct v4l2_ctrl_hevc_slice_params { + __u16 short_term_ref_pic_set_size; + __u16 long_term_ref_pic_set_size; + +- __u8 padding; ++ __u8 padding[5]; ++ ++ __u32 entry_point_offset_minus1[256]; + + /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ + struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; + +From f35f02f322ebb97970d021bc82d9cad0b6432e15 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 23 May 2020 15:17:45 +0000 +Subject: [PATCH] WIP: media: rkvdec: add HEVC backend + +NOTE: cabac table and scailing list code is copied 1:1 from mpp +TODO: fix lowdelay flag and rework the scaling list part + +Signed-off-by: Jonas Karlman +--- + drivers/staging/media/rkvdec/Makefile | 2 +- + drivers/staging/media/rkvdec/rkvdec-hevc.c | 2522 ++++++++++++++++++++ + drivers/staging/media/rkvdec/rkvdec-regs.h | 1 + + drivers/staging/media/rkvdec/rkvdec.c | 70 + + drivers/staging/media/rkvdec/rkvdec.h | 1 + + 5 files changed, 2595 insertions(+), 1 deletion(-) + create mode 100644 drivers/staging/media/rkvdec/rkvdec-hevc.c + +diff --git a/drivers/staging/media/rkvdec/Makefile b/drivers/staging/media/rkvdec/Makefile +index cb86b429cfaa..a77122641d14 100644 +--- a/drivers/staging/media/rkvdec/Makefile ++++ b/drivers/staging/media/rkvdec/Makefile +@@ -1,3 +1,3 @@ + obj-$(CONFIG_VIDEO_ROCKCHIP_VDEC) += rockchip-vdec.o + +-rockchip-vdec-y += rkvdec.o rkvdec-h264.o rkvdec-vp9.o ++rockchip-vdec-y += rkvdec.o rkvdec-h264.o rkvdec-hevc.o rkvdec-vp9.o +diff --git a/drivers/staging/media/rkvdec/rkvdec-hevc.c b/drivers/staging/media/rkvdec/rkvdec-hevc.c +new file mode 100644 +index 000000000000..03ba848411c6 +--- /dev/null ++++ b/drivers/staging/media/rkvdec/rkvdec-hevc.c +@@ -0,0 +1,2522 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Rockchip Video Decoder HEVC backend ++ * ++ * Copyright (C) 2019 Collabora, Ltd. ++ * Boris Brezillon ++ * ++ * Copyright (C) 2016 Rockchip Electronics Co., Ltd. ++ * Jeffy Chen ++ */ ++ ++#include ++ ++#include "rkvdec.h" ++#include "rkvdec-regs.h" ++ ++/* Size in u8/u32 units. */ ++#define RKV_CABAC_TABLE_SIZE 27456 ++#define RKV_SCALING_LIST_SIZE 1360 ++#define RKV_PPS_SIZE (80 / 4) ++#define RKV_PPS_LEN 64 ++#define RKV_RPS_SIZE (32 / 4) ++#define RKV_RPS_LEN 600 ++ ++struct rkvdec_sps_pps_packet { ++ u32 info[RKV_PPS_SIZE]; ++}; ++ ++struct rkvdec_rps_packet { ++ u32 info[RKV_RPS_SIZE]; ++}; ++ ++struct rkvdec_ps_field { ++ u16 offset; ++ u8 len; ++}; ++ ++#define PS_FIELD(_offset, _len) \ ++ ((struct rkvdec_ps_field){ _offset, _len }) ++ ++/* SPS */ ++#define VIDEO_PARAMETER_SET_ID PS_FIELD(0, 4) ++#define SEQ_PARAMETER_SET_ID PS_FIELD(4, 4) ++#define CHROMA_FORMAT_IDC PS_FIELD(8, 2) ++#define PIC_WIDTH_IN_LUMA_SAMPLES PS_FIELD(10, 13) ++#define PIC_HEIGHT_IN_LUMA_SAMPLES PS_FIELD(23, 13) ++#define BIT_DEPTH_LUMA PS_FIELD(36, 4) ++#define BIT_DEPTH_CHROMA PS_FIELD(40, 4) ++#define LOG2_MAX_PIC_ORDER_CNT_LSB PS_FIELD(44, 5) ++#define LOG2_DIFF_MAX_MIN_LUMA_CODING_BLOCK_SIZE PS_FIELD(49, 2) ++#define LOG2_MIN_LUMA_CODING_BLOCK_SIZE PS_FIELD(51, 3) ++#define LOG2_MIN_TRANSFORM_BLOCK_SIZE PS_FIELD(54, 3) ++#define LOG2_DIFF_MAX_MIN_LUMA_TRANSFORM_BLOCK_SIZE PS_FIELD(57, 2) ++#define MAX_TRANSFORM_HIERARCHY_DEPTH_INTER PS_FIELD(59, 3) ++#define MAX_TRANSFORM_HIERARCHY_DEPTH_INTRA PS_FIELD(62, 3) ++#define SCALING_LIST_ENABLED_FLAG PS_FIELD(65, 1) ++#define AMP_ENABLED_FLAG PS_FIELD(66, 1) ++#define SAMPLE_ADAPTIVE_OFFSET_ENABLED_FLAG PS_FIELD(67, 1) ++#define PCM_ENABLED_FLAG PS_FIELD(68, 1) ++#define PCM_SAMPLE_BIT_DEPTH_LUMA PS_FIELD(69, 4) ++#define PCM_SAMPLE_BIT_DEPTH_CHROMA PS_FIELD(73, 4) ++#define PCM_LOOP_FILTER_DISABLED_FLAG PS_FIELD(77, 1) ++#define LOG2_DIFF_MAX_MIN_PCM_LUMA_CODING_BLOCK_SIZE PS_FIELD(78, 3) ++#define LOG2_MIN_PCM_LUMA_CODING_BLOCK_SIZE PS_FIELD(81, 3) ++#define NUM_SHORT_TERM_REF_PIC_SETS PS_FIELD(84, 7) ++#define LONG_TERM_REF_PICS_PRESENT_FLAG PS_FIELD(91, 1) ++#define NUM_LONG_TERM_REF_PICS_SPS PS_FIELD(92, 6) ++#define SPS_TEMPORAL_MVP_ENABLED_FLAG PS_FIELD(98, 1) ++#define STRONG_INTRA_SMOOTHING_ENABLED_FLAG PS_FIELD(99, 1) ++/* PPS */ ++#define PIC_PARAMETER_SET_ID PS_FIELD(128, 6) ++#define PPS_SEQ_PARAMETER_SET_ID PS_FIELD(134, 4) ++#define DEPENDENT_SLICE_SEGMENTS_ENABLED_FLAG PS_FIELD(138, 1) ++#define OUTPUT_FLAG_PRESENT_FLAG PS_FIELD(139, 1) ++#define NUM_EXTRA_SLICE_HEADER_BITS PS_FIELD(140, 13) ++#define SIGN_DATA_HIDING_ENABLED_FLAG PS_FIELD(153, 1) ++#define CABAC_INIT_PRESENT_FLAG PS_FIELD(154, 1) ++#define NUM_REF_IDX_L0_DEFAULT_ACTIVE PS_FIELD(155, 4) ++#define NUM_REF_IDX_L1_DEFAULT_ACTIVE PS_FIELD(159, 4) ++#define INIT_QP_MINUS26 PS_FIELD(163, 7) ++#define CONSTRAINED_INTRA_PRED_FLAG PS_FIELD(170, 1) ++#define TRANSFORM_SKIP_ENABLED_FLAG PS_FIELD(171, 1) ++#define CU_QP_DELTA_ENABLED_FLAG PS_FIELD(172, 1) ++#define LOG2_MIN_CU_QP_DELTA_SIZE PS_FIELD(173, 3) ++#define PPS_CB_QP_OFFSET PS_FIELD(176, 5) ++#define PPS_CR_QP_OFFSET PS_FIELD(181, 5) ++#define PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT_FLAG PS_FIELD(186, 1) ++#define WEIGHTED_PRED_FLAG PS_FIELD(187, 1) ++#define WEIGHTED_BIPRED_FLAG PS_FIELD(188, 1) ++#define TRANSQUANT_BYPASS_ENABLED_FLAG PS_FIELD(189, 1) ++#define TILES_ENABLED_FLAG PS_FIELD(190, 1) ++#define ENTROPY_CODING_SYNC_ENABLED_FLAG PS_FIELD(191, 1) ++#define PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG PS_FIELD(192, 1) ++#define LOOP_FILTER_ACROSS_TILES_ENABLED_FLAG PS_FIELD(193, 1) ++#define DEBLOCKING_FILTER_OVERRIDE_ENABLED_FLAG PS_FIELD(194, 1) ++#define PPS_DEBLOCKING_FILTER_DISABLED_FLAG PS_FIELD(195, 1) ++#define PPS_BETA_OFFSET_DIV2 PS_FIELD(196, 4) ++#define PPS_TC_OFFSET_DIV2 PS_FIELD(200, 4) ++#define LISTS_MODIFICATION_PRESENT_FLAG PS_FIELD(204, 1) ++#define LOG2_PARALLEL_MERGE_LEVEL PS_FIELD(205, 3) ++#define SLICE_SEGMENT_HEADER_EXTENSION_PRESENT_FLAG PS_FIELD(208, 1) ++#define NUM_TILE_COLUMNS PS_FIELD(212, 5) ++#define NUM_TILE_ROWS PS_FIELD(217, 5) ++#define COLUMN_WIDTH(i) PS_FIELD(256 + (i * 8), 8) ++#define ROW_HEIGHT(i) PS_FIELD(416 + (i * 8), 8) ++#define SCALING_LIST_ADDRESS PS_FIELD(592, 32) ++ ++/* Data structure describing auxiliary buffer format. */ ++struct rkvdec_hevc_priv_tbl { ++ u8 cabac_table[RKV_CABAC_TABLE_SIZE]; ++ u8 scaling_list[RKV_SCALING_LIST_SIZE]; ++ struct rkvdec_sps_pps_packet param_set[RKV_PPS_LEN]; ++ struct rkvdec_rps_packet rps[RKV_RPS_LEN]; ++}; ++ ++struct rkvdec_hevc_run { ++ struct rkvdec_run base; ++ const struct v4l2_ctrl_hevc_slice_params *slices_params; ++ const struct v4l2_ctrl_hevc_sps *sps; ++ const struct v4l2_ctrl_hevc_pps *pps; ++ const struct v4l2_ctrl_hevc_scaling_matrix *scaling_matrix; ++ int num_slices; ++}; ++ ++struct rkvdec_hevc_ctx { ++ struct rkvdec_aux_buf priv_tbl; ++ struct v4l2_ctrl_hevc_scaling_matrix scaling_matrix_cache; ++}; ++ ++// TODO: refactor scaling list code, was copied 1:1 from mpp ++ ++typedef struct ScalingList { ++ /* This is a little wasteful, since sizeID 0 only needs 8 coeffs, ++ * and size ID 3 only has 2 arrays, not 6. */ ++ u8 sl[4][6][64]; ++ u8 sl_dc[2][6]; ++} scalingList_t; ++ ++typedef struct ScalingFactor_Model { ++ u8 scalingfactor0[1248]; ++ u8 scalingfactor1[96]; /*4X4 TU Rotate, total 16X4*/ ++ u8 scalingdc[12]; /*N1005 Vienna Meeting*/ ++ u8 reserverd[4]; /*16Bytes align*/ ++} scalingFactor_t; ++ ++#define SCALING_LIST_SIZE_NUM 4 ++ ++static void ++hal_record_scaling_list(scalingFactor_t *pScalingFactor_out, ++ scalingList_t *pScalingList) ++{ ++ int i; ++ u32 g_scalingListNum_model[SCALING_LIST_SIZE_NUM] = {6, 6, 6, 2}; // from C Model ++ u32 nIndex = 0; ++ u32 sizeId, matrixId, listId; ++ u8 *p = pScalingFactor_out->scalingfactor0; ++ u8 tmpBuf[8 * 8]; ++ ++ //output non-default scalingFactor Table (1248 BYTES) ++ for (sizeId = 0; sizeId < SCALING_LIST_SIZE_NUM; sizeId++) { ++ for (listId = 0; listId < g_scalingListNum_model[sizeId]; listId++) { ++ if (sizeId < 3) { ++ for (i = 0; i < (sizeId == 0 ? 16 : 64); i++) { ++ pScalingFactor_out->scalingfactor0[nIndex++] = (u8)pScalingList->sl[sizeId][listId][i]; ++ } ++ } else { ++ for (i = 0; i < 64; i ++) { ++ pScalingFactor_out->scalingfactor0[nIndex++] = (u8)pScalingList->sl[sizeId][listId][i]; ++ } ++ for (i = 0; i < 128; i ++) { ++ pScalingFactor_out->scalingfactor0[nIndex++] = 0; ++ } ++ } ++ } ++ } ++ //output non-default scalingFactor Table Rotation(96 Bytes) ++ nIndex = 0; ++ for (listId = 0; listId < g_scalingListNum_model[0]; listId++) { ++ u8 temp16[16] = {0}; ++ for (i = 0; i < 16; i ++) { ++ temp16[i] = (u8)pScalingList->sl[0][listId][i]; ++ } ++ for (i = 0; i < 4; i ++) { ++ pScalingFactor_out->scalingfactor1[nIndex++] = temp16[i]; ++ pScalingFactor_out->scalingfactor1[nIndex++] = temp16[i + 4]; ++ pScalingFactor_out->scalingfactor1[nIndex++] = temp16[i + 8]; ++ pScalingFactor_out->scalingfactor1[nIndex++] = temp16[i + 12]; ++ } ++ } ++ //output non-default ScalingList_DC_Coeff (12 BYTES) ++ nIndex = 0; ++ for (listId = 0; listId < g_scalingListNum_model[2]; listId++) { //sizeId = 2 ++ pScalingFactor_out->scalingdc[nIndex++] = (u8)pScalingList->sl_dc[0][listId];// zrh warning: sl_dc differed from scalingList->getScalingListDC ++ } ++ for (listId = 0; listId < g_scalingListNum_model[3]; listId++) { //sizeId = 3 ++ pScalingFactor_out->scalingdc[nIndex++] = (u8)pScalingList->sl_dc[1][listId];// zrh warning: sl_dc differed from scalingList->getScalingListDC ++ pScalingFactor_out->scalingdc[nIndex++] = 0; ++ pScalingFactor_out->scalingdc[nIndex++] = 0; ++ } ++ ++ //align 16X address ++ nIndex = 0; ++ for (i = 0; i < 4; i ++) { ++ pScalingFactor_out->reserverd[nIndex++] = 0; ++ } ++ ++ //----------------------All above code show the normal store way in HM-------------------------- ++ //--------from now on, the scalingfactor0 is rotated 90', the scalingfactor1 is also rotated 90' ++ ++ //sizeId == 0 ++ for (matrixId = 0; matrixId < 6; matrixId++) { ++ p = pScalingFactor_out->scalingfactor0 + matrixId * 16; ++ ++ for (i = 0; i < 4; i++) { ++ tmpBuf[4 * 0 + i] = p[i * 4 + 0]; ++ tmpBuf[4 * 1 + i] = p[i * 4 + 1]; ++ tmpBuf[4 * 2 + i] = p[i * 4 + 2]; ++ tmpBuf[4 * 3 + i] = p[i * 4 + 3]; ++ } ++ memcpy(p, tmpBuf, 4 * 4 * sizeof(u8)); ++ } ++ //sizeId == 1 ++ for (matrixId = 0; matrixId < 6; matrixId++) { ++ p = pScalingFactor_out->scalingfactor0 + 6 * 16 + matrixId * 64; ++ ++ for (i = 0; i < 8; i++) { ++ tmpBuf[8 * 0 + i] = p[i * 8 + 0]; ++ tmpBuf[8 * 1 + i] = p[i * 8 + 1]; ++ tmpBuf[8 * 2 + i] = p[i * 8 + 2]; ++ tmpBuf[8 * 3 + i] = p[i * 8 + 3]; ++ tmpBuf[8 * 4 + i] = p[i * 8 + 4]; ++ tmpBuf[8 * 5 + i] = p[i * 8 + 5]; ++ tmpBuf[8 * 6 + i] = p[i * 8 + 6]; ++ tmpBuf[8 * 7 + i] = p[i * 8 + 7]; ++ } ++ memcpy(p, tmpBuf, 8 * 8 * sizeof(u8)); ++ } ++ //sizeId == 2 ++ for (matrixId = 0; matrixId < 6; matrixId++) { ++ p = pScalingFactor_out->scalingfactor0 + 6 * 16 + 6 * 64 + matrixId * 64; ++ ++ for (i = 0; i < 8; i++) { ++ tmpBuf[8 * 0 + i] = p[i * 8 + 0]; ++ tmpBuf[8 * 1 + i] = p[i * 8 + 1]; ++ tmpBuf[8 * 2 + i] = p[i * 8 + 2]; ++ tmpBuf[8 * 3 + i] = p[i * 8 + 3]; ++ tmpBuf[8 * 4 + i] = p[i * 8 + 4]; ++ tmpBuf[8 * 5 + i] = p[i * 8 + 5]; ++ tmpBuf[8 * 6 + i] = p[i * 8 + 6]; ++ tmpBuf[8 * 7 + i] = p[i * 8 + 7]; ++ } ++ memcpy(p, tmpBuf, 8 * 8 * sizeof(u8)); ++ } ++ //sizeId == 3 ++ for (matrixId = 0; matrixId < 6; matrixId++) { ++ p = pScalingFactor_out->scalingfactor0 + 6 * 16 + 6 * 64 + 6 * 64 + matrixId * 64; ++ ++ for (i = 0; i < 8; i++) { ++ tmpBuf[8 * 0 + i] = p[i * 8 + 0]; ++ tmpBuf[8 * 1 + i] = p[i * 8 + 1]; ++ tmpBuf[8 * 2 + i] = p[i * 8 + 2]; ++ tmpBuf[8 * 3 + i] = p[i * 8 + 3]; ++ tmpBuf[8 * 4 + i] = p[i * 8 + 4]; ++ tmpBuf[8 * 5 + i] = p[i * 8 + 5]; ++ tmpBuf[8 * 6 + i] = p[i * 8 + 6]; ++ tmpBuf[8 * 7 + i] = p[i * 8 + 7]; ++ } ++ memcpy(p, tmpBuf, 8 * 8 * sizeof(u8)); ++ } ++ ++ //sizeId == 0 ++ for (matrixId = 0; matrixId < 6; matrixId++) { ++ p = pScalingFactor_out->scalingfactor1 + matrixId * 16; ++ ++ for (i = 0; i < 4; i++) { ++ tmpBuf[4 * 0 + i] = p[i * 4 + 0]; ++ tmpBuf[4 * 1 + i] = p[i * 4 + 1]; ++ tmpBuf[4 * 2 + i] = p[i * 4 + 2]; ++ tmpBuf[4 * 3 + i] = p[i * 4 + 3]; ++ } ++ memcpy(p, tmpBuf, 4 * 4 * sizeof(u8)); ++ } ++} ++ ++static const u8 rkvdec_hevc_cabac_table[RKV_CABAC_TABLE_SIZE] = { ++ 0x07, 0x0f, 0x48, 0x58, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0f, 0x40, 0x40, 0x40, 0x0f, 0x68, ++ 0x48, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x40, 0x40, 0x68, ++ 0x58, 0x60, 0x40, 0x1f, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x48, 0x48, 0x60, 0x60, 0x50, 0x58, ++ 0x50, 0x07, 0x58, 0x68, 0x50, 0x58, 0x68, 0x68, 0x68, 0x68, 0x68, 0x50, 0x48, 0x68, 0x60, 0x60, ++ 0x50, 0x58, 0x50, 0x07, 0x58, 0x68, 0x50, 0x58, 0x68, 0x68, 0x68, 0x68, 0x68, 0x50, 0x48, 0x68, ++ 0x48, 0x48, 0x1f, 0x58, 0x68, 0x68, 0x58, 0x60, 0x60, 0x60, 0x50, 0x50, 0x50, 0x48, 0x58, 0x58, ++ 0x37, 0x07, 0x58, 0x48, 0x58, 0x58, 0x37, 0x07, 0x58, 0x48, 0x58, 0x58, 0x37, 0x07, 0x58, 0x50, ++ 0x48, 0x1f, 0x1f, 0x0f, 0x0f, 0x0f, 0x0f, 0x07, 0x0f, 0x48, 0x68, 0x0f, 0x48, 0x68, 0x40, 0x40, ++ 0x50, 0x50, 0x07, 0x40, 0x50, 0x0f, 0x40, 0x48, 0x07, 0x40, 0x27, 0x50, 0x48, 0x48, 0x40, 0x0f, ++ 0x50, 0x37, 0x1f, 0x1f, 0x50, 0x37, 0x40, 0x27, 0x40, 0x07, 0x0f, 0x17, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x0f, 0x47, 0x57, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0f, 0x40, 0x40, 0x40, 0x0f, 0x66, ++ 0x47, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x00, 0x00, 0x67, ++ 0x57, 0x5e, 0x00, 0x1f, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x47, 0x47, 0x5f, 0x5f, 0x4f, 0x57, ++ 0x4f, 0x07, 0x57, 0x67, 0x4f, 0x57, 0x67, 0x67, 0x67, 0x67, 0x66, 0x4f, 0x47, 0x66, 0x5f, 0x5f, ++ 0x4f, 0x57, 0x4f, 0x07, 0x57, 0x67, 0x4f, 0x57, 0x67, 0x67, 0x67, 0x67, 0x66, 0x4f, 0x47, 0x66, ++ 0x46, 0x48, 0x20, 0x57, 0x67, 0x67, 0x57, 0x5f, 0x5f, 0x5e, 0x4f, 0x4f, 0x4f, 0x47, 0x57, 0x57, ++ 0x37, 0x07, 0x57, 0x47, 0x57, 0x57, 0x37, 0x07, 0x57, 0x47, 0x57, 0x57, 0x37, 0x07, 0x57, 0x4f, ++ 0x47, 0x1f, 0x1f, 0x0f, 0x10, 0x0f, 0x10, 0x07, 0x10, 0x47, 0x67, 0x10, 0x47, 0x67, 0x40, 0x40, ++ 0x4f, 0x4e, 0x08, 0x00, 0x4f, 0x0f, 0x00, 0x47, 0x07, 0x01, 0x27, 0x4e, 0x47, 0x47, 0x00, 0x0f, ++ 0x4f, 0x37, 0x1f, 0x1f, 0x4f, 0x36, 0x00, 0x27, 0x00, 0x07, 0x10, 0x17, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x0e, 0x47, 0x57, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0e, 0x40, 0x40, 0x40, 0x0e, 0x64, ++ 0x47, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x00, 0x00, 0x66, ++ 0x57, 0x5d, 0x00, 0x1e, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x47, 0x47, 0x5e, 0x5e, 0x4e, 0x56, ++ 0x4f, 0x07, 0x56, 0x66, 0x4f, 0x56, 0x66, 0x67, 0x66, 0x66, 0x64, 0x4e, 0x46, 0x64, 0x5e, 0x5e, ++ 0x4e, 0x56, 0x4f, 0x07, 0x56, 0x66, 0x4f, 0x56, 0x66, 0x67, 0x66, 0x66, 0x64, 0x4e, 0x46, 0x64, ++ 0x45, 0x48, 0x20, 0x57, 0x66, 0x66, 0x56, 0x5e, 0x5e, 0x5d, 0x4e, 0x4e, 0x4e, 0x46, 0x56, 0x57, ++ 0x36, 0x07, 0x56, 0x46, 0x56, 0x57, 0x36, 0x07, 0x56, 0x46, 0x56, 0x57, 0x36, 0x07, 0x56, 0x4f, ++ 0x47, 0x1e, 0x1e, 0x0f, 0x10, 0x0f, 0x10, 0x07, 0x10, 0x47, 0x66, 0x10, 0x47, 0x66, 0x40, 0x40, ++ 0x4f, 0x4d, 0x08, 0x00, 0x4f, 0x0f, 0x00, 0x47, 0x07, 0x03, 0x27, 0x4d, 0x47, 0x46, 0x01, 0x0f, ++ 0x4f, 0x36, 0x1f, 0x1e, 0x4f, 0x34, 0x01, 0x26, 0x00, 0x07, 0x10, 0x17, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x0d, 0x47, 0x57, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0e, 0x40, 0x40, 0x40, 0x0e, 0x62, ++ 0x47, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x00, 0x00, 0x65, ++ 0x57, 0x5c, 0x00, 0x1e, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x47, 0x47, 0x5d, 0x5d, 0x4e, 0x56, ++ 0x4f, 0x07, 0x56, 0x66, 0x4f, 0x55, 0x65, 0x67, 0x66, 0x65, 0x63, 0x4d, 0x46, 0x62, 0x5d, 0x5d, ++ 0x4e, 0x56, 0x4f, 0x07, 0x56, 0x66, 0x4f, 0x55, 0x65, 0x67, 0x66, 0x65, 0x63, 0x4d, 0x46, 0x62, ++ 0x44, 0x48, 0x20, 0x57, 0x65, 0x65, 0x56, 0x5d, 0x5d, 0x5c, 0x4e, 0x4d, 0x4e, 0x45, 0x56, 0x57, ++ 0x36, 0x07, 0x56, 0x45, 0x56, 0x57, 0x36, 0x07, 0x56, 0x45, 0x56, 0x57, 0x36, 0x07, 0x56, 0x4f, ++ 0x47, 0x1e, 0x1e, 0x0f, 0x10, 0x0f, 0x10, 0x07, 0x10, 0x47, 0x65, 0x10, 0x47, 0x65, 0x40, 0x40, ++ 0x4f, 0x4c, 0x08, 0x00, 0x4f, 0x0f, 0x00, 0x47, 0x07, 0x04, 0x27, 0x4c, 0x47, 0x45, 0x01, 0x0f, ++ 0x4f, 0x36, 0x1f, 0x1e, 0x4f, 0x33, 0x01, 0x25, 0x00, 0x07, 0x10, 0x17, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x0c, 0x46, 0x56, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0d, 0x40, 0x40, 0x40, 0x0d, 0x60, ++ 0x46, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x01, 0x01, 0x64, ++ 0x56, 0x5b, 0x01, 0x1d, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x46, 0x46, 0x5c, 0x5c, 0x4d, 0x55, ++ 0x4e, 0x07, 0x55, 0x65, 0x4e, 0x54, 0x64, 0x66, 0x65, 0x64, 0x61, 0x4c, 0x45, 0x60, 0x5c, 0x5c, ++ 0x4d, 0x55, 0x4e, 0x07, 0x55, 0x65, 0x4e, 0x54, 0x64, 0x66, 0x65, 0x64, 0x61, 0x4c, 0x45, 0x60, ++ 0x43, 0x49, 0x21, 0x56, 0x64, 0x64, 0x55, 0x5c, 0x5c, 0x5b, 0x4d, 0x4c, 0x4d, 0x44, 0x55, 0x56, ++ 0x35, 0x07, 0x55, 0x44, 0x55, 0x56, 0x35, 0x07, 0x55, 0x44, 0x55, 0x56, 0x35, 0x07, 0x55, 0x4e, ++ 0x46, 0x1d, 0x1d, 0x0f, 0x11, 0x0f, 0x11, 0x07, 0x11, 0x46, 0x64, 0x11, 0x46, 0x64, 0x40, 0x40, ++ 0x4e, 0x4b, 0x09, 0x01, 0x4e, 0x0f, 0x01, 0x46, 0x07, 0x06, 0x27, 0x4b, 0x46, 0x44, 0x02, 0x0f, ++ 0x4e, 0x35, 0x1e, 0x1d, 0x4e, 0x31, 0x02, 0x24, 0x01, 0x07, 0x11, 0x16, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x0b, 0x46, 0x56, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0c, 0x40, 0x40, 0x40, 0x0c, 0x5e, ++ 0x46, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x01, 0x01, 0x63, ++ 0x56, 0x59, 0x01, 0x1c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x46, 0x46, 0x5b, 0x5b, 0x4c, 0x54, ++ 0x4e, 0x07, 0x54, 0x64, 0x4e, 0x53, 0x63, 0x66, 0x64, 0x63, 0x60, 0x4b, 0x44, 0x5e, 0x5b, 0x5b, ++ 0x4c, 0x54, 0x4e, 0x07, 0x54, 0x64, 0x4e, 0x53, 0x63, 0x66, 0x64, 0x63, 0x60, 0x4b, 0x44, 0x5e, ++ 0x41, 0x49, 0x21, 0x56, 0x63, 0x63, 0x54, 0x5b, 0x5b, 0x59, 0x4c, 0x4b, 0x4c, 0x43, 0x54, 0x56, ++ 0x34, 0x07, 0x54, 0x43, 0x54, 0x56, 0x34, 0x07, 0x54, 0x43, 0x54, 0x56, 0x34, 0x07, 0x54, 0x4e, ++ 0x46, 0x1c, 0x1c, 0x0f, 0x11, 0x0f, 0x11, 0x07, 0x11, 0x46, 0x63, 0x11, 0x46, 0x63, 0x40, 0x40, ++ 0x4e, 0x49, 0x09, 0x01, 0x4e, 0x0f, 0x01, 0x46, 0x07, 0x07, 0x27, 0x49, 0x46, 0x43, 0x03, 0x0f, ++ 0x4e, 0x34, 0x1e, 0x1c, 0x4e, 0x30, 0x03, 0x23, 0x01, 0x07, 0x11, 0x16, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x0a, 0x46, 0x56, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0c, 0x40, 0x40, 0x40, 0x0c, 0x5c, ++ 0x46, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x01, 0x01, 0x62, ++ 0x56, 0x58, 0x01, 0x1c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x46, 0x46, 0x5a, 0x5a, 0x4c, 0x54, ++ 0x4e, 0x07, 0x54, 0x64, 0x4e, 0x52, 0x62, 0x66, 0x64, 0x62, 0x5e, 0x4a, 0x44, 0x5c, 0x5a, 0x5a, ++ 0x4c, 0x54, 0x4e, 0x07, 0x54, 0x64, 0x4e, 0x52, 0x62, 0x66, 0x64, 0x62, 0x5e, 0x4a, 0x44, 0x5c, ++ 0x40, 0x49, 0x21, 0x56, 0x62, 0x62, 0x54, 0x5a, 0x5a, 0x58, 0x4c, 0x4a, 0x4c, 0x42, 0x54, 0x56, ++ 0x34, 0x07, 0x54, 0x42, 0x54, 0x56, 0x34, 0x07, 0x54, 0x42, 0x54, 0x56, 0x34, 0x07, 0x54, 0x4e, ++ 0x46, 0x1c, 0x1c, 0x0f, 0x11, 0x0f, 0x11, 0x07, 0x11, 0x46, 0x62, 0x11, 0x46, 0x62, 0x40, 0x40, ++ 0x4e, 0x48, 0x09, 0x01, 0x4e, 0x0f, 0x01, 0x46, 0x07, 0x09, 0x27, 0x48, 0x46, 0x42, 0x03, 0x0f, ++ 0x4e, 0x34, 0x1e, 0x1c, 0x4e, 0x2e, 0x03, 0x22, 0x01, 0x07, 0x11, 0x16, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x09, 0x45, 0x55, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0b, 0x40, 0x40, 0x40, 0x0b, 0x5a, ++ 0x45, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x02, 0x02, 0x61, ++ 0x55, 0x57, 0x02, 0x1b, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x45, 0x45, 0x59, 0x59, 0x4b, 0x53, ++ 0x4d, 0x07, 0x53, 0x63, 0x4d, 0x51, 0x61, 0x65, 0x63, 0x61, 0x5d, 0x49, 0x43, 0x5a, 0x59, 0x59, ++ 0x4b, 0x53, 0x4d, 0x07, 0x53, 0x63, 0x4d, 0x51, 0x61, 0x65, 0x63, 0x61, 0x5d, 0x49, 0x43, 0x5a, ++ 0x00, 0x4a, 0x22, 0x55, 0x61, 0x61, 0x53, 0x59, 0x59, 0x57, 0x4b, 0x49, 0x4b, 0x41, 0x53, 0x55, ++ 0x33, 0x07, 0x53, 0x41, 0x53, 0x55, 0x33, 0x07, 0x53, 0x41, 0x53, 0x55, 0x33, 0x07, 0x53, 0x4d, ++ 0x45, 0x1b, 0x1b, 0x0f, 0x12, 0x0f, 0x12, 0x07, 0x12, 0x45, 0x61, 0x12, 0x45, 0x61, 0x40, 0x40, ++ 0x4d, 0x47, 0x0a, 0x02, 0x4d, 0x0f, 0x02, 0x45, 0x07, 0x0a, 0x27, 0x47, 0x45, 0x41, 0x04, 0x0f, ++ 0x4d, 0x33, 0x1d, 0x1b, 0x4d, 0x2d, 0x04, 0x21, 0x02, 0x07, 0x12, 0x15, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x08, 0x45, 0x55, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0a, 0x40, 0x40, 0x40, 0x0a, 0x59, ++ 0x45, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x02, 0x02, 0x60, ++ 0x55, 0x56, 0x02, 0x1a, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x45, 0x45, 0x58, 0x58, 0x4b, 0x53, ++ 0x4d, 0x07, 0x53, 0x63, 0x4d, 0x50, 0x60, 0x65, 0x63, 0x60, 0x5b, 0x48, 0x43, 0x59, 0x58, 0x58, ++ 0x4b, 0x53, 0x4d, 0x07, 0x53, 0x63, 0x4d, 0x50, 0x60, 0x65, 0x63, 0x60, 0x5b, 0x48, 0x43, 0x59, ++ 0x01, 0x4a, 0x22, 0x55, 0x60, 0x60, 0x53, 0x58, 0x58, 0x56, 0x4b, 0x48, 0x4b, 0x40, 0x53, 0x55, ++ 0x32, 0x07, 0x53, 0x40, 0x53, 0x55, 0x32, 0x07, 0x53, 0x40, 0x53, 0x55, 0x32, 0x07, 0x53, 0x4d, ++ 0x45, 0x1a, 0x1a, 0x0f, 0x12, 0x0f, 0x12, 0x07, 0x12, 0x45, 0x60, 0x12, 0x45, 0x60, 0x40, 0x40, ++ 0x4d, 0x46, 0x0a, 0x02, 0x4d, 0x0f, 0x02, 0x45, 0x07, 0x0c, 0x27, 0x46, 0x45, 0x40, 0x04, 0x0f, ++ 0x4d, 0x32, 0x1d, 0x1a, 0x4d, 0x2b, 0x04, 0x20, 0x02, 0x07, 0x12, 0x15, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x07, 0x45, 0x55, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0a, 0x40, 0x40, 0x40, 0x0a, 0x57, ++ 0x45, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x02, 0x02, 0x5f, ++ 0x55, 0x54, 0x02, 0x1a, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x45, 0x45, 0x57, 0x57, 0x4a, 0x52, ++ 0x4d, 0x07, 0x52, 0x62, 0x4d, 0x4f, 0x5f, 0x65, 0x62, 0x5f, 0x59, 0x47, 0x42, 0x57, 0x57, 0x57, ++ 0x4a, 0x52, 0x4d, 0x07, 0x52, 0x62, 0x4d, 0x4f, 0x5f, 0x65, 0x62, 0x5f, 0x59, 0x47, 0x42, 0x57, ++ 0x03, 0x4a, 0x22, 0x55, 0x5f, 0x5f, 0x52, 0x57, 0x57, 0x54, 0x4a, 0x47, 0x4a, 0x00, 0x52, 0x55, ++ 0x32, 0x07, 0x52, 0x00, 0x52, 0x55, 0x32, 0x07, 0x52, 0x00, 0x52, 0x55, 0x32, 0x07, 0x52, 0x4d, ++ 0x45, 0x1a, 0x1a, 0x0f, 0x12, 0x0f, 0x12, 0x07, 0x12, 0x45, 0x5f, 0x12, 0x45, 0x5f, 0x40, 0x40, ++ 0x4d, 0x44, 0x0a, 0x02, 0x4d, 0x0f, 0x02, 0x45, 0x07, 0x0e, 0x27, 0x44, 0x45, 0x00, 0x05, 0x0f, ++ 0x4d, 0x32, 0x1d, 0x1a, 0x4d, 0x29, 0x05, 0x1f, 0x02, 0x07, 0x12, 0x15, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x06, 0x44, 0x54, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x09, 0x40, 0x40, 0x40, 0x09, 0x55, ++ 0x44, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x03, 0x03, 0x5e, ++ 0x54, 0x53, 0x03, 0x19, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x44, 0x44, 0x56, 0x56, 0x49, 0x51, ++ 0x4c, 0x07, 0x51, 0x61, 0x4c, 0x4e, 0x5e, 0x64, 0x61, 0x5e, 0x58, 0x46, 0x41, 0x55, 0x56, 0x56, ++ 0x49, 0x51, 0x4c, 0x07, 0x51, 0x61, 0x4c, 0x4e, 0x5e, 0x64, 0x61, 0x5e, 0x58, 0x46, 0x41, 0x55, ++ 0x04, 0x4b, 0x23, 0x54, 0x5e, 0x5e, 0x51, 0x56, 0x56, 0x53, 0x49, 0x46, 0x49, 0x01, 0x51, 0x54, ++ 0x31, 0x07, 0x51, 0x01, 0x51, 0x54, 0x31, 0x07, 0x51, 0x01, 0x51, 0x54, 0x31, 0x07, 0x51, 0x4c, ++ 0x44, 0x19, 0x19, 0x0f, 0x13, 0x0f, 0x13, 0x07, 0x13, 0x44, 0x5e, 0x13, 0x44, 0x5e, 0x40, 0x40, ++ 0x4c, 0x43, 0x0b, 0x03, 0x4c, 0x0f, 0x03, 0x44, 0x07, 0x0f, 0x27, 0x43, 0x44, 0x01, 0x06, 0x0f, ++ 0x4c, 0x31, 0x1c, 0x19, 0x4c, 0x28, 0x06, 0x1e, 0x03, 0x07, 0x13, 0x14, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x05, 0x44, 0x54, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x09, 0x40, 0x40, 0x40, 0x09, 0x53, ++ 0x44, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x03, 0x03, 0x5d, ++ 0x54, 0x52, 0x03, 0x19, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x44, 0x44, 0x55, 0x55, 0x49, 0x51, ++ 0x4c, 0x07, 0x51, 0x61, 0x4c, 0x4d, 0x5d, 0x64, 0x61, 0x5d, 0x56, 0x45, 0x41, 0x53, 0x55, 0x55, ++ 0x49, 0x51, 0x4c, 0x07, 0x51, 0x61, 0x4c, 0x4d, 0x5d, 0x64, 0x61, 0x5d, 0x56, 0x45, 0x41, 0x53, ++ 0x05, 0x4b, 0x23, 0x54, 0x5d, 0x5d, 0x51, 0x55, 0x55, 0x52, 0x49, 0x45, 0x49, 0x02, 0x51, 0x54, ++ 0x31, 0x07, 0x51, 0x02, 0x51, 0x54, 0x31, 0x07, 0x51, 0x02, 0x51, 0x54, 0x31, 0x07, 0x51, 0x4c, ++ 0x44, 0x19, 0x19, 0x0f, 0x13, 0x0f, 0x13, 0x07, 0x13, 0x44, 0x5d, 0x13, 0x44, 0x5d, 0x40, 0x40, ++ 0x4c, 0x42, 0x0b, 0x03, 0x4c, 0x0f, 0x03, 0x44, 0x07, 0x11, 0x27, 0x42, 0x44, 0x02, 0x06, 0x0f, ++ 0x4c, 0x31, 0x1c, 0x19, 0x4c, 0x26, 0x06, 0x1d, 0x03, 0x07, 0x13, 0x14, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x04, 0x44, 0x54, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x08, 0x40, 0x40, 0x40, 0x08, 0x51, ++ 0x44, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x03, 0x03, 0x5c, ++ 0x54, 0x51, 0x03, 0x18, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x44, 0x44, 0x54, 0x54, 0x48, 0x50, ++ 0x4c, 0x07, 0x50, 0x60, 0x4c, 0x4c, 0x5c, 0x64, 0x60, 0x5c, 0x55, 0x44, 0x40, 0x51, 0x54, 0x54, ++ 0x48, 0x50, 0x4c, 0x07, 0x50, 0x60, 0x4c, 0x4c, 0x5c, 0x64, 0x60, 0x5c, 0x55, 0x44, 0x40, 0x51, ++ 0x06, 0x4b, 0x23, 0x54, 0x5c, 0x5c, 0x50, 0x54, 0x54, 0x51, 0x48, 0x44, 0x48, 0x03, 0x50, 0x54, ++ 0x30, 0x07, 0x50, 0x03, 0x50, 0x54, 0x30, 0x07, 0x50, 0x03, 0x50, 0x54, 0x30, 0x07, 0x50, 0x4c, ++ 0x44, 0x18, 0x18, 0x0f, 0x13, 0x0f, 0x13, 0x07, 0x13, 0x44, 0x5c, 0x13, 0x44, 0x5c, 0x40, 0x40, ++ 0x4c, 0x41, 0x0b, 0x03, 0x4c, 0x0f, 0x03, 0x44, 0x07, 0x12, 0x27, 0x41, 0x44, 0x03, 0x07, 0x0f, ++ 0x4c, 0x30, 0x1c, 0x18, 0x4c, 0x25, 0x07, 0x1c, 0x03, 0x07, 0x13, 0x14, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x03, 0x43, 0x53, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x40, 0x40, 0x40, 0x07, 0x4f, ++ 0x43, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x04, 0x04, 0x5b, ++ 0x53, 0x4f, 0x04, 0x17, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x43, 0x43, 0x53, 0x53, 0x47, 0x4f, ++ 0x4b, 0x07, 0x4f, 0x5f, 0x4b, 0x4b, 0x5b, 0x63, 0x5f, 0x5b, 0x53, 0x43, 0x00, 0x4f, 0x53, 0x53, ++ 0x47, 0x4f, 0x4b, 0x07, 0x4f, 0x5f, 0x4b, 0x4b, 0x5b, 0x63, 0x5f, 0x5b, 0x53, 0x43, 0x00, 0x4f, ++ 0x08, 0x4c, 0x24, 0x53, 0x5b, 0x5b, 0x4f, 0x53, 0x53, 0x4f, 0x47, 0x43, 0x47, 0x04, 0x4f, 0x53, ++ 0x2f, 0x07, 0x4f, 0x04, 0x4f, 0x53, 0x2f, 0x07, 0x4f, 0x04, 0x4f, 0x53, 0x2f, 0x07, 0x4f, 0x4b, ++ 0x43, 0x17, 0x17, 0x0f, 0x14, 0x0f, 0x14, 0x07, 0x14, 0x43, 0x5b, 0x14, 0x43, 0x5b, 0x40, 0x40, ++ 0x4b, 0x00, 0x0c, 0x04, 0x4b, 0x0f, 0x04, 0x43, 0x07, 0x14, 0x27, 0x00, 0x43, 0x04, 0x08, 0x0f, ++ 0x4b, 0x2f, 0x1b, 0x17, 0x4b, 0x23, 0x08, 0x1b, 0x04, 0x07, 0x14, 0x13, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x02, 0x43, 0x53, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x40, 0x40, 0x40, 0x07, 0x4d, ++ 0x43, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x04, 0x04, 0x5a, ++ 0x53, 0x4e, 0x04, 0x17, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x43, 0x43, 0x52, 0x52, 0x47, 0x4f, ++ 0x4b, 0x07, 0x4f, 0x5f, 0x4b, 0x4a, 0x5a, 0x63, 0x5f, 0x5a, 0x52, 0x42, 0x00, 0x4d, 0x52, 0x52, ++ 0x47, 0x4f, 0x4b, 0x07, 0x4f, 0x5f, 0x4b, 0x4a, 0x5a, 0x63, 0x5f, 0x5a, 0x52, 0x42, 0x00, 0x4d, ++ 0x09, 0x4c, 0x24, 0x53, 0x5a, 0x5a, 0x4f, 0x52, 0x52, 0x4e, 0x47, 0x42, 0x47, 0x05, 0x4f, 0x53, ++ 0x2f, 0x07, 0x4f, 0x05, 0x4f, 0x53, 0x2f, 0x07, 0x4f, 0x05, 0x4f, 0x53, 0x2f, 0x07, 0x4f, 0x4b, ++ 0x43, 0x17, 0x17, 0x0f, 0x14, 0x0f, 0x14, 0x07, 0x14, 0x43, 0x5a, 0x14, 0x43, 0x5a, 0x40, 0x40, ++ 0x4b, 0x01, 0x0c, 0x04, 0x4b, 0x0f, 0x04, 0x43, 0x07, 0x15, 0x27, 0x01, 0x43, 0x05, 0x08, 0x0f, ++ 0x4b, 0x2f, 0x1b, 0x17, 0x4b, 0x22, 0x08, 0x1a, 0x04, 0x07, 0x14, 0x13, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x01, 0x43, 0x53, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x06, 0x40, 0x40, 0x40, 0x06, 0x4b, ++ 0x43, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x04, 0x04, 0x59, ++ 0x53, 0x4d, 0x04, 0x16, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x43, 0x43, 0x51, 0x51, 0x46, 0x4e, ++ 0x4b, 0x07, 0x4e, 0x5e, 0x4b, 0x49, 0x59, 0x63, 0x5e, 0x59, 0x50, 0x41, 0x01, 0x4b, 0x51, 0x51, ++ 0x46, 0x4e, 0x4b, 0x07, 0x4e, 0x5e, 0x4b, 0x49, 0x59, 0x63, 0x5e, 0x59, 0x50, 0x41, 0x01, 0x4b, ++ 0x0a, 0x4c, 0x24, 0x53, 0x59, 0x59, 0x4e, 0x51, 0x51, 0x4d, 0x46, 0x41, 0x46, 0x06, 0x4e, 0x53, ++ 0x2e, 0x07, 0x4e, 0x06, 0x4e, 0x53, 0x2e, 0x07, 0x4e, 0x06, 0x4e, 0x53, 0x2e, 0x07, 0x4e, 0x4b, ++ 0x43, 0x16, 0x16, 0x0f, 0x14, 0x0f, 0x14, 0x07, 0x14, 0x43, 0x59, 0x14, 0x43, 0x59, 0x40, 0x40, ++ 0x4b, 0x02, 0x0c, 0x04, 0x4b, 0x0f, 0x04, 0x43, 0x07, 0x17, 0x27, 0x02, 0x43, 0x06, 0x09, 0x0f, ++ 0x4b, 0x2e, 0x1b, 0x16, 0x4b, 0x20, 0x09, 0x19, 0x04, 0x07, 0x14, 0x13, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x00, 0x43, 0x53, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x05, 0x40, 0x40, 0x40, 0x05, 0x4a, ++ 0x43, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x04, 0x04, 0x59, ++ 0x53, 0x4c, 0x04, 0x15, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x43, 0x43, 0x51, 0x51, 0x46, 0x4e, ++ 0x4b, 0x07, 0x4e, 0x5e, 0x4b, 0x49, 0x59, 0x63, 0x5e, 0x59, 0x4f, 0x41, 0x01, 0x4a, 0x51, 0x51, ++ 0x46, 0x4e, 0x4b, 0x07, 0x4e, 0x5e, 0x4b, 0x49, 0x59, 0x63, 0x5e, 0x59, 0x4f, 0x41, 0x01, 0x4a, ++ 0x0b, 0x4d, 0x24, 0x53, 0x59, 0x59, 0x4e, 0x51, 0x51, 0x4c, 0x46, 0x41, 0x46, 0x06, 0x4e, 0x53, ++ 0x2d, 0x07, 0x4e, 0x06, 0x4e, 0x53, 0x2d, 0x07, 0x4e, 0x06, 0x4e, 0x53, 0x2d, 0x07, 0x4e, 0x4b, ++ 0x43, 0x15, 0x15, 0x0f, 0x14, 0x0f, 0x14, 0x07, 0x14, 0x43, 0x59, 0x14, 0x43, 0x59, 0x40, 0x40, ++ 0x4b, 0x03, 0x0c, 0x04, 0x4b, 0x0f, 0x04, 0x43, 0x07, 0x18, 0x27, 0x03, 0x43, 0x06, 0x09, 0x0f, ++ 0x4b, 0x2d, 0x1a, 0x15, 0x4b, 0x1e, 0x09, 0x18, 0x04, 0x07, 0x14, 0x12, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x00, 0x42, 0x52, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x05, 0x40, 0x40, 0x40, 0x05, 0x48, ++ 0x42, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x05, 0x05, 0x58, ++ 0x52, 0x4a, 0x05, 0x15, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x42, 0x42, 0x50, 0x50, 0x45, 0x4d, ++ 0x4a, 0x07, 0x4d, 0x5d, 0x4a, 0x48, 0x58, 0x62, 0x5d, 0x58, 0x4d, 0x40, 0x02, 0x48, 0x50, 0x50, ++ 0x45, 0x4d, 0x4a, 0x07, 0x4d, 0x5d, 0x4a, 0x48, 0x58, 0x62, 0x5d, 0x58, 0x4d, 0x40, 0x02, 0x48, ++ 0x0d, 0x4d, 0x25, 0x52, 0x58, 0x58, 0x4d, 0x50, 0x50, 0x4a, 0x45, 0x40, 0x45, 0x07, 0x4d, 0x52, ++ 0x2d, 0x07, 0x4d, 0x07, 0x4d, 0x52, 0x2d, 0x07, 0x4d, 0x07, 0x4d, 0x52, 0x2d, 0x07, 0x4d, 0x4a, ++ 0x42, 0x15, 0x15, 0x0f, 0x15, 0x0f, 0x15, 0x07, 0x15, 0x42, 0x58, 0x15, 0x42, 0x58, 0x40, 0x40, ++ 0x4a, 0x05, 0x0d, 0x05, 0x4a, 0x0f, 0x05, 0x42, 0x07, 0x1a, 0x27, 0x05, 0x42, 0x07, 0x0a, 0x0f, ++ 0x4a, 0x2d, 0x1a, 0x15, 0x4a, 0x1d, 0x0a, 0x18, 0x05, 0x07, 0x15, 0x12, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x40, 0x42, 0x52, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x04, 0x40, 0x40, 0x40, 0x04, 0x46, ++ 0x42, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x05, 0x05, 0x57, ++ 0x52, 0x49, 0x05, 0x14, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x42, 0x42, 0x4f, 0x4f, 0x44, 0x4c, ++ 0x4a, 0x07, 0x4c, 0x5c, 0x4a, 0x47, 0x57, 0x62, 0x5c, 0x57, 0x4b, 0x00, 0x03, 0x46, 0x4f, 0x4f, ++ 0x44, 0x4c, 0x4a, 0x07, 0x4c, 0x5c, 0x4a, 0x47, 0x57, 0x62, 0x5c, 0x57, 0x4b, 0x00, 0x03, 0x46, ++ 0x0e, 0x4d, 0x25, 0x52, 0x57, 0x57, 0x4c, 0x4f, 0x4f, 0x49, 0x44, 0x00, 0x44, 0x08, 0x4c, 0x52, ++ 0x2c, 0x07, 0x4c, 0x08, 0x4c, 0x52, 0x2c, 0x07, 0x4c, 0x08, 0x4c, 0x52, 0x2c, 0x07, 0x4c, 0x4a, ++ 0x42, 0x14, 0x14, 0x0f, 0x15, 0x0f, 0x15, 0x07, 0x15, 0x42, 0x57, 0x15, 0x42, 0x57, 0x40, 0x40, ++ 0x4a, 0x06, 0x0d, 0x05, 0x4a, 0x0f, 0x05, 0x42, 0x07, 0x1c, 0x27, 0x06, 0x42, 0x08, 0x0b, 0x0f, ++ 0x4a, 0x2c, 0x1a, 0x14, 0x4a, 0x1b, 0x0b, 0x17, 0x05, 0x07, 0x15, 0x12, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x41, 0x42, 0x52, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x04, 0x40, 0x40, 0x40, 0x04, 0x44, ++ 0x42, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x05, 0x05, 0x56, ++ 0x52, 0x48, 0x05, 0x14, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x42, 0x42, 0x4e, 0x4e, 0x44, 0x4c, ++ 0x4a, 0x07, 0x4c, 0x5c, 0x4a, 0x46, 0x56, 0x62, 0x5c, 0x56, 0x4a, 0x01, 0x03, 0x44, 0x4e, 0x4e, ++ 0x44, 0x4c, 0x4a, 0x07, 0x4c, 0x5c, 0x4a, 0x46, 0x56, 0x62, 0x5c, 0x56, 0x4a, 0x01, 0x03, 0x44, ++ 0x0f, 0x4d, 0x25, 0x52, 0x56, 0x56, 0x4c, 0x4e, 0x4e, 0x48, 0x44, 0x01, 0x44, 0x09, 0x4c, 0x52, ++ 0x2c, 0x07, 0x4c, 0x09, 0x4c, 0x52, 0x2c, 0x07, 0x4c, 0x09, 0x4c, 0x52, 0x2c, 0x07, 0x4c, 0x4a, ++ 0x42, 0x14, 0x14, 0x0f, 0x15, 0x0f, 0x15, 0x07, 0x15, 0x42, 0x56, 0x15, 0x42, 0x56, 0x40, 0x40, ++ 0x4a, 0x07, 0x0d, 0x05, 0x4a, 0x0f, 0x05, 0x42, 0x07, 0x1d, 0x27, 0x07, 0x42, 0x09, 0x0b, 0x0f, ++ 0x4a, 0x2c, 0x1a, 0x14, 0x4a, 0x1a, 0x0b, 0x16, 0x05, 0x07, 0x15, 0x12, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x42, 0x41, 0x51, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x03, 0x40, 0x40, 0x40, 0x03, 0x42, ++ 0x41, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x06, 0x06, 0x55, ++ 0x51, 0x47, 0x06, 0x13, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4d, 0x4d, 0x43, 0x4b, ++ 0x49, 0x07, 0x4b, 0x5b, 0x49, 0x45, 0x55, 0x61, 0x5b, 0x55, 0x48, 0x02, 0x04, 0x42, 0x4d, 0x4d, ++ 0x43, 0x4b, 0x49, 0x07, 0x4b, 0x5b, 0x49, 0x45, 0x55, 0x61, 0x5b, 0x55, 0x48, 0x02, 0x04, 0x42, ++ 0x10, 0x4e, 0x26, 0x51, 0x55, 0x55, 0x4b, 0x4d, 0x4d, 0x47, 0x43, 0x02, 0x43, 0x0a, 0x4b, 0x51, ++ 0x2b, 0x07, 0x4b, 0x0a, 0x4b, 0x51, 0x2b, 0x07, 0x4b, 0x0a, 0x4b, 0x51, 0x2b, 0x07, 0x4b, 0x49, ++ 0x41, 0x13, 0x13, 0x0f, 0x16, 0x0f, 0x16, 0x07, 0x16, 0x41, 0x55, 0x16, 0x41, 0x55, 0x40, 0x40, ++ 0x49, 0x08, 0x0e, 0x06, 0x49, 0x0f, 0x06, 0x41, 0x07, 0x1f, 0x27, 0x08, 0x41, 0x0a, 0x0c, 0x0f, ++ 0x49, 0x2b, 0x19, 0x13, 0x49, 0x18, 0x0c, 0x15, 0x06, 0x07, 0x16, 0x11, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x43, 0x41, 0x51, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x02, 0x40, 0x40, 0x40, 0x02, 0x40, ++ 0x41, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x06, 0x06, 0x54, ++ 0x51, 0x45, 0x06, 0x12, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4c, 0x4c, 0x42, 0x4a, ++ 0x49, 0x07, 0x4a, 0x5a, 0x49, 0x44, 0x54, 0x61, 0x5a, 0x54, 0x47, 0x03, 0x05, 0x40, 0x4c, 0x4c, ++ 0x42, 0x4a, 0x49, 0x07, 0x4a, 0x5a, 0x49, 0x44, 0x54, 0x61, 0x5a, 0x54, 0x47, 0x03, 0x05, 0x40, ++ 0x12, 0x4e, 0x26, 0x51, 0x54, 0x54, 0x4a, 0x4c, 0x4c, 0x45, 0x42, 0x03, 0x42, 0x0b, 0x4a, 0x51, ++ 0x2a, 0x07, 0x4a, 0x0b, 0x4a, 0x51, 0x2a, 0x07, 0x4a, 0x0b, 0x4a, 0x51, 0x2a, 0x07, 0x4a, 0x49, ++ 0x41, 0x12, 0x12, 0x0f, 0x16, 0x0f, 0x16, 0x07, 0x16, 0x41, 0x54, 0x16, 0x41, 0x54, 0x40, 0x40, ++ 0x49, 0x0a, 0x0e, 0x06, 0x49, 0x0f, 0x06, 0x41, 0x07, 0x20, 0x27, 0x0a, 0x41, 0x0b, 0x0d, 0x0f, ++ 0x49, 0x2a, 0x19, 0x12, 0x49, 0x17, 0x0d, 0x14, 0x06, 0x07, 0x16, 0x11, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x44, 0x41, 0x51, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x02, 0x40, 0x40, 0x40, 0x02, 0x01, ++ 0x41, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x06, 0x06, 0x53, ++ 0x51, 0x44, 0x06, 0x12, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4b, 0x4b, 0x42, 0x4a, ++ 0x49, 0x07, 0x4a, 0x5a, 0x49, 0x43, 0x53, 0x61, 0x5a, 0x53, 0x45, 0x04, 0x05, 0x01, 0x4b, 0x4b, ++ 0x42, 0x4a, 0x49, 0x07, 0x4a, 0x5a, 0x49, 0x43, 0x53, 0x61, 0x5a, 0x53, 0x45, 0x04, 0x05, 0x01, ++ 0x13, 0x4e, 0x26, 0x51, 0x53, 0x53, 0x4a, 0x4b, 0x4b, 0x44, 0x42, 0x04, 0x42, 0x0c, 0x4a, 0x51, ++ 0x2a, 0x07, 0x4a, 0x0c, 0x4a, 0x51, 0x2a, 0x07, 0x4a, 0x0c, 0x4a, 0x51, 0x2a, 0x07, 0x4a, 0x49, ++ 0x41, 0x12, 0x12, 0x0f, 0x16, 0x0f, 0x16, 0x07, 0x16, 0x41, 0x53, 0x16, 0x41, 0x53, 0x40, 0x40, ++ 0x49, 0x0b, 0x0e, 0x06, 0x49, 0x0f, 0x06, 0x41, 0x07, 0x22, 0x27, 0x0b, 0x41, 0x0c, 0x0d, 0x0f, ++ 0x49, 0x2a, 0x19, 0x12, 0x49, 0x15, 0x0d, 0x13, 0x06, 0x07, 0x16, 0x11, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x45, 0x40, 0x50, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x01, 0x40, 0x40, 0x40, 0x01, 0x03, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x07, 0x07, 0x52, ++ 0x50, 0x43, 0x07, 0x11, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4a, 0x4a, 0x41, 0x49, ++ 0x48, 0x07, 0x49, 0x59, 0x48, 0x42, 0x52, 0x60, 0x59, 0x52, 0x44, 0x05, 0x06, 0x03, 0x4a, 0x4a, ++ 0x41, 0x49, 0x48, 0x07, 0x49, 0x59, 0x48, 0x42, 0x52, 0x60, 0x59, 0x52, 0x44, 0x05, 0x06, 0x03, ++ 0x14, 0x4f, 0x27, 0x50, 0x52, 0x52, 0x49, 0x4a, 0x4a, 0x43, 0x41, 0x05, 0x41, 0x0d, 0x49, 0x50, ++ 0x29, 0x07, 0x49, 0x0d, 0x49, 0x50, 0x29, 0x07, 0x49, 0x0d, 0x49, 0x50, 0x29, 0x07, 0x49, 0x48, ++ 0x40, 0x11, 0x11, 0x0f, 0x17, 0x0f, 0x17, 0x07, 0x17, 0x40, 0x52, 0x17, 0x40, 0x52, 0x40, 0x40, ++ 0x48, 0x0c, 0x0f, 0x07, 0x48, 0x0f, 0x07, 0x40, 0x07, 0x23, 0x27, 0x0c, 0x40, 0x0d, 0x0e, 0x0f, ++ 0x48, 0x29, 0x18, 0x11, 0x48, 0x14, 0x0e, 0x12, 0x07, 0x07, 0x17, 0x10, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x46, 0x40, 0x50, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, 0x04, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x07, 0x07, 0x51, ++ 0x50, 0x42, 0x07, 0x10, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x49, 0x49, 0x41, 0x49, ++ 0x48, 0x07, 0x49, 0x59, 0x48, 0x41, 0x51, 0x60, 0x59, 0x51, 0x42, 0x06, 0x06, 0x04, 0x49, 0x49, ++ 0x41, 0x49, 0x48, 0x07, 0x49, 0x59, 0x48, 0x41, 0x51, 0x60, 0x59, 0x51, 0x42, 0x06, 0x06, 0x04, ++ 0x15, 0x4f, 0x27, 0x50, 0x51, 0x51, 0x49, 0x49, 0x49, 0x42, 0x41, 0x06, 0x41, 0x0e, 0x49, 0x50, ++ 0x28, 0x07, 0x49, 0x0e, 0x49, 0x50, 0x28, 0x07, 0x49, 0x0e, 0x49, 0x50, 0x28, 0x07, 0x49, 0x48, ++ 0x40, 0x10, 0x10, 0x0f, 0x17, 0x0f, 0x17, 0x07, 0x17, 0x40, 0x51, 0x17, 0x40, 0x51, 0x40, 0x40, ++ 0x48, 0x0d, 0x0f, 0x07, 0x48, 0x0f, 0x07, 0x40, 0x07, 0x25, 0x27, 0x0d, 0x40, 0x0e, 0x0e, 0x0f, ++ 0x48, 0x28, 0x18, 0x10, 0x48, 0x12, 0x0e, 0x11, 0x07, 0x07, 0x17, 0x10, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x47, 0x40, 0x50, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, 0x06, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x07, 0x07, 0x50, ++ 0x50, 0x40, 0x07, 0x10, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x48, 0x48, 0x40, 0x48, ++ 0x48, 0x07, 0x48, 0x58, 0x48, 0x40, 0x50, 0x60, 0x58, 0x50, 0x40, 0x07, 0x07, 0x06, 0x48, 0x48, ++ 0x40, 0x48, 0x48, 0x07, 0x48, 0x58, 0x48, 0x40, 0x50, 0x60, 0x58, 0x50, 0x40, 0x07, 0x07, 0x06, ++ 0x17, 0x4f, 0x27, 0x50, 0x50, 0x50, 0x48, 0x48, 0x48, 0x40, 0x40, 0x07, 0x40, 0x0f, 0x48, 0x50, ++ 0x28, 0x07, 0x48, 0x0f, 0x48, 0x50, 0x28, 0x07, 0x48, 0x0f, 0x48, 0x50, 0x28, 0x07, 0x48, 0x48, ++ 0x40, 0x10, 0x10, 0x0f, 0x17, 0x0f, 0x17, 0x07, 0x17, 0x40, 0x50, 0x17, 0x40, 0x50, 0x40, 0x40, ++ 0x48, 0x0f, 0x0f, 0x07, 0x48, 0x0f, 0x07, 0x40, 0x07, 0x27, 0x27, 0x0f, 0x40, 0x0f, 0x0f, 0x0f, ++ 0x48, 0x28, 0x18, 0x10, 0x48, 0x10, 0x0f, 0x10, 0x07, 0x07, 0x17, 0x10, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x48, 0x00, 0x4f, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x08, ++ 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x08, 0x08, 0x4f, ++ 0x4f, 0x00, 0x08, 0x0f, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x47, 0x47, 0x00, 0x47, ++ 0x47, 0x07, 0x47, 0x57, 0x47, 0x00, 0x4f, 0x5f, 0x57, 0x4f, 0x00, 0x08, 0x08, 0x08, 0x47, 0x47, ++ 0x00, 0x47, 0x47, 0x07, 0x47, 0x57, 0x47, 0x00, 0x4f, 0x5f, 0x57, 0x4f, 0x00, 0x08, 0x08, 0x08, ++ 0x18, 0x50, 0x28, 0x4f, 0x4f, 0x4f, 0x47, 0x47, 0x47, 0x00, 0x00, 0x08, 0x00, 0x10, 0x47, 0x4f, ++ 0x27, 0x07, 0x47, 0x10, 0x47, 0x4f, 0x27, 0x07, 0x47, 0x10, 0x47, 0x4f, 0x27, 0x07, 0x47, 0x47, ++ 0x00, 0x0f, 0x0f, 0x0f, 0x18, 0x0f, 0x18, 0x07, 0x18, 0x00, 0x4f, 0x18, 0x00, 0x4f, 0x40, 0x40, ++ 0x47, 0x10, 0x10, 0x08, 0x47, 0x0f, 0x08, 0x00, 0x07, 0x28, 0x27, 0x10, 0x00, 0x10, 0x10, 0x0f, ++ 0x47, 0x27, 0x17, 0x0f, 0x47, 0x0f, 0x10, 0x0f, 0x08, 0x07, 0x18, 0x0f, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x49, 0x00, 0x4f, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0a, ++ 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x08, 0x08, 0x4e, ++ 0x4f, 0x01, 0x08, 0x0f, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x46, 0x46, 0x00, 0x47, ++ 0x47, 0x07, 0x47, 0x57, 0x47, 0x01, 0x4e, 0x5f, 0x57, 0x4e, 0x02, 0x09, 0x08, 0x0a, 0x46, 0x46, ++ 0x00, 0x47, 0x47, 0x07, 0x47, 0x57, 0x47, 0x01, 0x4e, 0x5f, 0x57, 0x4e, 0x02, 0x09, 0x08, 0x0a, ++ 0x19, 0x50, 0x28, 0x4f, 0x4e, 0x4e, 0x47, 0x46, 0x46, 0x01, 0x00, 0x09, 0x00, 0x11, 0x47, 0x4f, ++ 0x27, 0x07, 0x47, 0x11, 0x47, 0x4f, 0x27, 0x07, 0x47, 0x11, 0x47, 0x4f, 0x27, 0x07, 0x47, 0x47, ++ 0x00, 0x0f, 0x0f, 0x0f, 0x18, 0x0f, 0x18, 0x07, 0x18, 0x00, 0x4e, 0x18, 0x00, 0x4e, 0x40, 0x40, ++ 0x47, 0x11, 0x10, 0x08, 0x47, 0x0f, 0x08, 0x00, 0x07, 0x2a, 0x27, 0x11, 0x00, 0x11, 0x10, 0x0f, ++ 0x47, 0x27, 0x17, 0x0f, 0x47, 0x0d, 0x10, 0x0e, 0x08, 0x07, 0x18, 0x0f, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4a, 0x00, 0x4f, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x40, 0x40, 0x40, 0x41, 0x0c, ++ 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x08, 0x08, 0x4d, ++ 0x4f, 0x02, 0x08, 0x0e, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x45, 0x45, 0x01, 0x46, ++ 0x47, 0x07, 0x46, 0x56, 0x47, 0x02, 0x4d, 0x5f, 0x56, 0x4d, 0x03, 0x0a, 0x09, 0x0c, 0x45, 0x45, ++ 0x01, 0x46, 0x47, 0x07, 0x46, 0x56, 0x47, 0x02, 0x4d, 0x5f, 0x56, 0x4d, 0x03, 0x0a, 0x09, 0x0c, ++ 0x1a, 0x50, 0x28, 0x4f, 0x4d, 0x4d, 0x46, 0x45, 0x45, 0x02, 0x01, 0x0a, 0x01, 0x12, 0x46, 0x4f, ++ 0x26, 0x07, 0x46, 0x12, 0x46, 0x4f, 0x26, 0x07, 0x46, 0x12, 0x46, 0x4f, 0x26, 0x07, 0x46, 0x47, ++ 0x00, 0x0e, 0x0e, 0x0f, 0x18, 0x0f, 0x18, 0x07, 0x18, 0x00, 0x4d, 0x18, 0x00, 0x4d, 0x40, 0x40, ++ 0x47, 0x12, 0x10, 0x08, 0x47, 0x0f, 0x08, 0x00, 0x07, 0x2b, 0x27, 0x12, 0x00, 0x12, 0x11, 0x0f, ++ 0x47, 0x26, 0x17, 0x0e, 0x47, 0x0c, 0x11, 0x0d, 0x08, 0x07, 0x18, 0x0f, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4b, 0x01, 0x4e, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x42, 0x40, 0x40, 0x40, 0x42, 0x0e, ++ 0x01, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x09, 0x09, 0x4c, ++ 0x4e, 0x04, 0x09, 0x0d, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x01, 0x01, 0x44, 0x44, 0x02, 0x45, ++ 0x46, 0x07, 0x45, 0x55, 0x46, 0x03, 0x4c, 0x5e, 0x55, 0x4c, 0x05, 0x0b, 0x0a, 0x0e, 0x44, 0x44, ++ 0x02, 0x45, 0x46, 0x07, 0x45, 0x55, 0x46, 0x03, 0x4c, 0x5e, 0x55, 0x4c, 0x05, 0x0b, 0x0a, 0x0e, ++ 0x1c, 0x51, 0x29, 0x4e, 0x4c, 0x4c, 0x45, 0x44, 0x44, 0x04, 0x02, 0x0b, 0x02, 0x13, 0x45, 0x4e, ++ 0x25, 0x07, 0x45, 0x13, 0x45, 0x4e, 0x25, 0x07, 0x45, 0x13, 0x45, 0x4e, 0x25, 0x07, 0x45, 0x46, ++ 0x01, 0x0d, 0x0d, 0x0f, 0x19, 0x0f, 0x19, 0x07, 0x19, 0x01, 0x4c, 0x19, 0x01, 0x4c, 0x40, 0x40, ++ 0x46, 0x14, 0x11, 0x09, 0x46, 0x0f, 0x09, 0x01, 0x07, 0x2d, 0x27, 0x14, 0x01, 0x13, 0x12, 0x0f, ++ 0x46, 0x25, 0x16, 0x0d, 0x46, 0x0a, 0x12, 0x0c, 0x09, 0x07, 0x19, 0x0e, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4c, 0x01, 0x4e, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x42, 0x40, 0x40, 0x40, 0x42, 0x10, ++ 0x01, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x09, 0x09, 0x4b, ++ 0x4e, 0x05, 0x09, 0x0d, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x01, 0x01, 0x43, 0x43, 0x02, 0x45, ++ 0x46, 0x07, 0x45, 0x55, 0x46, 0x04, 0x4b, 0x5e, 0x55, 0x4b, 0x06, 0x0c, 0x0a, 0x10, 0x43, 0x43, ++ 0x02, 0x45, 0x46, 0x07, 0x45, 0x55, 0x46, 0x04, 0x4b, 0x5e, 0x55, 0x4b, 0x06, 0x0c, 0x0a, 0x10, ++ 0x1d, 0x51, 0x29, 0x4e, 0x4b, 0x4b, 0x45, 0x43, 0x43, 0x05, 0x02, 0x0c, 0x02, 0x14, 0x45, 0x4e, ++ 0x25, 0x07, 0x45, 0x14, 0x45, 0x4e, 0x25, 0x07, 0x45, 0x14, 0x45, 0x4e, 0x25, 0x07, 0x45, 0x46, ++ 0x01, 0x0d, 0x0d, 0x0f, 0x19, 0x0f, 0x19, 0x07, 0x19, 0x01, 0x4b, 0x19, 0x01, 0x4b, 0x40, 0x40, ++ 0x46, 0x15, 0x11, 0x09, 0x46, 0x0f, 0x09, 0x01, 0x07, 0x2e, 0x27, 0x15, 0x01, 0x14, 0x12, 0x0f, ++ 0x46, 0x25, 0x16, 0x0d, 0x46, 0x09, 0x12, 0x0b, 0x09, 0x07, 0x19, 0x0e, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4d, 0x01, 0x4e, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x43, 0x40, 0x40, 0x40, 0x43, 0x12, ++ 0x01, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x09, 0x09, 0x4a, ++ 0x4e, 0x06, 0x09, 0x0c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x01, 0x01, 0x42, 0x42, 0x03, 0x44, ++ 0x46, 0x07, 0x44, 0x54, 0x46, 0x05, 0x4a, 0x5e, 0x54, 0x4a, 0x08, 0x0d, 0x0b, 0x12, 0x42, 0x42, ++ 0x03, 0x44, 0x46, 0x07, 0x44, 0x54, 0x46, 0x05, 0x4a, 0x5e, 0x54, 0x4a, 0x08, 0x0d, 0x0b, 0x12, ++ 0x1e, 0x51, 0x29, 0x4e, 0x4a, 0x4a, 0x44, 0x42, 0x42, 0x06, 0x03, 0x0d, 0x03, 0x15, 0x44, 0x4e, ++ 0x24, 0x07, 0x44, 0x15, 0x44, 0x4e, 0x24, 0x07, 0x44, 0x15, 0x44, 0x4e, 0x24, 0x07, 0x44, 0x46, ++ 0x01, 0x0c, 0x0c, 0x0f, 0x19, 0x0f, 0x19, 0x07, 0x19, 0x01, 0x4a, 0x19, 0x01, 0x4a, 0x40, 0x40, ++ 0x46, 0x16, 0x11, 0x09, 0x46, 0x0f, 0x09, 0x01, 0x07, 0x30, 0x27, 0x16, 0x01, 0x15, 0x13, 0x0f, ++ 0x46, 0x24, 0x16, 0x0c, 0x46, 0x07, 0x13, 0x0a, 0x09, 0x07, 0x19, 0x0e, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4e, 0x01, 0x4e, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x44, 0x40, 0x40, 0x40, 0x44, 0x13, ++ 0x01, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x09, 0x09, 0x4a, ++ 0x4e, 0x07, 0x09, 0x0b, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x01, 0x01, 0x42, 0x42, 0x03, 0x44, ++ 0x46, 0x07, 0x44, 0x54, 0x46, 0x05, 0x4a, 0x5e, 0x54, 0x4a, 0x09, 0x0d, 0x0b, 0x13, 0x42, 0x42, ++ 0x03, 0x44, 0x46, 0x07, 0x44, 0x54, 0x46, 0x05, 0x4a, 0x5e, 0x54, 0x4a, 0x09, 0x0d, 0x0b, 0x13, ++ 0x1f, 0x52, 0x29, 0x4e, 0x4a, 0x4a, 0x44, 0x42, 0x42, 0x07, 0x03, 0x0d, 0x03, 0x15, 0x44, 0x4e, ++ 0x23, 0x07, 0x44, 0x15, 0x44, 0x4e, 0x23, 0x07, 0x44, 0x15, 0x44, 0x4e, 0x23, 0x07, 0x44, 0x46, ++ 0x01, 0x0b, 0x0b, 0x0f, 0x19, 0x0f, 0x19, 0x07, 0x19, 0x01, 0x4a, 0x19, 0x01, 0x4a, 0x40, 0x40, ++ 0x46, 0x17, 0x11, 0x09, 0x46, 0x0f, 0x09, 0x01, 0x07, 0x31, 0x27, 0x17, 0x01, 0x15, 0x13, 0x0f, ++ 0x46, 0x23, 0x15, 0x0b, 0x46, 0x05, 0x13, 0x09, 0x09, 0x07, 0x19, 0x0d, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4e, 0x02, 0x4d, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x44, 0x40, 0x40, 0x40, 0x44, 0x15, ++ 0x02, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0a, 0x0a, 0x49, ++ 0x4d, 0x09, 0x0a, 0x0b, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x02, 0x02, 0x41, 0x41, 0x04, 0x43, ++ 0x45, 0x07, 0x43, 0x53, 0x45, 0x06, 0x49, 0x5d, 0x53, 0x49, 0x0b, 0x0e, 0x0c, 0x15, 0x41, 0x41, ++ 0x04, 0x43, 0x45, 0x07, 0x43, 0x53, 0x45, 0x06, 0x49, 0x5d, 0x53, 0x49, 0x0b, 0x0e, 0x0c, 0x15, ++ 0x21, 0x52, 0x2a, 0x4d, 0x49, 0x49, 0x43, 0x41, 0x41, 0x09, 0x04, 0x0e, 0x04, 0x16, 0x43, 0x4d, ++ 0x23, 0x07, 0x43, 0x16, 0x43, 0x4d, 0x23, 0x07, 0x43, 0x16, 0x43, 0x4d, 0x23, 0x07, 0x43, 0x45, ++ 0x02, 0x0b, 0x0b, 0x0f, 0x1a, 0x0f, 0x1a, 0x07, 0x1a, 0x02, 0x49, 0x1a, 0x02, 0x49, 0x40, 0x40, ++ 0x45, 0x19, 0x12, 0x0a, 0x45, 0x0f, 0x0a, 0x02, 0x07, 0x33, 0x27, 0x19, 0x02, 0x16, 0x14, 0x0f, ++ 0x45, 0x23, 0x15, 0x0b, 0x45, 0x04, 0x14, 0x09, 0x0a, 0x07, 0x1a, 0x0d, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4f, 0x02, 0x4d, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x45, 0x40, 0x40, 0x40, 0x45, 0x17, ++ 0x02, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0a, 0x0a, 0x48, ++ 0x4d, 0x0a, 0x0a, 0x0a, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x02, 0x02, 0x40, 0x40, 0x05, 0x42, ++ 0x45, 0x07, 0x42, 0x52, 0x45, 0x07, 0x48, 0x5d, 0x52, 0x48, 0x0d, 0x0f, 0x0d, 0x17, 0x40, 0x40, ++ 0x05, 0x42, 0x45, 0x07, 0x42, 0x52, 0x45, 0x07, 0x48, 0x5d, 0x52, 0x48, 0x0d, 0x0f, 0x0d, 0x17, ++ 0x22, 0x52, 0x2a, 0x4d, 0x48, 0x48, 0x42, 0x40, 0x40, 0x0a, 0x05, 0x0f, 0x05, 0x17, 0x42, 0x4d, ++ 0x22, 0x07, 0x42, 0x17, 0x42, 0x4d, 0x22, 0x07, 0x42, 0x17, 0x42, 0x4d, 0x22, 0x07, 0x42, 0x45, ++ 0x02, 0x0a, 0x0a, 0x0f, 0x1a, 0x0f, 0x1a, 0x07, 0x1a, 0x02, 0x48, 0x1a, 0x02, 0x48, 0x40, 0x40, ++ 0x45, 0x1a, 0x12, 0x0a, 0x45, 0x0f, 0x0a, 0x02, 0x07, 0x35, 0x27, 0x1a, 0x02, 0x17, 0x15, 0x0f, ++ 0x45, 0x22, 0x15, 0x0a, 0x45, 0x02, 0x15, 0x08, 0x0a, 0x07, 0x1a, 0x0d, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x50, 0x02, 0x4d, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x45, 0x40, 0x40, 0x40, 0x45, 0x19, ++ 0x02, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0a, 0x0a, 0x47, ++ 0x4d, 0x0b, 0x0a, 0x0a, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x02, 0x02, 0x00, 0x00, 0x05, 0x42, ++ 0x45, 0x07, 0x42, 0x52, 0x45, 0x08, 0x47, 0x5d, 0x52, 0x47, 0x0e, 0x10, 0x0d, 0x19, 0x00, 0x00, ++ 0x05, 0x42, 0x45, 0x07, 0x42, 0x52, 0x45, 0x08, 0x47, 0x5d, 0x52, 0x47, 0x0e, 0x10, 0x0d, 0x19, ++ 0x23, 0x52, 0x2a, 0x4d, 0x47, 0x47, 0x42, 0x00, 0x00, 0x0b, 0x05, 0x10, 0x05, 0x18, 0x42, 0x4d, ++ 0x22, 0x07, 0x42, 0x18, 0x42, 0x4d, 0x22, 0x07, 0x42, 0x18, 0x42, 0x4d, 0x22, 0x07, 0x42, 0x45, ++ 0x02, 0x0a, 0x0a, 0x0f, 0x1a, 0x0f, 0x1a, 0x07, 0x1a, 0x02, 0x47, 0x1a, 0x02, 0x47, 0x40, 0x40, ++ 0x45, 0x1b, 0x12, 0x0a, 0x45, 0x0f, 0x0a, 0x02, 0x07, 0x36, 0x27, 0x1b, 0x02, 0x18, 0x15, 0x0f, ++ 0x45, 0x22, 0x15, 0x0a, 0x45, 0x01, 0x15, 0x07, 0x0a, 0x07, 0x1a, 0x0d, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x51, 0x03, 0x4c, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x46, 0x40, 0x40, 0x40, 0x46, 0x1b, ++ 0x03, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0b, 0x0b, 0x46, ++ 0x4c, 0x0c, 0x0b, 0x09, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x03, 0x03, 0x01, 0x01, 0x06, 0x41, ++ 0x44, 0x07, 0x41, 0x51, 0x44, 0x09, 0x46, 0x5c, 0x51, 0x46, 0x10, 0x11, 0x0e, 0x1b, 0x01, 0x01, ++ 0x06, 0x41, 0x44, 0x07, 0x41, 0x51, 0x44, 0x09, 0x46, 0x5c, 0x51, 0x46, 0x10, 0x11, 0x0e, 0x1b, ++ 0x24, 0x53, 0x2b, 0x4c, 0x46, 0x46, 0x41, 0x01, 0x01, 0x0c, 0x06, 0x11, 0x06, 0x19, 0x41, 0x4c, ++ 0x21, 0x07, 0x41, 0x19, 0x41, 0x4c, 0x21, 0x07, 0x41, 0x19, 0x41, 0x4c, 0x21, 0x07, 0x41, 0x44, ++ 0x03, 0x09, 0x09, 0x0f, 0x1b, 0x0f, 0x1b, 0x07, 0x1b, 0x03, 0x46, 0x1b, 0x03, 0x46, 0x40, 0x40, ++ 0x44, 0x1c, 0x13, 0x0b, 0x44, 0x0f, 0x0b, 0x03, 0x07, 0x38, 0x27, 0x1c, 0x03, 0x19, 0x16, 0x0f, ++ 0x44, 0x21, 0x14, 0x09, 0x44, 0x40, 0x16, 0x06, 0x0b, 0x07, 0x1b, 0x0c, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x52, 0x03, 0x4c, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x47, 0x40, 0x40, 0x40, 0x47, 0x1d, ++ 0x03, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0b, 0x0b, 0x45, ++ 0x4c, 0x0e, 0x0b, 0x08, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x03, 0x03, 0x02, 0x02, 0x07, 0x40, ++ 0x44, 0x07, 0x40, 0x50, 0x44, 0x0a, 0x45, 0x5c, 0x50, 0x45, 0x11, 0x12, 0x0f, 0x1d, 0x02, 0x02, ++ 0x07, 0x40, 0x44, 0x07, 0x40, 0x50, 0x44, 0x0a, 0x45, 0x5c, 0x50, 0x45, 0x11, 0x12, 0x0f, 0x1d, ++ 0x26, 0x53, 0x2b, 0x4c, 0x45, 0x45, 0x40, 0x02, 0x02, 0x0e, 0x07, 0x12, 0x07, 0x1a, 0x40, 0x4c, ++ 0x20, 0x07, 0x40, 0x1a, 0x40, 0x4c, 0x20, 0x07, 0x40, 0x1a, 0x40, 0x4c, 0x20, 0x07, 0x40, 0x44, ++ 0x03, 0x08, 0x08, 0x0f, 0x1b, 0x0f, 0x1b, 0x07, 0x1b, 0x03, 0x45, 0x1b, 0x03, 0x45, 0x40, 0x40, ++ 0x44, 0x1e, 0x13, 0x0b, 0x44, 0x0f, 0x0b, 0x03, 0x07, 0x39, 0x27, 0x1e, 0x03, 0x1a, 0x17, 0x0f, ++ 0x44, 0x20, 0x14, 0x08, 0x44, 0x41, 0x17, 0x05, 0x0b, 0x07, 0x1b, 0x0c, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x53, 0x03, 0x4c, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x47, 0x40, 0x40, 0x40, 0x47, 0x1f, ++ 0x03, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0b, 0x0b, 0x44, ++ 0x4c, 0x0f, 0x0b, 0x08, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x03, 0x03, 0x03, 0x03, 0x07, 0x40, ++ 0x44, 0x07, 0x40, 0x50, 0x44, 0x0b, 0x44, 0x5c, 0x50, 0x44, 0x13, 0x13, 0x0f, 0x1f, 0x03, 0x03, ++ 0x07, 0x40, 0x44, 0x07, 0x40, 0x50, 0x44, 0x0b, 0x44, 0x5c, 0x50, 0x44, 0x13, 0x13, 0x0f, 0x1f, ++ 0x27, 0x53, 0x2b, 0x4c, 0x44, 0x44, 0x40, 0x03, 0x03, 0x0f, 0x07, 0x13, 0x07, 0x1b, 0x40, 0x4c, ++ 0x20, 0x07, 0x40, 0x1b, 0x40, 0x4c, 0x20, 0x07, 0x40, 0x1b, 0x40, 0x4c, 0x20, 0x07, 0x40, 0x44, ++ 0x03, 0x08, 0x08, 0x0f, 0x1b, 0x0f, 0x1b, 0x07, 0x1b, 0x03, 0x44, 0x1b, 0x03, 0x44, 0x40, 0x40, ++ 0x44, 0x1f, 0x13, 0x0b, 0x44, 0x0f, 0x0b, 0x03, 0x07, 0x3b, 0x27, 0x1f, 0x03, 0x1b, 0x17, 0x0f, ++ 0x44, 0x20, 0x14, 0x08, 0x44, 0x43, 0x17, 0x04, 0x0b, 0x07, 0x1b, 0x0c, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x54, 0x04, 0x4b, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x48, 0x40, 0x40, 0x40, 0x48, 0x21, ++ 0x04, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0c, 0x0c, 0x43, ++ 0x4b, 0x10, 0x0c, 0x07, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x04, 0x04, 0x04, 0x04, 0x08, 0x00, ++ 0x43, 0x07, 0x00, 0x4f, 0x43, 0x0c, 0x43, 0x5b, 0x4f, 0x43, 0x14, 0x14, 0x10, 0x21, 0x04, 0x04, ++ 0x08, 0x00, 0x43, 0x07, 0x00, 0x4f, 0x43, 0x0c, 0x43, 0x5b, 0x4f, 0x43, 0x14, 0x14, 0x10, 0x21, ++ 0x28, 0x54, 0x2c, 0x4b, 0x43, 0x43, 0x00, 0x04, 0x04, 0x10, 0x08, 0x14, 0x08, 0x1c, 0x00, 0x4b, ++ 0x1f, 0x07, 0x00, 0x1c, 0x00, 0x4b, 0x1f, 0x07, 0x00, 0x1c, 0x00, 0x4b, 0x1f, 0x07, 0x00, 0x43, ++ 0x04, 0x07, 0x07, 0x0f, 0x1c, 0x0f, 0x1c, 0x07, 0x1c, 0x04, 0x43, 0x1c, 0x04, 0x43, 0x40, 0x40, ++ 0x43, 0x20, 0x14, 0x0c, 0x43, 0x0f, 0x0c, 0x04, 0x07, 0x3c, 0x27, 0x20, 0x04, 0x1c, 0x18, 0x0f, ++ 0x43, 0x1f, 0x13, 0x07, 0x43, 0x44, 0x18, 0x03, 0x0c, 0x07, 0x1c, 0x0b, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x55, 0x04, 0x4b, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x49, 0x40, 0x40, 0x40, 0x49, 0x22, ++ 0x04, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0c, 0x0c, 0x42, ++ 0x4b, 0x11, 0x0c, 0x06, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x04, 0x04, 0x05, 0x05, 0x08, 0x00, ++ 0x43, 0x07, 0x00, 0x4f, 0x43, 0x0d, 0x42, 0x5b, 0x4f, 0x42, 0x16, 0x15, 0x10, 0x22, 0x05, 0x05, ++ 0x08, 0x00, 0x43, 0x07, 0x00, 0x4f, 0x43, 0x0d, 0x42, 0x5b, 0x4f, 0x42, 0x16, 0x15, 0x10, 0x22, ++ 0x29, 0x54, 0x2c, 0x4b, 0x42, 0x42, 0x00, 0x05, 0x05, 0x11, 0x08, 0x15, 0x08, 0x1d, 0x00, 0x4b, ++ 0x1e, 0x07, 0x00, 0x1d, 0x00, 0x4b, 0x1e, 0x07, 0x00, 0x1d, 0x00, 0x4b, 0x1e, 0x07, 0x00, 0x43, ++ 0x04, 0x06, 0x06, 0x0f, 0x1c, 0x0f, 0x1c, 0x07, 0x1c, 0x04, 0x42, 0x1c, 0x04, 0x42, 0x40, 0x40, ++ 0x43, 0x21, 0x14, 0x0c, 0x43, 0x0f, 0x0c, 0x04, 0x07, 0x3e, 0x27, 0x21, 0x04, 0x1d, 0x18, 0x0f, ++ 0x43, 0x1e, 0x13, 0x06, 0x43, 0x46, 0x18, 0x02, 0x0c, 0x07, 0x1c, 0x0b, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x56, 0x04, 0x4b, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x49, 0x40, 0x40, 0x40, 0x49, 0x24, ++ 0x04, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0c, 0x0c, 0x41, ++ 0x4b, 0x13, 0x0c, 0x06, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x04, 0x04, 0x06, 0x06, 0x09, 0x01, ++ 0x43, 0x07, 0x01, 0x4e, 0x43, 0x0e, 0x41, 0x5b, 0x4e, 0x41, 0x18, 0x16, 0x11, 0x24, 0x06, 0x06, ++ 0x09, 0x01, 0x43, 0x07, 0x01, 0x4e, 0x43, 0x0e, 0x41, 0x5b, 0x4e, 0x41, 0x18, 0x16, 0x11, 0x24, ++ 0x2b, 0x54, 0x2c, 0x4b, 0x41, 0x41, 0x01, 0x06, 0x06, 0x13, 0x09, 0x16, 0x09, 0x1e, 0x01, 0x4b, ++ 0x1e, 0x07, 0x01, 0x1e, 0x01, 0x4b, 0x1e, 0x07, 0x01, 0x1e, 0x01, 0x4b, 0x1e, 0x07, 0x01, 0x43, ++ 0x04, 0x06, 0x06, 0x0f, 0x1c, 0x0f, 0x1c, 0x07, 0x1c, 0x04, 0x41, 0x1c, 0x04, 0x41, 0x40, 0x40, ++ 0x43, 0x23, 0x14, 0x0c, 0x43, 0x0f, 0x0c, 0x04, 0x07, 0x3e, 0x27, 0x23, 0x04, 0x1e, 0x19, 0x0f, ++ 0x43, 0x1e, 0x13, 0x06, 0x43, 0x48, 0x19, 0x01, 0x0c, 0x07, 0x1c, 0x0b, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x57, 0x05, 0x4a, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4a, 0x40, 0x40, 0x40, 0x4a, 0x26, ++ 0x05, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0d, 0x0d, 0x40, ++ 0x4a, 0x14, 0x0d, 0x05, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x05, 0x05, 0x07, 0x07, 0x0a, 0x02, ++ 0x42, 0x07, 0x02, 0x4d, 0x42, 0x0f, 0x40, 0x5a, 0x4d, 0x40, 0x19, 0x17, 0x12, 0x26, 0x07, 0x07, ++ 0x0a, 0x02, 0x42, 0x07, 0x02, 0x4d, 0x42, 0x0f, 0x40, 0x5a, 0x4d, 0x40, 0x19, 0x17, 0x12, 0x26, ++ 0x2c, 0x55, 0x2d, 0x4a, 0x40, 0x40, 0x02, 0x07, 0x07, 0x14, 0x0a, 0x17, 0x0a, 0x1f, 0x02, 0x4a, ++ 0x1d, 0x07, 0x02, 0x1f, 0x02, 0x4a, 0x1d, 0x07, 0x02, 0x1f, 0x02, 0x4a, 0x1d, 0x07, 0x02, 0x42, ++ 0x05, 0x05, 0x05, 0x0f, 0x1d, 0x0f, 0x1d, 0x07, 0x1d, 0x05, 0x40, 0x1d, 0x05, 0x40, 0x40, 0x40, ++ 0x42, 0x24, 0x15, 0x0d, 0x42, 0x0f, 0x0d, 0x05, 0x07, 0x3e, 0x27, 0x24, 0x05, 0x1f, 0x1a, 0x0f, ++ 0x42, 0x1d, 0x12, 0x05, 0x42, 0x49, 0x1a, 0x00, 0x0d, 0x07, 0x1d, 0x0a, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x58, 0x05, 0x4a, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4a, 0x40, 0x40, 0x40, 0x4a, 0x28, ++ 0x05, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0d, 0x0d, 0x00, ++ 0x4a, 0x15, 0x0d, 0x05, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x05, 0x05, 0x08, 0x08, 0x0a, 0x02, ++ 0x42, 0x07, 0x02, 0x4d, 0x42, 0x10, 0x00, 0x5a, 0x4d, 0x00, 0x1b, 0x18, 0x12, 0x28, 0x08, 0x08, ++ 0x0a, 0x02, 0x42, 0x07, 0x02, 0x4d, 0x42, 0x10, 0x00, 0x5a, 0x4d, 0x00, 0x1b, 0x18, 0x12, 0x28, ++ 0x2d, 0x55, 0x2d, 0x4a, 0x00, 0x00, 0x02, 0x08, 0x08, 0x15, 0x0a, 0x18, 0x0a, 0x20, 0x02, 0x4a, ++ 0x1d, 0x07, 0x02, 0x20, 0x02, 0x4a, 0x1d, 0x07, 0x02, 0x20, 0x02, 0x4a, 0x1d, 0x07, 0x02, 0x42, ++ 0x05, 0x05, 0x05, 0x0f, 0x1d, 0x0f, 0x1d, 0x07, 0x1d, 0x05, 0x00, 0x1d, 0x05, 0x00, 0x40, 0x40, ++ 0x42, 0x25, 0x15, 0x0d, 0x42, 0x0f, 0x0d, 0x05, 0x07, 0x3e, 0x27, 0x25, 0x05, 0x20, 0x1a, 0x0f, ++ 0x42, 0x1d, 0x12, 0x05, 0x42, 0x4b, 0x1a, 0x40, 0x0d, 0x07, 0x1d, 0x0a, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x59, 0x05, 0x4a, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4b, 0x40, 0x40, 0x40, 0x4b, 0x2a, ++ 0x05, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0d, 0x0d, 0x01, ++ 0x4a, 0x16, 0x0d, 0x04, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x05, 0x05, 0x09, 0x09, 0x0b, 0x03, ++ 0x42, 0x07, 0x03, 0x4c, 0x42, 0x11, 0x01, 0x5a, 0x4c, 0x01, 0x1c, 0x19, 0x13, 0x2a, 0x09, 0x09, ++ 0x0b, 0x03, 0x42, 0x07, 0x03, 0x4c, 0x42, 0x11, 0x01, 0x5a, 0x4c, 0x01, 0x1c, 0x19, 0x13, 0x2a, ++ 0x2e, 0x55, 0x2d, 0x4a, 0x01, 0x01, 0x03, 0x09, 0x09, 0x16, 0x0b, 0x19, 0x0b, 0x21, 0x03, 0x4a, ++ 0x1c, 0x07, 0x03, 0x21, 0x03, 0x4a, 0x1c, 0x07, 0x03, 0x21, 0x03, 0x4a, 0x1c, 0x07, 0x03, 0x42, ++ 0x05, 0x04, 0x04, 0x0f, 0x1d, 0x0f, 0x1d, 0x07, 0x1d, 0x05, 0x01, 0x1d, 0x05, 0x01, 0x40, 0x40, ++ 0x42, 0x26, 0x15, 0x0d, 0x42, 0x0f, 0x0d, 0x05, 0x07, 0x3e, 0x27, 0x26, 0x05, 0x21, 0x1b, 0x0f, ++ 0x42, 0x1c, 0x12, 0x04, 0x42, 0x4c, 0x1b, 0x41, 0x0d, 0x07, 0x1d, 0x0a, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x5a, 0x06, 0x49, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4c, 0x40, 0x40, 0x40, 0x4c, 0x2c, ++ 0x06, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0e, 0x0e, 0x02, ++ 0x49, 0x18, 0x0e, 0x03, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x06, 0x06, 0x0a, 0x0a, 0x0c, 0x04, ++ 0x41, 0x07, 0x04, 0x4b, 0x41, 0x12, 0x02, 0x59, 0x4b, 0x02, 0x1e, 0x1a, 0x14, 0x2c, 0x0a, 0x0a, ++ 0x0c, 0x04, 0x41, 0x07, 0x04, 0x4b, 0x41, 0x12, 0x02, 0x59, 0x4b, 0x02, 0x1e, 0x1a, 0x14, 0x2c, ++ 0x30, 0x56, 0x2e, 0x49, 0x02, 0x02, 0x04, 0x0a, 0x0a, 0x18, 0x0c, 0x1a, 0x0c, 0x22, 0x04, 0x49, ++ 0x1b, 0x07, 0x04, 0x22, 0x04, 0x49, 0x1b, 0x07, 0x04, 0x22, 0x04, 0x49, 0x1b, 0x07, 0x04, 0x41, ++ 0x06, 0x03, 0x03, 0x0f, 0x1e, 0x0f, 0x1e, 0x07, 0x1e, 0x06, 0x02, 0x1e, 0x06, 0x02, 0x40, 0x40, ++ 0x41, 0x28, 0x16, 0x0e, 0x41, 0x0f, 0x0e, 0x06, 0x07, 0x3e, 0x27, 0x28, 0x06, 0x22, 0x1c, 0x0f, ++ 0x41, 0x1b, 0x11, 0x03, 0x41, 0x4e, 0x1c, 0x42, 0x0e, 0x07, 0x1e, 0x09, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x5b, 0x06, 0x49, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4c, 0x40, 0x40, 0x40, 0x4c, 0x2e, ++ 0x06, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0e, 0x0e, 0x03, ++ 0x49, 0x19, 0x0e, 0x03, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x06, 0x06, 0x0b, 0x0b, 0x0c, 0x04, ++ 0x41, 0x07, 0x04, 0x4b, 0x41, 0x13, 0x03, 0x59, 0x4b, 0x03, 0x1f, 0x1b, 0x14, 0x2e, 0x0b, 0x0b, ++ 0x0c, 0x04, 0x41, 0x07, 0x04, 0x4b, 0x41, 0x13, 0x03, 0x59, 0x4b, 0x03, 0x1f, 0x1b, 0x14, 0x2e, ++ 0x31, 0x56, 0x2e, 0x49, 0x03, 0x03, 0x04, 0x0b, 0x0b, 0x19, 0x0c, 0x1b, 0x0c, 0x23, 0x04, 0x49, ++ 0x1b, 0x07, 0x04, 0x23, 0x04, 0x49, 0x1b, 0x07, 0x04, 0x23, 0x04, 0x49, 0x1b, 0x07, 0x04, 0x41, ++ 0x06, 0x03, 0x03, 0x0f, 0x1e, 0x0f, 0x1e, 0x07, 0x1e, 0x06, 0x03, 0x1e, 0x06, 0x03, 0x40, 0x40, ++ 0x41, 0x29, 0x16, 0x0e, 0x41, 0x0f, 0x0e, 0x06, 0x07, 0x3e, 0x27, 0x29, 0x06, 0x23, 0x1c, 0x0f, ++ 0x41, 0x1b, 0x11, 0x03, 0x41, 0x4f, 0x1c, 0x43, 0x0e, 0x07, 0x1e, 0x09, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x5c, 0x06, 0x49, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4d, 0x40, 0x40, 0x40, 0x4d, 0x30, ++ 0x06, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0e, 0x0e, 0x04, ++ 0x49, 0x1a, 0x0e, 0x02, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x06, 0x06, 0x0c, 0x0c, 0x0d, 0x05, ++ 0x41, 0x07, 0x05, 0x4a, 0x41, 0x14, 0x04, 0x59, 0x4a, 0x04, 0x21, 0x1c, 0x15, 0x30, 0x0c, 0x0c, ++ 0x0d, 0x05, 0x41, 0x07, 0x05, 0x4a, 0x41, 0x14, 0x04, 0x59, 0x4a, 0x04, 0x21, 0x1c, 0x15, 0x30, ++ 0x32, 0x56, 0x2e, 0x49, 0x04, 0x04, 0x05, 0x0c, 0x0c, 0x1a, 0x0d, 0x1c, 0x0d, 0x24, 0x05, 0x49, ++ 0x1a, 0x07, 0x05, 0x24, 0x05, 0x49, 0x1a, 0x07, 0x05, 0x24, 0x05, 0x49, 0x1a, 0x07, 0x05, 0x41, ++ 0x06, 0x02, 0x02, 0x0f, 0x1e, 0x0f, 0x1e, 0x07, 0x1e, 0x06, 0x04, 0x1e, 0x06, 0x04, 0x40, 0x40, ++ 0x41, 0x2a, 0x16, 0x0e, 0x41, 0x0f, 0x0e, 0x06, 0x07, 0x3e, 0x27, 0x2a, 0x06, 0x24, 0x1d, 0x0f, ++ 0x41, 0x1a, 0x11, 0x02, 0x41, 0x51, 0x1d, 0x44, 0x0e, 0x07, 0x1e, 0x09, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x5d, 0x06, 0x49, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4e, 0x40, 0x40, 0x40, 0x4e, 0x31, ++ 0x06, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0e, 0x0e, 0x04, ++ 0x49, 0x1b, 0x0e, 0x01, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x06, 0x06, 0x0c, 0x0c, 0x0d, 0x05, ++ 0x41, 0x07, 0x05, 0x4a, 0x41, 0x14, 0x04, 0x59, 0x4a, 0x04, 0x22, 0x1c, 0x15, 0x31, 0x0c, 0x0c, ++ 0x0d, 0x05, 0x41, 0x07, 0x05, 0x4a, 0x41, 0x14, 0x04, 0x59, 0x4a, 0x04, 0x22, 0x1c, 0x15, 0x31, ++ 0x33, 0x57, 0x2e, 0x49, 0x04, 0x04, 0x05, 0x0c, 0x0c, 0x1b, 0x0d, 0x1c, 0x0d, 0x24, 0x05, 0x49, ++ 0x19, 0x07, 0x05, 0x24, 0x05, 0x49, 0x19, 0x07, 0x05, 0x24, 0x05, 0x49, 0x19, 0x07, 0x05, 0x41, ++ 0x06, 0x01, 0x01, 0x0f, 0x1e, 0x0f, 0x1e, 0x07, 0x1e, 0x06, 0x04, 0x1e, 0x06, 0x04, 0x40, 0x40, ++ 0x41, 0x2b, 0x16, 0x0e, 0x41, 0x0f, 0x0e, 0x06, 0x07, 0x3e, 0x27, 0x2b, 0x06, 0x24, 0x1d, 0x0f, ++ 0x41, 0x19, 0x10, 0x01, 0x41, 0x53, 0x1d, 0x45, 0x0e, 0x07, 0x1e, 0x08, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x5d, 0x07, 0x48, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4e, 0x40, 0x40, 0x40, 0x4e, 0x33, ++ 0x07, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0f, 0x0f, 0x05, ++ 0x48, 0x1d, 0x0f, 0x01, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x07, 0x0d, 0x0d, 0x0e, 0x06, ++ 0x40, 0x07, 0x06, 0x49, 0x40, 0x15, 0x05, 0x58, 0x49, 0x05, 0x24, 0x1d, 0x16, 0x33, 0x0d, 0x0d, ++ 0x0e, 0x06, 0x40, 0x07, 0x06, 0x49, 0x40, 0x15, 0x05, 0x58, 0x49, 0x05, 0x24, 0x1d, 0x16, 0x33, ++ 0x35, 0x57, 0x2f, 0x48, 0x05, 0x05, 0x06, 0x0d, 0x0d, 0x1d, 0x0e, 0x1d, 0x0e, 0x25, 0x06, 0x48, ++ 0x19, 0x07, 0x06, 0x25, 0x06, 0x48, 0x19, 0x07, 0x06, 0x25, 0x06, 0x48, 0x19, 0x07, 0x06, 0x40, ++ 0x07, 0x01, 0x01, 0x0f, 0x1f, 0x0f, 0x1f, 0x07, 0x1f, 0x07, 0x05, 0x1f, 0x07, 0x05, 0x40, 0x40, ++ 0x40, 0x2d, 0x17, 0x0f, 0x40, 0x0f, 0x0f, 0x07, 0x07, 0x3e, 0x27, 0x2d, 0x07, 0x25, 0x1e, 0x0f, ++ 0x40, 0x19, 0x10, 0x01, 0x40, 0x54, 0x1e, 0x45, 0x0f, 0x07, 0x1f, 0x08, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x5e, 0x07, 0x48, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4f, 0x40, 0x40, 0x40, 0x4f, 0x35, ++ 0x07, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0f, 0x0f, 0x06, ++ 0x48, 0x1e, 0x0f, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x07, 0x0e, 0x0e, 0x0f, 0x07, ++ 0x40, 0x07, 0x07, 0x48, 0x40, 0x16, 0x06, 0x58, 0x48, 0x06, 0x26, 0x1e, 0x17, 0x35, 0x0e, 0x0e, ++ 0x0f, 0x07, 0x40, 0x07, 0x07, 0x48, 0x40, 0x16, 0x06, 0x58, 0x48, 0x06, 0x26, 0x1e, 0x17, 0x35, ++ 0x36, 0x57, 0x2f, 0x48, 0x06, 0x06, 0x07, 0x0e, 0x0e, 0x1e, 0x0f, 0x1e, 0x0f, 0x26, 0x07, 0x48, ++ 0x18, 0x07, 0x07, 0x26, 0x07, 0x48, 0x18, 0x07, 0x07, 0x26, 0x07, 0x48, 0x18, 0x07, 0x07, 0x40, ++ 0x07, 0x00, 0x00, 0x0f, 0x1f, 0x0f, 0x1f, 0x07, 0x1f, 0x07, 0x06, 0x1f, 0x07, 0x06, 0x40, 0x40, ++ 0x40, 0x2e, 0x17, 0x0f, 0x40, 0x0f, 0x0f, 0x07, 0x07, 0x3e, 0x27, 0x2e, 0x07, 0x26, 0x1f, 0x0f, ++ 0x40, 0x18, 0x10, 0x00, 0x40, 0x56, 0x1f, 0x46, 0x0f, 0x07, 0x1f, 0x08, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x5f, 0x07, 0x48, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4f, 0x40, 0x40, 0x40, 0x4f, 0x37, ++ 0x07, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0f, 0x0f, 0x07, ++ 0x48, 0x1f, 0x0f, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x07, 0x0f, 0x0f, 0x0f, 0x07, ++ 0x40, 0x07, 0x07, 0x48, 0x40, 0x17, 0x07, 0x58, 0x48, 0x07, 0x27, 0x1f, 0x17, 0x37, 0x0f, 0x0f, ++ 0x0f, 0x07, 0x40, 0x07, 0x07, 0x48, 0x40, 0x17, 0x07, 0x58, 0x48, 0x07, 0x27, 0x1f, 0x17, 0x37, ++ 0x37, 0x57, 0x2f, 0x48, 0x07, 0x07, 0x07, 0x0f, 0x0f, 0x1f, 0x0f, 0x1f, 0x0f, 0x27, 0x07, 0x48, ++ 0x18, 0x07, 0x07, 0x27, 0x07, 0x48, 0x18, 0x07, 0x07, 0x27, 0x07, 0x48, 0x18, 0x07, 0x07, 0x40, ++ 0x07, 0x00, 0x00, 0x0f, 0x1f, 0x0f, 0x1f, 0x07, 0x1f, 0x07, 0x07, 0x1f, 0x07, 0x07, 0x40, 0x40, ++ 0x40, 0x2f, 0x17, 0x0f, 0x40, 0x0f, 0x0f, 0x07, 0x07, 0x3e, 0x27, 0x2f, 0x07, 0x27, 0x1f, 0x0f, ++ 0x40, 0x18, 0x10, 0x00, 0x40, 0x57, 0x1f, 0x47, 0x0f, 0x07, 0x1f, 0x08, 0x0f, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x07, 0x48, 0x48, 0x60, 0x40, 0x27, 0x07, 0x07, 0x27, 0x40, 0x48, 0x40, 0x40, 0x40, 0x0f, ++ 0x48, 0x68, 0x60, 0x40, 0x68, 0x68, 0x68, 0x68, 0x68, 0x07, 0x07, 0x0f, 0x50, 0x40, 0x60, 0x07, ++ 0x68, 0x27, 0x48, 0x17, 0x40, 0x50, 0x1f, 0x40, 0x40, 0x40, 0x48, 0x48, 0x58, 0x60, 0x60, 0x60, ++ 0x68, 0x68, 0x58, 0x68, 0x60, 0x60, 0x60, 0x68, 0x68, 0x68, 0x60, 0x50, 0x48, 0x50, 0x58, 0x60, ++ 0x60, 0x60, 0x68, 0x68, 0x58, 0x68, 0x60, 0x60, 0x60, 0x68, 0x68, 0x68, 0x60, 0x50, 0x48, 0x50, ++ 0x07, 0x50, 0x58, 0x40, 0x48, 0x40, 0x48, 0x07, 0x48, 0x48, 0x48, 0x68, 0x07, 0x1f, 0x17, 0x50, ++ 0x0f, 0x07, 0x40, 0x1f, 0x17, 0x50, 0x0f, 0x07, 0x40, 0x1f, 0x17, 0x50, 0x0f, 0x07, 0x40, 0x40, ++ 0x07, 0x48, 0x48, 0x48, 0x07, 0x48, 0x07, 0x17, 0x17, 0x17, 0x50, 0x17, 0x17, 0x50, 0x40, 0x40, ++ 0x40, 0x2f, 0x2f, 0x17, 0x40, 0x0f, 0x17, 0x1f, 0x1f, 0x1f, 0x27, 0x0f, 0x07, 0x07, 0x0f, 0x07, ++ 0x07, 0x3e, 0x1f, 0x17, 0x40, 0x17, 0x07, 0x1f, 0x48, 0x17, 0x48, 0x40, 0x48, 0x17, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x07, 0x47, 0x47, 0x5f, 0x40, 0x27, 0x07, 0x07, 0x27, 0x40, 0x47, 0x40, 0x40, 0x40, 0x0f, ++ 0x47, 0x66, 0x5f, 0x00, 0x66, 0x66, 0x66, 0x65, 0x65, 0x07, 0x07, 0x0f, 0x4f, 0x00, 0x5e, 0x07, ++ 0x67, 0x27, 0x47, 0x17, 0x40, 0x4f, 0x1f, 0x40, 0x40, 0x40, 0x47, 0x47, 0x57, 0x5f, 0x5e, 0x5f, ++ 0x66, 0x66, 0x57, 0x67, 0x5f, 0x5e, 0x5f, 0x67, 0x67, 0x66, 0x5e, 0x4f, 0x47, 0x4f, 0x57, 0x5f, ++ 0x5e, 0x5f, 0x66, 0x66, 0x57, 0x67, 0x5f, 0x5e, 0x5f, 0x67, 0x67, 0x66, 0x5e, 0x4f, 0x47, 0x4f, ++ 0x08, 0x4f, 0x56, 0x40, 0x48, 0x40, 0x47, 0x07, 0x47, 0x47, 0x47, 0x66, 0x07, 0x1f, 0x17, 0x4f, ++ 0x10, 0x07, 0x40, 0x1f, 0x17, 0x4f, 0x10, 0x07, 0x40, 0x1f, 0x17, 0x4f, 0x10, 0x07, 0x40, 0x40, ++ 0x07, 0x47, 0x47, 0x47, 0x08, 0x47, 0x08, 0x17, 0x17, 0x17, 0x4f, 0x17, 0x17, 0x4f, 0x40, 0x40, ++ 0x40, 0x2f, 0x2f, 0x17, 0x40, 0x0f, 0x17, 0x1f, 0x1f, 0x20, 0x27, 0x10, 0x07, 0x08, 0x10, 0x08, ++ 0x07, 0x3e, 0x1f, 0x17, 0x40, 0x17, 0x08, 0x1f, 0x47, 0x17, 0x46, 0x00, 0x47, 0x17, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x06, 0x46, 0x47, 0x5e, 0x40, 0x26, 0x06, 0x06, 0x27, 0x40, 0x47, 0x40, 0x40, 0x40, 0x0f, ++ 0x47, 0x64, 0x5e, 0x01, 0x65, 0x64, 0x64, 0x63, 0x63, 0x07, 0x07, 0x0f, 0x4e, 0x00, 0x5d, 0x07, ++ 0x66, 0x27, 0x46, 0x17, 0x40, 0x4f, 0x1e, 0x40, 0x40, 0x40, 0x47, 0x47, 0x56, 0x5e, 0x5d, 0x5e, ++ 0x65, 0x64, 0x56, 0x66, 0x5e, 0x5c, 0x5e, 0x66, 0x66, 0x65, 0x5d, 0x4e, 0x46, 0x4e, 0x56, 0x5e, ++ 0x5d, 0x5e, 0x65, 0x64, 0x56, 0x66, 0x5e, 0x5c, 0x5e, 0x66, 0x66, 0x65, 0x5d, 0x4e, 0x46, 0x4e, ++ 0x09, 0x4f, 0x54, 0x40, 0x48, 0x40, 0x47, 0x07, 0x47, 0x46, 0x46, 0x64, 0x07, 0x1f, 0x16, 0x4f, ++ 0x10, 0x07, 0x40, 0x1f, 0x16, 0x4f, 0x10, 0x07, 0x40, 0x1f, 0x16, 0x4f, 0x10, 0x07, 0x40, 0x40, ++ 0x07, 0x46, 0x46, 0x46, 0x09, 0x46, 0x09, 0x17, 0x17, 0x16, 0x4f, 0x17, 0x16, 0x4f, 0x40, 0x40, ++ 0x40, 0x2e, 0x2e, 0x17, 0x40, 0x0f, 0x17, 0x1e, 0x1e, 0x20, 0x27, 0x10, 0x07, 0x09, 0x10, 0x08, ++ 0x07, 0x3e, 0x1f, 0x17, 0x40, 0x17, 0x08, 0x1e, 0x46, 0x17, 0x45, 0x01, 0x46, 0x17, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x06, 0x45, 0x47, 0x5e, 0x40, 0x25, 0x06, 0x05, 0x27, 0x40, 0x47, 0x40, 0x40, 0x40, 0x0f, ++ 0x47, 0x63, 0x5d, 0x01, 0x64, 0x63, 0x62, 0x60, 0x60, 0x07, 0x07, 0x0f, 0x4e, 0x00, 0x5c, 0x07, ++ 0x65, 0x27, 0x45, 0x17, 0x40, 0x4f, 0x1d, 0x40, 0x40, 0x40, 0x47, 0x47, 0x56, 0x5d, 0x5c, 0x5d, ++ 0x64, 0x63, 0x56, 0x65, 0x5d, 0x5b, 0x5d, 0x65, 0x65, 0x64, 0x5c, 0x4d, 0x46, 0x4d, 0x56, 0x5d, ++ 0x5c, 0x5d, 0x64, 0x63, 0x56, 0x65, 0x5d, 0x5b, 0x5d, 0x65, 0x65, 0x64, 0x5c, 0x4d, 0x46, 0x4d, ++ 0x09, 0x4f, 0x52, 0x40, 0x48, 0x40, 0x47, 0x07, 0x47, 0x46, 0x46, 0x62, 0x07, 0x1f, 0x16, 0x4f, ++ 0x10, 0x07, 0x40, 0x1f, 0x16, 0x4f, 0x10, 0x07, 0x40, 0x1f, 0x16, 0x4f, 0x10, 0x07, 0x40, 0x40, ++ 0x07, 0x46, 0x46, 0x45, 0x09, 0x45, 0x09, 0x17, 0x17, 0x16, 0x4f, 0x17, 0x16, 0x4f, 0x40, 0x40, ++ 0x40, 0x2d, 0x2d, 0x17, 0x40, 0x0f, 0x17, 0x1e, 0x1e, 0x20, 0x27, 0x10, 0x07, 0x09, 0x10, 0x08, ++ 0x07, 0x3d, 0x1f, 0x17, 0x40, 0x17, 0x08, 0x1e, 0x45, 0x17, 0x44, 0x01, 0x45, 0x17, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x05, 0x44, 0x46, 0x5d, 0x40, 0x24, 0x05, 0x04, 0x27, 0x40, 0x46, 0x40, 0x40, 0x40, 0x0f, ++ 0x46, 0x61, 0x5c, 0x02, 0x63, 0x61, 0x60, 0x5e, 0x5e, 0x07, 0x07, 0x0e, 0x4d, 0x01, 0x5b, 0x07, ++ 0x64, 0x27, 0x44, 0x16, 0x40, 0x4e, 0x1c, 0x40, 0x40, 0x40, 0x46, 0x46, 0x55, 0x5c, 0x5b, 0x5c, ++ 0x63, 0x61, 0x55, 0x64, 0x5c, 0x59, 0x5c, 0x64, 0x64, 0x63, 0x5b, 0x4c, 0x45, 0x4c, 0x55, 0x5c, ++ 0x5b, 0x5c, 0x63, 0x61, 0x55, 0x64, 0x5c, 0x59, 0x5c, 0x64, 0x64, 0x63, 0x5b, 0x4c, 0x45, 0x4c, ++ 0x0a, 0x4e, 0x50, 0x40, 0x48, 0x40, 0x46, 0x07, 0x46, 0x45, 0x45, 0x60, 0x07, 0x1e, 0x15, 0x4e, ++ 0x11, 0x07, 0x40, 0x1e, 0x15, 0x4e, 0x11, 0x07, 0x40, 0x1e, 0x15, 0x4e, 0x11, 0x07, 0x40, 0x41, ++ 0x07, 0x45, 0x45, 0x44, 0x0a, 0x44, 0x0a, 0x16, 0x17, 0x15, 0x4e, 0x17, 0x15, 0x4e, 0x40, 0x40, ++ 0x40, 0x2c, 0x2c, 0x16, 0x40, 0x0f, 0x16, 0x1d, 0x1d, 0x21, 0x27, 0x11, 0x07, 0x0a, 0x11, 0x09, ++ 0x06, 0x3c, 0x1e, 0x16, 0x40, 0x16, 0x09, 0x1d, 0x44, 0x16, 0x43, 0x02, 0x44, 0x16, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x04, 0x43, 0x46, 0x5c, 0x40, 0x23, 0x04, 0x03, 0x27, 0x40, 0x46, 0x40, 0x40, 0x40, 0x0f, ++ 0x46, 0x60, 0x5b, 0x03, 0x61, 0x60, 0x5e, 0x5b, 0x5b, 0x07, 0x07, 0x0e, 0x4c, 0x01, 0x59, 0x07, ++ 0x63, 0x27, 0x43, 0x16, 0x40, 0x4e, 0x1b, 0x40, 0x40, 0x40, 0x46, 0x46, 0x54, 0x5b, 0x59, 0x5b, ++ 0x61, 0x60, 0x54, 0x63, 0x5b, 0x58, 0x5b, 0x63, 0x63, 0x61, 0x59, 0x4b, 0x44, 0x4b, 0x54, 0x5b, ++ 0x59, 0x5b, 0x61, 0x60, 0x54, 0x63, 0x5b, 0x58, 0x5b, 0x63, 0x63, 0x61, 0x59, 0x4b, 0x44, 0x4b, ++ 0x0b, 0x4e, 0x4e, 0x40, 0x48, 0x40, 0x46, 0x07, 0x46, 0x44, 0x44, 0x5e, 0x07, 0x1e, 0x14, 0x4e, ++ 0x11, 0x07, 0x40, 0x1e, 0x14, 0x4e, 0x11, 0x07, 0x40, 0x1e, 0x14, 0x4e, 0x11, 0x07, 0x40, 0x41, ++ 0x07, 0x44, 0x44, 0x43, 0x0b, 0x43, 0x0b, 0x16, 0x17, 0x14, 0x4e, 0x17, 0x14, 0x4e, 0x40, 0x40, ++ 0x40, 0x2b, 0x2b, 0x16, 0x40, 0x0f, 0x16, 0x1c, 0x1c, 0x21, 0x27, 0x11, 0x07, 0x0b, 0x11, 0x09, ++ 0x06, 0x3b, 0x1e, 0x16, 0x40, 0x16, 0x09, 0x1c, 0x43, 0x16, 0x41, 0x03, 0x43, 0x16, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x04, 0x42, 0x46, 0x5c, 0x40, 0x22, 0x04, 0x02, 0x27, 0x40, 0x46, 0x40, 0x40, 0x40, 0x0f, ++ 0x46, 0x5e, 0x5a, 0x03, 0x60, 0x5e, 0x5c, 0x59, 0x59, 0x07, 0x07, 0x0e, 0x4c, 0x01, 0x58, 0x07, ++ 0x62, 0x27, 0x42, 0x16, 0x40, 0x4e, 0x1a, 0x40, 0x40, 0x40, 0x46, 0x46, 0x54, 0x5a, 0x58, 0x5a, ++ 0x60, 0x5e, 0x54, 0x62, 0x5a, 0x56, 0x5a, 0x62, 0x62, 0x60, 0x58, 0x4a, 0x44, 0x4a, 0x54, 0x5a, ++ 0x58, 0x5a, 0x60, 0x5e, 0x54, 0x62, 0x5a, 0x56, 0x5a, 0x62, 0x62, 0x60, 0x58, 0x4a, 0x44, 0x4a, ++ 0x0b, 0x4e, 0x4c, 0x40, 0x48, 0x40, 0x46, 0x07, 0x46, 0x44, 0x44, 0x5c, 0x07, 0x1e, 0x14, 0x4e, ++ 0x11, 0x07, 0x40, 0x1e, 0x14, 0x4e, 0x11, 0x07, 0x40, 0x1e, 0x14, 0x4e, 0x11, 0x07, 0x40, 0x41, ++ 0x07, 0x44, 0x44, 0x42, 0x0b, 0x42, 0x0b, 0x16, 0x17, 0x14, 0x4e, 0x17, 0x14, 0x4e, 0x40, 0x40, ++ 0x40, 0x2a, 0x2a, 0x16, 0x40, 0x0f, 0x16, 0x1c, 0x1c, 0x21, 0x27, 0x11, 0x07, 0x0b, 0x11, 0x09, ++ 0x06, 0x3a, 0x1e, 0x16, 0x40, 0x16, 0x09, 0x1c, 0x42, 0x16, 0x40, 0x03, 0x42, 0x16, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x03, 0x41, 0x45, 0x5b, 0x40, 0x21, 0x03, 0x01, 0x27, 0x40, 0x45, 0x40, 0x40, 0x40, 0x0f, ++ 0x45, 0x5d, 0x59, 0x04, 0x5f, 0x5d, 0x5a, 0x56, 0x56, 0x07, 0x07, 0x0d, 0x4b, 0x02, 0x57, 0x07, ++ 0x61, 0x27, 0x41, 0x15, 0x40, 0x4d, 0x19, 0x40, 0x40, 0x40, 0x45, 0x45, 0x53, 0x59, 0x57, 0x59, ++ 0x5f, 0x5d, 0x53, 0x61, 0x59, 0x55, 0x59, 0x61, 0x61, 0x5f, 0x57, 0x49, 0x43, 0x49, 0x53, 0x59, ++ 0x57, 0x59, 0x5f, 0x5d, 0x53, 0x61, 0x59, 0x55, 0x59, 0x61, 0x61, 0x5f, 0x57, 0x49, 0x43, 0x49, ++ 0x0c, 0x4d, 0x4a, 0x40, 0x48, 0x40, 0x45, 0x07, 0x45, 0x43, 0x43, 0x5a, 0x07, 0x1d, 0x13, 0x4d, ++ 0x12, 0x07, 0x40, 0x1d, 0x13, 0x4d, 0x12, 0x07, 0x40, 0x1d, 0x13, 0x4d, 0x12, 0x07, 0x40, 0x42, ++ 0x07, 0x43, 0x43, 0x41, 0x0c, 0x41, 0x0c, 0x15, 0x17, 0x13, 0x4d, 0x17, 0x13, 0x4d, 0x40, 0x40, ++ 0x40, 0x29, 0x29, 0x15, 0x40, 0x0f, 0x15, 0x1b, 0x1b, 0x22, 0x27, 0x12, 0x07, 0x0c, 0x12, 0x0a, ++ 0x05, 0x39, 0x1d, 0x15, 0x40, 0x15, 0x0a, 0x1b, 0x41, 0x15, 0x00, 0x04, 0x41, 0x15, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x02, 0x40, 0x45, 0x5b, 0x40, 0x20, 0x02, 0x00, 0x27, 0x40, 0x45, 0x40, 0x40, 0x40, 0x0f, ++ 0x45, 0x5b, 0x58, 0x04, 0x5e, 0x5b, 0x59, 0x54, 0x54, 0x07, 0x07, 0x0d, 0x4b, 0x02, 0x56, 0x07, ++ 0x60, 0x27, 0x40, 0x15, 0x40, 0x4d, 0x18, 0x40, 0x40, 0x40, 0x45, 0x45, 0x53, 0x58, 0x56, 0x58, ++ 0x5e, 0x5b, 0x53, 0x60, 0x58, 0x53, 0x58, 0x60, 0x60, 0x5e, 0x56, 0x48, 0x43, 0x48, 0x53, 0x58, ++ 0x56, 0x58, 0x5e, 0x5b, 0x53, 0x60, 0x58, 0x53, 0x58, 0x60, 0x60, 0x5e, 0x56, 0x48, 0x43, 0x48, ++ 0x0c, 0x4d, 0x49, 0x40, 0x48, 0x40, 0x45, 0x07, 0x45, 0x43, 0x43, 0x59, 0x07, 0x1d, 0x12, 0x4d, ++ 0x12, 0x07, 0x40, 0x1d, 0x12, 0x4d, 0x12, 0x07, 0x40, 0x1d, 0x12, 0x4d, 0x12, 0x07, 0x40, 0x42, ++ 0x07, 0x43, 0x43, 0x40, 0x0c, 0x40, 0x0c, 0x15, 0x17, 0x12, 0x4d, 0x17, 0x12, 0x4d, 0x40, 0x40, ++ 0x40, 0x28, 0x28, 0x15, 0x40, 0x0f, 0x15, 0x1a, 0x1a, 0x22, 0x27, 0x12, 0x07, 0x0c, 0x12, 0x0a, ++ 0x05, 0x38, 0x1d, 0x15, 0x40, 0x15, 0x0a, 0x1a, 0x40, 0x15, 0x01, 0x04, 0x40, 0x15, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x02, 0x00, 0x45, 0x5a, 0x40, 0x1f, 0x02, 0x40, 0x27, 0x40, 0x45, 0x40, 0x40, 0x40, 0x0f, ++ 0x45, 0x59, 0x57, 0x05, 0x5c, 0x59, 0x57, 0x51, 0x51, 0x07, 0x07, 0x0d, 0x4a, 0x02, 0x54, 0x07, ++ 0x5f, 0x27, 0x00, 0x15, 0x40, 0x4d, 0x17, 0x40, 0x40, 0x40, 0x45, 0x45, 0x52, 0x57, 0x54, 0x57, ++ 0x5c, 0x59, 0x52, 0x5f, 0x57, 0x51, 0x57, 0x5f, 0x5f, 0x5c, 0x54, 0x47, 0x42, 0x47, 0x52, 0x57, ++ 0x54, 0x57, 0x5c, 0x59, 0x52, 0x5f, 0x57, 0x51, 0x57, 0x5f, 0x5f, 0x5c, 0x54, 0x47, 0x42, 0x47, ++ 0x0d, 0x4d, 0x47, 0x40, 0x48, 0x40, 0x45, 0x07, 0x45, 0x42, 0x42, 0x57, 0x07, 0x1d, 0x12, 0x4d, ++ 0x12, 0x07, 0x40, 0x1d, 0x12, 0x4d, 0x12, 0x07, 0x40, 0x1d, 0x12, 0x4d, 0x12, 0x07, 0x40, 0x42, ++ 0x07, 0x42, 0x42, 0x00, 0x0d, 0x00, 0x0d, 0x15, 0x17, 0x12, 0x4d, 0x17, 0x12, 0x4d, 0x40, 0x40, ++ 0x40, 0x27, 0x27, 0x15, 0x40, 0x0f, 0x15, 0x1a, 0x1a, 0x22, 0x27, 0x12, 0x07, 0x0d, 0x12, 0x0a, ++ 0x05, 0x37, 0x1d, 0x15, 0x40, 0x15, 0x0a, 0x1a, 0x00, 0x15, 0x03, 0x05, 0x00, 0x15, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x01, 0x01, 0x44, 0x59, 0x40, 0x1e, 0x01, 0x41, 0x27, 0x40, 0x44, 0x40, 0x40, 0x40, 0x0f, ++ 0x44, 0x58, 0x56, 0x06, 0x5b, 0x58, 0x55, 0x4f, 0x4f, 0x07, 0x07, 0x0c, 0x49, 0x03, 0x53, 0x07, ++ 0x5e, 0x27, 0x01, 0x14, 0x40, 0x4c, 0x16, 0x40, 0x40, 0x40, 0x44, 0x44, 0x51, 0x56, 0x53, 0x56, ++ 0x5b, 0x58, 0x51, 0x5e, 0x56, 0x50, 0x56, 0x5e, 0x5e, 0x5b, 0x53, 0x46, 0x41, 0x46, 0x51, 0x56, ++ 0x53, 0x56, 0x5b, 0x58, 0x51, 0x5e, 0x56, 0x50, 0x56, 0x5e, 0x5e, 0x5b, 0x53, 0x46, 0x41, 0x46, ++ 0x0e, 0x4c, 0x45, 0x40, 0x48, 0x40, 0x44, 0x07, 0x44, 0x41, 0x41, 0x55, 0x07, 0x1c, 0x11, 0x4c, ++ 0x13, 0x07, 0x40, 0x1c, 0x11, 0x4c, 0x13, 0x07, 0x40, 0x1c, 0x11, 0x4c, 0x13, 0x07, 0x40, 0x43, ++ 0x07, 0x41, 0x41, 0x01, 0x0e, 0x01, 0x0e, 0x14, 0x17, 0x11, 0x4c, 0x17, 0x11, 0x4c, 0x40, 0x40, ++ 0x40, 0x26, 0x26, 0x14, 0x40, 0x0f, 0x14, 0x19, 0x19, 0x23, 0x27, 0x13, 0x07, 0x0e, 0x13, 0x0b, ++ 0x04, 0x36, 0x1c, 0x14, 0x40, 0x14, 0x0b, 0x19, 0x01, 0x14, 0x04, 0x06, 0x01, 0x14, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x01, 0x02, 0x44, 0x59, 0x40, 0x1d, 0x01, 0x42, 0x27, 0x40, 0x44, 0x40, 0x40, 0x40, 0x0f, ++ 0x44, 0x56, 0x55, 0x06, 0x5a, 0x56, 0x53, 0x4c, 0x4c, 0x07, 0x07, 0x0c, 0x49, 0x03, 0x52, 0x07, ++ 0x5d, 0x27, 0x02, 0x14, 0x40, 0x4c, 0x15, 0x40, 0x40, 0x40, 0x44, 0x44, 0x51, 0x55, 0x52, 0x55, ++ 0x5a, 0x56, 0x51, 0x5d, 0x55, 0x4e, 0x55, 0x5d, 0x5d, 0x5a, 0x52, 0x45, 0x41, 0x45, 0x51, 0x55, ++ 0x52, 0x55, 0x5a, 0x56, 0x51, 0x5d, 0x55, 0x4e, 0x55, 0x5d, 0x5d, 0x5a, 0x52, 0x45, 0x41, 0x45, ++ 0x0e, 0x4c, 0x43, 0x40, 0x48, 0x40, 0x44, 0x07, 0x44, 0x41, 0x41, 0x53, 0x07, 0x1c, 0x11, 0x4c, ++ 0x13, 0x07, 0x40, 0x1c, 0x11, 0x4c, 0x13, 0x07, 0x40, 0x1c, 0x11, 0x4c, 0x13, 0x07, 0x40, 0x43, ++ 0x07, 0x41, 0x41, 0x02, 0x0e, 0x02, 0x0e, 0x14, 0x17, 0x11, 0x4c, 0x17, 0x11, 0x4c, 0x40, 0x40, ++ 0x40, 0x25, 0x25, 0x14, 0x40, 0x0f, 0x14, 0x19, 0x19, 0x23, 0x27, 0x13, 0x07, 0x0e, 0x13, 0x0b, ++ 0x04, 0x35, 0x1c, 0x14, 0x40, 0x14, 0x0b, 0x19, 0x02, 0x14, 0x05, 0x06, 0x02, 0x14, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x00, 0x03, 0x44, 0x58, 0x40, 0x1c, 0x00, 0x43, 0x27, 0x40, 0x44, 0x40, 0x40, 0x40, 0x0f, ++ 0x44, 0x55, 0x54, 0x07, 0x59, 0x55, 0x51, 0x4a, 0x4a, 0x07, 0x07, 0x0c, 0x48, 0x03, 0x51, 0x07, ++ 0x5c, 0x27, 0x03, 0x14, 0x40, 0x4c, 0x14, 0x40, 0x40, 0x40, 0x44, 0x44, 0x50, 0x54, 0x51, 0x54, ++ 0x59, 0x55, 0x50, 0x5c, 0x54, 0x4d, 0x54, 0x5c, 0x5c, 0x59, 0x51, 0x44, 0x40, 0x44, 0x50, 0x54, ++ 0x51, 0x54, 0x59, 0x55, 0x50, 0x5c, 0x54, 0x4d, 0x54, 0x5c, 0x5c, 0x59, 0x51, 0x44, 0x40, 0x44, ++ 0x0f, 0x4c, 0x41, 0x40, 0x48, 0x40, 0x44, 0x07, 0x44, 0x40, 0x40, 0x51, 0x07, 0x1c, 0x10, 0x4c, ++ 0x13, 0x07, 0x40, 0x1c, 0x10, 0x4c, 0x13, 0x07, 0x40, 0x1c, 0x10, 0x4c, 0x13, 0x07, 0x40, 0x43, ++ 0x07, 0x40, 0x40, 0x03, 0x0f, 0x03, 0x0f, 0x14, 0x17, 0x10, 0x4c, 0x17, 0x10, 0x4c, 0x40, 0x40, ++ 0x40, 0x24, 0x24, 0x14, 0x40, 0x0f, 0x14, 0x18, 0x18, 0x23, 0x27, 0x13, 0x07, 0x0f, 0x13, 0x0b, ++ 0x04, 0x34, 0x1c, 0x14, 0x40, 0x14, 0x0b, 0x18, 0x03, 0x14, 0x06, 0x07, 0x03, 0x14, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x40, 0x04, 0x43, 0x57, 0x40, 0x1b, 0x40, 0x44, 0x27, 0x40, 0x43, 0x40, 0x40, 0x40, 0x0f, ++ 0x43, 0x53, 0x53, 0x08, 0x57, 0x53, 0x4f, 0x47, 0x47, 0x07, 0x07, 0x0b, 0x47, 0x04, 0x4f, 0x07, ++ 0x5b, 0x27, 0x04, 0x13, 0x40, 0x4b, 0x13, 0x40, 0x40, 0x40, 0x43, 0x43, 0x4f, 0x53, 0x4f, 0x53, ++ 0x57, 0x53, 0x4f, 0x5b, 0x53, 0x4b, 0x53, 0x5b, 0x5b, 0x57, 0x4f, 0x43, 0x00, 0x43, 0x4f, 0x53, ++ 0x4f, 0x53, 0x57, 0x53, 0x4f, 0x5b, 0x53, 0x4b, 0x53, 0x5b, 0x5b, 0x57, 0x4f, 0x43, 0x00, 0x43, ++ 0x10, 0x4b, 0x00, 0x40, 0x48, 0x40, 0x43, 0x07, 0x43, 0x00, 0x00, 0x4f, 0x07, 0x1b, 0x0f, 0x4b, ++ 0x14, 0x07, 0x40, 0x1b, 0x0f, 0x4b, 0x14, 0x07, 0x40, 0x1b, 0x0f, 0x4b, 0x14, 0x07, 0x40, 0x44, ++ 0x07, 0x00, 0x00, 0x04, 0x10, 0x04, 0x10, 0x13, 0x17, 0x0f, 0x4b, 0x17, 0x0f, 0x4b, 0x40, 0x40, ++ 0x40, 0x23, 0x23, 0x13, 0x40, 0x0f, 0x13, 0x17, 0x17, 0x24, 0x27, 0x14, 0x07, 0x10, 0x14, 0x0c, ++ 0x03, 0x33, 0x1b, 0x13, 0x40, 0x13, 0x0c, 0x17, 0x04, 0x13, 0x08, 0x08, 0x04, 0x13, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x40, 0x05, 0x43, 0x57, 0x40, 0x1a, 0x40, 0x45, 0x27, 0x40, 0x43, 0x40, 0x40, 0x40, 0x0f, ++ 0x43, 0x52, 0x52, 0x08, 0x56, 0x52, 0x4d, 0x45, 0x45, 0x07, 0x07, 0x0b, 0x47, 0x04, 0x4e, 0x07, ++ 0x5a, 0x27, 0x05, 0x13, 0x40, 0x4b, 0x12, 0x40, 0x40, 0x40, 0x43, 0x43, 0x4f, 0x52, 0x4e, 0x52, ++ 0x56, 0x52, 0x4f, 0x5a, 0x52, 0x4a, 0x52, 0x5a, 0x5a, 0x56, 0x4e, 0x42, 0x00, 0x42, 0x4f, 0x52, ++ 0x4e, 0x52, 0x56, 0x52, 0x4f, 0x5a, 0x52, 0x4a, 0x52, 0x5a, 0x5a, 0x56, 0x4e, 0x42, 0x00, 0x42, ++ 0x10, 0x4b, 0x02, 0x40, 0x48, 0x40, 0x43, 0x07, 0x43, 0x00, 0x00, 0x4d, 0x07, 0x1b, 0x0f, 0x4b, ++ 0x14, 0x07, 0x40, 0x1b, 0x0f, 0x4b, 0x14, 0x07, 0x40, 0x1b, 0x0f, 0x4b, 0x14, 0x07, 0x40, 0x44, ++ 0x07, 0x00, 0x00, 0x05, 0x10, 0x05, 0x10, 0x13, 0x17, 0x0f, 0x4b, 0x17, 0x0f, 0x4b, 0x40, 0x40, ++ 0x40, 0x22, 0x22, 0x13, 0x40, 0x0f, 0x13, 0x17, 0x17, 0x24, 0x27, 0x14, 0x07, 0x10, 0x14, 0x0c, ++ 0x03, 0x32, 0x1b, 0x13, 0x40, 0x13, 0x0c, 0x17, 0x05, 0x13, 0x09, 0x08, 0x05, 0x13, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x41, 0x06, 0x43, 0x56, 0x40, 0x19, 0x41, 0x46, 0x27, 0x40, 0x43, 0x40, 0x40, 0x40, 0x0f, ++ 0x43, 0x50, 0x51, 0x09, 0x55, 0x50, 0x4b, 0x42, 0x42, 0x07, 0x07, 0x0b, 0x46, 0x04, 0x4d, 0x07, ++ 0x59, 0x27, 0x06, 0x13, 0x40, 0x4b, 0x11, 0x40, 0x40, 0x40, 0x43, 0x43, 0x4e, 0x51, 0x4d, 0x51, ++ 0x55, 0x50, 0x4e, 0x59, 0x51, 0x48, 0x51, 0x59, 0x59, 0x55, 0x4d, 0x41, 0x01, 0x41, 0x4e, 0x51, ++ 0x4d, 0x51, 0x55, 0x50, 0x4e, 0x59, 0x51, 0x48, 0x51, 0x59, 0x59, 0x55, 0x4d, 0x41, 0x01, 0x41, ++ 0x11, 0x4b, 0x04, 0x40, 0x48, 0x40, 0x43, 0x07, 0x43, 0x01, 0x01, 0x4b, 0x07, 0x1b, 0x0e, 0x4b, ++ 0x14, 0x07, 0x40, 0x1b, 0x0e, 0x4b, 0x14, 0x07, 0x40, 0x1b, 0x0e, 0x4b, 0x14, 0x07, 0x40, 0x44, ++ 0x07, 0x01, 0x01, 0x06, 0x11, 0x06, 0x11, 0x13, 0x17, 0x0e, 0x4b, 0x17, 0x0e, 0x4b, 0x40, 0x40, ++ 0x40, 0x21, 0x21, 0x13, 0x40, 0x0f, 0x13, 0x16, 0x16, 0x24, 0x27, 0x14, 0x07, 0x11, 0x14, 0x0c, ++ 0x03, 0x31, 0x1b, 0x13, 0x40, 0x13, 0x0c, 0x16, 0x06, 0x13, 0x0a, 0x09, 0x06, 0x13, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x42, 0x06, 0x43, 0x56, 0x40, 0x18, 0x42, 0x47, 0x27, 0x40, 0x43, 0x40, 0x40, 0x40, 0x0f, ++ 0x43, 0x4f, 0x51, 0x09, 0x54, 0x4f, 0x4a, 0x40, 0x40, 0x07, 0x07, 0x0a, 0x46, 0x04, 0x4c, 0x07, ++ 0x59, 0x27, 0x06, 0x12, 0x40, 0x4b, 0x10, 0x40, 0x40, 0x40, 0x43, 0x43, 0x4e, 0x51, 0x4c, 0x51, ++ 0x54, 0x4f, 0x4e, 0x59, 0x51, 0x47, 0x51, 0x59, 0x59, 0x54, 0x4c, 0x41, 0x01, 0x41, 0x4e, 0x51, ++ 0x4c, 0x51, 0x54, 0x4f, 0x4e, 0x59, 0x51, 0x47, 0x51, 0x59, 0x59, 0x54, 0x4c, 0x41, 0x01, 0x41, ++ 0x11, 0x4b, 0x05, 0x40, 0x48, 0x40, 0x43, 0x07, 0x43, 0x01, 0x01, 0x4a, 0x07, 0x1a, 0x0d, 0x4b, ++ 0x14, 0x07, 0x40, 0x1a, 0x0d, 0x4b, 0x14, 0x07, 0x40, 0x1a, 0x0d, 0x4b, 0x14, 0x07, 0x40, 0x45, ++ 0x07, 0x01, 0x01, 0x06, 0x11, 0x06, 0x11, 0x12, 0x17, 0x0d, 0x4b, 0x17, 0x0d, 0x4b, 0x40, 0x40, ++ 0x40, 0x20, 0x20, 0x12, 0x40, 0x0f, 0x12, 0x15, 0x15, 0x24, 0x27, 0x14, 0x07, 0x11, 0x14, 0x0c, ++ 0x02, 0x30, 0x1a, 0x12, 0x40, 0x12, 0x0c, 0x15, 0x06, 0x12, 0x0b, 0x09, 0x06, 0x12, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x42, 0x07, 0x42, 0x55, 0x40, 0x18, 0x42, 0x47, 0x27, 0x40, 0x42, 0x40, 0x40, 0x40, 0x0f, ++ 0x42, 0x4d, 0x50, 0x0a, 0x52, 0x4d, 0x48, 0x02, 0x02, 0x07, 0x07, 0x0a, 0x45, 0x05, 0x4a, 0x07, ++ 0x58, 0x27, 0x07, 0x12, 0x40, 0x4a, 0x10, 0x40, 0x40, 0x40, 0x42, 0x42, 0x4d, 0x50, 0x4a, 0x50, ++ 0x52, 0x4d, 0x4d, 0x58, 0x50, 0x45, 0x50, 0x58, 0x58, 0x52, 0x4a, 0x40, 0x02, 0x40, 0x4d, 0x50, ++ 0x4a, 0x50, 0x52, 0x4d, 0x4d, 0x58, 0x50, 0x45, 0x50, 0x58, 0x58, 0x52, 0x4a, 0x40, 0x02, 0x40, ++ 0x12, 0x4a, 0x07, 0x40, 0x48, 0x40, 0x42, 0x07, 0x42, 0x02, 0x02, 0x48, 0x07, 0x1a, 0x0d, 0x4a, ++ 0x15, 0x07, 0x40, 0x1a, 0x0d, 0x4a, 0x15, 0x07, 0x40, 0x1a, 0x0d, 0x4a, 0x15, 0x07, 0x40, 0x45, ++ 0x07, 0x02, 0x02, 0x07, 0x12, 0x07, 0x12, 0x12, 0x17, 0x0d, 0x4a, 0x17, 0x0d, 0x4a, 0x40, 0x40, ++ 0x40, 0x20, 0x20, 0x12, 0x40, 0x0f, 0x12, 0x15, 0x15, 0x25, 0x27, 0x15, 0x07, 0x12, 0x15, 0x0d, ++ 0x02, 0x30, 0x1a, 0x12, 0x40, 0x12, 0x0d, 0x15, 0x07, 0x12, 0x0d, 0x0a, 0x07, 0x12, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x43, 0x08, 0x42, 0x54, 0x40, 0x17, 0x43, 0x48, 0x27, 0x40, 0x42, 0x40, 0x40, 0x40, 0x0f, ++ 0x42, 0x4b, 0x4f, 0x0b, 0x51, 0x4b, 0x46, 0x04, 0x04, 0x07, 0x07, 0x0a, 0x44, 0x05, 0x49, 0x07, ++ 0x57, 0x27, 0x08, 0x12, 0x40, 0x4a, 0x0f, 0x40, 0x40, 0x40, 0x42, 0x42, 0x4c, 0x4f, 0x49, 0x4f, ++ 0x51, 0x4b, 0x4c, 0x57, 0x4f, 0x43, 0x4f, 0x57, 0x57, 0x51, 0x49, 0x00, 0x03, 0x00, 0x4c, 0x4f, ++ 0x49, 0x4f, 0x51, 0x4b, 0x4c, 0x57, 0x4f, 0x43, 0x4f, 0x57, 0x57, 0x51, 0x49, 0x00, 0x03, 0x00, ++ 0x13, 0x4a, 0x09, 0x40, 0x48, 0x40, 0x42, 0x07, 0x42, 0x03, 0x03, 0x46, 0x07, 0x1a, 0x0c, 0x4a, ++ 0x15, 0x07, 0x40, 0x1a, 0x0c, 0x4a, 0x15, 0x07, 0x40, 0x1a, 0x0c, 0x4a, 0x15, 0x07, 0x40, 0x45, ++ 0x07, 0x03, 0x03, 0x08, 0x13, 0x08, 0x13, 0x12, 0x17, 0x0c, 0x4a, 0x17, 0x0c, 0x4a, 0x40, 0x40, ++ 0x40, 0x1f, 0x1f, 0x12, 0x40, 0x0f, 0x12, 0x14, 0x14, 0x25, 0x27, 0x15, 0x07, 0x13, 0x15, 0x0d, ++ 0x02, 0x2f, 0x1a, 0x12, 0x40, 0x12, 0x0d, 0x14, 0x08, 0x12, 0x0e, 0x0b, 0x08, 0x12, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x43, 0x09, 0x42, 0x54, 0x40, 0x16, 0x43, 0x49, 0x27, 0x40, 0x42, 0x40, 0x40, 0x40, 0x0f, ++ 0x42, 0x4a, 0x4e, 0x0b, 0x50, 0x4a, 0x44, 0x07, 0x07, 0x07, 0x07, 0x0a, 0x44, 0x05, 0x48, 0x07, ++ 0x56, 0x27, 0x09, 0x12, 0x40, 0x4a, 0x0e, 0x40, 0x40, 0x40, 0x42, 0x42, 0x4c, 0x4e, 0x48, 0x4e, ++ 0x50, 0x4a, 0x4c, 0x56, 0x4e, 0x42, 0x4e, 0x56, 0x56, 0x50, 0x48, 0x01, 0x03, 0x01, 0x4c, 0x4e, ++ 0x48, 0x4e, 0x50, 0x4a, 0x4c, 0x56, 0x4e, 0x42, 0x4e, 0x56, 0x56, 0x50, 0x48, 0x01, 0x03, 0x01, ++ 0x13, 0x4a, 0x0b, 0x40, 0x48, 0x40, 0x42, 0x07, 0x42, 0x03, 0x03, 0x44, 0x07, 0x1a, 0x0c, 0x4a, ++ 0x15, 0x07, 0x40, 0x1a, 0x0c, 0x4a, 0x15, 0x07, 0x40, 0x1a, 0x0c, 0x4a, 0x15, 0x07, 0x40, 0x45, ++ 0x07, 0x03, 0x03, 0x09, 0x13, 0x09, 0x13, 0x12, 0x17, 0x0c, 0x4a, 0x17, 0x0c, 0x4a, 0x40, 0x40, ++ 0x40, 0x1e, 0x1e, 0x12, 0x40, 0x0f, 0x12, 0x14, 0x14, 0x25, 0x27, 0x15, 0x07, 0x13, 0x15, 0x0d, ++ 0x02, 0x2e, 0x1a, 0x12, 0x40, 0x12, 0x0d, 0x14, 0x09, 0x12, 0x0f, 0x0b, 0x09, 0x12, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x44, 0x0a, 0x41, 0x53, 0x40, 0x15, 0x44, 0x4a, 0x27, 0x40, 0x41, 0x40, 0x40, 0x40, 0x0f, ++ 0x41, 0x48, 0x4d, 0x0c, 0x4f, 0x48, 0x42, 0x09, 0x09, 0x07, 0x07, 0x09, 0x43, 0x06, 0x47, 0x07, ++ 0x55, 0x27, 0x0a, 0x11, 0x40, 0x49, 0x0d, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4b, 0x4d, 0x47, 0x4d, ++ 0x4f, 0x48, 0x4b, 0x55, 0x4d, 0x40, 0x4d, 0x55, 0x55, 0x4f, 0x47, 0x02, 0x04, 0x02, 0x4b, 0x4d, ++ 0x47, 0x4d, 0x4f, 0x48, 0x4b, 0x55, 0x4d, 0x40, 0x4d, 0x55, 0x55, 0x4f, 0x47, 0x02, 0x04, 0x02, ++ 0x14, 0x49, 0x0d, 0x40, 0x48, 0x40, 0x41, 0x07, 0x41, 0x04, 0x04, 0x42, 0x07, 0x19, 0x0b, 0x49, ++ 0x16, 0x07, 0x40, 0x19, 0x0b, 0x49, 0x16, 0x07, 0x40, 0x19, 0x0b, 0x49, 0x16, 0x07, 0x40, 0x46, ++ 0x07, 0x04, 0x04, 0x0a, 0x14, 0x0a, 0x14, 0x11, 0x17, 0x0b, 0x49, 0x17, 0x0b, 0x49, 0x40, 0x40, ++ 0x40, 0x1d, 0x1d, 0x11, 0x40, 0x0f, 0x11, 0x13, 0x13, 0x26, 0x27, 0x16, 0x07, 0x14, 0x16, 0x0e, ++ 0x01, 0x2d, 0x19, 0x11, 0x40, 0x11, 0x0e, 0x13, 0x0a, 0x11, 0x10, 0x0c, 0x0a, 0x11, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x45, 0x0b, 0x41, 0x52, 0x40, 0x14, 0x45, 0x4b, 0x27, 0x40, 0x41, 0x40, 0x40, 0x40, 0x0f, ++ 0x41, 0x47, 0x4c, 0x0d, 0x4d, 0x47, 0x40, 0x0c, 0x0c, 0x07, 0x07, 0x09, 0x42, 0x06, 0x45, 0x07, ++ 0x54, 0x27, 0x0b, 0x11, 0x40, 0x49, 0x0c, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4a, 0x4c, 0x45, 0x4c, ++ 0x4d, 0x47, 0x4a, 0x54, 0x4c, 0x00, 0x4c, 0x54, 0x54, 0x4d, 0x45, 0x03, 0x05, 0x03, 0x4a, 0x4c, ++ 0x45, 0x4c, 0x4d, 0x47, 0x4a, 0x54, 0x4c, 0x00, 0x4c, 0x54, 0x54, 0x4d, 0x45, 0x03, 0x05, 0x03, ++ 0x15, 0x49, 0x0f, 0x40, 0x48, 0x40, 0x41, 0x07, 0x41, 0x05, 0x05, 0x40, 0x07, 0x19, 0x0a, 0x49, ++ 0x16, 0x07, 0x40, 0x19, 0x0a, 0x49, 0x16, 0x07, 0x40, 0x19, 0x0a, 0x49, 0x16, 0x07, 0x40, 0x46, ++ 0x07, 0x05, 0x05, 0x0b, 0x15, 0x0b, 0x15, 0x11, 0x17, 0x0a, 0x49, 0x17, 0x0a, 0x49, 0x40, 0x40, ++ 0x40, 0x1c, 0x1c, 0x11, 0x40, 0x0f, 0x11, 0x12, 0x12, 0x26, 0x27, 0x16, 0x07, 0x15, 0x16, 0x0e, ++ 0x01, 0x2c, 0x19, 0x11, 0x40, 0x11, 0x0e, 0x12, 0x0b, 0x11, 0x12, 0x0d, 0x0b, 0x11, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x45, 0x0c, 0x41, 0x52, 0x40, 0x13, 0x45, 0x4c, 0x27, 0x40, 0x41, 0x40, 0x40, 0x40, 0x0f, ++ 0x41, 0x45, 0x4b, 0x0d, 0x4c, 0x45, 0x01, 0x0e, 0x0e, 0x07, 0x07, 0x09, 0x42, 0x06, 0x44, 0x07, ++ 0x53, 0x27, 0x0c, 0x11, 0x40, 0x49, 0x0b, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4a, 0x4b, 0x44, 0x4b, ++ 0x4c, 0x45, 0x4a, 0x53, 0x4b, 0x02, 0x4b, 0x53, 0x53, 0x4c, 0x44, 0x04, 0x05, 0x04, 0x4a, 0x4b, ++ 0x44, 0x4b, 0x4c, 0x45, 0x4a, 0x53, 0x4b, 0x02, 0x4b, 0x53, 0x53, 0x4c, 0x44, 0x04, 0x05, 0x04, ++ 0x15, 0x49, 0x11, 0x40, 0x48, 0x40, 0x41, 0x07, 0x41, 0x05, 0x05, 0x01, 0x07, 0x19, 0x0a, 0x49, ++ 0x16, 0x07, 0x40, 0x19, 0x0a, 0x49, 0x16, 0x07, 0x40, 0x19, 0x0a, 0x49, 0x16, 0x07, 0x40, 0x46, ++ 0x07, 0x05, 0x05, 0x0c, 0x15, 0x0c, 0x15, 0x11, 0x17, 0x0a, 0x49, 0x17, 0x0a, 0x49, 0x40, 0x40, ++ 0x40, 0x1b, 0x1b, 0x11, 0x40, 0x0f, 0x11, 0x12, 0x12, 0x26, 0x27, 0x16, 0x07, 0x15, 0x16, 0x0e, ++ 0x01, 0x2b, 0x19, 0x11, 0x40, 0x11, 0x0e, 0x12, 0x0c, 0x11, 0x13, 0x0d, 0x0c, 0x11, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x46, 0x0d, 0x40, 0x51, 0x40, 0x12, 0x46, 0x4d, 0x27, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0f, ++ 0x40, 0x44, 0x4a, 0x0e, 0x4b, 0x44, 0x03, 0x11, 0x11, 0x07, 0x07, 0x08, 0x41, 0x07, 0x43, 0x07, ++ 0x52, 0x27, 0x0d, 0x10, 0x40, 0x48, 0x0a, 0x40, 0x40, 0x40, 0x40, 0x40, 0x49, 0x4a, 0x43, 0x4a, ++ 0x4b, 0x44, 0x49, 0x52, 0x4a, 0x03, 0x4a, 0x52, 0x52, 0x4b, 0x43, 0x05, 0x06, 0x05, 0x49, 0x4a, ++ 0x43, 0x4a, 0x4b, 0x44, 0x49, 0x52, 0x4a, 0x03, 0x4a, 0x52, 0x52, 0x4b, 0x43, 0x05, 0x06, 0x05, ++ 0x16, 0x48, 0x13, 0x40, 0x48, 0x40, 0x40, 0x07, 0x40, 0x06, 0x06, 0x03, 0x07, 0x18, 0x09, 0x48, ++ 0x17, 0x07, 0x40, 0x18, 0x09, 0x48, 0x17, 0x07, 0x40, 0x18, 0x09, 0x48, 0x17, 0x07, 0x40, 0x47, ++ 0x07, 0x06, 0x06, 0x0d, 0x16, 0x0d, 0x16, 0x10, 0x17, 0x09, 0x48, 0x17, 0x09, 0x48, 0x40, 0x40, ++ 0x40, 0x1a, 0x1a, 0x10, 0x40, 0x0f, 0x10, 0x11, 0x11, 0x27, 0x27, 0x17, 0x07, 0x16, 0x17, 0x0f, ++ 0x00, 0x2a, 0x18, 0x10, 0x40, 0x10, 0x0f, 0x11, 0x0d, 0x10, 0x14, 0x0e, 0x0d, 0x10, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x47, 0x0e, 0x40, 0x51, 0x40, 0x11, 0x47, 0x4e, 0x27, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0f, ++ 0x40, 0x42, 0x49, 0x0e, 0x4a, 0x42, 0x04, 0x13, 0x13, 0x07, 0x07, 0x08, 0x41, 0x07, 0x42, 0x07, ++ 0x51, 0x27, 0x0e, 0x10, 0x40, 0x48, 0x09, 0x40, 0x40, 0x40, 0x40, 0x40, 0x49, 0x49, 0x42, 0x49, ++ 0x4a, 0x42, 0x49, 0x51, 0x49, 0x05, 0x49, 0x51, 0x51, 0x4a, 0x42, 0x06, 0x06, 0x06, 0x49, 0x49, ++ 0x42, 0x49, 0x4a, 0x42, 0x49, 0x51, 0x49, 0x05, 0x49, 0x51, 0x51, 0x4a, 0x42, 0x06, 0x06, 0x06, ++ 0x16, 0x48, 0x14, 0x40, 0x48, 0x40, 0x40, 0x07, 0x40, 0x06, 0x06, 0x04, 0x07, 0x18, 0x08, 0x48, ++ 0x17, 0x07, 0x40, 0x18, 0x08, 0x48, 0x17, 0x07, 0x40, 0x18, 0x08, 0x48, 0x17, 0x07, 0x40, 0x47, ++ 0x07, 0x06, 0x06, 0x0e, 0x16, 0x0e, 0x16, 0x10, 0x17, 0x08, 0x48, 0x17, 0x08, 0x48, 0x40, 0x40, ++ 0x40, 0x19, 0x19, 0x10, 0x40, 0x0f, 0x10, 0x10, 0x10, 0x27, 0x27, 0x17, 0x07, 0x16, 0x17, 0x0f, ++ 0x00, 0x29, 0x18, 0x10, 0x40, 0x10, 0x0f, 0x10, 0x0e, 0x10, 0x15, 0x0e, 0x0e, 0x10, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x47, 0x0f, 0x40, 0x50, 0x40, 0x10, 0x47, 0x4f, 0x27, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0f, ++ 0x40, 0x40, 0x48, 0x0f, 0x48, 0x40, 0x06, 0x16, 0x16, 0x07, 0x07, 0x08, 0x40, 0x07, 0x40, 0x07, ++ 0x50, 0x27, 0x0f, 0x10, 0x40, 0x48, 0x08, 0x40, 0x40, 0x40, 0x40, 0x40, 0x48, 0x48, 0x40, 0x48, ++ 0x48, 0x40, 0x48, 0x50, 0x48, 0x07, 0x48, 0x50, 0x50, 0x48, 0x40, 0x07, 0x07, 0x07, 0x48, 0x48, ++ 0x40, 0x48, 0x48, 0x40, 0x48, 0x50, 0x48, 0x07, 0x48, 0x50, 0x50, 0x48, 0x40, 0x07, 0x07, 0x07, ++ 0x17, 0x48, 0x16, 0x40, 0x48, 0x40, 0x40, 0x07, 0x40, 0x07, 0x07, 0x06, 0x07, 0x18, 0x08, 0x48, ++ 0x17, 0x07, 0x40, 0x18, 0x08, 0x48, 0x17, 0x07, 0x40, 0x18, 0x08, 0x48, 0x17, 0x07, 0x40, 0x47, ++ 0x07, 0x07, 0x07, 0x0f, 0x17, 0x0f, 0x17, 0x10, 0x17, 0x08, 0x48, 0x17, 0x08, 0x48, 0x40, 0x40, ++ 0x40, 0x18, 0x18, 0x10, 0x40, 0x0f, 0x10, 0x10, 0x10, 0x27, 0x27, 0x17, 0x07, 0x17, 0x17, 0x0f, ++ 0x00, 0x28, 0x18, 0x10, 0x40, 0x10, 0x0f, 0x10, 0x0f, 0x10, 0x17, 0x0f, 0x0f, 0x10, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x48, 0x10, 0x00, 0x4f, 0x40, 0x0f, 0x48, 0x50, 0x27, 0x40, 0x00, 0x40, 0x40, 0x40, 0x0f, ++ 0x00, 0x00, 0x47, 0x10, 0x47, 0x00, 0x08, 0x18, 0x18, 0x07, 0x07, 0x07, 0x00, 0x08, 0x00, 0x07, ++ 0x4f, 0x27, 0x10, 0x0f, 0x40, 0x47, 0x07, 0x40, 0x40, 0x40, 0x00, 0x00, 0x47, 0x47, 0x00, 0x47, ++ 0x47, 0x00, 0x47, 0x4f, 0x47, 0x08, 0x47, 0x4f, 0x4f, 0x47, 0x00, 0x08, 0x08, 0x08, 0x47, 0x47, ++ 0x00, 0x47, 0x47, 0x00, 0x47, 0x4f, 0x47, 0x08, 0x47, 0x4f, 0x4f, 0x47, 0x00, 0x08, 0x08, 0x08, ++ 0x18, 0x47, 0x18, 0x40, 0x48, 0x40, 0x00, 0x07, 0x00, 0x08, 0x08, 0x08, 0x07, 0x17, 0x07, 0x47, ++ 0x18, 0x07, 0x40, 0x17, 0x07, 0x47, 0x18, 0x07, 0x40, 0x17, 0x07, 0x47, 0x18, 0x07, 0x40, 0x48, ++ 0x07, 0x08, 0x08, 0x10, 0x18, 0x10, 0x18, 0x0f, 0x17, 0x07, 0x47, 0x17, 0x07, 0x47, 0x40, 0x40, ++ 0x40, 0x17, 0x17, 0x0f, 0x40, 0x0f, 0x0f, 0x0f, 0x0f, 0x28, 0x27, 0x18, 0x07, 0x18, 0x18, 0x10, ++ 0x40, 0x27, 0x17, 0x0f, 0x40, 0x0f, 0x10, 0x0f, 0x10, 0x0f, 0x18, 0x10, 0x10, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x48, 0x11, 0x00, 0x4f, 0x40, 0x0e, 0x48, 0x51, 0x27, 0x40, 0x00, 0x40, 0x40, 0x40, 0x0f, ++ 0x00, 0x02, 0x46, 0x10, 0x46, 0x02, 0x0a, 0x1b, 0x1b, 0x07, 0x07, 0x07, 0x00, 0x08, 0x01, 0x07, ++ 0x4e, 0x27, 0x11, 0x0f, 0x40, 0x47, 0x06, 0x40, 0x40, 0x40, 0x00, 0x00, 0x47, 0x46, 0x01, 0x46, ++ 0x46, 0x02, 0x47, 0x4e, 0x46, 0x0a, 0x46, 0x4e, 0x4e, 0x46, 0x01, 0x09, 0x08, 0x09, 0x47, 0x46, ++ 0x01, 0x46, 0x46, 0x02, 0x47, 0x4e, 0x46, 0x0a, 0x46, 0x4e, 0x4e, 0x46, 0x01, 0x09, 0x08, 0x09, ++ 0x18, 0x47, 0x1a, 0x40, 0x48, 0x40, 0x00, 0x07, 0x00, 0x08, 0x08, 0x0a, 0x07, 0x17, 0x07, 0x47, ++ 0x18, 0x07, 0x40, 0x17, 0x07, 0x47, 0x18, 0x07, 0x40, 0x17, 0x07, 0x47, 0x18, 0x07, 0x40, 0x48, ++ 0x07, 0x08, 0x08, 0x11, 0x18, 0x11, 0x18, 0x0f, 0x17, 0x07, 0x47, 0x17, 0x07, 0x47, 0x40, 0x40, ++ 0x40, 0x16, 0x16, 0x0f, 0x40, 0x0f, 0x0f, 0x0f, 0x0f, 0x28, 0x27, 0x18, 0x07, 0x18, 0x18, 0x10, ++ 0x40, 0x26, 0x17, 0x0f, 0x40, 0x0f, 0x10, 0x0f, 0x11, 0x0f, 0x19, 0x10, 0x11, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x49, 0x12, 0x00, 0x4e, 0x40, 0x0d, 0x49, 0x52, 0x27, 0x40, 0x00, 0x40, 0x40, 0x40, 0x0f, ++ 0x00, 0x03, 0x45, 0x11, 0x45, 0x03, 0x0c, 0x1d, 0x1d, 0x07, 0x07, 0x07, 0x01, 0x08, 0x02, 0x07, ++ 0x4d, 0x27, 0x12, 0x0f, 0x40, 0x47, 0x05, 0x40, 0x40, 0x40, 0x00, 0x00, 0x46, 0x45, 0x02, 0x45, ++ 0x45, 0x03, 0x46, 0x4d, 0x45, 0x0b, 0x45, 0x4d, 0x4d, 0x45, 0x02, 0x0a, 0x09, 0x0a, 0x46, 0x45, ++ 0x02, 0x45, 0x45, 0x03, 0x46, 0x4d, 0x45, 0x0b, 0x45, 0x4d, 0x4d, 0x45, 0x02, 0x0a, 0x09, 0x0a, ++ 0x19, 0x47, 0x1c, 0x40, 0x48, 0x40, 0x00, 0x07, 0x00, 0x09, 0x09, 0x0c, 0x07, 0x17, 0x06, 0x47, ++ 0x18, 0x07, 0x40, 0x17, 0x06, 0x47, 0x18, 0x07, 0x40, 0x17, 0x06, 0x47, 0x18, 0x07, 0x40, 0x48, ++ 0x07, 0x09, 0x09, 0x12, 0x19, 0x12, 0x19, 0x0f, 0x17, 0x06, 0x47, 0x17, 0x06, 0x47, 0x40, 0x40, ++ 0x40, 0x15, 0x15, 0x0f, 0x40, 0x0f, 0x0f, 0x0e, 0x0e, 0x28, 0x27, 0x18, 0x07, 0x19, 0x18, 0x10, ++ 0x40, 0x25, 0x17, 0x0f, 0x40, 0x0f, 0x10, 0x0e, 0x12, 0x0f, 0x1a, 0x11, 0x12, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4a, 0x13, 0x01, 0x4d, 0x40, 0x0c, 0x4a, 0x53, 0x27, 0x40, 0x01, 0x40, 0x40, 0x40, 0x0f, ++ 0x01, 0x05, 0x44, 0x12, 0x43, 0x05, 0x0e, 0x20, 0x20, 0x07, 0x07, 0x06, 0x02, 0x09, 0x04, 0x07, ++ 0x4c, 0x27, 0x13, 0x0e, 0x40, 0x46, 0x04, 0x40, 0x40, 0x40, 0x01, 0x01, 0x45, 0x44, 0x04, 0x44, ++ 0x43, 0x05, 0x45, 0x4c, 0x44, 0x0d, 0x44, 0x4c, 0x4c, 0x43, 0x04, 0x0b, 0x0a, 0x0b, 0x45, 0x44, ++ 0x04, 0x44, 0x43, 0x05, 0x45, 0x4c, 0x44, 0x0d, 0x44, 0x4c, 0x4c, 0x43, 0x04, 0x0b, 0x0a, 0x0b, ++ 0x1a, 0x46, 0x1e, 0x40, 0x48, 0x40, 0x01, 0x07, 0x01, 0x0a, 0x0a, 0x0e, 0x07, 0x16, 0x05, 0x46, ++ 0x19, 0x07, 0x40, 0x16, 0x05, 0x46, 0x19, 0x07, 0x40, 0x16, 0x05, 0x46, 0x19, 0x07, 0x40, 0x49, ++ 0x07, 0x0a, 0x0a, 0x13, 0x1a, 0x13, 0x1a, 0x0e, 0x17, 0x05, 0x46, 0x17, 0x05, 0x46, 0x40, 0x40, ++ 0x40, 0x14, 0x14, 0x0e, 0x40, 0x0f, 0x0e, 0x0d, 0x0d, 0x29, 0x27, 0x19, 0x07, 0x1a, 0x19, 0x11, ++ 0x41, 0x24, 0x16, 0x0e, 0x40, 0x0e, 0x11, 0x0d, 0x13, 0x0e, 0x1c, 0x12, 0x13, 0x0e, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4a, 0x14, 0x01, 0x4d, 0x40, 0x0b, 0x4a, 0x54, 0x27, 0x40, 0x01, 0x40, 0x40, 0x40, 0x0f, ++ 0x01, 0x06, 0x43, 0x12, 0x42, 0x06, 0x10, 0x22, 0x22, 0x07, 0x07, 0x06, 0x02, 0x09, 0x05, 0x07, ++ 0x4b, 0x27, 0x14, 0x0e, 0x40, 0x46, 0x03, 0x40, 0x40, 0x40, 0x01, 0x01, 0x45, 0x43, 0x05, 0x43, ++ 0x42, 0x06, 0x45, 0x4b, 0x43, 0x0e, 0x43, 0x4b, 0x4b, 0x42, 0x05, 0x0c, 0x0a, 0x0c, 0x45, 0x43, ++ 0x05, 0x43, 0x42, 0x06, 0x45, 0x4b, 0x43, 0x0e, 0x43, 0x4b, 0x4b, 0x42, 0x05, 0x0c, 0x0a, 0x0c, ++ 0x1a, 0x46, 0x20, 0x40, 0x48, 0x40, 0x01, 0x07, 0x01, 0x0a, 0x0a, 0x10, 0x07, 0x16, 0x05, 0x46, ++ 0x19, 0x07, 0x40, 0x16, 0x05, 0x46, 0x19, 0x07, 0x40, 0x16, 0x05, 0x46, 0x19, 0x07, 0x40, 0x49, ++ 0x07, 0x0a, 0x0a, 0x14, 0x1a, 0x14, 0x1a, 0x0e, 0x17, 0x05, 0x46, 0x17, 0x05, 0x46, 0x40, 0x40, ++ 0x40, 0x13, 0x13, 0x0e, 0x40, 0x0f, 0x0e, 0x0d, 0x0d, 0x29, 0x27, 0x19, 0x07, 0x1a, 0x19, 0x11, ++ 0x41, 0x23, 0x16, 0x0e, 0x40, 0x0e, 0x11, 0x0d, 0x14, 0x0e, 0x1d, 0x12, 0x14, 0x0e, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4b, 0x15, 0x01, 0x4c, 0x40, 0x0a, 0x4b, 0x55, 0x27, 0x40, 0x01, 0x40, 0x40, 0x40, 0x0f, ++ 0x01, 0x08, 0x42, 0x13, 0x41, 0x08, 0x12, 0x25, 0x25, 0x07, 0x07, 0x06, 0x03, 0x09, 0x06, 0x07, ++ 0x4a, 0x27, 0x15, 0x0e, 0x40, 0x46, 0x02, 0x40, 0x40, 0x40, 0x01, 0x01, 0x44, 0x42, 0x06, 0x42, ++ 0x41, 0x08, 0x44, 0x4a, 0x42, 0x10, 0x42, 0x4a, 0x4a, 0x41, 0x06, 0x0d, 0x0b, 0x0d, 0x44, 0x42, ++ 0x06, 0x42, 0x41, 0x08, 0x44, 0x4a, 0x42, 0x10, 0x42, 0x4a, 0x4a, 0x41, 0x06, 0x0d, 0x0b, 0x0d, ++ 0x1b, 0x46, 0x22, 0x40, 0x48, 0x40, 0x01, 0x07, 0x01, 0x0b, 0x0b, 0x12, 0x07, 0x16, 0x04, 0x46, ++ 0x19, 0x07, 0x40, 0x16, 0x04, 0x46, 0x19, 0x07, 0x40, 0x16, 0x04, 0x46, 0x19, 0x07, 0x40, 0x49, ++ 0x07, 0x0b, 0x0b, 0x15, 0x1b, 0x15, 0x1b, 0x0e, 0x17, 0x04, 0x46, 0x17, 0x04, 0x46, 0x40, 0x40, ++ 0x40, 0x12, 0x12, 0x0e, 0x40, 0x0f, 0x0e, 0x0c, 0x0c, 0x29, 0x27, 0x19, 0x07, 0x1b, 0x19, 0x11, ++ 0x41, 0x22, 0x16, 0x0e, 0x40, 0x0e, 0x11, 0x0c, 0x15, 0x0e, 0x1e, 0x13, 0x15, 0x0e, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4c, 0x15, 0x01, 0x4c, 0x40, 0x09, 0x4c, 0x56, 0x27, 0x40, 0x01, 0x40, 0x40, 0x40, 0x0f, ++ 0x01, 0x09, 0x42, 0x13, 0x40, 0x09, 0x13, 0x27, 0x27, 0x07, 0x07, 0x05, 0x03, 0x09, 0x07, 0x07, ++ 0x4a, 0x27, 0x15, 0x0d, 0x40, 0x46, 0x01, 0x40, 0x40, 0x40, 0x01, 0x01, 0x44, 0x42, 0x07, 0x42, ++ 0x40, 0x09, 0x44, 0x4a, 0x42, 0x11, 0x42, 0x4a, 0x4a, 0x40, 0x07, 0x0d, 0x0b, 0x0d, 0x44, 0x42, ++ 0x07, 0x42, 0x40, 0x09, 0x44, 0x4a, 0x42, 0x11, 0x42, 0x4a, 0x4a, 0x40, 0x07, 0x0d, 0x0b, 0x0d, ++ 0x1b, 0x46, 0x23, 0x40, 0x48, 0x40, 0x01, 0x07, 0x01, 0x0b, 0x0b, 0x13, 0x07, 0x15, 0x03, 0x46, ++ 0x19, 0x07, 0x40, 0x15, 0x03, 0x46, 0x19, 0x07, 0x40, 0x15, 0x03, 0x46, 0x19, 0x07, 0x40, 0x4a, ++ 0x07, 0x0b, 0x0b, 0x15, 0x1b, 0x15, 0x1b, 0x0d, 0x17, 0x03, 0x46, 0x17, 0x03, 0x46, 0x40, 0x40, ++ 0x40, 0x11, 0x11, 0x0d, 0x40, 0x0f, 0x0d, 0x0b, 0x0b, 0x29, 0x27, 0x19, 0x07, 0x1b, 0x19, 0x11, ++ 0x42, 0x21, 0x15, 0x0d, 0x40, 0x0d, 0x11, 0x0b, 0x15, 0x0d, 0x1f, 0x13, 0x15, 0x0d, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4c, 0x16, 0x02, 0x4b, 0x40, 0x09, 0x4c, 0x56, 0x27, 0x40, 0x02, 0x40, 0x40, 0x40, 0x0f, ++ 0x02, 0x0b, 0x41, 0x14, 0x01, 0x0b, 0x15, 0x2a, 0x2a, 0x07, 0x07, 0x05, 0x04, 0x0a, 0x09, 0x07, ++ 0x49, 0x27, 0x16, 0x0d, 0x40, 0x45, 0x01, 0x40, 0x40, 0x40, 0x02, 0x02, 0x43, 0x41, 0x09, 0x41, ++ 0x01, 0x0b, 0x43, 0x49, 0x41, 0x13, 0x41, 0x49, 0x49, 0x01, 0x09, 0x0e, 0x0c, 0x0e, 0x43, 0x41, ++ 0x09, 0x41, 0x01, 0x0b, 0x43, 0x49, 0x41, 0x13, 0x41, 0x49, 0x49, 0x01, 0x09, 0x0e, 0x0c, 0x0e, ++ 0x1c, 0x45, 0x25, 0x40, 0x48, 0x40, 0x02, 0x07, 0x02, 0x0c, 0x0c, 0x15, 0x07, 0x15, 0x03, 0x45, ++ 0x1a, 0x07, 0x40, 0x15, 0x03, 0x45, 0x1a, 0x07, 0x40, 0x15, 0x03, 0x45, 0x1a, 0x07, 0x40, 0x4a, ++ 0x07, 0x0c, 0x0c, 0x16, 0x1c, 0x16, 0x1c, 0x0d, 0x17, 0x03, 0x45, 0x17, 0x03, 0x45, 0x40, 0x40, ++ 0x40, 0x11, 0x11, 0x0d, 0x40, 0x0f, 0x0d, 0x0b, 0x0b, 0x2a, 0x27, 0x1a, 0x07, 0x1c, 0x1a, 0x12, ++ 0x42, 0x21, 0x15, 0x0d, 0x40, 0x0d, 0x12, 0x0b, 0x16, 0x0d, 0x21, 0x14, 0x16, 0x0d, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4d, 0x17, 0x02, 0x4a, 0x40, 0x08, 0x4d, 0x57, 0x27, 0x40, 0x02, 0x40, 0x40, 0x40, 0x0f, ++ 0x02, 0x0d, 0x40, 0x15, 0x02, 0x0d, 0x17, 0x2c, 0x2c, 0x07, 0x07, 0x05, 0x05, 0x0a, 0x0a, 0x07, ++ 0x48, 0x27, 0x17, 0x0d, 0x40, 0x45, 0x00, 0x40, 0x40, 0x40, 0x02, 0x02, 0x42, 0x40, 0x0a, 0x40, ++ 0x02, 0x0d, 0x42, 0x48, 0x40, 0x15, 0x40, 0x48, 0x48, 0x02, 0x0a, 0x0f, 0x0d, 0x0f, 0x42, 0x40, ++ 0x0a, 0x40, 0x02, 0x0d, 0x42, 0x48, 0x40, 0x15, 0x40, 0x48, 0x48, 0x02, 0x0a, 0x0f, 0x0d, 0x0f, ++ 0x1d, 0x45, 0x27, 0x40, 0x48, 0x40, 0x02, 0x07, 0x02, 0x0d, 0x0d, 0x17, 0x07, 0x15, 0x02, 0x45, ++ 0x1a, 0x07, 0x40, 0x15, 0x02, 0x45, 0x1a, 0x07, 0x40, 0x15, 0x02, 0x45, 0x1a, 0x07, 0x40, 0x4a, ++ 0x07, 0x0d, 0x0d, 0x17, 0x1d, 0x17, 0x1d, 0x0d, 0x17, 0x02, 0x45, 0x17, 0x02, 0x45, 0x40, 0x40, ++ 0x40, 0x10, 0x10, 0x0d, 0x40, 0x0f, 0x0d, 0x0a, 0x0a, 0x2a, 0x27, 0x1a, 0x07, 0x1d, 0x1a, 0x12, ++ 0x42, 0x20, 0x15, 0x0d, 0x40, 0x0d, 0x12, 0x0a, 0x17, 0x0d, 0x22, 0x15, 0x17, 0x0d, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4d, 0x18, 0x02, 0x4a, 0x40, 0x07, 0x4d, 0x58, 0x27, 0x40, 0x02, 0x40, 0x40, 0x40, 0x0f, ++ 0x02, 0x0e, 0x00, 0x15, 0x03, 0x0e, 0x19, 0x2f, 0x2f, 0x07, 0x07, 0x05, 0x05, 0x0a, 0x0b, 0x07, ++ 0x47, 0x27, 0x18, 0x0d, 0x40, 0x45, 0x40, 0x40, 0x40, 0x40, 0x02, 0x02, 0x42, 0x00, 0x0b, 0x00, ++ 0x03, 0x0e, 0x42, 0x47, 0x00, 0x16, 0x00, 0x47, 0x47, 0x03, 0x0b, 0x10, 0x0d, 0x10, 0x42, 0x00, ++ 0x0b, 0x00, 0x03, 0x0e, 0x42, 0x47, 0x00, 0x16, 0x00, 0x47, 0x47, 0x03, 0x0b, 0x10, 0x0d, 0x10, ++ 0x1d, 0x45, 0x29, 0x40, 0x48, 0x40, 0x02, 0x07, 0x02, 0x0d, 0x0d, 0x19, 0x07, 0x15, 0x02, 0x45, ++ 0x1a, 0x07, 0x40, 0x15, 0x02, 0x45, 0x1a, 0x07, 0x40, 0x15, 0x02, 0x45, 0x1a, 0x07, 0x40, 0x4a, ++ 0x07, 0x0d, 0x0d, 0x18, 0x1d, 0x18, 0x1d, 0x0d, 0x17, 0x02, 0x45, 0x17, 0x02, 0x45, 0x40, 0x40, ++ 0x40, 0x0f, 0x0f, 0x0d, 0x40, 0x0f, 0x0d, 0x0a, 0x0a, 0x2a, 0x27, 0x1a, 0x07, 0x1d, 0x1a, 0x12, ++ 0x42, 0x1f, 0x15, 0x0d, 0x40, 0x0d, 0x12, 0x0a, 0x18, 0x0d, 0x23, 0x15, 0x18, 0x0d, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4e, 0x19, 0x03, 0x49, 0x40, 0x06, 0x4e, 0x59, 0x27, 0x40, 0x03, 0x40, 0x40, 0x40, 0x0f, ++ 0x03, 0x10, 0x01, 0x16, 0x04, 0x10, 0x1b, 0x31, 0x31, 0x07, 0x07, 0x04, 0x06, 0x0b, 0x0c, 0x07, ++ 0x46, 0x27, 0x19, 0x0c, 0x40, 0x44, 0x41, 0x40, 0x40, 0x40, 0x03, 0x03, 0x41, 0x01, 0x0c, 0x01, ++ 0x04, 0x10, 0x41, 0x46, 0x01, 0x18, 0x01, 0x46, 0x46, 0x04, 0x0c, 0x11, 0x0e, 0x11, 0x41, 0x01, ++ 0x0c, 0x01, 0x04, 0x10, 0x41, 0x46, 0x01, 0x18, 0x01, 0x46, 0x46, 0x04, 0x0c, 0x11, 0x0e, 0x11, ++ 0x1e, 0x44, 0x2b, 0x40, 0x48, 0x40, 0x03, 0x07, 0x03, 0x0e, 0x0e, 0x1b, 0x07, 0x14, 0x01, 0x44, ++ 0x1b, 0x07, 0x40, 0x14, 0x01, 0x44, 0x1b, 0x07, 0x40, 0x14, 0x01, 0x44, 0x1b, 0x07, 0x40, 0x4b, ++ 0x07, 0x0e, 0x0e, 0x19, 0x1e, 0x19, 0x1e, 0x0c, 0x17, 0x01, 0x44, 0x17, 0x01, 0x44, 0x40, 0x40, ++ 0x40, 0x0e, 0x0e, 0x0c, 0x40, 0x0f, 0x0c, 0x09, 0x09, 0x2b, 0x27, 0x1b, 0x07, 0x1e, 0x1b, 0x13, ++ 0x43, 0x1e, 0x14, 0x0c, 0x40, 0x0c, 0x13, 0x09, 0x19, 0x0c, 0x24, 0x16, 0x19, 0x0c, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4f, 0x1a, 0x03, 0x48, 0x40, 0x05, 0x4f, 0x5a, 0x27, 0x40, 0x03, 0x40, 0x40, 0x40, 0x0f, ++ 0x03, 0x11, 0x02, 0x17, 0x06, 0x11, 0x1d, 0x34, 0x34, 0x07, 0x07, 0x04, 0x07, 0x0b, 0x0e, 0x07, ++ 0x45, 0x27, 0x1a, 0x0c, 0x40, 0x44, 0x42, 0x40, 0x40, 0x40, 0x03, 0x03, 0x40, 0x02, 0x0e, 0x02, ++ 0x06, 0x11, 0x40, 0x45, 0x02, 0x19, 0x02, 0x45, 0x45, 0x06, 0x0e, 0x12, 0x0f, 0x12, 0x40, 0x02, ++ 0x0e, 0x02, 0x06, 0x11, 0x40, 0x45, 0x02, 0x19, 0x02, 0x45, 0x45, 0x06, 0x0e, 0x12, 0x0f, 0x12, ++ 0x1f, 0x44, 0x2d, 0x40, 0x48, 0x40, 0x03, 0x07, 0x03, 0x0f, 0x0f, 0x1d, 0x07, 0x14, 0x00, 0x44, ++ 0x1b, 0x07, 0x40, 0x14, 0x00, 0x44, 0x1b, 0x07, 0x40, 0x14, 0x00, 0x44, 0x1b, 0x07, 0x40, 0x4b, ++ 0x07, 0x0f, 0x0f, 0x1a, 0x1f, 0x1a, 0x1f, 0x0c, 0x17, 0x00, 0x44, 0x17, 0x00, 0x44, 0x40, 0x40, ++ 0x40, 0x0d, 0x0d, 0x0c, 0x40, 0x0f, 0x0c, 0x08, 0x08, 0x2b, 0x27, 0x1b, 0x07, 0x1f, 0x1b, 0x13, ++ 0x43, 0x1d, 0x14, 0x0c, 0x40, 0x0c, 0x13, 0x08, 0x1a, 0x0c, 0x26, 0x17, 0x1a, 0x0c, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x4f, 0x1b, 0x03, 0x48, 0x40, 0x04, 0x4f, 0x5b, 0x27, 0x40, 0x03, 0x40, 0x40, 0x40, 0x0f, ++ 0x03, 0x13, 0x03, 0x17, 0x07, 0x13, 0x1f, 0x36, 0x36, 0x07, 0x07, 0x04, 0x07, 0x0b, 0x0f, 0x07, ++ 0x44, 0x27, 0x1b, 0x0c, 0x40, 0x44, 0x43, 0x40, 0x40, 0x40, 0x03, 0x03, 0x40, 0x03, 0x0f, 0x03, ++ 0x07, 0x13, 0x40, 0x44, 0x03, 0x1b, 0x03, 0x44, 0x44, 0x07, 0x0f, 0x13, 0x0f, 0x13, 0x40, 0x03, ++ 0x0f, 0x03, 0x07, 0x13, 0x40, 0x44, 0x03, 0x1b, 0x03, 0x44, 0x44, 0x07, 0x0f, 0x13, 0x0f, 0x13, ++ 0x1f, 0x44, 0x2f, 0x40, 0x48, 0x40, 0x03, 0x07, 0x03, 0x0f, 0x0f, 0x1f, 0x07, 0x14, 0x00, 0x44, ++ 0x1b, 0x07, 0x40, 0x14, 0x00, 0x44, 0x1b, 0x07, 0x40, 0x14, 0x00, 0x44, 0x1b, 0x07, 0x40, 0x4b, ++ 0x07, 0x0f, 0x0f, 0x1b, 0x1f, 0x1b, 0x1f, 0x0c, 0x17, 0x00, 0x44, 0x17, 0x00, 0x44, 0x40, 0x40, ++ 0x40, 0x0c, 0x0c, 0x0c, 0x40, 0x0f, 0x0c, 0x08, 0x08, 0x2b, 0x27, 0x1b, 0x07, 0x1f, 0x1b, 0x13, ++ 0x43, 0x1c, 0x14, 0x0c, 0x40, 0x0c, 0x13, 0x08, 0x1b, 0x0c, 0x27, 0x17, 0x1b, 0x0c, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x50, 0x1c, 0x04, 0x47, 0x40, 0x03, 0x50, 0x5c, 0x27, 0x40, 0x04, 0x40, 0x40, 0x40, 0x0f, ++ 0x04, 0x14, 0x04, 0x18, 0x08, 0x14, 0x21, 0x39, 0x39, 0x07, 0x07, 0x03, 0x08, 0x0c, 0x10, 0x07, ++ 0x43, 0x27, 0x1c, 0x0b, 0x40, 0x43, 0x44, 0x40, 0x40, 0x40, 0x04, 0x04, 0x00, 0x04, 0x10, 0x04, ++ 0x08, 0x14, 0x00, 0x43, 0x04, 0x1c, 0x04, 0x43, 0x43, 0x08, 0x10, 0x14, 0x10, 0x14, 0x00, 0x04, ++ 0x10, 0x04, 0x08, 0x14, 0x00, 0x43, 0x04, 0x1c, 0x04, 0x43, 0x43, 0x08, 0x10, 0x14, 0x10, 0x14, ++ 0x20, 0x43, 0x31, 0x40, 0x48, 0x40, 0x04, 0x07, 0x04, 0x10, 0x10, 0x21, 0x07, 0x13, 0x40, 0x43, ++ 0x1c, 0x07, 0x40, 0x13, 0x40, 0x43, 0x1c, 0x07, 0x40, 0x13, 0x40, 0x43, 0x1c, 0x07, 0x40, 0x4c, ++ 0x07, 0x10, 0x10, 0x1c, 0x20, 0x1c, 0x20, 0x0b, 0x17, 0x40, 0x43, 0x17, 0x40, 0x43, 0x40, 0x40, ++ 0x40, 0x0b, 0x0b, 0x0b, 0x40, 0x0f, 0x0b, 0x07, 0x07, 0x2c, 0x27, 0x1c, 0x07, 0x20, 0x1c, 0x14, ++ 0x44, 0x1b, 0x13, 0x0b, 0x40, 0x0b, 0x14, 0x07, 0x1c, 0x0b, 0x28, 0x18, 0x1c, 0x0b, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x51, 0x1d, 0x04, 0x47, 0x40, 0x02, 0x51, 0x5d, 0x27, 0x40, 0x04, 0x40, 0x40, 0x40, 0x0f, ++ 0x04, 0x16, 0x05, 0x18, 0x09, 0x16, 0x22, 0x3b, 0x3b, 0x07, 0x07, 0x03, 0x08, 0x0c, 0x11, 0x07, ++ 0x42, 0x27, 0x1d, 0x0b, 0x40, 0x43, 0x45, 0x40, 0x40, 0x40, 0x04, 0x04, 0x00, 0x05, 0x11, 0x05, ++ 0x09, 0x16, 0x00, 0x42, 0x05, 0x1e, 0x05, 0x42, 0x42, 0x09, 0x11, 0x15, 0x10, 0x15, 0x00, 0x05, ++ 0x11, 0x05, 0x09, 0x16, 0x00, 0x42, 0x05, 0x1e, 0x05, 0x42, 0x42, 0x09, 0x11, 0x15, 0x10, 0x15, ++ 0x20, 0x43, 0x32, 0x40, 0x48, 0x40, 0x04, 0x07, 0x04, 0x10, 0x10, 0x22, 0x07, 0x13, 0x41, 0x43, ++ 0x1c, 0x07, 0x40, 0x13, 0x41, 0x43, 0x1c, 0x07, 0x40, 0x13, 0x41, 0x43, 0x1c, 0x07, 0x40, 0x4c, ++ 0x07, 0x10, 0x10, 0x1d, 0x20, 0x1d, 0x20, 0x0b, 0x17, 0x41, 0x43, 0x17, 0x41, 0x43, 0x40, 0x40, ++ 0x40, 0x0a, 0x0a, 0x0b, 0x40, 0x0f, 0x0b, 0x06, 0x06, 0x2c, 0x27, 0x1c, 0x07, 0x20, 0x1c, 0x14, ++ 0x44, 0x1a, 0x13, 0x0b, 0x40, 0x0b, 0x14, 0x06, 0x1d, 0x0b, 0x29, 0x18, 0x1d, 0x0b, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x51, 0x1e, 0x04, 0x46, 0x40, 0x01, 0x51, 0x5e, 0x27, 0x40, 0x04, 0x40, 0x40, 0x40, 0x0f, ++ 0x04, 0x18, 0x06, 0x19, 0x0b, 0x18, 0x24, 0x3e, 0x3e, 0x07, 0x07, 0x03, 0x09, 0x0c, 0x13, 0x07, ++ 0x41, 0x27, 0x1e, 0x0b, 0x40, 0x43, 0x46, 0x40, 0x40, 0x40, 0x04, 0x04, 0x01, 0x06, 0x13, 0x06, ++ 0x0b, 0x18, 0x01, 0x41, 0x06, 0x20, 0x06, 0x41, 0x41, 0x0b, 0x13, 0x16, 0x11, 0x16, 0x01, 0x06, ++ 0x13, 0x06, 0x0b, 0x18, 0x01, 0x41, 0x06, 0x20, 0x06, 0x41, 0x41, 0x0b, 0x13, 0x16, 0x11, 0x16, ++ 0x21, 0x43, 0x34, 0x40, 0x48, 0x40, 0x04, 0x07, 0x04, 0x11, 0x11, 0x24, 0x07, 0x13, 0x41, 0x43, ++ 0x1c, 0x07, 0x40, 0x13, 0x41, 0x43, 0x1c, 0x07, 0x40, 0x13, 0x41, 0x43, 0x1c, 0x07, 0x40, 0x4c, ++ 0x07, 0x11, 0x11, 0x1e, 0x21, 0x1e, 0x21, 0x0b, 0x17, 0x41, 0x43, 0x17, 0x41, 0x43, 0x40, 0x40, ++ 0x40, 0x09, 0x09, 0x0b, 0x40, 0x0f, 0x0b, 0x06, 0x06, 0x2c, 0x27, 0x1c, 0x07, 0x21, 0x1c, 0x14, ++ 0x44, 0x19, 0x13, 0x0b, 0x40, 0x0b, 0x14, 0x06, 0x1e, 0x0b, 0x2b, 0x19, 0x1e, 0x0b, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x52, 0x1f, 0x05, 0x45, 0x40, 0x00, 0x52, 0x5f, 0x27, 0x40, 0x05, 0x40, 0x40, 0x40, 0x0f, ++ 0x05, 0x19, 0x07, 0x1a, 0x0c, 0x19, 0x26, 0x3e, 0x3e, 0x07, 0x07, 0x02, 0x0a, 0x0d, 0x14, 0x07, ++ 0x40, 0x27, 0x1f, 0x0a, 0x40, 0x42, 0x47, 0x40, 0x40, 0x40, 0x05, 0x05, 0x02, 0x07, 0x14, 0x07, ++ 0x0c, 0x19, 0x02, 0x40, 0x07, 0x21, 0x07, 0x40, 0x40, 0x0c, 0x14, 0x17, 0x12, 0x17, 0x02, 0x07, ++ 0x14, 0x07, 0x0c, 0x19, 0x02, 0x40, 0x07, 0x21, 0x07, 0x40, 0x40, 0x0c, 0x14, 0x17, 0x12, 0x17, ++ 0x22, 0x42, 0x36, 0x40, 0x48, 0x40, 0x05, 0x07, 0x05, 0x12, 0x12, 0x26, 0x07, 0x12, 0x42, 0x42, ++ 0x1d, 0x07, 0x40, 0x12, 0x42, 0x42, 0x1d, 0x07, 0x40, 0x12, 0x42, 0x42, 0x1d, 0x07, 0x40, 0x4d, ++ 0x07, 0x12, 0x12, 0x1f, 0x22, 0x1f, 0x22, 0x0a, 0x17, 0x42, 0x42, 0x17, 0x42, 0x42, 0x40, 0x40, ++ 0x40, 0x08, 0x08, 0x0a, 0x40, 0x0f, 0x0a, 0x05, 0x05, 0x2d, 0x27, 0x1d, 0x07, 0x22, 0x1d, 0x15, ++ 0x45, 0x18, 0x12, 0x0a, 0x40, 0x0a, 0x15, 0x05, 0x1f, 0x0a, 0x2c, 0x1a, 0x1f, 0x0a, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x52, 0x20, 0x05, 0x45, 0x40, 0x40, 0x52, 0x60, 0x27, 0x40, 0x05, 0x40, 0x40, 0x40, 0x0f, ++ 0x05, 0x1b, 0x08, 0x1a, 0x0d, 0x1b, 0x28, 0x3e, 0x3e, 0x07, 0x07, 0x02, 0x0a, 0x0d, 0x15, 0x07, ++ 0x00, 0x27, 0x20, 0x0a, 0x40, 0x42, 0x48, 0x40, 0x40, 0x40, 0x05, 0x05, 0x02, 0x08, 0x15, 0x08, ++ 0x0d, 0x1b, 0x02, 0x00, 0x08, 0x23, 0x08, 0x00, 0x00, 0x0d, 0x15, 0x18, 0x12, 0x18, 0x02, 0x08, ++ 0x15, 0x08, 0x0d, 0x1b, 0x02, 0x00, 0x08, 0x23, 0x08, 0x00, 0x00, 0x0d, 0x15, 0x18, 0x12, 0x18, ++ 0x22, 0x42, 0x38, 0x40, 0x48, 0x40, 0x05, 0x07, 0x05, 0x12, 0x12, 0x28, 0x07, 0x12, 0x42, 0x42, ++ 0x1d, 0x07, 0x40, 0x12, 0x42, 0x42, 0x1d, 0x07, 0x40, 0x12, 0x42, 0x42, 0x1d, 0x07, 0x40, 0x4d, ++ 0x07, 0x12, 0x12, 0x20, 0x22, 0x20, 0x22, 0x0a, 0x17, 0x42, 0x42, 0x17, 0x42, 0x42, 0x40, 0x40, ++ 0x40, 0x07, 0x07, 0x0a, 0x40, 0x0f, 0x0a, 0x05, 0x05, 0x2d, 0x27, 0x1d, 0x07, 0x22, 0x1d, 0x15, ++ 0x45, 0x17, 0x12, 0x0a, 0x40, 0x0a, 0x15, 0x05, 0x20, 0x0a, 0x2d, 0x1a, 0x20, 0x0a, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x53, 0x21, 0x05, 0x44, 0x40, 0x41, 0x53, 0x61, 0x27, 0x40, 0x05, 0x40, 0x40, 0x40, 0x0f, ++ 0x05, 0x1c, 0x09, 0x1b, 0x0e, 0x1c, 0x2a, 0x3e, 0x3e, 0x07, 0x07, 0x02, 0x0b, 0x0d, 0x16, 0x07, ++ 0x01, 0x27, 0x21, 0x0a, 0x40, 0x42, 0x49, 0x40, 0x40, 0x40, 0x05, 0x05, 0x03, 0x09, 0x16, 0x09, ++ 0x0e, 0x1c, 0x03, 0x01, 0x09, 0x24, 0x09, 0x01, 0x01, 0x0e, 0x16, 0x19, 0x13, 0x19, 0x03, 0x09, ++ 0x16, 0x09, 0x0e, 0x1c, 0x03, 0x01, 0x09, 0x24, 0x09, 0x01, 0x01, 0x0e, 0x16, 0x19, 0x13, 0x19, ++ 0x23, 0x42, 0x3a, 0x40, 0x48, 0x40, 0x05, 0x07, 0x05, 0x13, 0x13, 0x2a, 0x07, 0x12, 0x43, 0x42, ++ 0x1d, 0x07, 0x40, 0x12, 0x43, 0x42, 0x1d, 0x07, 0x40, 0x12, 0x43, 0x42, 0x1d, 0x07, 0x40, 0x4d, ++ 0x07, 0x13, 0x13, 0x21, 0x23, 0x21, 0x23, 0x0a, 0x17, 0x43, 0x42, 0x17, 0x43, 0x42, 0x40, 0x40, ++ 0x40, 0x06, 0x06, 0x0a, 0x40, 0x0f, 0x0a, 0x04, 0x04, 0x2d, 0x27, 0x1d, 0x07, 0x23, 0x1d, 0x15, ++ 0x45, 0x16, 0x12, 0x0a, 0x40, 0x0a, 0x15, 0x04, 0x21, 0x0a, 0x2e, 0x1b, 0x21, 0x0a, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x54, 0x22, 0x06, 0x43, 0x40, 0x42, 0x54, 0x62, 0x27, 0x40, 0x06, 0x40, 0x40, 0x40, 0x0f, ++ 0x06, 0x1e, 0x0a, 0x1c, 0x10, 0x1e, 0x2c, 0x3e, 0x3e, 0x07, 0x07, 0x01, 0x0c, 0x0e, 0x18, 0x07, ++ 0x02, 0x27, 0x22, 0x09, 0x40, 0x41, 0x4a, 0x40, 0x40, 0x40, 0x06, 0x06, 0x04, 0x0a, 0x18, 0x0a, ++ 0x10, 0x1e, 0x04, 0x02, 0x0a, 0x26, 0x0a, 0x02, 0x02, 0x10, 0x18, 0x1a, 0x14, 0x1a, 0x04, 0x0a, ++ 0x18, 0x0a, 0x10, 0x1e, 0x04, 0x02, 0x0a, 0x26, 0x0a, 0x02, 0x02, 0x10, 0x18, 0x1a, 0x14, 0x1a, ++ 0x24, 0x41, 0x3c, 0x40, 0x48, 0x40, 0x06, 0x07, 0x06, 0x14, 0x14, 0x2c, 0x07, 0x11, 0x44, 0x41, ++ 0x1e, 0x07, 0x40, 0x11, 0x44, 0x41, 0x1e, 0x07, 0x40, 0x11, 0x44, 0x41, 0x1e, 0x07, 0x40, 0x4e, ++ 0x07, 0x14, 0x14, 0x22, 0x24, 0x22, 0x24, 0x09, 0x17, 0x44, 0x41, 0x17, 0x44, 0x41, 0x40, 0x40, ++ 0x40, 0x05, 0x05, 0x09, 0x40, 0x0f, 0x09, 0x03, 0x03, 0x2e, 0x27, 0x1e, 0x07, 0x24, 0x1e, 0x16, ++ 0x46, 0x15, 0x11, 0x09, 0x40, 0x09, 0x16, 0x03, 0x22, 0x09, 0x30, 0x1c, 0x22, 0x09, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x54, 0x23, 0x06, 0x43, 0x40, 0x43, 0x54, 0x63, 0x27, 0x40, 0x06, 0x40, 0x40, 0x40, 0x0f, ++ 0x06, 0x1f, 0x0b, 0x1c, 0x11, 0x1f, 0x2e, 0x3e, 0x3e, 0x07, 0x07, 0x01, 0x0c, 0x0e, 0x19, 0x07, ++ 0x03, 0x27, 0x23, 0x09, 0x40, 0x41, 0x4b, 0x40, 0x40, 0x40, 0x06, 0x06, 0x04, 0x0b, 0x19, 0x0b, ++ 0x11, 0x1f, 0x04, 0x03, 0x0b, 0x27, 0x0b, 0x03, 0x03, 0x11, 0x19, 0x1b, 0x14, 0x1b, 0x04, 0x0b, ++ 0x19, 0x0b, 0x11, 0x1f, 0x04, 0x03, 0x0b, 0x27, 0x0b, 0x03, 0x03, 0x11, 0x19, 0x1b, 0x14, 0x1b, ++ 0x24, 0x41, 0x3e, 0x40, 0x48, 0x40, 0x06, 0x07, 0x06, 0x14, 0x14, 0x2e, 0x07, 0x11, 0x44, 0x41, ++ 0x1e, 0x07, 0x40, 0x11, 0x44, 0x41, 0x1e, 0x07, 0x40, 0x11, 0x44, 0x41, 0x1e, 0x07, 0x40, 0x4e, ++ 0x07, 0x14, 0x14, 0x23, 0x24, 0x23, 0x24, 0x09, 0x17, 0x44, 0x41, 0x17, 0x44, 0x41, 0x40, 0x40, ++ 0x40, 0x04, 0x04, 0x09, 0x40, 0x0f, 0x09, 0x03, 0x03, 0x2e, 0x27, 0x1e, 0x07, 0x24, 0x1e, 0x16, ++ 0x46, 0x14, 0x11, 0x09, 0x40, 0x09, 0x16, 0x03, 0x23, 0x09, 0x31, 0x1c, 0x23, 0x09, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x55, 0x24, 0x06, 0x42, 0x40, 0x44, 0x55, 0x64, 0x27, 0x40, 0x06, 0x40, 0x40, 0x40, 0x0f, ++ 0x06, 0x21, 0x0c, 0x1d, 0x12, 0x21, 0x30, 0x3e, 0x3e, 0x07, 0x07, 0x01, 0x0d, 0x0e, 0x1a, 0x07, ++ 0x04, 0x27, 0x24, 0x09, 0x40, 0x41, 0x4c, 0x40, 0x40, 0x40, 0x06, 0x06, 0x05, 0x0c, 0x1a, 0x0c, ++ 0x12, 0x21, 0x05, 0x04, 0x0c, 0x29, 0x0c, 0x04, 0x04, 0x12, 0x1a, 0x1c, 0x15, 0x1c, 0x05, 0x0c, ++ 0x1a, 0x0c, 0x12, 0x21, 0x05, 0x04, 0x0c, 0x29, 0x0c, 0x04, 0x04, 0x12, 0x1a, 0x1c, 0x15, 0x1c, ++ 0x25, 0x41, 0x3e, 0x40, 0x48, 0x40, 0x06, 0x07, 0x06, 0x15, 0x15, 0x30, 0x07, 0x11, 0x45, 0x41, ++ 0x1e, 0x07, 0x40, 0x11, 0x45, 0x41, 0x1e, 0x07, 0x40, 0x11, 0x45, 0x41, 0x1e, 0x07, 0x40, 0x4e, ++ 0x07, 0x15, 0x15, 0x24, 0x25, 0x24, 0x25, 0x09, 0x17, 0x45, 0x41, 0x17, 0x45, 0x41, 0x40, 0x40, ++ 0x40, 0x03, 0x03, 0x09, 0x40, 0x0f, 0x09, 0x02, 0x02, 0x2e, 0x27, 0x1e, 0x07, 0x25, 0x1e, 0x16, ++ 0x46, 0x13, 0x11, 0x09, 0x40, 0x09, 0x16, 0x02, 0x24, 0x09, 0x32, 0x1d, 0x24, 0x09, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x56, 0x24, 0x06, 0x42, 0x40, 0x45, 0x56, 0x65, 0x27, 0x40, 0x06, 0x40, 0x40, 0x40, 0x0f, ++ 0x06, 0x22, 0x0c, 0x1d, 0x13, 0x22, 0x31, 0x3e, 0x3e, 0x07, 0x07, 0x00, 0x0d, 0x0e, 0x1b, 0x07, ++ 0x04, 0x27, 0x24, 0x08, 0x40, 0x41, 0x4d, 0x40, 0x40, 0x40, 0x06, 0x06, 0x05, 0x0c, 0x1b, 0x0c, ++ 0x13, 0x22, 0x05, 0x04, 0x0c, 0x2a, 0x0c, 0x04, 0x04, 0x13, 0x1b, 0x1c, 0x15, 0x1c, 0x05, 0x0c, ++ 0x1b, 0x0c, 0x13, 0x22, 0x05, 0x04, 0x0c, 0x2a, 0x0c, 0x04, 0x04, 0x13, 0x1b, 0x1c, 0x15, 0x1c, ++ 0x25, 0x41, 0x3e, 0x40, 0x48, 0x40, 0x06, 0x07, 0x06, 0x15, 0x15, 0x31, 0x07, 0x10, 0x46, 0x41, ++ 0x1e, 0x07, 0x40, 0x10, 0x46, 0x41, 0x1e, 0x07, 0x40, 0x10, 0x46, 0x41, 0x1e, 0x07, 0x40, 0x4f, ++ 0x07, 0x15, 0x15, 0x24, 0x25, 0x24, 0x25, 0x08, 0x17, 0x46, 0x41, 0x17, 0x46, 0x41, 0x40, 0x40, ++ 0x40, 0x02, 0x02, 0x08, 0x40, 0x0f, 0x08, 0x01, 0x01, 0x2e, 0x27, 0x1e, 0x07, 0x25, 0x1e, 0x16, ++ 0x47, 0x12, 0x10, 0x08, 0x40, 0x08, 0x16, 0x01, 0x24, 0x08, 0x33, 0x1d, 0x24, 0x08, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x56, 0x25, 0x07, 0x41, 0x40, 0x45, 0x56, 0x65, 0x27, 0x40, 0x07, 0x40, 0x40, 0x40, 0x0f, ++ 0x07, 0x24, 0x0d, 0x1e, 0x15, 0x24, 0x33, 0x3e, 0x3e, 0x07, 0x07, 0x00, 0x0e, 0x0f, 0x1d, 0x07, ++ 0x05, 0x27, 0x25, 0x08, 0x40, 0x40, 0x4d, 0x40, 0x40, 0x40, 0x07, 0x07, 0x06, 0x0d, 0x1d, 0x0d, ++ 0x15, 0x24, 0x06, 0x05, 0x0d, 0x2c, 0x0d, 0x05, 0x05, 0x15, 0x1d, 0x1d, 0x16, 0x1d, 0x06, 0x0d, ++ 0x1d, 0x0d, 0x15, 0x24, 0x06, 0x05, 0x0d, 0x2c, 0x0d, 0x05, 0x05, 0x15, 0x1d, 0x1d, 0x16, 0x1d, ++ 0x26, 0x40, 0x3e, 0x40, 0x48, 0x40, 0x07, 0x07, 0x07, 0x16, 0x16, 0x33, 0x07, 0x10, 0x46, 0x40, ++ 0x1f, 0x07, 0x40, 0x10, 0x46, 0x40, 0x1f, 0x07, 0x40, 0x10, 0x46, 0x40, 0x1f, 0x07, 0x40, 0x4f, ++ 0x07, 0x16, 0x16, 0x25, 0x26, 0x25, 0x26, 0x08, 0x17, 0x46, 0x40, 0x17, 0x46, 0x40, 0x40, 0x40, ++ 0x40, 0x02, 0x02, 0x08, 0x40, 0x0f, 0x08, 0x01, 0x01, 0x2f, 0x27, 0x1f, 0x07, 0x26, 0x1f, 0x17, ++ 0x47, 0x12, 0x10, 0x08, 0x40, 0x08, 0x17, 0x01, 0x25, 0x08, 0x35, 0x1e, 0x25, 0x08, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x57, 0x26, 0x07, 0x40, 0x40, 0x46, 0x57, 0x66, 0x27, 0x40, 0x07, 0x40, 0x40, 0x40, 0x0f, ++ 0x07, 0x26, 0x0e, 0x1f, 0x16, 0x26, 0x35, 0x3e, 0x3e, 0x07, 0x07, 0x00, 0x0f, 0x0f, 0x1e, 0x07, ++ 0x06, 0x27, 0x26, 0x08, 0x40, 0x40, 0x4e, 0x40, 0x40, 0x40, 0x07, 0x07, 0x07, 0x0e, 0x1e, 0x0e, ++ 0x16, 0x26, 0x07, 0x06, 0x0e, 0x2e, 0x0e, 0x06, 0x06, 0x16, 0x1e, 0x1e, 0x17, 0x1e, 0x07, 0x0e, ++ 0x1e, 0x0e, 0x16, 0x26, 0x07, 0x06, 0x0e, 0x2e, 0x0e, 0x06, 0x06, 0x16, 0x1e, 0x1e, 0x17, 0x1e, ++ 0x27, 0x40, 0x3e, 0x40, 0x48, 0x40, 0x07, 0x07, 0x07, 0x17, 0x17, 0x35, 0x07, 0x10, 0x47, 0x40, ++ 0x1f, 0x07, 0x40, 0x10, 0x47, 0x40, 0x1f, 0x07, 0x40, 0x10, 0x47, 0x40, 0x1f, 0x07, 0x40, 0x4f, ++ 0x07, 0x17, 0x17, 0x26, 0x27, 0x26, 0x27, 0x08, 0x17, 0x47, 0x40, 0x17, 0x47, 0x40, 0x40, 0x40, ++ 0x40, 0x01, 0x01, 0x08, 0x40, 0x0f, 0x08, 0x00, 0x00, 0x2f, 0x27, 0x1f, 0x07, 0x27, 0x1f, 0x17, ++ 0x47, 0x11, 0x10, 0x08, 0x40, 0x08, 0x17, 0x00, 0x26, 0x08, 0x36, 0x1f, 0x26, 0x08, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x57, 0x27, 0x07, 0x40, 0x40, 0x47, 0x57, 0x67, 0x27, 0x40, 0x07, 0x40, 0x40, 0x40, 0x0f, ++ 0x07, 0x27, 0x0f, 0x1f, 0x17, 0x27, 0x37, 0x3e, 0x3e, 0x07, 0x07, 0x00, 0x0f, 0x0f, 0x1f, 0x07, ++ 0x07, 0x27, 0x27, 0x08, 0x40, 0x40, 0x4f, 0x40, 0x40, 0x40, 0x07, 0x07, 0x07, 0x0f, 0x1f, 0x0f, ++ 0x17, 0x27, 0x07, 0x07, 0x0f, 0x2f, 0x0f, 0x07, 0x07, 0x17, 0x1f, 0x1f, 0x17, 0x1f, 0x07, 0x0f, ++ 0x1f, 0x0f, 0x17, 0x27, 0x07, 0x07, 0x0f, 0x2f, 0x0f, 0x07, 0x07, 0x17, 0x1f, 0x1f, 0x17, 0x1f, ++ 0x27, 0x40, 0x3e, 0x40, 0x48, 0x40, 0x07, 0x07, 0x07, 0x17, 0x17, 0x37, 0x07, 0x10, 0x47, 0x40, ++ 0x1f, 0x07, 0x40, 0x10, 0x47, 0x40, 0x1f, 0x07, 0x40, 0x10, 0x47, 0x40, 0x1f, 0x07, 0x40, 0x4f, ++ 0x07, 0x17, 0x17, 0x27, 0x27, 0x27, 0x27, 0x08, 0x17, 0x47, 0x40, 0x17, 0x47, 0x40, 0x40, 0x40, ++ 0x40, 0x00, 0x00, 0x08, 0x40, 0x0f, 0x08, 0x00, 0x00, 0x2f, 0x27, 0x1f, 0x07, 0x27, 0x1f, 0x17, ++ 0x47, 0x10, 0x10, 0x08, 0x40, 0x08, 0x17, 0x00, 0x27, 0x08, 0x37, 0x1f, 0x27, 0x08, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x48, 0x48, 0x60, 0x40, 0x27, 0x07, 0x07, 0x1f, 0x40, 0x48, 0x40, 0x40, 0x17, 0x0f, ++ 0x48, 0x68, 0x40, 0x07, 0x68, 0x68, 0x68, 0x68, 0x68, 0x07, 0x07, 0x0f, 0x3e, 0x17, 0x40, 0x07, ++ 0x68, 0x27, 0x50, 0x17, 0x40, 0x07, 0x1f, 0x40, 0x40, 0x40, 0x48, 0x48, 0x58, 0x60, 0x50, 0x60, ++ 0x68, 0x60, 0x58, 0x68, 0x68, 0x68, 0x58, 0x60, 0x68, 0x68, 0x68, 0x50, 0x48, 0x58, 0x58, 0x60, ++ 0x50, 0x60, 0x68, 0x60, 0x58, 0x68, 0x68, 0x68, 0x58, 0x60, 0x68, 0x68, 0x68, 0x50, 0x48, 0x58, ++ 0x07, 0x50, 0x58, 0x40, 0x40, 0x40, 0x48, 0x07, 0x48, 0x48, 0x48, 0x68, 0x50, 0x1f, 0x17, 0x50, ++ 0x0f, 0x07, 0x40, 0x1f, 0x17, 0x50, 0x0f, 0x07, 0x40, 0x1f, 0x17, 0x50, 0x0f, 0x07, 0x40, 0x40, ++ 0x07, 0x40, 0x40, 0x40, 0x07, 0x40, 0x07, 0x17, 0x17, 0x17, 0x50, 0x17, 0x17, 0x50, 0x40, 0x40, ++ 0x40, 0x2f, 0x17, 0x17, 0x40, 0x0f, 0x17, 0x1f, 0x1f, 0x1f, 0x27, 0x0f, 0x07, 0x07, 0x0f, 0x40, ++ 0x07, 0x3e, 0x1f, 0x17, 0x40, 0x0f, 0x17, 0x1f, 0x48, 0x17, 0x48, 0x48, 0x48, 0x17, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x47, 0x47, 0x5f, 0x40, 0x27, 0x07, 0x07, 0x20, 0x40, 0x47, 0x40, 0x40, 0x17, 0x0f, ++ 0x47, 0x66, 0x40, 0x08, 0x66, 0x66, 0x66, 0x65, 0x65, 0x07, 0x07, 0x0f, 0x3e, 0x17, 0x00, 0x07, ++ 0x67, 0x27, 0x4e, 0x17, 0x40, 0x07, 0x1f, 0x40, 0x40, 0x40, 0x47, 0x47, 0x57, 0x5f, 0x4f, 0x5f, ++ 0x66, 0x5e, 0x57, 0x67, 0x67, 0x66, 0x57, 0x5f, 0x67, 0x67, 0x66, 0x4f, 0x47, 0x56, 0x57, 0x5f, ++ 0x4f, 0x5f, 0x66, 0x5e, 0x57, 0x67, 0x67, 0x66, 0x57, 0x5f, 0x67, 0x67, 0x66, 0x4f, 0x47, 0x56, ++ 0x08, 0x4f, 0x56, 0x40, 0x40, 0x40, 0x47, 0x07, 0x47, 0x47, 0x47, 0x66, 0x4f, 0x1f, 0x17, 0x4f, ++ 0x10, 0x07, 0x40, 0x1f, 0x17, 0x4f, 0x10, 0x07, 0x40, 0x1f, 0x17, 0x4f, 0x10, 0x07, 0x40, 0x40, ++ 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x17, 0x17, 0x17, 0x4f, 0x17, 0x17, 0x4f, 0x40, 0x40, ++ 0x40, 0x2f, 0x17, 0x17, 0x40, 0x0f, 0x17, 0x1f, 0x1f, 0x20, 0x27, 0x10, 0x07, 0x08, 0x10, 0x00, ++ 0x07, 0x3e, 0x1f, 0x17, 0x40, 0x0f, 0x17, 0x1f, 0x47, 0x17, 0x46, 0x47, 0x47, 0x17, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x46, 0x47, 0x5e, 0x40, 0x26, 0x06, 0x06, 0x20, 0x40, 0x47, 0x40, 0x40, 0x16, 0x0f, ++ 0x47, 0x64, 0x40, 0x08, 0x65, 0x64, 0x64, 0x63, 0x63, 0x07, 0x07, 0x0f, 0x3e, 0x17, 0x01, 0x07, ++ 0x66, 0x27, 0x4d, 0x17, 0x40, 0x07, 0x1e, 0x40, 0x40, 0x40, 0x47, 0x47, 0x56, 0x5e, 0x4e, 0x5e, ++ 0x65, 0x5d, 0x56, 0x66, 0x66, 0x64, 0x56, 0x5e, 0x66, 0x66, 0x64, 0x4e, 0x46, 0x55, 0x56, 0x5e, ++ 0x4e, 0x5e, 0x65, 0x5d, 0x56, 0x66, 0x66, 0x64, 0x56, 0x5e, 0x66, 0x66, 0x64, 0x4e, 0x46, 0x55, ++ 0x09, 0x4f, 0x54, 0x40, 0x40, 0x40, 0x47, 0x07, 0x47, 0x46, 0x46, 0x64, 0x4e, 0x1f, 0x16, 0x4f, ++ 0x10, 0x07, 0x40, 0x1f, 0x16, 0x4f, 0x10, 0x07, 0x40, 0x1f, 0x16, 0x4f, 0x10, 0x07, 0x40, 0x40, ++ 0x07, 0x00, 0x00, 0x01, 0x09, 0x01, 0x09, 0x17, 0x17, 0x16, 0x4f, 0x17, 0x16, 0x4f, 0x40, 0x40, ++ 0x40, 0x2e, 0x17, 0x17, 0x40, 0x0f, 0x17, 0x1e, 0x1e, 0x20, 0x27, 0x10, 0x07, 0x09, 0x10, 0x01, ++ 0x07, 0x3e, 0x1f, 0x17, 0x40, 0x0f, 0x17, 0x1e, 0x46, 0x17, 0x45, 0x46, 0x46, 0x17, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x45, 0x47, 0x5e, 0x40, 0x25, 0x06, 0x05, 0x20, 0x40, 0x47, 0x40, 0x40, 0x16, 0x0f, ++ 0x47, 0x63, 0x40, 0x08, 0x64, 0x63, 0x62, 0x60, 0x60, 0x07, 0x07, 0x0f, 0x3e, 0x17, 0x01, 0x07, ++ 0x65, 0x27, 0x4c, 0x17, 0x40, 0x07, 0x1d, 0x40, 0x40, 0x40, 0x47, 0x47, 0x56, 0x5d, 0x4e, 0x5d, ++ 0x64, 0x5c, 0x56, 0x65, 0x65, 0x63, 0x56, 0x5e, 0x65, 0x65, 0x63, 0x4d, 0x46, 0x54, 0x56, 0x5d, ++ 0x4e, 0x5d, 0x64, 0x5c, 0x56, 0x65, 0x65, 0x63, 0x56, 0x5e, 0x65, 0x65, 0x63, 0x4d, 0x46, 0x54, ++ 0x09, 0x4f, 0x52, 0x40, 0x40, 0x40, 0x47, 0x07, 0x47, 0x46, 0x46, 0x62, 0x4e, 0x1f, 0x16, 0x4f, ++ 0x10, 0x07, 0x40, 0x1f, 0x16, 0x4f, 0x10, 0x07, 0x40, 0x1f, 0x16, 0x4f, 0x10, 0x07, 0x40, 0x40, ++ 0x07, 0x00, 0x00, 0x01, 0x09, 0x01, 0x09, 0x17, 0x17, 0x16, 0x4f, 0x17, 0x16, 0x4f, 0x40, 0x40, ++ 0x40, 0x2d, 0x17, 0x17, 0x40, 0x0f, 0x17, 0x1e, 0x1e, 0x20, 0x27, 0x10, 0x07, 0x09, 0x10, 0x01, ++ 0x07, 0x3e, 0x1f, 0x17, 0x40, 0x0f, 0x17, 0x1e, 0x45, 0x17, 0x44, 0x45, 0x45, 0x17, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x44, 0x46, 0x5d, 0x40, 0x24, 0x05, 0x04, 0x21, 0x40, 0x46, 0x40, 0x40, 0x15, 0x0f, ++ 0x46, 0x61, 0x40, 0x09, 0x63, 0x61, 0x60, 0x5e, 0x5e, 0x07, 0x07, 0x0e, 0x3e, 0x16, 0x02, 0x07, ++ 0x64, 0x27, 0x4b, 0x16, 0x40, 0x06, 0x1c, 0x40, 0x40, 0x40, 0x46, 0x46, 0x55, 0x5c, 0x4d, 0x5c, ++ 0x63, 0x5b, 0x55, 0x64, 0x64, 0x61, 0x55, 0x5d, 0x64, 0x64, 0x61, 0x4c, 0x45, 0x53, 0x55, 0x5c, ++ 0x4d, 0x5c, 0x63, 0x5b, 0x55, 0x64, 0x64, 0x61, 0x55, 0x5d, 0x64, 0x64, 0x61, 0x4c, 0x45, 0x53, ++ 0x0a, 0x4e, 0x50, 0x40, 0x41, 0x40, 0x46, 0x07, 0x46, 0x45, 0x45, 0x60, 0x4d, 0x1e, 0x15, 0x4e, ++ 0x11, 0x07, 0x40, 0x1e, 0x15, 0x4e, 0x11, 0x07, 0x40, 0x1e, 0x15, 0x4e, 0x11, 0x07, 0x40, 0x41, ++ 0x07, 0x01, 0x01, 0x02, 0x0a, 0x02, 0x0a, 0x16, 0x17, 0x15, 0x4e, 0x17, 0x15, 0x4e, 0x40, 0x40, ++ 0x40, 0x2c, 0x16, 0x16, 0x40, 0x0f, 0x16, 0x1d, 0x1d, 0x21, 0x27, 0x11, 0x07, 0x0a, 0x11, 0x02, ++ 0x06, 0x3e, 0x1e, 0x16, 0x40, 0x0f, 0x16, 0x1d, 0x44, 0x16, 0x43, 0x44, 0x44, 0x16, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x43, 0x46, 0x5c, 0x40, 0x23, 0x04, 0x03, 0x21, 0x40, 0x46, 0x40, 0x40, 0x14, 0x0f, ++ 0x46, 0x60, 0x40, 0x09, 0x61, 0x60, 0x5e, 0x5b, 0x5b, 0x07, 0x07, 0x0e, 0x3e, 0x16, 0x03, 0x07, ++ 0x63, 0x27, 0x49, 0x16, 0x40, 0x06, 0x1b, 0x40, 0x40, 0x40, 0x46, 0x46, 0x54, 0x5b, 0x4c, 0x5b, ++ 0x61, 0x59, 0x54, 0x63, 0x63, 0x60, 0x54, 0x5c, 0x63, 0x63, 0x60, 0x4b, 0x44, 0x51, 0x54, 0x5b, ++ 0x4c, 0x5b, 0x61, 0x59, 0x54, 0x63, 0x63, 0x60, 0x54, 0x5c, 0x63, 0x63, 0x60, 0x4b, 0x44, 0x51, ++ 0x0b, 0x4e, 0x4e, 0x40, 0x41, 0x40, 0x46, 0x07, 0x46, 0x44, 0x44, 0x5e, 0x4c, 0x1e, 0x14, 0x4e, ++ 0x11, 0x07, 0x40, 0x1e, 0x14, 0x4e, 0x11, 0x07, 0x40, 0x1e, 0x14, 0x4e, 0x11, 0x07, 0x40, 0x41, ++ 0x07, 0x01, 0x01, 0x03, 0x0b, 0x03, 0x0b, 0x16, 0x17, 0x14, 0x4e, 0x17, 0x14, 0x4e, 0x40, 0x40, ++ 0x40, 0x2b, 0x16, 0x16, 0x40, 0x0f, 0x16, 0x1c, 0x1c, 0x21, 0x27, 0x11, 0x07, 0x0b, 0x11, 0x03, ++ 0x06, 0x3e, 0x1e, 0x16, 0x40, 0x0f, 0x16, 0x1c, 0x43, 0x16, 0x41, 0x43, 0x43, 0x16, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x42, 0x46, 0x5c, 0x40, 0x22, 0x04, 0x02, 0x21, 0x40, 0x46, 0x40, 0x40, 0x14, 0x0f, ++ 0x46, 0x5e, 0x40, 0x09, 0x60, 0x5e, 0x5c, 0x59, 0x59, 0x07, 0x07, 0x0e, 0x3e, 0x16, 0x03, 0x07, ++ 0x62, 0x27, 0x48, 0x16, 0x40, 0x06, 0x1a, 0x40, 0x40, 0x40, 0x46, 0x46, 0x54, 0x5a, 0x4c, 0x5a, ++ 0x60, 0x58, 0x54, 0x62, 0x62, 0x5e, 0x54, 0x5c, 0x62, 0x62, 0x5e, 0x4a, 0x44, 0x50, 0x54, 0x5a, ++ 0x4c, 0x5a, 0x60, 0x58, 0x54, 0x62, 0x62, 0x5e, 0x54, 0x5c, 0x62, 0x62, 0x5e, 0x4a, 0x44, 0x50, ++ 0x0b, 0x4e, 0x4c, 0x40, 0x41, 0x40, 0x46, 0x07, 0x46, 0x44, 0x44, 0x5c, 0x4c, 0x1e, 0x14, 0x4e, ++ 0x11, 0x07, 0x40, 0x1e, 0x14, 0x4e, 0x11, 0x07, 0x40, 0x1e, 0x14, 0x4e, 0x11, 0x07, 0x40, 0x41, ++ 0x07, 0x01, 0x01, 0x03, 0x0b, 0x03, 0x0b, 0x16, 0x17, 0x14, 0x4e, 0x17, 0x14, 0x4e, 0x40, 0x40, ++ 0x40, 0x2a, 0x16, 0x16, 0x40, 0x0f, 0x16, 0x1c, 0x1c, 0x21, 0x27, 0x11, 0x07, 0x0b, 0x11, 0x03, ++ 0x06, 0x3e, 0x1e, 0x16, 0x40, 0x0f, 0x16, 0x1c, 0x42, 0x16, 0x40, 0x42, 0x42, 0x16, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x41, 0x45, 0x5b, 0x40, 0x21, 0x03, 0x01, 0x22, 0x40, 0x45, 0x40, 0x40, 0x13, 0x0f, ++ 0x45, 0x5d, 0x40, 0x0a, 0x5f, 0x5d, 0x5a, 0x56, 0x56, 0x07, 0x07, 0x0d, 0x3e, 0x15, 0x04, 0x07, ++ 0x61, 0x27, 0x47, 0x15, 0x40, 0x05, 0x19, 0x40, 0x40, 0x40, 0x45, 0x45, 0x53, 0x59, 0x4b, 0x59, ++ 0x5f, 0x57, 0x53, 0x61, 0x61, 0x5d, 0x53, 0x5b, 0x61, 0x61, 0x5d, 0x49, 0x43, 0x4f, 0x53, 0x59, ++ 0x4b, 0x59, 0x5f, 0x57, 0x53, 0x61, 0x61, 0x5d, 0x53, 0x5b, 0x61, 0x61, 0x5d, 0x49, 0x43, 0x4f, ++ 0x0c, 0x4d, 0x4a, 0x40, 0x42, 0x40, 0x45, 0x07, 0x45, 0x43, 0x43, 0x5a, 0x4b, 0x1d, 0x13, 0x4d, ++ 0x12, 0x07, 0x40, 0x1d, 0x13, 0x4d, 0x12, 0x07, 0x40, 0x1d, 0x13, 0x4d, 0x12, 0x07, 0x40, 0x42, ++ 0x07, 0x02, 0x02, 0x04, 0x0c, 0x04, 0x0c, 0x15, 0x17, 0x13, 0x4d, 0x17, 0x13, 0x4d, 0x40, 0x40, ++ 0x40, 0x29, 0x15, 0x15, 0x40, 0x0f, 0x15, 0x1b, 0x1b, 0x22, 0x27, 0x12, 0x07, 0x0c, 0x12, 0x04, ++ 0x05, 0x3e, 0x1d, 0x15, 0x40, 0x0f, 0x15, 0x1b, 0x41, 0x15, 0x00, 0x41, 0x41, 0x15, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x40, 0x45, 0x5b, 0x40, 0x20, 0x02, 0x00, 0x22, 0x40, 0x45, 0x40, 0x40, 0x12, 0x0f, ++ 0x45, 0x5b, 0x40, 0x0a, 0x5e, 0x5b, 0x59, 0x54, 0x54, 0x07, 0x07, 0x0d, 0x3e, 0x15, 0x04, 0x07, ++ 0x60, 0x27, 0x46, 0x15, 0x40, 0x05, 0x18, 0x40, 0x40, 0x40, 0x45, 0x45, 0x53, 0x58, 0x4b, 0x58, ++ 0x5e, 0x56, 0x53, 0x60, 0x60, 0x5b, 0x53, 0x5b, 0x60, 0x60, 0x5b, 0x48, 0x43, 0x4e, 0x53, 0x58, ++ 0x4b, 0x58, 0x5e, 0x56, 0x53, 0x60, 0x60, 0x5b, 0x53, 0x5b, 0x60, 0x60, 0x5b, 0x48, 0x43, 0x4e, ++ 0x0c, 0x4d, 0x49, 0x40, 0x42, 0x40, 0x45, 0x07, 0x45, 0x43, 0x43, 0x59, 0x4b, 0x1d, 0x12, 0x4d, ++ 0x12, 0x07, 0x40, 0x1d, 0x12, 0x4d, 0x12, 0x07, 0x40, 0x1d, 0x12, 0x4d, 0x12, 0x07, 0x40, 0x42, ++ 0x07, 0x02, 0x02, 0x04, 0x0c, 0x04, 0x0c, 0x15, 0x17, 0x12, 0x4d, 0x17, 0x12, 0x4d, 0x40, 0x40, ++ 0x40, 0x28, 0x15, 0x15, 0x40, 0x0f, 0x15, 0x1a, 0x1a, 0x22, 0x27, 0x12, 0x07, 0x0c, 0x12, 0x04, ++ 0x05, 0x3e, 0x1d, 0x15, 0x40, 0x0f, 0x15, 0x1a, 0x40, 0x15, 0x01, 0x40, 0x40, 0x15, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x00, 0x45, 0x5a, 0x40, 0x1f, 0x02, 0x40, 0x22, 0x40, 0x45, 0x40, 0x40, 0x12, 0x0f, ++ 0x45, 0x59, 0x40, 0x0a, 0x5c, 0x59, 0x57, 0x51, 0x51, 0x07, 0x07, 0x0d, 0x3e, 0x15, 0x05, 0x07, ++ 0x5f, 0x27, 0x44, 0x15, 0x40, 0x05, 0x17, 0x40, 0x40, 0x40, 0x45, 0x45, 0x52, 0x57, 0x4a, 0x57, ++ 0x5c, 0x54, 0x52, 0x5f, 0x5f, 0x59, 0x52, 0x5a, 0x5f, 0x5f, 0x59, 0x47, 0x42, 0x4c, 0x52, 0x57, ++ 0x4a, 0x57, 0x5c, 0x54, 0x52, 0x5f, 0x5f, 0x59, 0x52, 0x5a, 0x5f, 0x5f, 0x59, 0x47, 0x42, 0x4c, ++ 0x0d, 0x4d, 0x47, 0x40, 0x42, 0x40, 0x45, 0x07, 0x45, 0x42, 0x42, 0x57, 0x4a, 0x1d, 0x12, 0x4d, ++ 0x12, 0x07, 0x40, 0x1d, 0x12, 0x4d, 0x12, 0x07, 0x40, 0x1d, 0x12, 0x4d, 0x12, 0x07, 0x40, 0x42, ++ 0x07, 0x02, 0x02, 0x05, 0x0d, 0x05, 0x0d, 0x15, 0x17, 0x12, 0x4d, 0x17, 0x12, 0x4d, 0x40, 0x40, ++ 0x40, 0x27, 0x15, 0x15, 0x40, 0x0f, 0x15, 0x1a, 0x1a, 0x22, 0x27, 0x12, 0x07, 0x0d, 0x12, 0x05, ++ 0x05, 0x3e, 0x1d, 0x15, 0x40, 0x0f, 0x15, 0x1a, 0x00, 0x15, 0x03, 0x00, 0x00, 0x15, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x01, 0x44, 0x59, 0x40, 0x1e, 0x01, 0x41, 0x23, 0x40, 0x44, 0x40, 0x40, 0x11, 0x0f, ++ 0x44, 0x58, 0x40, 0x0b, 0x5b, 0x58, 0x55, 0x4f, 0x4f, 0x07, 0x07, 0x0c, 0x3e, 0x14, 0x06, 0x07, ++ 0x5e, 0x27, 0x43, 0x14, 0x40, 0x04, 0x16, 0x40, 0x40, 0x40, 0x44, 0x44, 0x51, 0x56, 0x49, 0x56, ++ 0x5b, 0x53, 0x51, 0x5e, 0x5e, 0x58, 0x51, 0x59, 0x5e, 0x5e, 0x58, 0x46, 0x41, 0x4b, 0x51, 0x56, ++ 0x49, 0x56, 0x5b, 0x53, 0x51, 0x5e, 0x5e, 0x58, 0x51, 0x59, 0x5e, 0x5e, 0x58, 0x46, 0x41, 0x4b, ++ 0x0e, 0x4c, 0x45, 0x40, 0x43, 0x40, 0x44, 0x07, 0x44, 0x41, 0x41, 0x55, 0x49, 0x1c, 0x11, 0x4c, ++ 0x13, 0x07, 0x40, 0x1c, 0x11, 0x4c, 0x13, 0x07, 0x40, 0x1c, 0x11, 0x4c, 0x13, 0x07, 0x40, 0x43, ++ 0x07, 0x03, 0x03, 0x06, 0x0e, 0x06, 0x0e, 0x14, 0x17, 0x11, 0x4c, 0x17, 0x11, 0x4c, 0x40, 0x40, ++ 0x40, 0x26, 0x14, 0x14, 0x40, 0x0f, 0x14, 0x19, 0x19, 0x23, 0x27, 0x13, 0x07, 0x0e, 0x13, 0x06, ++ 0x04, 0x3e, 0x1c, 0x14, 0x40, 0x0f, 0x14, 0x19, 0x01, 0x14, 0x04, 0x01, 0x01, 0x14, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x02, 0x44, 0x59, 0x40, 0x1d, 0x01, 0x42, 0x23, 0x40, 0x44, 0x40, 0x40, 0x11, 0x0f, ++ 0x44, 0x56, 0x40, 0x0b, 0x5a, 0x56, 0x53, 0x4c, 0x4c, 0x07, 0x07, 0x0c, 0x3e, 0x14, 0x06, 0x07, ++ 0x5d, 0x27, 0x42, 0x14, 0x40, 0x04, 0x15, 0x40, 0x40, 0x40, 0x44, 0x44, 0x51, 0x55, 0x49, 0x55, ++ 0x5a, 0x52, 0x51, 0x5d, 0x5d, 0x56, 0x51, 0x59, 0x5d, 0x5d, 0x56, 0x45, 0x41, 0x4a, 0x51, 0x55, ++ 0x49, 0x55, 0x5a, 0x52, 0x51, 0x5d, 0x5d, 0x56, 0x51, 0x59, 0x5d, 0x5d, 0x56, 0x45, 0x41, 0x4a, ++ 0x0e, 0x4c, 0x43, 0x40, 0x43, 0x40, 0x44, 0x07, 0x44, 0x41, 0x41, 0x53, 0x49, 0x1c, 0x11, 0x4c, ++ 0x13, 0x07, 0x40, 0x1c, 0x11, 0x4c, 0x13, 0x07, 0x40, 0x1c, 0x11, 0x4c, 0x13, 0x07, 0x40, 0x43, ++ 0x07, 0x03, 0x03, 0x06, 0x0e, 0x06, 0x0e, 0x14, 0x17, 0x11, 0x4c, 0x17, 0x11, 0x4c, 0x40, 0x40, ++ 0x40, 0x25, 0x14, 0x14, 0x40, 0x0f, 0x14, 0x19, 0x19, 0x23, 0x27, 0x13, 0x07, 0x0e, 0x13, 0x06, ++ 0x04, 0x3e, 0x1c, 0x14, 0x40, 0x0f, 0x14, 0x19, 0x02, 0x14, 0x05, 0x02, 0x02, 0x14, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x03, 0x44, 0x58, 0x40, 0x1c, 0x00, 0x43, 0x23, 0x40, 0x44, 0x40, 0x40, 0x10, 0x0f, ++ 0x44, 0x55, 0x40, 0x0b, 0x59, 0x55, 0x51, 0x4a, 0x4a, 0x07, 0x07, 0x0c, 0x3d, 0x14, 0x07, 0x07, ++ 0x5c, 0x27, 0x41, 0x14, 0x40, 0x04, 0x14, 0x40, 0x40, 0x40, 0x44, 0x44, 0x50, 0x54, 0x48, 0x54, ++ 0x59, 0x51, 0x50, 0x5c, 0x5c, 0x55, 0x50, 0x58, 0x5c, 0x5c, 0x55, 0x44, 0x40, 0x49, 0x50, 0x54, ++ 0x48, 0x54, 0x59, 0x51, 0x50, 0x5c, 0x5c, 0x55, 0x50, 0x58, 0x5c, 0x5c, 0x55, 0x44, 0x40, 0x49, ++ 0x0f, 0x4c, 0x41, 0x40, 0x43, 0x40, 0x44, 0x07, 0x44, 0x40, 0x40, 0x51, 0x48, 0x1c, 0x10, 0x4c, ++ 0x13, 0x07, 0x40, 0x1c, 0x10, 0x4c, 0x13, 0x07, 0x40, 0x1c, 0x10, 0x4c, 0x13, 0x07, 0x40, 0x43, ++ 0x07, 0x03, 0x03, 0x07, 0x0f, 0x07, 0x0f, 0x14, 0x17, 0x10, 0x4c, 0x17, 0x10, 0x4c, 0x40, 0x40, ++ 0x40, 0x24, 0x14, 0x14, 0x40, 0x0f, 0x14, 0x18, 0x18, 0x23, 0x27, 0x13, 0x07, 0x0f, 0x13, 0x07, ++ 0x04, 0x3e, 0x1c, 0x14, 0x40, 0x0f, 0x14, 0x18, 0x03, 0x14, 0x06, 0x03, 0x03, 0x14, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x04, 0x43, 0x57, 0x40, 0x1b, 0x40, 0x44, 0x24, 0x40, 0x43, 0x40, 0x40, 0x0f, 0x0f, ++ 0x43, 0x53, 0x40, 0x0c, 0x57, 0x53, 0x4f, 0x47, 0x47, 0x07, 0x07, 0x0b, 0x3b, 0x13, 0x08, 0x07, ++ 0x5b, 0x27, 0x00, 0x13, 0x40, 0x03, 0x13, 0x40, 0x40, 0x40, 0x43, 0x43, 0x4f, 0x53, 0x47, 0x53, ++ 0x57, 0x4f, 0x4f, 0x5b, 0x5b, 0x53, 0x4f, 0x57, 0x5b, 0x5b, 0x53, 0x43, 0x00, 0x47, 0x4f, 0x53, ++ 0x47, 0x53, 0x57, 0x4f, 0x4f, 0x5b, 0x5b, 0x53, 0x4f, 0x57, 0x5b, 0x5b, 0x53, 0x43, 0x00, 0x47, ++ 0x10, 0x4b, 0x00, 0x40, 0x44, 0x40, 0x43, 0x07, 0x43, 0x00, 0x00, 0x4f, 0x47, 0x1b, 0x0f, 0x4b, ++ 0x14, 0x07, 0x40, 0x1b, 0x0f, 0x4b, 0x14, 0x07, 0x40, 0x1b, 0x0f, 0x4b, 0x14, 0x07, 0x40, 0x44, ++ 0x07, 0x04, 0x04, 0x08, 0x10, 0x08, 0x10, 0x13, 0x17, 0x0f, 0x4b, 0x17, 0x0f, 0x4b, 0x40, 0x40, ++ 0x40, 0x23, 0x13, 0x13, 0x40, 0x0f, 0x13, 0x17, 0x17, 0x24, 0x27, 0x14, 0x07, 0x10, 0x14, 0x08, ++ 0x03, 0x3e, 0x1b, 0x13, 0x40, 0x0f, 0x13, 0x17, 0x04, 0x13, 0x08, 0x04, 0x04, 0x13, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x05, 0x43, 0x57, 0x40, 0x1a, 0x40, 0x45, 0x24, 0x40, 0x43, 0x40, 0x40, 0x0f, 0x0f, ++ 0x43, 0x52, 0x40, 0x0c, 0x56, 0x52, 0x4d, 0x45, 0x45, 0x07, 0x07, 0x0b, 0x3a, 0x13, 0x08, 0x07, ++ 0x5a, 0x27, 0x01, 0x13, 0x40, 0x03, 0x12, 0x40, 0x40, 0x40, 0x43, 0x43, 0x4f, 0x52, 0x47, 0x52, ++ 0x56, 0x4e, 0x4f, 0x5a, 0x5a, 0x52, 0x4f, 0x57, 0x5a, 0x5a, 0x52, 0x42, 0x00, 0x46, 0x4f, 0x52, ++ 0x47, 0x52, 0x56, 0x4e, 0x4f, 0x5a, 0x5a, 0x52, 0x4f, 0x57, 0x5a, 0x5a, 0x52, 0x42, 0x00, 0x46, ++ 0x10, 0x4b, 0x02, 0x40, 0x44, 0x40, 0x43, 0x07, 0x43, 0x00, 0x00, 0x4d, 0x47, 0x1b, 0x0f, 0x4b, ++ 0x14, 0x07, 0x40, 0x1b, 0x0f, 0x4b, 0x14, 0x07, 0x40, 0x1b, 0x0f, 0x4b, 0x14, 0x07, 0x40, 0x44, ++ 0x07, 0x04, 0x04, 0x08, 0x10, 0x08, 0x10, 0x13, 0x17, 0x0f, 0x4b, 0x17, 0x0f, 0x4b, 0x40, 0x40, ++ 0x40, 0x22, 0x13, 0x13, 0x40, 0x0f, 0x13, 0x17, 0x17, 0x24, 0x27, 0x14, 0x07, 0x10, 0x14, 0x08, ++ 0x03, 0x3e, 0x1b, 0x13, 0x40, 0x0f, 0x13, 0x17, 0x05, 0x13, 0x09, 0x05, 0x05, 0x13, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x06, 0x43, 0x56, 0x40, 0x19, 0x41, 0x46, 0x24, 0x40, 0x43, 0x40, 0x40, 0x0e, 0x0f, ++ 0x43, 0x50, 0x40, 0x0c, 0x55, 0x50, 0x4b, 0x42, 0x42, 0x07, 0x07, 0x0b, 0x38, 0x13, 0x09, 0x07, ++ 0x59, 0x27, 0x02, 0x13, 0x40, 0x03, 0x11, 0x40, 0x40, 0x40, 0x43, 0x43, 0x4e, 0x51, 0x46, 0x51, ++ 0x55, 0x4d, 0x4e, 0x59, 0x59, 0x50, 0x4e, 0x56, 0x59, 0x59, 0x50, 0x41, 0x01, 0x45, 0x4e, 0x51, ++ 0x46, 0x51, 0x55, 0x4d, 0x4e, 0x59, 0x59, 0x50, 0x4e, 0x56, 0x59, 0x59, 0x50, 0x41, 0x01, 0x45, ++ 0x11, 0x4b, 0x04, 0x40, 0x44, 0x40, 0x43, 0x07, 0x43, 0x01, 0x01, 0x4b, 0x46, 0x1b, 0x0e, 0x4b, ++ 0x14, 0x07, 0x40, 0x1b, 0x0e, 0x4b, 0x14, 0x07, 0x40, 0x1b, 0x0e, 0x4b, 0x14, 0x07, 0x40, 0x44, ++ 0x07, 0x04, 0x04, 0x09, 0x11, 0x09, 0x11, 0x13, 0x17, 0x0e, 0x4b, 0x17, 0x0e, 0x4b, 0x40, 0x40, ++ 0x40, 0x21, 0x13, 0x13, 0x40, 0x0f, 0x13, 0x16, 0x16, 0x24, 0x27, 0x14, 0x07, 0x11, 0x14, 0x09, ++ 0x03, 0x3d, 0x1b, 0x13, 0x40, 0x0f, 0x13, 0x16, 0x06, 0x13, 0x0a, 0x06, 0x06, 0x13, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x06, 0x43, 0x56, 0x40, 0x18, 0x42, 0x47, 0x24, 0x40, 0x43, 0x40, 0x40, 0x0d, 0x0f, ++ 0x43, 0x4f, 0x40, 0x0c, 0x54, 0x4f, 0x4a, 0x40, 0x40, 0x07, 0x07, 0x0a, 0x36, 0x12, 0x09, 0x07, ++ 0x59, 0x27, 0x03, 0x12, 0x40, 0x02, 0x10, 0x40, 0x40, 0x40, 0x43, 0x43, 0x4e, 0x51, 0x46, 0x51, ++ 0x54, 0x4c, 0x4e, 0x59, 0x59, 0x4f, 0x4e, 0x56, 0x59, 0x59, 0x4f, 0x41, 0x01, 0x44, 0x4e, 0x51, ++ 0x46, 0x51, 0x54, 0x4c, 0x4e, 0x59, 0x59, 0x4f, 0x4e, 0x56, 0x59, 0x59, 0x4f, 0x41, 0x01, 0x44, ++ 0x11, 0x4b, 0x05, 0x40, 0x45, 0x40, 0x43, 0x07, 0x43, 0x01, 0x01, 0x4a, 0x46, 0x1a, 0x0d, 0x4b, ++ 0x14, 0x07, 0x40, 0x1a, 0x0d, 0x4b, 0x14, 0x07, 0x40, 0x1a, 0x0d, 0x4b, 0x14, 0x07, 0x40, 0x45, ++ 0x07, 0x04, 0x04, 0x09, 0x11, 0x09, 0x11, 0x12, 0x17, 0x0d, 0x4b, 0x17, 0x0d, 0x4b, 0x40, 0x40, ++ 0x40, 0x20, 0x12, 0x12, 0x40, 0x0f, 0x12, 0x15, 0x15, 0x24, 0x27, 0x14, 0x07, 0x11, 0x14, 0x09, ++ 0x02, 0x3b, 0x1a, 0x12, 0x40, 0x0f, 0x12, 0x15, 0x06, 0x12, 0x0b, 0x06, 0x06, 0x12, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x07, 0x42, 0x55, 0x40, 0x18, 0x42, 0x47, 0x25, 0x40, 0x42, 0x40, 0x40, 0x0d, 0x0f, ++ 0x42, 0x4d, 0x40, 0x0d, 0x52, 0x4d, 0x48, 0x02, 0x02, 0x07, 0x07, 0x0a, 0x35, 0x12, 0x0a, 0x07, ++ 0x58, 0x27, 0x05, 0x12, 0x40, 0x02, 0x10, 0x40, 0x40, 0x40, 0x42, 0x42, 0x4d, 0x50, 0x45, 0x50, ++ 0x52, 0x4a, 0x4d, 0x58, 0x58, 0x4d, 0x4d, 0x55, 0x58, 0x58, 0x4d, 0x40, 0x02, 0x42, 0x4d, 0x50, ++ 0x45, 0x50, 0x52, 0x4a, 0x4d, 0x58, 0x58, 0x4d, 0x4d, 0x55, 0x58, 0x58, 0x4d, 0x40, 0x02, 0x42, ++ 0x12, 0x4a, 0x07, 0x40, 0x45, 0x40, 0x42, 0x07, 0x42, 0x02, 0x02, 0x48, 0x45, 0x1a, 0x0d, 0x4a, ++ 0x15, 0x07, 0x40, 0x1a, 0x0d, 0x4a, 0x15, 0x07, 0x40, 0x1a, 0x0d, 0x4a, 0x15, 0x07, 0x40, 0x45, ++ 0x07, 0x05, 0x05, 0x0a, 0x12, 0x0a, 0x12, 0x12, 0x17, 0x0d, 0x4a, 0x17, 0x0d, 0x4a, 0x40, 0x40, ++ 0x40, 0x20, 0x12, 0x12, 0x40, 0x0f, 0x12, 0x15, 0x15, 0x25, 0x27, 0x15, 0x07, 0x12, 0x15, 0x0a, ++ 0x02, 0x3a, 0x1a, 0x12, 0x40, 0x0f, 0x12, 0x15, 0x07, 0x12, 0x0d, 0x07, 0x07, 0x12, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x08, 0x42, 0x54, 0x40, 0x17, 0x43, 0x48, 0x25, 0x40, 0x42, 0x40, 0x40, 0x0c, 0x0f, ++ 0x42, 0x4b, 0x40, 0x0d, 0x51, 0x4b, 0x46, 0x04, 0x04, 0x07, 0x07, 0x0a, 0x33, 0x12, 0x0b, 0x07, ++ 0x57, 0x27, 0x06, 0x12, 0x40, 0x02, 0x0f, 0x40, 0x40, 0x40, 0x42, 0x42, 0x4c, 0x4f, 0x44, 0x4f, ++ 0x51, 0x49, 0x4c, 0x57, 0x57, 0x4b, 0x4c, 0x54, 0x57, 0x57, 0x4b, 0x00, 0x03, 0x41, 0x4c, 0x4f, ++ 0x44, 0x4f, 0x51, 0x49, 0x4c, 0x57, 0x57, 0x4b, 0x4c, 0x54, 0x57, 0x57, 0x4b, 0x00, 0x03, 0x41, ++ 0x13, 0x4a, 0x09, 0x40, 0x45, 0x40, 0x42, 0x07, 0x42, 0x03, 0x03, 0x46, 0x44, 0x1a, 0x0c, 0x4a, ++ 0x15, 0x07, 0x40, 0x1a, 0x0c, 0x4a, 0x15, 0x07, 0x40, 0x1a, 0x0c, 0x4a, 0x15, 0x07, 0x40, 0x45, ++ 0x07, 0x05, 0x05, 0x0b, 0x13, 0x0b, 0x13, 0x12, 0x17, 0x0c, 0x4a, 0x17, 0x0c, 0x4a, 0x40, 0x40, ++ 0x40, 0x1f, 0x12, 0x12, 0x40, 0x0f, 0x12, 0x14, 0x14, 0x25, 0x27, 0x15, 0x07, 0x13, 0x15, 0x0b, ++ 0x02, 0x39, 0x1a, 0x12, 0x40, 0x0f, 0x12, 0x14, 0x08, 0x12, 0x0e, 0x08, 0x08, 0x12, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x09, 0x42, 0x54, 0x40, 0x16, 0x43, 0x49, 0x25, 0x40, 0x42, 0x40, 0x40, 0x0c, 0x0f, ++ 0x42, 0x4a, 0x40, 0x0d, 0x50, 0x4a, 0x44, 0x07, 0x07, 0x07, 0x07, 0x0a, 0x32, 0x12, 0x0b, 0x07, ++ 0x56, 0x27, 0x07, 0x12, 0x40, 0x02, 0x0e, 0x40, 0x40, 0x40, 0x42, 0x42, 0x4c, 0x4e, 0x44, 0x4e, ++ 0x50, 0x48, 0x4c, 0x56, 0x56, 0x4a, 0x4c, 0x54, 0x56, 0x56, 0x4a, 0x01, 0x03, 0x40, 0x4c, 0x4e, ++ 0x44, 0x4e, 0x50, 0x48, 0x4c, 0x56, 0x56, 0x4a, 0x4c, 0x54, 0x56, 0x56, 0x4a, 0x01, 0x03, 0x40, ++ 0x13, 0x4a, 0x0b, 0x40, 0x45, 0x40, 0x42, 0x07, 0x42, 0x03, 0x03, 0x44, 0x44, 0x1a, 0x0c, 0x4a, ++ 0x15, 0x07, 0x40, 0x1a, 0x0c, 0x4a, 0x15, 0x07, 0x40, 0x1a, 0x0c, 0x4a, 0x15, 0x07, 0x40, 0x45, ++ 0x07, 0x05, 0x05, 0x0b, 0x13, 0x0b, 0x13, 0x12, 0x17, 0x0c, 0x4a, 0x17, 0x0c, 0x4a, 0x40, 0x40, ++ 0x40, 0x1e, 0x12, 0x12, 0x40, 0x0f, 0x12, 0x14, 0x14, 0x25, 0x27, 0x15, 0x07, 0x13, 0x15, 0x0b, ++ 0x02, 0x38, 0x1a, 0x12, 0x40, 0x0f, 0x12, 0x14, 0x09, 0x12, 0x0f, 0x09, 0x09, 0x12, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x0a, 0x41, 0x53, 0x40, 0x15, 0x44, 0x4a, 0x26, 0x40, 0x41, 0x40, 0x40, 0x0b, 0x0f, ++ 0x41, 0x48, 0x40, 0x0e, 0x4f, 0x48, 0x42, 0x09, 0x09, 0x07, 0x07, 0x09, 0x30, 0x11, 0x0c, 0x07, ++ 0x55, 0x27, 0x08, 0x11, 0x40, 0x01, 0x0d, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4b, 0x4d, 0x43, 0x4d, ++ 0x4f, 0x47, 0x4b, 0x55, 0x55, 0x48, 0x4b, 0x53, 0x55, 0x55, 0x48, 0x02, 0x04, 0x00, 0x4b, 0x4d, ++ 0x43, 0x4d, 0x4f, 0x47, 0x4b, 0x55, 0x55, 0x48, 0x4b, 0x53, 0x55, 0x55, 0x48, 0x02, 0x04, 0x00, ++ 0x14, 0x49, 0x0d, 0x40, 0x46, 0x40, 0x41, 0x07, 0x41, 0x04, 0x04, 0x42, 0x43, 0x19, 0x0b, 0x49, ++ 0x16, 0x07, 0x40, 0x19, 0x0b, 0x49, 0x16, 0x07, 0x40, 0x19, 0x0b, 0x49, 0x16, 0x07, 0x40, 0x46, ++ 0x07, 0x06, 0x06, 0x0c, 0x14, 0x0c, 0x14, 0x11, 0x17, 0x0b, 0x49, 0x17, 0x0b, 0x49, 0x40, 0x40, ++ 0x40, 0x1d, 0x11, 0x11, 0x40, 0x0f, 0x11, 0x13, 0x13, 0x26, 0x27, 0x16, 0x07, 0x14, 0x16, 0x0c, ++ 0x01, 0x36, 0x19, 0x11, 0x40, 0x0f, 0x11, 0x13, 0x0a, 0x11, 0x10, 0x0a, 0x0a, 0x11, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x0b, 0x41, 0x52, 0x40, 0x14, 0x45, 0x4b, 0x26, 0x40, 0x41, 0x40, 0x40, 0x0a, 0x0f, ++ 0x41, 0x47, 0x40, 0x0e, 0x4d, 0x47, 0x40, 0x0c, 0x0c, 0x07, 0x07, 0x09, 0x2f, 0x11, 0x0d, 0x07, ++ 0x54, 0x27, 0x0a, 0x11, 0x40, 0x01, 0x0c, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4a, 0x4c, 0x42, 0x4c, ++ 0x4d, 0x45, 0x4a, 0x54, 0x54, 0x47, 0x4a, 0x52, 0x54, 0x54, 0x47, 0x03, 0x05, 0x02, 0x4a, 0x4c, ++ 0x42, 0x4c, 0x4d, 0x45, 0x4a, 0x54, 0x54, 0x47, 0x4a, 0x52, 0x54, 0x54, 0x47, 0x03, 0x05, 0x02, ++ 0x15, 0x49, 0x0f, 0x40, 0x46, 0x40, 0x41, 0x07, 0x41, 0x05, 0x05, 0x40, 0x42, 0x19, 0x0a, 0x49, ++ 0x16, 0x07, 0x40, 0x19, 0x0a, 0x49, 0x16, 0x07, 0x40, 0x19, 0x0a, 0x49, 0x16, 0x07, 0x40, 0x46, ++ 0x07, 0x06, 0x06, 0x0d, 0x15, 0x0d, 0x15, 0x11, 0x17, 0x0a, 0x49, 0x17, 0x0a, 0x49, 0x40, 0x40, ++ 0x40, 0x1c, 0x11, 0x11, 0x40, 0x0f, 0x11, 0x12, 0x12, 0x26, 0x27, 0x16, 0x07, 0x15, 0x16, 0x0d, ++ 0x01, 0x35, 0x19, 0x11, 0x40, 0x0f, 0x11, 0x12, 0x0b, 0x11, 0x12, 0x0b, 0x0b, 0x11, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x0c, 0x41, 0x52, 0x40, 0x13, 0x45, 0x4c, 0x26, 0x40, 0x41, 0x40, 0x40, 0x0a, 0x0f, ++ 0x41, 0x45, 0x40, 0x0e, 0x4c, 0x45, 0x01, 0x0e, 0x0e, 0x07, 0x07, 0x09, 0x2d, 0x11, 0x0d, 0x07, ++ 0x53, 0x27, 0x0b, 0x11, 0x40, 0x01, 0x0b, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4a, 0x4b, 0x42, 0x4b, ++ 0x4c, 0x44, 0x4a, 0x53, 0x53, 0x45, 0x4a, 0x52, 0x53, 0x53, 0x45, 0x04, 0x05, 0x03, 0x4a, 0x4b, ++ 0x42, 0x4b, 0x4c, 0x44, 0x4a, 0x53, 0x53, 0x45, 0x4a, 0x52, 0x53, 0x53, 0x45, 0x04, 0x05, 0x03, ++ 0x15, 0x49, 0x11, 0x40, 0x46, 0x40, 0x41, 0x07, 0x41, 0x05, 0x05, 0x01, 0x42, 0x19, 0x0a, 0x49, ++ 0x16, 0x07, 0x40, 0x19, 0x0a, 0x49, 0x16, 0x07, 0x40, 0x19, 0x0a, 0x49, 0x16, 0x07, 0x40, 0x46, ++ 0x07, 0x06, 0x06, 0x0d, 0x15, 0x0d, 0x15, 0x11, 0x17, 0x0a, 0x49, 0x17, 0x0a, 0x49, 0x40, 0x40, ++ 0x40, 0x1b, 0x11, 0x11, 0x40, 0x0f, 0x11, 0x12, 0x12, 0x26, 0x27, 0x16, 0x07, 0x15, 0x16, 0x0d, ++ 0x01, 0x34, 0x19, 0x11, 0x40, 0x0f, 0x11, 0x12, 0x0c, 0x11, 0x13, 0x0c, 0x0c, 0x11, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x0d, 0x40, 0x51, 0x40, 0x12, 0x46, 0x4d, 0x27, 0x40, 0x40, 0x40, 0x40, 0x09, 0x0f, ++ 0x40, 0x44, 0x40, 0x0f, 0x4b, 0x44, 0x03, 0x11, 0x11, 0x07, 0x07, 0x08, 0x2c, 0x10, 0x0e, 0x07, ++ 0x52, 0x27, 0x0c, 0x10, 0x40, 0x00, 0x0a, 0x40, 0x40, 0x40, 0x40, 0x40, 0x49, 0x4a, 0x41, 0x4a, ++ 0x4b, 0x43, 0x49, 0x52, 0x52, 0x44, 0x49, 0x51, 0x52, 0x52, 0x44, 0x05, 0x06, 0x04, 0x49, 0x4a, ++ 0x41, 0x4a, 0x4b, 0x43, 0x49, 0x52, 0x52, 0x44, 0x49, 0x51, 0x52, 0x52, 0x44, 0x05, 0x06, 0x04, ++ 0x16, 0x48, 0x13, 0x40, 0x47, 0x40, 0x40, 0x07, 0x40, 0x06, 0x06, 0x03, 0x41, 0x18, 0x09, 0x48, ++ 0x17, 0x07, 0x40, 0x18, 0x09, 0x48, 0x17, 0x07, 0x40, 0x18, 0x09, 0x48, 0x17, 0x07, 0x40, 0x47, ++ 0x07, 0x07, 0x07, 0x0e, 0x16, 0x0e, 0x16, 0x10, 0x17, 0x09, 0x48, 0x17, 0x09, 0x48, 0x40, 0x40, ++ 0x40, 0x1a, 0x10, 0x10, 0x40, 0x0f, 0x10, 0x11, 0x11, 0x27, 0x27, 0x17, 0x07, 0x16, 0x17, 0x0e, ++ 0x00, 0x33, 0x18, 0x10, 0x40, 0x0f, 0x10, 0x11, 0x0d, 0x10, 0x14, 0x0d, 0x0d, 0x10, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x0e, 0x40, 0x51, 0x40, 0x11, 0x47, 0x4e, 0x27, 0x40, 0x40, 0x40, 0x40, 0x08, 0x0f, ++ 0x40, 0x42, 0x40, 0x0f, 0x4a, 0x42, 0x04, 0x13, 0x13, 0x07, 0x07, 0x08, 0x2a, 0x10, 0x0e, 0x07, ++ 0x51, 0x27, 0x0d, 0x10, 0x40, 0x00, 0x09, 0x40, 0x40, 0x40, 0x40, 0x40, 0x49, 0x49, 0x41, 0x49, ++ 0x4a, 0x42, 0x49, 0x51, 0x51, 0x42, 0x49, 0x51, 0x51, 0x51, 0x42, 0x06, 0x06, 0x05, 0x49, 0x49, ++ 0x41, 0x49, 0x4a, 0x42, 0x49, 0x51, 0x51, 0x42, 0x49, 0x51, 0x51, 0x51, 0x42, 0x06, 0x06, 0x05, ++ 0x16, 0x48, 0x14, 0x40, 0x47, 0x40, 0x40, 0x07, 0x40, 0x06, 0x06, 0x04, 0x41, 0x18, 0x08, 0x48, ++ 0x17, 0x07, 0x40, 0x18, 0x08, 0x48, 0x17, 0x07, 0x40, 0x18, 0x08, 0x48, 0x17, 0x07, 0x40, 0x47, ++ 0x07, 0x07, 0x07, 0x0e, 0x16, 0x0e, 0x16, 0x10, 0x17, 0x08, 0x48, 0x17, 0x08, 0x48, 0x40, 0x40, ++ 0x40, 0x19, 0x10, 0x10, 0x40, 0x0f, 0x10, 0x10, 0x10, 0x27, 0x27, 0x17, 0x07, 0x16, 0x17, 0x0e, ++ 0x00, 0x31, 0x18, 0x10, 0x40, 0x0f, 0x10, 0x10, 0x0e, 0x10, 0x15, 0x0e, 0x0e, 0x10, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x0f, 0x40, 0x50, 0x40, 0x10, 0x47, 0x4f, 0x27, 0x40, 0x40, 0x40, 0x40, 0x08, 0x0f, ++ 0x40, 0x40, 0x40, 0x0f, 0x48, 0x40, 0x06, 0x16, 0x16, 0x07, 0x07, 0x08, 0x28, 0x10, 0x0f, 0x07, ++ 0x50, 0x27, 0x0f, 0x10, 0x40, 0x00, 0x08, 0x40, 0x40, 0x40, 0x40, 0x40, 0x48, 0x48, 0x40, 0x48, ++ 0x48, 0x40, 0x48, 0x50, 0x50, 0x40, 0x48, 0x50, 0x50, 0x50, 0x40, 0x07, 0x07, 0x07, 0x48, 0x48, ++ 0x40, 0x48, 0x48, 0x40, 0x48, 0x50, 0x50, 0x40, 0x48, 0x50, 0x50, 0x50, 0x40, 0x07, 0x07, 0x07, ++ 0x17, 0x48, 0x16, 0x40, 0x47, 0x40, 0x40, 0x07, 0x40, 0x07, 0x07, 0x06, 0x40, 0x18, 0x08, 0x48, ++ 0x17, 0x07, 0x40, 0x18, 0x08, 0x48, 0x17, 0x07, 0x40, 0x18, 0x08, 0x48, 0x17, 0x07, 0x40, 0x47, ++ 0x07, 0x07, 0x07, 0x0f, 0x17, 0x0f, 0x17, 0x10, 0x17, 0x08, 0x48, 0x17, 0x08, 0x48, 0x40, 0x40, ++ 0x40, 0x18, 0x10, 0x10, 0x40, 0x0f, 0x10, 0x10, 0x10, 0x27, 0x27, 0x17, 0x07, 0x17, 0x17, 0x0f, ++ 0x00, 0x30, 0x18, 0x10, 0x40, 0x0f, 0x10, 0x10, 0x0f, 0x10, 0x17, 0x0f, 0x0f, 0x10, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x10, 0x00, 0x4f, 0x40, 0x0f, 0x48, 0x50, 0x28, 0x40, 0x00, 0x40, 0x40, 0x07, 0x0f, ++ 0x00, 0x00, 0x40, 0x10, 0x47, 0x00, 0x08, 0x18, 0x18, 0x07, 0x07, 0x07, 0x27, 0x0f, 0x10, 0x07, ++ 0x4f, 0x27, 0x10, 0x0f, 0x40, 0x40, 0x07, 0x40, 0x40, 0x40, 0x00, 0x00, 0x47, 0x47, 0x00, 0x47, ++ 0x47, 0x00, 0x47, 0x4f, 0x4f, 0x00, 0x47, 0x4f, 0x4f, 0x4f, 0x00, 0x08, 0x08, 0x08, 0x47, 0x47, ++ 0x00, 0x47, 0x47, 0x00, 0x47, 0x4f, 0x4f, 0x00, 0x47, 0x4f, 0x4f, 0x4f, 0x00, 0x08, 0x08, 0x08, ++ 0x18, 0x47, 0x18, 0x40, 0x48, 0x40, 0x00, 0x07, 0x00, 0x08, 0x08, 0x08, 0x00, 0x17, 0x07, 0x47, ++ 0x18, 0x07, 0x40, 0x17, 0x07, 0x47, 0x18, 0x07, 0x40, 0x17, 0x07, 0x47, 0x18, 0x07, 0x40, 0x48, ++ 0x07, 0x08, 0x08, 0x10, 0x18, 0x10, 0x18, 0x0f, 0x17, 0x07, 0x47, 0x17, 0x07, 0x47, 0x40, 0x40, ++ 0x40, 0x17, 0x0f, 0x0f, 0x40, 0x0f, 0x0f, 0x0f, 0x0f, 0x28, 0x27, 0x18, 0x07, 0x18, 0x18, 0x10, ++ 0x40, 0x2f, 0x17, 0x0f, 0x40, 0x0f, 0x0f, 0x0f, 0x10, 0x0f, 0x18, 0x10, 0x10, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x11, 0x00, 0x4f, 0x40, 0x0e, 0x48, 0x51, 0x28, 0x40, 0x00, 0x40, 0x40, 0x07, 0x0f, ++ 0x00, 0x02, 0x40, 0x10, 0x46, 0x02, 0x0a, 0x1b, 0x1b, 0x07, 0x07, 0x07, 0x25, 0x0f, 0x10, 0x07, ++ 0x4e, 0x27, 0x11, 0x0f, 0x40, 0x40, 0x06, 0x40, 0x40, 0x40, 0x00, 0x00, 0x47, 0x46, 0x00, 0x46, ++ 0x46, 0x01, 0x47, 0x4e, 0x4e, 0x02, 0x47, 0x4f, 0x4e, 0x4e, 0x02, 0x09, 0x08, 0x09, 0x47, 0x46, ++ 0x00, 0x46, 0x46, 0x01, 0x47, 0x4e, 0x4e, 0x02, 0x47, 0x4f, 0x4e, 0x4e, 0x02, 0x09, 0x08, 0x09, ++ 0x18, 0x47, 0x1a, 0x40, 0x48, 0x40, 0x00, 0x07, 0x00, 0x08, 0x08, 0x0a, 0x00, 0x17, 0x07, 0x47, ++ 0x18, 0x07, 0x40, 0x17, 0x07, 0x47, 0x18, 0x07, 0x40, 0x17, 0x07, 0x47, 0x18, 0x07, 0x40, 0x48, ++ 0x07, 0x08, 0x08, 0x10, 0x18, 0x10, 0x18, 0x0f, 0x17, 0x07, 0x47, 0x17, 0x07, 0x47, 0x40, 0x40, ++ 0x40, 0x16, 0x0f, 0x0f, 0x40, 0x0f, 0x0f, 0x0f, 0x0f, 0x28, 0x27, 0x18, 0x07, 0x18, 0x18, 0x10, ++ 0x40, 0x2e, 0x17, 0x0f, 0x40, 0x0f, 0x0f, 0x0f, 0x11, 0x0f, 0x19, 0x11, 0x11, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x12, 0x00, 0x4e, 0x40, 0x0d, 0x49, 0x52, 0x28, 0x40, 0x00, 0x40, 0x40, 0x06, 0x0f, ++ 0x00, 0x03, 0x40, 0x10, 0x45, 0x03, 0x0c, 0x1d, 0x1d, 0x07, 0x07, 0x07, 0x24, 0x0f, 0x11, 0x07, ++ 0x4d, 0x27, 0x12, 0x0f, 0x40, 0x40, 0x05, 0x40, 0x40, 0x40, 0x00, 0x00, 0x46, 0x45, 0x01, 0x45, ++ 0x45, 0x02, 0x46, 0x4d, 0x4d, 0x03, 0x46, 0x4e, 0x4d, 0x4d, 0x03, 0x0a, 0x09, 0x0a, 0x46, 0x45, ++ 0x01, 0x45, 0x45, 0x02, 0x46, 0x4d, 0x4d, 0x03, 0x46, 0x4e, 0x4d, 0x4d, 0x03, 0x0a, 0x09, 0x0a, ++ 0x19, 0x47, 0x1c, 0x40, 0x48, 0x40, 0x00, 0x07, 0x00, 0x09, 0x09, 0x0c, 0x01, 0x17, 0x06, 0x47, ++ 0x18, 0x07, 0x40, 0x17, 0x06, 0x47, 0x18, 0x07, 0x40, 0x17, 0x06, 0x47, 0x18, 0x07, 0x40, 0x48, ++ 0x07, 0x08, 0x08, 0x11, 0x19, 0x11, 0x19, 0x0f, 0x17, 0x06, 0x47, 0x17, 0x06, 0x47, 0x40, 0x40, ++ 0x40, 0x15, 0x0f, 0x0f, 0x40, 0x0f, 0x0f, 0x0e, 0x0e, 0x28, 0x27, 0x18, 0x07, 0x19, 0x18, 0x11, ++ 0x40, 0x2c, 0x17, 0x0f, 0x40, 0x0f, 0x0f, 0x0e, 0x12, 0x0f, 0x1a, 0x12, 0x12, 0x0f, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x13, 0x01, 0x4d, 0x40, 0x0c, 0x4a, 0x53, 0x29, 0x40, 0x01, 0x40, 0x40, 0x05, 0x0f, ++ 0x01, 0x05, 0x40, 0x11, 0x43, 0x05, 0x0e, 0x20, 0x20, 0x07, 0x07, 0x06, 0x22, 0x0e, 0x12, 0x07, ++ 0x4c, 0x27, 0x14, 0x0e, 0x40, 0x41, 0x04, 0x40, 0x40, 0x40, 0x01, 0x01, 0x45, 0x44, 0x02, 0x44, ++ 0x43, 0x04, 0x45, 0x4c, 0x4c, 0x05, 0x45, 0x4d, 0x4c, 0x4c, 0x05, 0x0b, 0x0a, 0x0c, 0x45, 0x44, ++ 0x02, 0x44, 0x43, 0x04, 0x45, 0x4c, 0x4c, 0x05, 0x45, 0x4d, 0x4c, 0x4c, 0x05, 0x0b, 0x0a, 0x0c, ++ 0x1a, 0x46, 0x1e, 0x40, 0x49, 0x40, 0x01, 0x07, 0x01, 0x0a, 0x0a, 0x0e, 0x02, 0x16, 0x05, 0x46, ++ 0x19, 0x07, 0x40, 0x16, 0x05, 0x46, 0x19, 0x07, 0x40, 0x16, 0x05, 0x46, 0x19, 0x07, 0x40, 0x49, ++ 0x07, 0x09, 0x09, 0x12, 0x1a, 0x12, 0x1a, 0x0e, 0x17, 0x05, 0x46, 0x17, 0x05, 0x46, 0x40, 0x40, ++ 0x40, 0x14, 0x0e, 0x0e, 0x40, 0x0f, 0x0e, 0x0d, 0x0d, 0x29, 0x27, 0x19, 0x07, 0x1a, 0x19, 0x12, ++ 0x41, 0x2b, 0x16, 0x0e, 0x40, 0x0f, 0x0e, 0x0d, 0x13, 0x0e, 0x1c, 0x13, 0x13, 0x0e, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x14, 0x01, 0x4d, 0x40, 0x0b, 0x4a, 0x54, 0x29, 0x40, 0x01, 0x40, 0x40, 0x05, 0x0f, ++ 0x01, 0x06, 0x40, 0x11, 0x42, 0x06, 0x10, 0x22, 0x22, 0x07, 0x07, 0x06, 0x21, 0x0e, 0x12, 0x07, ++ 0x4b, 0x27, 0x15, 0x0e, 0x40, 0x41, 0x03, 0x40, 0x40, 0x40, 0x01, 0x01, 0x45, 0x43, 0x02, 0x43, ++ 0x42, 0x05, 0x45, 0x4b, 0x4b, 0x06, 0x45, 0x4d, 0x4b, 0x4b, 0x06, 0x0c, 0x0a, 0x0d, 0x45, 0x43, ++ 0x02, 0x43, 0x42, 0x05, 0x45, 0x4b, 0x4b, 0x06, 0x45, 0x4d, 0x4b, 0x4b, 0x06, 0x0c, 0x0a, 0x0d, ++ 0x1a, 0x46, 0x20, 0x40, 0x49, 0x40, 0x01, 0x07, 0x01, 0x0a, 0x0a, 0x10, 0x02, 0x16, 0x05, 0x46, ++ 0x19, 0x07, 0x40, 0x16, 0x05, 0x46, 0x19, 0x07, 0x40, 0x16, 0x05, 0x46, 0x19, 0x07, 0x40, 0x49, ++ 0x07, 0x09, 0x09, 0x12, 0x1a, 0x12, 0x1a, 0x0e, 0x17, 0x05, 0x46, 0x17, 0x05, 0x46, 0x40, 0x40, ++ 0x40, 0x13, 0x0e, 0x0e, 0x40, 0x0f, 0x0e, 0x0d, 0x0d, 0x29, 0x27, 0x19, 0x07, 0x1a, 0x19, 0x12, ++ 0x41, 0x2a, 0x16, 0x0e, 0x40, 0x0f, 0x0e, 0x0d, 0x14, 0x0e, 0x1d, 0x14, 0x14, 0x0e, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x15, 0x01, 0x4c, 0x40, 0x0a, 0x4b, 0x55, 0x29, 0x40, 0x01, 0x40, 0x40, 0x04, 0x0f, ++ 0x01, 0x08, 0x40, 0x11, 0x41, 0x08, 0x12, 0x25, 0x25, 0x07, 0x07, 0x06, 0x1f, 0x0e, 0x13, 0x07, ++ 0x4a, 0x27, 0x16, 0x0e, 0x40, 0x41, 0x02, 0x40, 0x40, 0x40, 0x01, 0x01, 0x44, 0x42, 0x03, 0x42, ++ 0x41, 0x06, 0x44, 0x4a, 0x4a, 0x08, 0x44, 0x4c, 0x4a, 0x4a, 0x08, 0x0d, 0x0b, 0x0e, 0x44, 0x42, ++ 0x03, 0x42, 0x41, 0x06, 0x44, 0x4a, 0x4a, 0x08, 0x44, 0x4c, 0x4a, 0x4a, 0x08, 0x0d, 0x0b, 0x0e, ++ 0x1b, 0x46, 0x22, 0x40, 0x49, 0x40, 0x01, 0x07, 0x01, 0x0b, 0x0b, 0x12, 0x03, 0x16, 0x04, 0x46, ++ 0x19, 0x07, 0x40, 0x16, 0x04, 0x46, 0x19, 0x07, 0x40, 0x16, 0x04, 0x46, 0x19, 0x07, 0x40, 0x49, ++ 0x07, 0x09, 0x09, 0x13, 0x1b, 0x13, 0x1b, 0x0e, 0x17, 0x04, 0x46, 0x17, 0x04, 0x46, 0x40, 0x40, ++ 0x40, 0x12, 0x0e, 0x0e, 0x40, 0x0f, 0x0e, 0x0c, 0x0c, 0x29, 0x27, 0x19, 0x07, 0x1b, 0x19, 0x13, ++ 0x41, 0x29, 0x16, 0x0e, 0x40, 0x0f, 0x0e, 0x0c, 0x15, 0x0e, 0x1e, 0x15, 0x15, 0x0e, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x15, 0x01, 0x4c, 0x40, 0x09, 0x4c, 0x56, 0x29, 0x40, 0x01, 0x40, 0x40, 0x03, 0x0f, ++ 0x01, 0x09, 0x40, 0x11, 0x40, 0x09, 0x13, 0x27, 0x27, 0x07, 0x07, 0x05, 0x1d, 0x0d, 0x13, 0x07, ++ 0x4a, 0x27, 0x17, 0x0d, 0x40, 0x42, 0x01, 0x40, 0x40, 0x40, 0x01, 0x01, 0x44, 0x42, 0x03, 0x42, ++ 0x40, 0x07, 0x44, 0x4a, 0x4a, 0x09, 0x44, 0x4c, 0x4a, 0x4a, 0x09, 0x0d, 0x0b, 0x0f, 0x44, 0x42, ++ 0x03, 0x42, 0x40, 0x07, 0x44, 0x4a, 0x4a, 0x09, 0x44, 0x4c, 0x4a, 0x4a, 0x09, 0x0d, 0x0b, 0x0f, ++ 0x1b, 0x46, 0x23, 0x40, 0x4a, 0x40, 0x01, 0x07, 0x01, 0x0b, 0x0b, 0x13, 0x03, 0x15, 0x03, 0x46, ++ 0x19, 0x07, 0x40, 0x15, 0x03, 0x46, 0x19, 0x07, 0x40, 0x15, 0x03, 0x46, 0x19, 0x07, 0x40, 0x4a, ++ 0x07, 0x09, 0x09, 0x13, 0x1b, 0x13, 0x1b, 0x0d, 0x17, 0x03, 0x46, 0x17, 0x03, 0x46, 0x40, 0x40, ++ 0x40, 0x11, 0x0d, 0x0d, 0x40, 0x0f, 0x0d, 0x0b, 0x0b, 0x29, 0x27, 0x19, 0x07, 0x1b, 0x19, 0x13, ++ 0x42, 0x27, 0x15, 0x0d, 0x40, 0x0f, 0x0d, 0x0b, 0x15, 0x0d, 0x1f, 0x15, 0x15, 0x0d, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x16, 0x02, 0x4b, 0x40, 0x09, 0x4c, 0x56, 0x2a, 0x40, 0x02, 0x40, 0x40, 0x03, 0x0f, ++ 0x02, 0x0b, 0x40, 0x12, 0x01, 0x0b, 0x15, 0x2a, 0x2a, 0x07, 0x07, 0x05, 0x1c, 0x0d, 0x14, 0x07, ++ 0x49, 0x27, 0x19, 0x0d, 0x40, 0x42, 0x01, 0x40, 0x40, 0x40, 0x02, 0x02, 0x43, 0x41, 0x04, 0x41, ++ 0x01, 0x09, 0x43, 0x49, 0x49, 0x0b, 0x43, 0x4b, 0x49, 0x49, 0x0b, 0x0e, 0x0c, 0x11, 0x43, 0x41, ++ 0x04, 0x41, 0x01, 0x09, 0x43, 0x49, 0x49, 0x0b, 0x43, 0x4b, 0x49, 0x49, 0x0b, 0x0e, 0x0c, 0x11, ++ 0x1c, 0x45, 0x25, 0x40, 0x4a, 0x40, 0x02, 0x07, 0x02, 0x0c, 0x0c, 0x15, 0x04, 0x15, 0x03, 0x45, ++ 0x1a, 0x07, 0x40, 0x15, 0x03, 0x45, 0x1a, 0x07, 0x40, 0x15, 0x03, 0x45, 0x1a, 0x07, 0x40, 0x4a, ++ 0x07, 0x0a, 0x0a, 0x14, 0x1c, 0x14, 0x1c, 0x0d, 0x17, 0x03, 0x45, 0x17, 0x03, 0x45, 0x40, 0x40, ++ 0x40, 0x11, 0x0d, 0x0d, 0x40, 0x0f, 0x0d, 0x0b, 0x0b, 0x2a, 0x27, 0x1a, 0x07, 0x1c, 0x1a, 0x14, ++ 0x42, 0x26, 0x15, 0x0d, 0x40, 0x0f, 0x0d, 0x0b, 0x16, 0x0d, 0x21, 0x16, 0x16, 0x0d, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x17, 0x02, 0x4a, 0x40, 0x08, 0x4d, 0x57, 0x2a, 0x40, 0x02, 0x40, 0x40, 0x02, 0x0f, ++ 0x02, 0x0d, 0x40, 0x12, 0x02, 0x0d, 0x17, 0x2c, 0x2c, 0x07, 0x07, 0x05, 0x1a, 0x0d, 0x15, 0x07, ++ 0x48, 0x27, 0x1a, 0x0d, 0x40, 0x42, 0x00, 0x40, 0x40, 0x40, 0x02, 0x02, 0x42, 0x40, 0x05, 0x40, ++ 0x02, 0x0a, 0x42, 0x48, 0x48, 0x0d, 0x42, 0x4a, 0x48, 0x48, 0x0d, 0x0f, 0x0d, 0x12, 0x42, 0x40, ++ 0x05, 0x40, 0x02, 0x0a, 0x42, 0x48, 0x48, 0x0d, 0x42, 0x4a, 0x48, 0x48, 0x0d, 0x0f, 0x0d, 0x12, ++ 0x1d, 0x45, 0x27, 0x40, 0x4a, 0x40, 0x02, 0x07, 0x02, 0x0d, 0x0d, 0x17, 0x05, 0x15, 0x02, 0x45, ++ 0x1a, 0x07, 0x40, 0x15, 0x02, 0x45, 0x1a, 0x07, 0x40, 0x15, 0x02, 0x45, 0x1a, 0x07, 0x40, 0x4a, ++ 0x07, 0x0a, 0x0a, 0x15, 0x1d, 0x15, 0x1d, 0x0d, 0x17, 0x02, 0x45, 0x17, 0x02, 0x45, 0x40, 0x40, ++ 0x40, 0x10, 0x0d, 0x0d, 0x40, 0x0f, 0x0d, 0x0a, 0x0a, 0x2a, 0x27, 0x1a, 0x07, 0x1d, 0x1a, 0x15, ++ 0x42, 0x25, 0x15, 0x0d, 0x40, 0x0f, 0x0d, 0x0a, 0x17, 0x0d, 0x22, 0x17, 0x17, 0x0d, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x18, 0x02, 0x4a, 0x40, 0x07, 0x4d, 0x58, 0x2a, 0x40, 0x02, 0x40, 0x40, 0x02, 0x0f, ++ 0x02, 0x0e, 0x40, 0x12, 0x03, 0x0e, 0x19, 0x2f, 0x2f, 0x07, 0x07, 0x05, 0x19, 0x0d, 0x15, 0x07, ++ 0x47, 0x27, 0x1b, 0x0d, 0x40, 0x42, 0x40, 0x40, 0x40, 0x40, 0x02, 0x02, 0x42, 0x00, 0x05, 0x00, ++ 0x03, 0x0b, 0x42, 0x47, 0x47, 0x0e, 0x42, 0x4a, 0x47, 0x47, 0x0e, 0x10, 0x0d, 0x13, 0x42, 0x00, ++ 0x05, 0x00, 0x03, 0x0b, 0x42, 0x47, 0x47, 0x0e, 0x42, 0x4a, 0x47, 0x47, 0x0e, 0x10, 0x0d, 0x13, ++ 0x1d, 0x45, 0x29, 0x40, 0x4a, 0x40, 0x02, 0x07, 0x02, 0x0d, 0x0d, 0x19, 0x05, 0x15, 0x02, 0x45, ++ 0x1a, 0x07, 0x40, 0x15, 0x02, 0x45, 0x1a, 0x07, 0x40, 0x15, 0x02, 0x45, 0x1a, 0x07, 0x40, 0x4a, ++ 0x07, 0x0a, 0x0a, 0x15, 0x1d, 0x15, 0x1d, 0x0d, 0x17, 0x02, 0x45, 0x17, 0x02, 0x45, 0x40, 0x40, ++ 0x40, 0x0f, 0x0d, 0x0d, 0x40, 0x0f, 0x0d, 0x0a, 0x0a, 0x2a, 0x27, 0x1a, 0x07, 0x1d, 0x1a, 0x15, ++ 0x42, 0x24, 0x15, 0x0d, 0x40, 0x0f, 0x0d, 0x0a, 0x18, 0x0d, 0x23, 0x18, 0x18, 0x0d, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x19, 0x03, 0x49, 0x40, 0x06, 0x4e, 0x59, 0x2b, 0x40, 0x03, 0x40, 0x40, 0x01, 0x0f, ++ 0x03, 0x10, 0x40, 0x13, 0x04, 0x10, 0x1b, 0x31, 0x31, 0x07, 0x07, 0x04, 0x17, 0x0c, 0x16, 0x07, ++ 0x46, 0x27, 0x1c, 0x0c, 0x40, 0x43, 0x41, 0x40, 0x40, 0x40, 0x03, 0x03, 0x41, 0x01, 0x06, 0x01, ++ 0x04, 0x0c, 0x41, 0x46, 0x46, 0x10, 0x41, 0x49, 0x46, 0x46, 0x10, 0x11, 0x0e, 0x14, 0x41, 0x01, ++ 0x06, 0x01, 0x04, 0x0c, 0x41, 0x46, 0x46, 0x10, 0x41, 0x49, 0x46, 0x46, 0x10, 0x11, 0x0e, 0x14, ++ 0x1e, 0x44, 0x2b, 0x40, 0x4b, 0x40, 0x03, 0x07, 0x03, 0x0e, 0x0e, 0x1b, 0x06, 0x14, 0x01, 0x44, ++ 0x1b, 0x07, 0x40, 0x14, 0x01, 0x44, 0x1b, 0x07, 0x40, 0x14, 0x01, 0x44, 0x1b, 0x07, 0x40, 0x4b, ++ 0x07, 0x0b, 0x0b, 0x16, 0x1e, 0x16, 0x1e, 0x0c, 0x17, 0x01, 0x44, 0x17, 0x01, 0x44, 0x40, 0x40, ++ 0x40, 0x0e, 0x0c, 0x0c, 0x40, 0x0f, 0x0c, 0x09, 0x09, 0x2b, 0x27, 0x1b, 0x07, 0x1e, 0x1b, 0x16, ++ 0x43, 0x22, 0x14, 0x0c, 0x40, 0x0f, 0x0c, 0x09, 0x19, 0x0c, 0x24, 0x19, 0x19, 0x0c, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x1a, 0x03, 0x48, 0x40, 0x05, 0x4f, 0x5a, 0x2b, 0x40, 0x03, 0x40, 0x40, 0x00, 0x0f, ++ 0x03, 0x11, 0x40, 0x13, 0x06, 0x11, 0x1d, 0x34, 0x34, 0x07, 0x07, 0x04, 0x16, 0x0c, 0x17, 0x07, ++ 0x45, 0x27, 0x1e, 0x0c, 0x40, 0x43, 0x42, 0x40, 0x40, 0x40, 0x03, 0x03, 0x40, 0x02, 0x07, 0x02, ++ 0x06, 0x0e, 0x40, 0x45, 0x45, 0x11, 0x40, 0x48, 0x45, 0x45, 0x11, 0x12, 0x0f, 0x16, 0x40, 0x02, ++ 0x07, 0x02, 0x06, 0x0e, 0x40, 0x45, 0x45, 0x11, 0x40, 0x48, 0x45, 0x45, 0x11, 0x12, 0x0f, 0x16, ++ 0x1f, 0x44, 0x2d, 0x40, 0x4b, 0x40, 0x03, 0x07, 0x03, 0x0f, 0x0f, 0x1d, 0x07, 0x14, 0x00, 0x44, ++ 0x1b, 0x07, 0x40, 0x14, 0x00, 0x44, 0x1b, 0x07, 0x40, 0x14, 0x00, 0x44, 0x1b, 0x07, 0x40, 0x4b, ++ 0x07, 0x0b, 0x0b, 0x17, 0x1f, 0x17, 0x1f, 0x0c, 0x17, 0x00, 0x44, 0x17, 0x00, 0x44, 0x40, 0x40, ++ 0x40, 0x0d, 0x0c, 0x0c, 0x40, 0x0f, 0x0c, 0x08, 0x08, 0x2b, 0x27, 0x1b, 0x07, 0x1f, 0x1b, 0x17, ++ 0x43, 0x21, 0x14, 0x0c, 0x40, 0x0f, 0x0c, 0x08, 0x1a, 0x0c, 0x26, 0x1a, 0x1a, 0x0c, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x1b, 0x03, 0x48, 0x40, 0x04, 0x4f, 0x5b, 0x2b, 0x40, 0x03, 0x40, 0x40, 0x00, 0x0f, ++ 0x03, 0x13, 0x40, 0x13, 0x07, 0x13, 0x1f, 0x36, 0x36, 0x07, 0x07, 0x04, 0x14, 0x0c, 0x17, 0x07, ++ 0x44, 0x27, 0x1f, 0x0c, 0x40, 0x43, 0x43, 0x40, 0x40, 0x40, 0x03, 0x03, 0x40, 0x03, 0x07, 0x03, ++ 0x07, 0x0f, 0x40, 0x44, 0x44, 0x13, 0x40, 0x48, 0x44, 0x44, 0x13, 0x13, 0x0f, 0x17, 0x40, 0x03, ++ 0x07, 0x03, 0x07, 0x0f, 0x40, 0x44, 0x44, 0x13, 0x40, 0x48, 0x44, 0x44, 0x13, 0x13, 0x0f, 0x17, ++ 0x1f, 0x44, 0x2f, 0x40, 0x4b, 0x40, 0x03, 0x07, 0x03, 0x0f, 0x0f, 0x1f, 0x07, 0x14, 0x00, 0x44, ++ 0x1b, 0x07, 0x40, 0x14, 0x00, 0x44, 0x1b, 0x07, 0x40, 0x14, 0x00, 0x44, 0x1b, 0x07, 0x40, 0x4b, ++ 0x07, 0x0b, 0x0b, 0x17, 0x1f, 0x17, 0x1f, 0x0c, 0x17, 0x00, 0x44, 0x17, 0x00, 0x44, 0x40, 0x40, ++ 0x40, 0x0c, 0x0c, 0x0c, 0x40, 0x0f, 0x0c, 0x08, 0x08, 0x2b, 0x27, 0x1b, 0x07, 0x1f, 0x1b, 0x17, ++ 0x43, 0x20, 0x14, 0x0c, 0x40, 0x0f, 0x0c, 0x08, 0x1b, 0x0c, 0x27, 0x1b, 0x1b, 0x0c, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x1c, 0x04, 0x47, 0x40, 0x03, 0x50, 0x5c, 0x2c, 0x40, 0x04, 0x40, 0x40, 0x40, 0x0f, ++ 0x04, 0x14, 0x40, 0x14, 0x08, 0x14, 0x21, 0x39, 0x39, 0x07, 0x07, 0x03, 0x13, 0x0b, 0x18, 0x07, ++ 0x43, 0x27, 0x20, 0x0b, 0x40, 0x44, 0x44, 0x40, 0x40, 0x40, 0x04, 0x04, 0x00, 0x04, 0x08, 0x04, ++ 0x08, 0x10, 0x00, 0x43, 0x43, 0x14, 0x00, 0x47, 0x43, 0x43, 0x14, 0x14, 0x10, 0x18, 0x00, 0x04, ++ 0x08, 0x04, 0x08, 0x10, 0x00, 0x43, 0x43, 0x14, 0x00, 0x47, 0x43, 0x43, 0x14, 0x14, 0x10, 0x18, ++ 0x20, 0x43, 0x31, 0x40, 0x4c, 0x40, 0x04, 0x07, 0x04, 0x10, 0x10, 0x21, 0x08, 0x13, 0x40, 0x43, ++ 0x1c, 0x07, 0x40, 0x13, 0x40, 0x43, 0x1c, 0x07, 0x40, 0x13, 0x40, 0x43, 0x1c, 0x07, 0x40, 0x4c, ++ 0x07, 0x0c, 0x0c, 0x18, 0x20, 0x18, 0x20, 0x0b, 0x17, 0x40, 0x43, 0x17, 0x40, 0x43, 0x40, 0x40, ++ 0x40, 0x0b, 0x0b, 0x0b, 0x40, 0x0f, 0x0b, 0x07, 0x07, 0x2c, 0x27, 0x1c, 0x07, 0x20, 0x1c, 0x18, ++ 0x44, 0x1f, 0x13, 0x0b, 0x40, 0x0f, 0x0b, 0x07, 0x1c, 0x0b, 0x28, 0x1c, 0x1c, 0x0b, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x1d, 0x04, 0x47, 0x40, 0x02, 0x51, 0x5d, 0x2c, 0x40, 0x04, 0x40, 0x40, 0x41, 0x0f, ++ 0x04, 0x16, 0x40, 0x14, 0x09, 0x16, 0x22, 0x3b, 0x3b, 0x07, 0x07, 0x03, 0x11, 0x0b, 0x18, 0x07, ++ 0x42, 0x27, 0x21, 0x0b, 0x40, 0x44, 0x45, 0x40, 0x40, 0x40, 0x04, 0x04, 0x00, 0x05, 0x08, 0x05, ++ 0x09, 0x11, 0x00, 0x42, 0x42, 0x16, 0x00, 0x47, 0x42, 0x42, 0x16, 0x15, 0x10, 0x19, 0x00, 0x05, ++ 0x08, 0x05, 0x09, 0x11, 0x00, 0x42, 0x42, 0x16, 0x00, 0x47, 0x42, 0x42, 0x16, 0x15, 0x10, 0x19, ++ 0x20, 0x43, 0x32, 0x40, 0x4c, 0x40, 0x04, 0x07, 0x04, 0x10, 0x10, 0x22, 0x08, 0x13, 0x41, 0x43, ++ 0x1c, 0x07, 0x40, 0x13, 0x41, 0x43, 0x1c, 0x07, 0x40, 0x13, 0x41, 0x43, 0x1c, 0x07, 0x40, 0x4c, ++ 0x07, 0x0c, 0x0c, 0x18, 0x20, 0x18, 0x20, 0x0b, 0x17, 0x41, 0x43, 0x17, 0x41, 0x43, 0x40, 0x40, ++ 0x40, 0x0a, 0x0b, 0x0b, 0x40, 0x0f, 0x0b, 0x06, 0x06, 0x2c, 0x27, 0x1c, 0x07, 0x20, 0x1c, 0x18, ++ 0x44, 0x1d, 0x13, 0x0b, 0x40, 0x0f, 0x0b, 0x06, 0x1d, 0x0b, 0x29, 0x1d, 0x1d, 0x0b, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x1e, 0x04, 0x46, 0x40, 0x01, 0x51, 0x5e, 0x2c, 0x40, 0x04, 0x40, 0x40, 0x41, 0x0f, ++ 0x04, 0x18, 0x40, 0x14, 0x0b, 0x18, 0x24, 0x3e, 0x3e, 0x07, 0x07, 0x03, 0x0f, 0x0b, 0x19, 0x07, ++ 0x41, 0x27, 0x23, 0x0b, 0x40, 0x44, 0x46, 0x40, 0x40, 0x40, 0x04, 0x04, 0x01, 0x06, 0x09, 0x06, ++ 0x0b, 0x13, 0x01, 0x41, 0x41, 0x18, 0x01, 0x46, 0x41, 0x41, 0x18, 0x16, 0x11, 0x1b, 0x01, 0x06, ++ 0x09, 0x06, 0x0b, 0x13, 0x01, 0x41, 0x41, 0x18, 0x01, 0x46, 0x41, 0x41, 0x18, 0x16, 0x11, 0x1b, ++ 0x21, 0x43, 0x34, 0x40, 0x4c, 0x40, 0x04, 0x07, 0x04, 0x11, 0x11, 0x24, 0x09, 0x13, 0x41, 0x43, ++ 0x1c, 0x07, 0x40, 0x13, 0x41, 0x43, 0x1c, 0x07, 0x40, 0x13, 0x41, 0x43, 0x1c, 0x07, 0x40, 0x4c, ++ 0x07, 0x0c, 0x0c, 0x19, 0x21, 0x19, 0x21, 0x0b, 0x17, 0x41, 0x43, 0x17, 0x41, 0x43, 0x40, 0x40, ++ 0x40, 0x09, 0x0b, 0x0b, 0x40, 0x0f, 0x0b, 0x06, 0x06, 0x2c, 0x27, 0x1c, 0x07, 0x21, 0x1c, 0x19, ++ 0x44, 0x1c, 0x13, 0x0b, 0x40, 0x0f, 0x0b, 0x06, 0x1e, 0x0b, 0x2b, 0x1e, 0x1e, 0x0b, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x1f, 0x05, 0x45, 0x40, 0x00, 0x52, 0x5f, 0x2d, 0x40, 0x05, 0x40, 0x40, 0x42, 0x0f, ++ 0x05, 0x19, 0x40, 0x15, 0x0c, 0x19, 0x26, 0x3e, 0x3e, 0x07, 0x07, 0x02, 0x0e, 0x0a, 0x1a, 0x07, ++ 0x40, 0x27, 0x24, 0x0a, 0x40, 0x45, 0x47, 0x40, 0x40, 0x40, 0x05, 0x05, 0x02, 0x07, 0x0a, 0x07, ++ 0x0c, 0x14, 0x02, 0x40, 0x40, 0x19, 0x02, 0x45, 0x40, 0x40, 0x19, 0x17, 0x12, 0x1c, 0x02, 0x07, ++ 0x0a, 0x07, 0x0c, 0x14, 0x02, 0x40, 0x40, 0x19, 0x02, 0x45, 0x40, 0x40, 0x19, 0x17, 0x12, 0x1c, ++ 0x22, 0x42, 0x36, 0x40, 0x4d, 0x40, 0x05, 0x07, 0x05, 0x12, 0x12, 0x26, 0x0a, 0x12, 0x42, 0x42, ++ 0x1d, 0x07, 0x40, 0x12, 0x42, 0x42, 0x1d, 0x07, 0x40, 0x12, 0x42, 0x42, 0x1d, 0x07, 0x40, 0x4d, ++ 0x07, 0x0d, 0x0d, 0x1a, 0x22, 0x1a, 0x22, 0x0a, 0x17, 0x42, 0x42, 0x17, 0x42, 0x42, 0x40, 0x40, ++ 0x40, 0x08, 0x0a, 0x0a, 0x40, 0x0f, 0x0a, 0x05, 0x05, 0x2d, 0x27, 0x1d, 0x07, 0x22, 0x1d, 0x1a, ++ 0x45, 0x1b, 0x12, 0x0a, 0x40, 0x0f, 0x0a, 0x05, 0x1f, 0x0a, 0x2c, 0x1f, 0x1f, 0x0a, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x20, 0x05, 0x45, 0x40, 0x40, 0x52, 0x60, 0x2d, 0x40, 0x05, 0x40, 0x40, 0x42, 0x0f, ++ 0x05, 0x1b, 0x40, 0x15, 0x0d, 0x1b, 0x28, 0x3e, 0x3e, 0x07, 0x07, 0x02, 0x0c, 0x0a, 0x1a, 0x07, ++ 0x00, 0x27, 0x25, 0x0a, 0x40, 0x45, 0x48, 0x40, 0x40, 0x40, 0x05, 0x05, 0x02, 0x08, 0x0a, 0x08, ++ 0x0d, 0x15, 0x02, 0x00, 0x00, 0x1b, 0x02, 0x45, 0x00, 0x00, 0x1b, 0x18, 0x12, 0x1d, 0x02, 0x08, ++ 0x0a, 0x08, 0x0d, 0x15, 0x02, 0x00, 0x00, 0x1b, 0x02, 0x45, 0x00, 0x00, 0x1b, 0x18, 0x12, 0x1d, ++ 0x22, 0x42, 0x38, 0x40, 0x4d, 0x40, 0x05, 0x07, 0x05, 0x12, 0x12, 0x28, 0x0a, 0x12, 0x42, 0x42, ++ 0x1d, 0x07, 0x40, 0x12, 0x42, 0x42, 0x1d, 0x07, 0x40, 0x12, 0x42, 0x42, 0x1d, 0x07, 0x40, 0x4d, ++ 0x07, 0x0d, 0x0d, 0x1a, 0x22, 0x1a, 0x22, 0x0a, 0x17, 0x42, 0x42, 0x17, 0x42, 0x42, 0x40, 0x40, ++ 0x40, 0x07, 0x0a, 0x0a, 0x40, 0x0f, 0x0a, 0x05, 0x05, 0x2d, 0x27, 0x1d, 0x07, 0x22, 0x1d, 0x1a, ++ 0x45, 0x1a, 0x12, 0x0a, 0x40, 0x0f, 0x0a, 0x05, 0x20, 0x0a, 0x2d, 0x20, 0x20, 0x0a, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x21, 0x05, 0x44, 0x40, 0x41, 0x53, 0x61, 0x2d, 0x40, 0x05, 0x40, 0x40, 0x43, 0x0f, ++ 0x05, 0x1c, 0x40, 0x15, 0x0e, 0x1c, 0x2a, 0x3e, 0x3e, 0x07, 0x07, 0x02, 0x0b, 0x0a, 0x1b, 0x07, ++ 0x01, 0x27, 0x26, 0x0a, 0x40, 0x45, 0x49, 0x40, 0x40, 0x40, 0x05, 0x05, 0x03, 0x09, 0x0b, 0x09, ++ 0x0e, 0x16, 0x03, 0x01, 0x01, 0x1c, 0x03, 0x44, 0x01, 0x01, 0x1c, 0x19, 0x13, 0x1e, 0x03, 0x09, ++ 0x0b, 0x09, 0x0e, 0x16, 0x03, 0x01, 0x01, 0x1c, 0x03, 0x44, 0x01, 0x01, 0x1c, 0x19, 0x13, 0x1e, ++ 0x23, 0x42, 0x3a, 0x40, 0x4d, 0x40, 0x05, 0x07, 0x05, 0x13, 0x13, 0x2a, 0x0b, 0x12, 0x43, 0x42, ++ 0x1d, 0x07, 0x40, 0x12, 0x43, 0x42, 0x1d, 0x07, 0x40, 0x12, 0x43, 0x42, 0x1d, 0x07, 0x40, 0x4d, ++ 0x07, 0x0d, 0x0d, 0x1b, 0x23, 0x1b, 0x23, 0x0a, 0x17, 0x43, 0x42, 0x17, 0x43, 0x42, 0x40, 0x40, ++ 0x40, 0x06, 0x0a, 0x0a, 0x40, 0x0f, 0x0a, 0x04, 0x04, 0x2d, 0x27, 0x1d, 0x07, 0x23, 0x1d, 0x1b, ++ 0x45, 0x18, 0x12, 0x0a, 0x40, 0x0f, 0x0a, 0x04, 0x21, 0x0a, 0x2e, 0x21, 0x21, 0x0a, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x22, 0x06, 0x43, 0x40, 0x42, 0x54, 0x62, 0x2e, 0x40, 0x06, 0x40, 0x40, 0x44, 0x0f, ++ 0x06, 0x1e, 0x40, 0x16, 0x10, 0x1e, 0x2c, 0x3e, 0x3e, 0x07, 0x07, 0x01, 0x09, 0x09, 0x1c, 0x07, ++ 0x02, 0x27, 0x28, 0x09, 0x40, 0x46, 0x4a, 0x40, 0x40, 0x40, 0x06, 0x06, 0x04, 0x0a, 0x0c, 0x0a, ++ 0x10, 0x18, 0x04, 0x02, 0x02, 0x1e, 0x04, 0x43, 0x02, 0x02, 0x1e, 0x1a, 0x14, 0x20, 0x04, 0x0a, ++ 0x0c, 0x0a, 0x10, 0x18, 0x04, 0x02, 0x02, 0x1e, 0x04, 0x43, 0x02, 0x02, 0x1e, 0x1a, 0x14, 0x20, ++ 0x24, 0x41, 0x3c, 0x40, 0x4e, 0x40, 0x06, 0x07, 0x06, 0x14, 0x14, 0x2c, 0x0c, 0x11, 0x44, 0x41, ++ 0x1e, 0x07, 0x40, 0x11, 0x44, 0x41, 0x1e, 0x07, 0x40, 0x11, 0x44, 0x41, 0x1e, 0x07, 0x40, 0x4e, ++ 0x07, 0x0e, 0x0e, 0x1c, 0x24, 0x1c, 0x24, 0x09, 0x17, 0x44, 0x41, 0x17, 0x44, 0x41, 0x40, 0x40, ++ 0x40, 0x05, 0x09, 0x09, 0x40, 0x0f, 0x09, 0x03, 0x03, 0x2e, 0x27, 0x1e, 0x07, 0x24, 0x1e, 0x1c, ++ 0x46, 0x17, 0x11, 0x09, 0x40, 0x0f, 0x09, 0x03, 0x22, 0x09, 0x30, 0x22, 0x22, 0x09, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x23, 0x06, 0x43, 0x40, 0x43, 0x54, 0x63, 0x2e, 0x40, 0x06, 0x40, 0x40, 0x44, 0x0f, ++ 0x06, 0x1f, 0x40, 0x16, 0x11, 0x1f, 0x2e, 0x3e, 0x3e, 0x07, 0x07, 0x01, 0x08, 0x09, 0x1c, 0x07, ++ 0x03, 0x27, 0x29, 0x09, 0x40, 0x46, 0x4b, 0x40, 0x40, 0x40, 0x06, 0x06, 0x04, 0x0b, 0x0c, 0x0b, ++ 0x11, 0x19, 0x04, 0x03, 0x03, 0x1f, 0x04, 0x43, 0x03, 0x03, 0x1f, 0x1b, 0x14, 0x21, 0x04, 0x0b, ++ 0x0c, 0x0b, 0x11, 0x19, 0x04, 0x03, 0x03, 0x1f, 0x04, 0x43, 0x03, 0x03, 0x1f, 0x1b, 0x14, 0x21, ++ 0x24, 0x41, 0x3e, 0x40, 0x4e, 0x40, 0x06, 0x07, 0x06, 0x14, 0x14, 0x2e, 0x0c, 0x11, 0x44, 0x41, ++ 0x1e, 0x07, 0x40, 0x11, 0x44, 0x41, 0x1e, 0x07, 0x40, 0x11, 0x44, 0x41, 0x1e, 0x07, 0x40, 0x4e, ++ 0x07, 0x0e, 0x0e, 0x1c, 0x24, 0x1c, 0x24, 0x09, 0x17, 0x44, 0x41, 0x17, 0x44, 0x41, 0x40, 0x40, ++ 0x40, 0x04, 0x09, 0x09, 0x40, 0x0f, 0x09, 0x03, 0x03, 0x2e, 0x27, 0x1e, 0x07, 0x24, 0x1e, 0x1c, ++ 0x46, 0x16, 0x11, 0x09, 0x40, 0x0f, 0x09, 0x03, 0x23, 0x09, 0x31, 0x23, 0x23, 0x09, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x24, 0x06, 0x42, 0x40, 0x44, 0x55, 0x64, 0x2e, 0x40, 0x06, 0x40, 0x40, 0x45, 0x0f, ++ 0x06, 0x21, 0x40, 0x16, 0x12, 0x21, 0x30, 0x3e, 0x3e, 0x07, 0x07, 0x01, 0x06, 0x09, 0x1d, 0x07, ++ 0x04, 0x27, 0x2a, 0x09, 0x40, 0x46, 0x4c, 0x40, 0x40, 0x40, 0x06, 0x06, 0x05, 0x0c, 0x0d, 0x0c, ++ 0x12, 0x1a, 0x05, 0x04, 0x04, 0x21, 0x05, 0x42, 0x04, 0x04, 0x21, 0x1c, 0x15, 0x22, 0x05, 0x0c, ++ 0x0d, 0x0c, 0x12, 0x1a, 0x05, 0x04, 0x04, 0x21, 0x05, 0x42, 0x04, 0x04, 0x21, 0x1c, 0x15, 0x22, ++ 0x25, 0x41, 0x3e, 0x40, 0x4e, 0x40, 0x06, 0x07, 0x06, 0x15, 0x15, 0x30, 0x0d, 0x11, 0x45, 0x41, ++ 0x1e, 0x07, 0x40, 0x11, 0x45, 0x41, 0x1e, 0x07, 0x40, 0x11, 0x45, 0x41, 0x1e, 0x07, 0x40, 0x4e, ++ 0x07, 0x0e, 0x0e, 0x1d, 0x25, 0x1d, 0x25, 0x09, 0x17, 0x45, 0x41, 0x17, 0x45, 0x41, 0x40, 0x40, ++ 0x40, 0x03, 0x09, 0x09, 0x40, 0x0f, 0x09, 0x02, 0x02, 0x2e, 0x27, 0x1e, 0x07, 0x25, 0x1e, 0x1d, ++ 0x46, 0x15, 0x11, 0x09, 0x40, 0x0f, 0x09, 0x02, 0x24, 0x09, 0x32, 0x24, 0x24, 0x09, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x24, 0x06, 0x42, 0x40, 0x45, 0x56, 0x65, 0x2e, 0x40, 0x06, 0x40, 0x40, 0x46, 0x0f, ++ 0x06, 0x22, 0x40, 0x16, 0x13, 0x22, 0x31, 0x3e, 0x3e, 0x07, 0x07, 0x00, 0x04, 0x08, 0x1d, 0x07, ++ 0x04, 0x27, 0x2b, 0x08, 0x40, 0x47, 0x4d, 0x40, 0x40, 0x40, 0x06, 0x06, 0x05, 0x0c, 0x0d, 0x0c, ++ 0x13, 0x1b, 0x05, 0x04, 0x04, 0x22, 0x05, 0x42, 0x04, 0x04, 0x22, 0x1c, 0x15, 0x23, 0x05, 0x0c, ++ 0x0d, 0x0c, 0x13, 0x1b, 0x05, 0x04, 0x04, 0x22, 0x05, 0x42, 0x04, 0x04, 0x22, 0x1c, 0x15, 0x23, ++ 0x25, 0x41, 0x3e, 0x40, 0x4f, 0x40, 0x06, 0x07, 0x06, 0x15, 0x15, 0x31, 0x0d, 0x10, 0x46, 0x41, ++ 0x1e, 0x07, 0x40, 0x10, 0x46, 0x41, 0x1e, 0x07, 0x40, 0x10, 0x46, 0x41, 0x1e, 0x07, 0x40, 0x4f, ++ 0x07, 0x0e, 0x0e, 0x1d, 0x25, 0x1d, 0x25, 0x08, 0x17, 0x46, 0x41, 0x17, 0x46, 0x41, 0x40, 0x40, ++ 0x40, 0x02, 0x08, 0x08, 0x40, 0x0f, 0x08, 0x01, 0x01, 0x2e, 0x27, 0x1e, 0x07, 0x25, 0x1e, 0x1d, ++ 0x47, 0x13, 0x10, 0x08, 0x40, 0x0f, 0x08, 0x01, 0x24, 0x08, 0x33, 0x24, 0x24, 0x08, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x25, 0x07, 0x41, 0x40, 0x45, 0x56, 0x65, 0x2f, 0x40, 0x07, 0x40, 0x40, 0x46, 0x0f, ++ 0x07, 0x24, 0x40, 0x17, 0x15, 0x24, 0x33, 0x3e, 0x3e, 0x07, 0x07, 0x00, 0x03, 0x08, 0x1e, 0x07, ++ 0x05, 0x27, 0x2d, 0x08, 0x40, 0x47, 0x4d, 0x40, 0x40, 0x40, 0x07, 0x07, 0x06, 0x0d, 0x0e, 0x0d, ++ 0x15, 0x1d, 0x06, 0x05, 0x05, 0x24, 0x06, 0x41, 0x05, 0x05, 0x24, 0x1d, 0x16, 0x25, 0x06, 0x0d, ++ 0x0e, 0x0d, 0x15, 0x1d, 0x06, 0x05, 0x05, 0x24, 0x06, 0x41, 0x05, 0x05, 0x24, 0x1d, 0x16, 0x25, ++ 0x26, 0x40, 0x3e, 0x40, 0x4f, 0x40, 0x07, 0x07, 0x07, 0x16, 0x16, 0x33, 0x0e, 0x10, 0x46, 0x40, ++ 0x1f, 0x07, 0x40, 0x10, 0x46, 0x40, 0x1f, 0x07, 0x40, 0x10, 0x46, 0x40, 0x1f, 0x07, 0x40, 0x4f, ++ 0x07, 0x0f, 0x0f, 0x1e, 0x26, 0x1e, 0x26, 0x08, 0x17, 0x46, 0x40, 0x17, 0x46, 0x40, 0x40, 0x40, ++ 0x40, 0x02, 0x08, 0x08, 0x40, 0x0f, 0x08, 0x01, 0x01, 0x2f, 0x27, 0x1f, 0x07, 0x26, 0x1f, 0x1e, ++ 0x47, 0x12, 0x10, 0x08, 0x40, 0x0f, 0x08, 0x01, 0x25, 0x08, 0x35, 0x25, 0x25, 0x08, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x26, 0x07, 0x40, 0x40, 0x46, 0x57, 0x66, 0x2f, 0x40, 0x07, 0x40, 0x40, 0x47, 0x0f, ++ 0x07, 0x26, 0x40, 0x17, 0x16, 0x26, 0x35, 0x3e, 0x3e, 0x07, 0x07, 0x00, 0x01, 0x08, 0x1f, 0x07, ++ 0x06, 0x27, 0x2e, 0x08, 0x40, 0x47, 0x4e, 0x40, 0x40, 0x40, 0x07, 0x07, 0x07, 0x0e, 0x0f, 0x0e, ++ 0x16, 0x1e, 0x07, 0x06, 0x06, 0x26, 0x07, 0x40, 0x06, 0x06, 0x26, 0x1e, 0x17, 0x26, 0x07, 0x0e, ++ 0x0f, 0x0e, 0x16, 0x1e, 0x07, 0x06, 0x06, 0x26, 0x07, 0x40, 0x06, 0x06, 0x26, 0x1e, 0x17, 0x26, ++ 0x27, 0x40, 0x3e, 0x40, 0x4f, 0x40, 0x07, 0x07, 0x07, 0x17, 0x17, 0x35, 0x0f, 0x10, 0x47, 0x40, ++ 0x1f, 0x07, 0x40, 0x10, 0x47, 0x40, 0x1f, 0x07, 0x40, 0x10, 0x47, 0x40, 0x1f, 0x07, 0x40, 0x4f, ++ 0x07, 0x0f, 0x0f, 0x1f, 0x27, 0x1f, 0x27, 0x08, 0x17, 0x47, 0x40, 0x17, 0x47, 0x40, 0x40, 0x40, ++ 0x40, 0x01, 0x08, 0x08, 0x40, 0x0f, 0x08, 0x00, 0x00, 0x2f, 0x27, 0x1f, 0x07, 0x27, 0x1f, 0x1f, ++ 0x47, 0x11, 0x10, 0x08, 0x40, 0x0f, 0x08, 0x00, 0x26, 0x08, 0x36, 0x26, 0x26, 0x08, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x3e, 0x27, 0x07, 0x40, 0x40, 0x47, 0x57, 0x67, 0x2f, 0x40, 0x07, 0x40, 0x40, 0x47, 0x0f, ++ 0x07, 0x27, 0x40, 0x17, 0x17, 0x27, 0x37, 0x3e, 0x3e, 0x07, 0x07, 0x00, 0x00, 0x08, 0x1f, 0x07, ++ 0x07, 0x27, 0x2f, 0x08, 0x40, 0x47, 0x4f, 0x40, 0x40, 0x40, 0x07, 0x07, 0x07, 0x0f, 0x0f, 0x0f, ++ 0x17, 0x1f, 0x07, 0x07, 0x07, 0x27, 0x07, 0x40, 0x07, 0x07, 0x27, 0x1f, 0x17, 0x27, 0x07, 0x0f, ++ 0x0f, 0x0f, 0x17, 0x1f, 0x07, 0x07, 0x07, 0x27, 0x07, 0x40, 0x07, 0x07, 0x27, 0x1f, 0x17, 0x27, ++ 0x27, 0x40, 0x3e, 0x40, 0x4f, 0x40, 0x07, 0x07, 0x07, 0x17, 0x17, 0x37, 0x0f, 0x10, 0x47, 0x40, ++ 0x1f, 0x07, 0x40, 0x10, 0x47, 0x40, 0x1f, 0x07, 0x40, 0x10, 0x47, 0x40, 0x1f, 0x07, 0x40, 0x4f, ++ 0x07, 0x0f, 0x0f, 0x1f, 0x27, 0x1f, 0x27, 0x08, 0x17, 0x47, 0x40, 0x17, 0x47, 0x40, 0x40, 0x40, ++ 0x40, 0x00, 0x08, 0x08, 0x40, 0x0f, 0x08, 0x00, 0x00, 0x2f, 0x27, 0x1f, 0x07, 0x27, 0x1f, 0x1f, ++ 0x47, 0x10, 0x10, 0x08, 0x40, 0x0f, 0x08, 0x00, 0x27, 0x08, 0x37, 0x27, 0x27, 0x08, 0x40, 0x40, ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++}; ++ ++static void set_ps_field(u32 *buf, struct rkvdec_ps_field field, u32 value) ++{ ++ u8 bit = field.offset % 32, word = field.offset / 32; ++ u64 mask = GENMASK_ULL(bit + field.len - 1, bit); ++ u64 val = ((u64)value << bit) & mask; ++ ++ buf[word] &= ~mask; ++ buf[word] |= val; ++ if (bit + field.len > 32) { ++ buf[word + 1] &= ~(mask >> 32); ++ buf[word + 1] |= val >> 32; ++ } ++} ++ ++static void assemble_hw_pps(struct rkvdec_ctx *ctx, ++ struct rkvdec_hevc_run *run) ++{ ++ struct rkvdec_hevc_ctx *hevc_ctx = ctx->priv; ++ const struct v4l2_ctrl_hevc_sps *sps = run->sps; ++ const struct v4l2_ctrl_hevc_pps *pps = run->pps; ++ struct rkvdec_hevc_priv_tbl *priv_tbl = hevc_ctx->priv_tbl.cpu; ++ struct rkvdec_sps_pps_packet *hw_ps; ++ u32 min_cb_log2_size_y, ctb_log2_size_y, ctb_size_y; ++ u32 log2_min_cu_qp_delta_size; ++ dma_addr_t scaling_list_address; ++ u32 scaling_distance; ++ int i; ++ ++ /* ++ * HW read the SPS/PPS information from PPS packet index by PPS id. ++ * offset from the base can be calculated by PPS_id * 80 (size per PPS ++ * packet unit). so the driver copy SPS/PPS information to the exact PPS ++ * packet unit for HW accessing. ++ */ ++ hw_ps = &priv_tbl->param_set[pps->pic_parameter_set_id]; ++ memset(hw_ps, 0, sizeof(*hw_ps)); ++ ++ min_cb_log2_size_y = sps->log2_min_luma_coding_block_size_minus3 + 3; ++ ctb_log2_size_y = min_cb_log2_size_y + ++ sps->log2_diff_max_min_luma_coding_block_size; ++ ctb_size_y = 1 << ctb_log2_size_y; ++ ++#define WRITE_PPS(value, field) set_ps_field(hw_ps->info, field, value) ++ /* write sps */ ++ WRITE_PPS(sps->video_parameter_set_id, VIDEO_PARAMETER_SET_ID); ++ WRITE_PPS(sps->seq_parameter_set_id, SEQ_PARAMETER_SET_ID); ++ WRITE_PPS(1, CHROMA_FORMAT_IDC); ++ WRITE_PPS(sps->pic_width_in_luma_samples, PIC_WIDTH_IN_LUMA_SAMPLES); ++ WRITE_PPS(sps->pic_height_in_luma_samples, PIC_HEIGHT_IN_LUMA_SAMPLES); ++ WRITE_PPS(sps->bit_depth_luma_minus8 + 8, BIT_DEPTH_LUMA); ++ WRITE_PPS(sps->bit_depth_chroma_minus8 + 8, BIT_DEPTH_CHROMA); ++ WRITE_PPS(sps->log2_max_pic_order_cnt_lsb_minus4 + 4, ++ LOG2_MAX_PIC_ORDER_CNT_LSB); ++ WRITE_PPS(sps->log2_diff_max_min_luma_coding_block_size, ++ LOG2_DIFF_MAX_MIN_LUMA_CODING_BLOCK_SIZE); ++ WRITE_PPS(sps->log2_min_luma_coding_block_size_minus3 + 3, ++ LOG2_MIN_LUMA_CODING_BLOCK_SIZE); ++ WRITE_PPS(sps->log2_min_luma_transform_block_size_minus2 + 2, ++ LOG2_MIN_TRANSFORM_BLOCK_SIZE); ++ WRITE_PPS(sps->log2_diff_max_min_luma_transform_block_size, ++ LOG2_DIFF_MAX_MIN_LUMA_TRANSFORM_BLOCK_SIZE); ++ WRITE_PPS(sps->max_transform_hierarchy_depth_inter, ++ MAX_TRANSFORM_HIERARCHY_DEPTH_INTER); ++ WRITE_PPS(sps->max_transform_hierarchy_depth_intra, ++ MAX_TRANSFORM_HIERARCHY_DEPTH_INTRA); ++ WRITE_PPS(!!(sps->flags & V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED), ++ SCALING_LIST_ENABLED_FLAG); ++ WRITE_PPS(!!(sps->flags & V4L2_HEVC_SPS_FLAG_AMP_ENABLED), ++ AMP_ENABLED_FLAG); ++ WRITE_PPS(!!(sps->flags & V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET), ++ SAMPLE_ADAPTIVE_OFFSET_ENABLED_FLAG); ++ if (sps->flags & V4L2_HEVC_SPS_FLAG_PCM_ENABLED) { ++ WRITE_PPS(1, PCM_ENABLED_FLAG); ++ WRITE_PPS(sps->pcm_sample_bit_depth_luma_minus1 + 1, ++ PCM_SAMPLE_BIT_DEPTH_LUMA); ++ WRITE_PPS(sps->pcm_sample_bit_depth_chroma_minus1 + 1, ++ PCM_SAMPLE_BIT_DEPTH_CHROMA); ++ WRITE_PPS(!!(sps->flags & V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED), ++ PCM_LOOP_FILTER_DISABLED_FLAG); ++ WRITE_PPS(sps->log2_diff_max_min_pcm_luma_coding_block_size, ++ LOG2_DIFF_MAX_MIN_PCM_LUMA_CODING_BLOCK_SIZE); ++ WRITE_PPS(sps->log2_min_pcm_luma_coding_block_size_minus3 + 3, ++ LOG2_MIN_PCM_LUMA_CODING_BLOCK_SIZE); ++ } ++ WRITE_PPS(sps->num_short_term_ref_pic_sets, NUM_SHORT_TERM_REF_PIC_SETS); ++ WRITE_PPS(!!(sps->flags & V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT), ++ LONG_TERM_REF_PICS_PRESENT_FLAG); ++ WRITE_PPS(sps->num_long_term_ref_pics_sps, NUM_LONG_TERM_REF_PICS_SPS); ++ WRITE_PPS(!!(sps->flags & V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED), ++ SPS_TEMPORAL_MVP_ENABLED_FLAG); ++ WRITE_PPS(!!(sps->flags & V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED), ++ STRONG_INTRA_SMOOTHING_ENABLED_FLAG); ++ //WRITE_PPS(0, PS_FIELD(100, 7)); ++ //WRITE_PPS(0x1fffff, PS_FIELD(107, 21)); ++ ++ /* write pps */ ++ WRITE_PPS(pps->pic_parameter_set_id, PIC_PARAMETER_SET_ID); ++ WRITE_PPS(sps->seq_parameter_set_id, PPS_SEQ_PARAMETER_SET_ID); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT), ++ DEPENDENT_SLICE_SEGMENTS_ENABLED_FLAG); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_OUTPUT_FLAG_PRESENT), ++ OUTPUT_FLAG_PRESENT_FLAG); ++ WRITE_PPS(pps->num_extra_slice_header_bits, NUM_EXTRA_SLICE_HEADER_BITS); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED), ++ SIGN_DATA_HIDING_ENABLED_FLAG); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_CABAC_INIT_PRESENT), ++ CABAC_INIT_PRESENT_FLAG); ++ WRITE_PPS(pps->num_ref_idx_l0_default_active_minus1 + 1, ++ NUM_REF_IDX_L0_DEFAULT_ACTIVE); ++ WRITE_PPS(pps->num_ref_idx_l1_default_active_minus1 + 1, ++ NUM_REF_IDX_L1_DEFAULT_ACTIVE); ++ WRITE_PPS(pps->init_qp_minus26, INIT_QP_MINUS26); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED), ++ CONSTRAINED_INTRA_PRED_FLAG); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_TRANSFORM_SKIP_ENABLED), ++ TRANSFORM_SKIP_ENABLED_FLAG); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED), ++ CU_QP_DELTA_ENABLED_FLAG); ++ ++ log2_min_cu_qp_delta_size = ctb_log2_size_y - pps->diff_cu_qp_delta_depth; ++ WRITE_PPS(log2_min_cu_qp_delta_size, LOG2_MIN_CU_QP_DELTA_SIZE); ++ ++ WRITE_PPS(pps->pps_cb_qp_offset, PPS_CB_QP_OFFSET); ++ WRITE_PPS(pps->pps_cr_qp_offset, PPS_CR_QP_OFFSET); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT), ++ PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT_FLAG); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED), ++ WEIGHTED_PRED_FLAG); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED), ++ WEIGHTED_BIPRED_FLAG); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED), ++ TRANSQUANT_BYPASS_ENABLED_FLAG); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_TILES_ENABLED), ++ TILES_ENABLED_FLAG); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED), ++ ENTROPY_CODING_SYNC_ENABLED_FLAG); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED), ++ PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED), ++ LOOP_FILTER_ACROSS_TILES_ENABLED_FLAG); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_OVERRIDE_ENABLED), ++ DEBLOCKING_FILTER_OVERRIDE_ENABLED_FLAG); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_PPS_DISABLE_DEBLOCKING_FILTER), ++ PPS_DEBLOCKING_FILTER_DISABLED_FLAG); ++ WRITE_PPS(pps->pps_beta_offset_div2, PPS_BETA_OFFSET_DIV2); ++ WRITE_PPS(pps->pps_tc_offset_div2, PPS_TC_OFFSET_DIV2); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_LISTS_MODIFICATION_PRESENT), ++ LISTS_MODIFICATION_PRESENT_FLAG); ++ WRITE_PPS(pps->log2_parallel_merge_level_minus2 + 2, LOG2_PARALLEL_MERGE_LEVEL); ++ WRITE_PPS(!!(pps->flags & V4L2_HEVC_PPS_FLAG_SLICE_SEGMENT_HEADER_EXTENSION_PRESENT), ++ SLICE_SEGMENT_HEADER_EXTENSION_PRESENT_FLAG); ++ //WRITE_PPS(0, PS_FIELD(209, 3)); ++ WRITE_PPS(pps->num_tile_columns_minus1 + 1, NUM_TILE_COLUMNS); ++ WRITE_PPS(pps->num_tile_rows_minus1 + 1, NUM_TILE_ROWS); ++ //WRITE_PPS(0x2, PS_FIELD(222, 2)); ++ //WRITE_PPS(0xffffffff, PS_FIELD(224, 32)); ++ ++ if (pps->flags & V4L2_HEVC_PPS_FLAG_TILES_ENABLED) { ++ for (i = 0; i <= pps->num_tile_columns_minus1; i++) ++ WRITE_PPS(pps->column_width_minus1[i], COLUMN_WIDTH(i)); ++ for (i = 0; i <= pps->num_tile_rows_minus1; i++) ++ WRITE_PPS(pps->row_height_minus1[i], ROW_HEIGHT(i)); ++ } else { ++ WRITE_PPS(round_up(sps->pic_width_in_luma_samples, ctb_size_y) - 1, ++ COLUMN_WIDTH(0)); ++ WRITE_PPS(round_up(sps->pic_height_in_luma_samples, ctb_size_y) - 1, ++ ROW_HEIGHT(0)); ++ } ++ ++ scaling_distance = offsetof(struct rkvdec_hevc_priv_tbl, scaling_list); ++ scaling_list_address = hevc_ctx->priv_tbl.dma + scaling_distance; ++ WRITE_PPS(scaling_list_address, SCALING_LIST_ADDRESS); ++ //WRITE_PPS(0xffff, PS_FIELD(624, 16)); ++} ++ ++static void assemble_hw_rps(struct rkvdec_ctx *ctx, ++ struct rkvdec_hevc_run *run) ++{ ++ const struct v4l2_ctrl_hevc_slice_params *sl_params; ++ const struct v4l2_hevc_dpb_entry *dpb; ++ struct rkvdec_hevc_ctx *hevc_ctx = ctx->priv; ++ struct rkvdec_hevc_priv_tbl *priv_tbl = hevc_ctx->priv_tbl.cpu; ++ struct rkvdec_rps_packet *hw_ps; ++ int i, j; ++ ++#define WRITE_RPS(value, field) set_ps_field(hw_ps->info, field, value) ++ ++#define REF_PIC_LONG_TERM_L0(i) PS_FIELD(i * 5, 1) ++#define REF_PIC_IDX_L0(i) PS_FIELD(1 + (i * 5), 4) ++#define REF_PIC_LONG_TERM_L1(i) PS_FIELD((i < 5 ? 75 : 132) + (i * 5), 1) ++#define REF_PIC_IDX_L1(i) PS_FIELD((i < 4 ? 76 : 128) + (i * 5), 4) ++ ++#define LOWDELAY PS_FIELD(182, 1) ++#define SHORT_TERM_REF_PIC_SET_SIZE PS_FIELD(183, 10) ++#define LONG_TERM_REF_PIC_SET_SIZE PS_FIELD(193, 9) ++#define NUM_RPS_POC PS_FIELD(202, 4) ++ ++ for (j = 0; j < run->num_slices; j++) { ++ sl_params = &run->slices_params[j]; ++ dpb = sl_params->dpb; ++ ++ hw_ps = &priv_tbl->rps[j]; ++ memset(hw_ps, 0, sizeof(*hw_ps)); ++ ++ for (i = 0; i <= sl_params->num_ref_idx_l0_active_minus1; i++) { ++ WRITE_RPS(!!(dpb[sl_params->ref_idx_l0[i]].rps == V4L2_HEVC_DPB_ENTRY_RPS_LT_CURR), ++ REF_PIC_LONG_TERM_L0(i)); ++ WRITE_RPS(sl_params->ref_idx_l0[i], REF_PIC_IDX_L0(i)); ++ } ++ ++ for (i = 0; i <= sl_params->num_ref_idx_l1_active_minus1; i++) { ++ WRITE_RPS(!!(dpb[sl_params->ref_idx_l1[i]].rps == V4L2_HEVC_DPB_ENTRY_RPS_LT_CURR), ++ REF_PIC_LONG_TERM_L1(i)); ++ WRITE_RPS(sl_params->ref_idx_l1[i], REF_PIC_IDX_L1(i)); ++ } ++ ++ //WRITE_RPS(0xffffffff, PS_FIELD(96, 32)); ++ ++ // TODO: lowdelay ++ WRITE_RPS(0, LOWDELAY); ++ ++ // NOTE: these two differs from mpp ++ WRITE_RPS(sl_params->short_term_ref_pic_set_size, ++ SHORT_TERM_REF_PIC_SET_SIZE); ++ WRITE_RPS(sl_params->long_term_ref_pic_set_size, ++ LONG_TERM_REF_PIC_SET_SIZE); ++ ++ WRITE_RPS(sl_params->num_rps_poc_st_curr_before + ++ sl_params->num_rps_poc_st_curr_after + ++ sl_params->num_rps_poc_lt_curr, ++ NUM_RPS_POC); ++ ++ //WRITE_RPS(0x3ffff, PS_FIELD(206, 18)); ++ //WRITE_RPS(0xffffffff, PS_FIELD(224, 32)); ++ } ++} ++ ++static void assemble_hw_scaling_list(struct rkvdec_ctx *ctx, ++ struct rkvdec_hevc_run *run) ++{ ++ const struct v4l2_ctrl_hevc_scaling_matrix *scaling = run->scaling_matrix; ++ struct rkvdec_hevc_ctx *hevc_ctx = ctx->priv; ++ struct rkvdec_hevc_priv_tbl *tbl = hevc_ctx->priv_tbl.cpu; ++ u8 *dst; ++ scalingList_t sl; ++ int i, j; ++ ++ if (!memcmp((void*)&hevc_ctx->scaling_matrix_cache, scaling, ++ sizeof(struct v4l2_ctrl_hevc_scaling_matrix))) ++ return; ++ ++ memset(&sl, 0, sizeof(scalingList_t)); ++ ++ for (i = 0; i < 6; i++) { ++ for (j = 0; j < 16; j++) ++ sl.sl[0][i][j] = scaling->scaling_list_4x4[i][j]; ++ for (j = 0; j < 64; j++) { ++ sl.sl[1][i][j] = scaling->scaling_list_8x8[i][j]; ++ sl.sl[2][i][j] = scaling->scaling_list_16x16[i][j]; ++ if (i < 2) ++ sl.sl[3][i][j] = scaling->scaling_list_32x32[i][j]; ++ } ++ sl.sl_dc[0][i] = scaling->scaling_list_dc_coef_16x16[i]; ++ if (i < 2) ++ sl.sl_dc[1][i] = scaling->scaling_list_dc_coef_32x32[i]; ++ } ++ ++ dst = tbl->scaling_list; ++ hal_record_scaling_list((scalingFactor_t *)dst, &sl); ++ ++ memcpy((void*)&hevc_ctx->scaling_matrix_cache, scaling, ++ sizeof(struct v4l2_ctrl_hevc_scaling_matrix)); ++} ++ ++static struct vb2_buffer * ++get_ref_buf(struct rkvdec_ctx *ctx, struct rkvdec_hevc_run *run, ++ unsigned int dpb_idx) ++{ ++ struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx; ++ const struct v4l2_ctrl_hevc_slice_params *sl_params = &run->slices_params[0]; ++ const struct v4l2_hevc_dpb_entry *dpb = sl_params->dpb; ++ struct vb2_queue *cap_q = &m2m_ctx->cap_q_ctx.q; ++ int buf_idx = -1; ++ ++ if (dpb_idx < sl_params->num_active_dpb_entries) ++ buf_idx = vb2_find_timestamp(cap_q, ++ dpb[dpb_idx].timestamp, 0); ++ ++ /* ++ * If a DPB entry is unused or invalid, address of current destination ++ * buffer is returned. ++ */ ++ if (buf_idx < 0) ++ return &run->base.bufs.dst->vb2_buf; ++ ++ return vb2_get_buffer(cap_q, buf_idx); ++} ++ ++static void config_registers(struct rkvdec_ctx *ctx, ++ struct rkvdec_hevc_run *run) ++{ ++ struct rkvdec_dev *rkvdec = ctx->dev; ++ const struct v4l2_ctrl_hevc_slice_params *sl_params = &run->slices_params[0]; ++ const struct v4l2_hevc_dpb_entry *dpb = sl_params->dpb; ++ struct rkvdec_hevc_ctx *hevc_ctx = ctx->priv; ++ dma_addr_t priv_start_addr = hevc_ctx->priv_tbl.dma; ++ const struct v4l2_pix_format_mplane *dst_fmt; ++ struct vb2_v4l2_buffer *src_buf = run->base.bufs.src; ++ struct vb2_v4l2_buffer *dst_buf = run->base.bufs.dst; ++ const struct v4l2_format *f; ++ dma_addr_t rlc_addr; ++ dma_addr_t refer_addr; ++ u32 rlc_len; ++ u32 hor_virstride; ++ u32 ver_virstride; ++ u32 y_virstride; ++ u32 uv_virstride; ++ u32 yuv_virstride; ++ u32 offset; ++ dma_addr_t dst_addr; ++ u32 reg, i; ++ ++ reg = RKVDEC_MODE(RKVDEC_MODE_HEVC); ++ writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_SYSCTRL); ++ ++ f = &ctx->decoded_fmt; ++ dst_fmt = &f->fmt.pix_mp; ++ hor_virstride = dst_fmt->plane_fmt[0].bytesperline; ++ ver_virstride = dst_fmt->height; ++ y_virstride = hor_virstride * ver_virstride; ++ uv_virstride = y_virstride / 2; ++ yuv_virstride = y_virstride + uv_virstride; ++ ++ reg = RKVDEC_Y_HOR_VIRSTRIDE(hor_virstride / 16) | ++ RKVDEC_UV_HOR_VIRSTRIDE(hor_virstride / 16) | ++ RKVDEC_SLICE_NUM_LOWBITS(run->num_slices); ++ writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_PICPAR); ++ ++ /* config rlc base address */ ++ rlc_addr = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); ++ writel_relaxed(rlc_addr, rkvdec->regs + RKVDEC_REG_STRM_RLC_BASE); ++ ++ rlc_len = vb2_get_plane_payload(&src_buf->vb2_buf, 0); ++ reg = RKVDEC_STRM_LEN(round_up(rlc_len, 16) + 64); ++ writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_STRM_LEN); ++ ++ /* config cabac table */ ++ offset = offsetof(struct rkvdec_hevc_priv_tbl, cabac_table); ++ writel_relaxed(priv_start_addr + offset, ++ rkvdec->regs + RKVDEC_REG_CABACTBL_PROB_BASE); ++ ++ /* config output base address */ ++ dst_addr = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); ++ writel_relaxed(dst_addr, rkvdec->regs + RKVDEC_REG_DECOUT_BASE); ++ ++ reg = RKVDEC_Y_VIRSTRIDE(y_virstride / 16); ++ writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_Y_VIRSTRIDE); ++ ++ reg = RKVDEC_YUV_VIRSTRIDE(yuv_virstride / 16); ++ writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_YUV_VIRSTRIDE); ++ ++ /* config ref pic address */ ++ for (i = 0; i < 15; i++) { ++ struct vb2_buffer *vb_buf = get_ref_buf(ctx, run, i); ++ ++ if (i < 4 && sl_params->num_active_dpb_entries) { ++ reg = GENMASK(sl_params->num_active_dpb_entries - 1, 0); ++ reg = (reg >> (i * 4)) & 0xf; ++ } else ++ reg = 0; ++ ++ refer_addr = vb2_dma_contig_plane_dma_addr(vb_buf, 0); ++ writel_relaxed(refer_addr | reg, ++ rkvdec->regs + RKVDEC_REG_H264_BASE_REFER(i)); ++ ++ reg = RKVDEC_POC_REFER(i < sl_params->num_active_dpb_entries ? dpb[i].pic_order_cnt[0] : 0); ++ writel_relaxed(reg, ++ rkvdec->regs + RKVDEC_REG_H264_POC_REFER0(i)); ++ } ++ ++ reg = RKVDEC_CUR_POC(sl_params->slice_pic_order_cnt); ++ writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_CUR_POC0); ++ ++ /* config hw pps address */ ++ offset = offsetof(struct rkvdec_hevc_priv_tbl, param_set); ++ writel_relaxed(priv_start_addr + offset, ++ rkvdec->regs + RKVDEC_REG_PPS_BASE); ++ ++ /* config hw rps address */ ++ offset = offsetof(struct rkvdec_hevc_priv_tbl, rps); ++ writel_relaxed(priv_start_addr + offset, ++ rkvdec->regs + RKVDEC_REG_RPS_BASE); ++ ++ reg = RKVDEC_AXI_DDR_RDATA(0); ++ writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_AXI_DDR_RDATA); ++ ++ reg = RKVDEC_AXI_DDR_WDATA(0); ++ writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_AXI_DDR_WDATA); ++} ++ ++#define RKVDEC_HEVC_MAX_DEPTH_IN_BYTES 2 ++ ++static int rkvdec_hevc_adjust_fmt(struct rkvdec_ctx *ctx, ++ struct v4l2_format *f) ++{ ++ struct v4l2_pix_format_mplane *fmt = &f->fmt.pix_mp; ++ ++ fmt->num_planes = 1; ++ if (!fmt->plane_fmt[0].sizeimage) ++ fmt->plane_fmt[0].sizeimage = fmt->width * fmt->height * ++ RKVDEC_HEVC_MAX_DEPTH_IN_BYTES; ++ return 0; ++} ++ ++static int rkvdec_hevc_start(struct rkvdec_ctx *ctx) ++{ ++ struct rkvdec_dev *rkvdec = ctx->dev; ++ struct rkvdec_hevc_priv_tbl *priv_tbl; ++ struct rkvdec_hevc_ctx *hevc_ctx; ++ int ret; ++ ++ hevc_ctx = kzalloc(sizeof(*hevc_ctx), GFP_KERNEL); ++ if (!hevc_ctx) ++ return -ENOMEM; ++ ++ priv_tbl = dma_alloc_coherent(rkvdec->dev, sizeof(*priv_tbl), ++ &hevc_ctx->priv_tbl.dma, GFP_KERNEL); ++ if (!priv_tbl) { ++ ret = -ENOMEM; ++ goto err_free_ctx; ++ } ++ ++ hevc_ctx->priv_tbl.size = sizeof(*priv_tbl); ++ hevc_ctx->priv_tbl.cpu = priv_tbl; ++ memset(priv_tbl, 0, sizeof(*priv_tbl)); ++ memcpy(priv_tbl->cabac_table, rkvdec_hevc_cabac_table, ++ sizeof(rkvdec_hevc_cabac_table)); ++ ++ ctx->priv = hevc_ctx; ++ return 0; ++ ++err_free_ctx: ++ kfree(hevc_ctx); ++ return ret; ++} ++ ++static void rkvdec_hevc_stop(struct rkvdec_ctx *ctx) ++{ ++ struct rkvdec_hevc_ctx *hevc_ctx = ctx->priv; ++ struct rkvdec_dev *rkvdec = ctx->dev; ++ ++ dma_free_coherent(rkvdec->dev, hevc_ctx->priv_tbl.size, ++ hevc_ctx->priv_tbl.cpu, hevc_ctx->priv_tbl.dma); ++ kfree(hevc_ctx); ++} ++ ++static void rkvdec_hevc_run_preamble(struct rkvdec_ctx *ctx, ++ struct rkvdec_hevc_run *run) ++{ ++ struct v4l2_ctrl *ctrl; ++ ++ ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, ++ V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS); ++ run->slices_params = ctrl ? ctrl->p_cur.p : NULL; ++ ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, ++ V4L2_CID_MPEG_VIDEO_HEVC_SPS); ++ run->sps = ctrl ? ctrl->p_cur.p : NULL; ++ ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, ++ V4L2_CID_MPEG_VIDEO_HEVC_PPS); ++ run->pps = ctrl ? ctrl->p_cur.p : NULL; ++ ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, ++ V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX); ++ run->scaling_matrix = ctrl ? ctrl->p_cur.p : NULL; ++ ++ rkvdec_run_preamble(ctx, &run->base); ++ ++ // HACK: we need num slices from somewhere ++ run->num_slices = run->sps->num_slices; ++} ++ ++static int rkvdec_hevc_run(struct rkvdec_ctx *ctx) ++{ ++ struct rkvdec_dev *rkvdec = ctx->dev; ++ struct rkvdec_hevc_run run; ++ ++ rkvdec_hevc_run_preamble(ctx, &run); ++ ++ assemble_hw_scaling_list(ctx, &run); ++ assemble_hw_pps(ctx, &run); ++ assemble_hw_rps(ctx, &run); ++ config_registers(ctx, &run); ++ ++ rkvdec_run_postamble(ctx, &run.base); ++ ++ // sw_cabac_error_e - cabac error enable ++ writel_relaxed(0xfdfffffd, rkvdec->regs + RKVDEC_REG_STRMD_ERR_EN); ++ // slice end error enable = BIT(28) ++ // frame end error enable = BIT(29) ++ writel_relaxed(0x30000000, rkvdec->regs + RKVDEC_REG_H264_ERR_E); ++ ++ schedule_delayed_work(&rkvdec->watchdog_work, msecs_to_jiffies(2000)); ++ ++ writel(1, rkvdec->regs + RKVDEC_REG_PREF_LUMA_CACHE_COMMAND); ++ writel(1, rkvdec->regs + RKVDEC_REG_PREF_CHR_CACHE_COMMAND); ++ ++ /* Start decoding! */ ++ writel(RKVDEC_INTERRUPT_DEC_E | RKVDEC_CONFIG_DEC_CLK_GATE_E | ++ RKVDEC_TIMEOUT_E | RKVDEC_BUF_EMPTY_E, ++ rkvdec->regs + RKVDEC_REG_INTERRUPT); ++ ++ return 0; ++} ++ ++const struct rkvdec_coded_fmt_ops rkvdec_hevc_fmt_ops = { ++ .adjust_fmt = rkvdec_hevc_adjust_fmt, ++ .start = rkvdec_hevc_start, ++ .stop = rkvdec_hevc_stop, ++ .run = rkvdec_hevc_run, ++}; +diff --git a/drivers/staging/media/rkvdec/rkvdec-regs.h b/drivers/staging/media/rkvdec/rkvdec-regs.h +index 15b9bee92016..83bf790ed9b7 100644 +--- a/drivers/staging/media/rkvdec/rkvdec-regs.h ++++ b/drivers/staging/media/rkvdec/rkvdec-regs.h +@@ -43,6 +43,7 @@ + #define RKVDEC_RLC_MODE BIT(11) + #define RKVDEC_STRM_START_BIT(x) (((x) & 0x7f) << 12) + #define RKVDEC_MODE(x) (((x) & 0x03) << 20) ++#define RKVDEC_MODE_HEVC 0 + #define RKVDEC_MODE_H264 1 + #define RKVDEC_MODE_VP9 2 + #define RKVDEC_RPS_MODE BIT(24) +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index 658fb6028e72..2141633c7437 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -159,6 +159,61 @@ static const u32 rkvdec_h264_decoded_fmts[] = { + V4L2_PIX_FMT_NV20, + }; + ++static const struct rkvdec_ctrl_desc rkvdec_hevc_ctrl_descs[] = { ++ { ++ .mandatory = true, ++ .cfg.id = V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS, ++ // HACK: match ffmpeg v4l2 request api hwaccel size, ++ // we should support variable length up to 600 slices ++ .cfg.dims = { 16 }, ++ }, ++ { ++ .mandatory = true, ++ .cfg.id = V4L2_CID_MPEG_VIDEO_HEVC_SPS, ++ }, ++ { ++ .mandatory = true, ++ .cfg.id = V4L2_CID_MPEG_VIDEO_HEVC_PPS, ++ }, ++ { ++ .mandatory = true, ++ .cfg.id = V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX, ++ }, ++ { ++ .cfg.id = V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE, ++ .cfg.min = V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_FRAME_BASED, ++ .cfg.max = V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_FRAME_BASED, ++ .cfg.def = V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_FRAME_BASED, ++ }, ++ { ++ .cfg.id = V4L2_CID_MPEG_VIDEO_HEVC_START_CODE, ++ .cfg.min = V4L2_MPEG_VIDEO_HEVC_START_CODE_ANNEX_B, ++ .cfg.def = V4L2_MPEG_VIDEO_HEVC_START_CODE_ANNEX_B, ++ .cfg.max = V4L2_MPEG_VIDEO_HEVC_START_CODE_ANNEX_B, ++ }, ++ { ++ .cfg.id = V4L2_CID_MPEG_VIDEO_HEVC_PROFILE, ++ .cfg.min = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, ++ .cfg.max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10, ++ .cfg.def = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, ++ }, ++ { ++ .cfg.id = V4L2_CID_MPEG_VIDEO_HEVC_LEVEL, ++ .cfg.min = V4L2_MPEG_VIDEO_HEVC_LEVEL_1, ++ .cfg.max = V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1, ++ }, ++}; ++ ++static const struct rkvdec_ctrls rkvdec_hevc_ctrls = { ++ .ctrls = rkvdec_hevc_ctrl_descs, ++ .num_ctrls = ARRAY_SIZE(rkvdec_hevc_ctrl_descs), ++}; ++ ++static const u32 rkvdec_hevc_decoded_fmts[] = { ++ V4L2_PIX_FMT_NV12, ++ V4L2_PIX_FMT_NV15, ++}; ++ + static const struct rkvdec_ctrl_desc rkvdec_vp9_ctrl_descs[] = { + { + .mandatory = true, +@@ -209,6 +264,21 @@ static const struct rkvdec_coded_fmt_desc rkvdec_coded_fmts[] = { + .num_decoded_fmts = ARRAY_SIZE(rkvdec_h264_decoded_fmts), + .decoded_fmts = rkvdec_h264_decoded_fmts, + }, ++ { ++ .fourcc = V4L2_PIX_FMT_HEVC_SLICE, ++ .frmsize = { ++ .min_width = 64, ++ .max_width = 4096, ++ .step_width = 64, ++ .min_height = 64, ++ .max_height = 2304, ++ .step_height = 16, ++ }, ++ .ctrls = &rkvdec_hevc_ctrls, ++ .ops = &rkvdec_hevc_fmt_ops, ++ .num_decoded_fmts = ARRAY_SIZE(rkvdec_hevc_decoded_fmts), ++ .decoded_fmts = rkvdec_hevc_decoded_fmts, ++ }, + { + .fourcc = V4L2_PIX_FMT_VP9_FRAME, + .frmsize = { +diff --git a/drivers/staging/media/rkvdec/rkvdec.h b/drivers/staging/media/rkvdec/rkvdec.h +index 5f66f07acac5..d5600c6a4c17 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.h ++++ b/drivers/staging/media/rkvdec/rkvdec.h +@@ -123,6 +123,7 @@ void rkvdec_run_preamble(struct rkvdec_ctx *ctx, struct rkvdec_run *run); + void rkvdec_run_postamble(struct rkvdec_ctx *ctx, struct rkvdec_run *run); + + extern const struct rkvdec_coded_fmt_ops rkvdec_h264_fmt_ops; ++extern const struct rkvdec_coded_fmt_ops rkvdec_hevc_fmt_ops; + extern const struct rkvdec_coded_fmt_ops rkvdec_vp9_fmt_ops; + + #endif /* RKVDEC_H_ */ + +From 42bf64d9be3b320b3ff6617a63b177f6dae206fb Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 1 Aug 2020 12:24:58 +0000 +Subject: [PATCH] WIP: media: rkvdec: add HEVC format validation + +--- + drivers/staging/media/rkvdec/rkvdec-hevc.c | 11 +++++++++++ + drivers/staging/media/rkvdec/rkvdec.c | 23 +++++++++++++++++++++- + 2 files changed, 33 insertions(+), 1 deletion(-) + +diff --git a/drivers/staging/media/rkvdec/rkvdec-hevc.c b/drivers/staging/media/rkvdec/rkvdec-hevc.c +index 03ba848411c6..b8ad7fc2271c 100644 +--- a/drivers/staging/media/rkvdec/rkvdec-hevc.c ++++ b/drivers/staging/media/rkvdec/rkvdec-hevc.c +@@ -2415,6 +2415,16 @@ static int rkvdec_hevc_adjust_fmt(struct rkvdec_ctx *ctx, + return 0; + } + ++static u32 rkvdec_hevc_valid_fmt(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl) ++{ ++ const struct v4l2_ctrl_hevc_sps *sps = ctrl->p_new.p_hevc_sps; ++ ++ if (sps->bit_depth_luma_minus8 == 2) ++ return V4L2_PIX_FMT_NV15; ++ else ++ return V4L2_PIX_FMT_NV12; ++} ++ + static int rkvdec_hevc_start(struct rkvdec_ctx *ctx) + { + struct rkvdec_dev *rkvdec = ctx->dev; +@@ -2516,6 +2526,7 @@ static int rkvdec_hevc_run(struct rkvdec_ctx *ctx) + + const struct rkvdec_coded_fmt_ops rkvdec_hevc_fmt_ops = { + .adjust_fmt = rkvdec_hevc_adjust_fmt, ++ .valid_fmt = rkvdec_hevc_valid_fmt, + .start = rkvdec_hevc_start, + .stop = rkvdec_hevc_stop, + .run = rkvdec_hevc_run, +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index 2141633c7437..869275a411c8 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -76,6 +76,26 @@ static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl) + if (width > ctx->coded_fmt.fmt.pix_mp.width || + height > ctx->coded_fmt.fmt.pix_mp.height) + return -EINVAL; ++ } else if (ctrl->id == V4L2_CID_MPEG_VIDEO_HEVC_SPS) { ++ const struct v4l2_ctrl_hevc_sps *sps = ctrl->p_new.p_hevc_sps; ++ ++ if (sps->chroma_format_idc > 1) ++ /* Only 4:0:0 and 4:2:0 are supported */ ++ return -EINVAL; ++ if (sps->bit_depth_luma_minus8 != sps->bit_depth_chroma_minus8) ++ /* Luma and chroma bit depth mismatch */ ++ return -EINVAL; ++ if (sps->bit_depth_luma_minus8 != 0 && sps->bit_depth_luma_minus8 != 2) ++ /* Only 8-bit and 10-bit is supported */ ++ return -EINVAL; ++ ++ if (ctx->valid_fmt && ctx->valid_fmt != rkvdec_valid_fmt(ctx, ctrl)) ++ /* Only current valid format */ ++ return -EINVAL; ++ ++ if (sps->pic_width_in_luma_samples > ctx->coded_fmt.fmt.pix_mp.width || ++ sps->pic_height_in_luma_samples > ctx->coded_fmt.fmt.pix_mp.height) ++ return -EINVAL; + } + return 0; + } +@@ -84,7 +104,7 @@ static int rkvdec_s_ctrl(struct v4l2_ctrl *ctrl) + { + struct rkvdec_ctx *ctx = container_of(ctrl->handler, struct rkvdec_ctx, ctrl_hdl); + +- if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_SPS && !ctx->valid_fmt) { ++ if (!ctx->valid_fmt) { + ctx->valid_fmt = rkvdec_valid_fmt(ctx, ctrl); + if (ctx->valid_fmt) { + struct v4l2_pix_format_mplane *pix_mp; +@@ -170,6 +190,7 @@ static const struct rkvdec_ctrl_desc rkvdec_hevc_ctrl_descs[] = { + { + .mandatory = true, + .cfg.id = V4L2_CID_MPEG_VIDEO_HEVC_SPS, ++ .cfg.ops = &rkvdec_ctrl_ops, + }, + { + .mandatory = true, + +From d37481b9f7f915f93efaee842548a4b42b2da4ce Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Tue, 29 Oct 2019 01:26:02 +0000 +Subject: [PATCH] RFC: media: hantro: Fix H264 decoding of field encoded + content + +This still need code cleanup and formatting + +Signed-off-by: Jonas Karlman +--- + .../staging/media/hantro/hantro_g1_h264_dec.c | 17 +--- + drivers/staging/media/hantro/hantro_h264.c | 81 ++++++++++++++++--- + drivers/staging/media/hantro/hantro_hw.h | 2 + + 3 files changed, 74 insertions(+), 26 deletions(-) + +diff --git a/drivers/staging/media/hantro/hantro_g1_h264_dec.c b/drivers/staging/media/hantro/hantro_g1_h264_dec.c +index 845bef73d218..869ee261a5db 100644 +--- a/drivers/staging/media/hantro/hantro_g1_h264_dec.c ++++ b/drivers/staging/media/hantro/hantro_g1_h264_dec.c +@@ -130,25 +130,12 @@ static void set_ref(struct hantro_ctx *ctx) + struct v4l2_h264_dpb_entry *dpb = ctx->h264_dec.dpb; + const u8 *b0_reflist, *b1_reflist, *p_reflist; + struct hantro_dev *vpu = ctx->dev; +- u32 dpb_longterm = 0; +- u32 dpb_valid = 0; + int reg_num; + u32 reg; + int i; + +- /* +- * Set up bit maps of valid and long term DPBs. +- * NOTE: The bits are reversed, i.e. MSb is DPB 0. +- */ +- for (i = 0; i < HANTRO_H264_DPB_SIZE; ++i) { +- if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE) +- dpb_valid |= BIT(HANTRO_H264_DPB_SIZE - 1 - i); +- +- if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM) +- dpb_longterm |= BIT(HANTRO_H264_DPB_SIZE - 1 - i); +- } +- vdpu_write_relaxed(vpu, dpb_valid << 16, G1_REG_VALID_REF); +- vdpu_write_relaxed(vpu, dpb_longterm << 16, G1_REG_LT_REF); ++ vdpu_write_relaxed(vpu, ctx->h264_dec.dpb_valid, G1_REG_VALID_REF); ++ vdpu_write_relaxed(vpu, ctx->h264_dec.dpb_longterm, G1_REG_LT_REF); + + /* + * Set up reference frame picture numbers. +diff --git a/drivers/staging/media/hantro/hantro_h264.c b/drivers/staging/media/hantro/hantro_h264.c +index b1bdc00ac262..bc2af450a94c 100644 +--- a/drivers/staging/media/hantro/hantro_h264.c ++++ b/drivers/staging/media/hantro/hantro_h264.c +@@ -227,17 +227,67 @@ static void prepare_table(struct hantro_ctx *ctx) + { + const struct hantro_h264_dec_ctrls *ctrls = &ctx->h264_dec.ctrls; + const struct v4l2_ctrl_h264_decode_params *dec_param = ctrls->decode; ++ const struct v4l2_ctrl_h264_sps *sps = ctrls->sps; + struct hantro_h264_dec_priv_tbl *tbl = ctx->h264_dec.priv.cpu; + const struct v4l2_h264_dpb_entry *dpb = ctx->h264_dec.dpb; ++ u32 dpb_longterm = 0; ++ u32 dpb_valid = 0; + int i; + ++ /* ++ * Set up bit maps of valid and long term DPBs. ++ * NOTE: The bits are reversed, i.e. MSb is DPB 0. ++ */ ++ if ((dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC) || (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD)) { ++ for (i = 0; i < HANTRO_H264_DPB_SIZE * 2; ++i) { ++ // check for correct reference use ++ enum v4l2_h264_field_reference parity = (i & 0x1) ? ++ V4L2_H264_BOTTOM_FIELD_REF : V4L2_H264_TOP_FIELD_REF; ++ if (dpb[i / 2].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE && ++ dpb[i / 2].reference & parity) ++ dpb_valid |= BIT(HANTRO_H264_DPB_SIZE * 2 - 1 - i); ++ ++ if (dpb[i / 2].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM) ++ dpb_longterm |= BIT(HANTRO_H264_DPB_SIZE * 2 - 1 - i); ++ } ++ ++ ctx->h264_dec.dpb_valid = dpb_valid; ++ ctx->h264_dec.dpb_longterm = dpb_longterm; ++ } else { ++ for (i = 0; i < HANTRO_H264_DPB_SIZE; ++i) { ++ if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE) ++ dpb_valid |= BIT(HANTRO_H264_DPB_SIZE - 1 - i); ++ ++ if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM) ++ dpb_longterm |= BIT(HANTRO_H264_DPB_SIZE - 1 - i); ++ } ++ ++ ctx->h264_dec.dpb_valid = dpb_valid << 16; ++ ctx->h264_dec.dpb_longterm = dpb_longterm << 16; ++ } ++ + for (i = 0; i < HANTRO_H264_DPB_SIZE; ++i) { +- tbl->poc[i * 2] = dpb[i].top_field_order_cnt; +- tbl->poc[i * 2 + 1] = dpb[i].bottom_field_order_cnt; ++ if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE) { ++ tbl->poc[i * 2] = dpb[i].top_field_order_cnt; ++ tbl->poc[i * 2 + 1] = dpb[i].bottom_field_order_cnt; ++ } else { ++ tbl->poc[i * 2] = 0; ++ tbl->poc[i * 2 + 1] = 0; ++ } + } + +- tbl->poc[32] = dec_param->top_field_order_cnt; +- tbl->poc[33] = dec_param->bottom_field_order_cnt; ++ if ((dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC) || !(sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD)) { ++ if ((dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC)) ++ tbl->poc[32] = (dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD) ? ++ dec_param->bottom_field_order_cnt : ++ dec_param->top_field_order_cnt; ++ else ++ tbl->poc[32] = min(dec_param->top_field_order_cnt, dec_param->bottom_field_order_cnt); ++ tbl->poc[33] = 0; ++ } else { ++ tbl->poc[32] = dec_param->top_field_order_cnt; ++ tbl->poc[33] = dec_param->bottom_field_order_cnt; ++ } + + assemble_scaling_list(ctx); + } +@@ -245,8 +295,7 @@ static void prepare_table(struct hantro_ctx *ctx) + static bool dpb_entry_match(const struct v4l2_h264_dpb_entry *a, + const struct v4l2_h264_dpb_entry *b) + { +- return a->top_field_order_cnt == b->top_field_order_cnt && +- a->bottom_field_order_cnt == b->bottom_field_order_cnt; ++ return a->reference_ts == b->reference_ts; + } + + static void update_dpb(struct hantro_ctx *ctx) +@@ -260,13 +309,13 @@ static void update_dpb(struct hantro_ctx *ctx) + + /* Disable all entries by default. */ + for (i = 0; i < ARRAY_SIZE(ctx->h264_dec.dpb); i++) +- ctx->h264_dec.dpb[i].flags &= ~V4L2_H264_DPB_ENTRY_FLAG_ACTIVE; ++ ctx->h264_dec.dpb[i].flags = 0; + + /* Try to match new DPB entries with existing ones by their POCs. */ + for (i = 0; i < ARRAY_SIZE(dec_param->dpb); i++) { + const struct v4l2_h264_dpb_entry *ndpb = &dec_param->dpb[i]; + +- if (!(ndpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)) ++ if (!(ndpb->flags & V4L2_H264_DPB_ENTRY_FLAG_VALID)) + continue; + + /* +@@ -277,8 +326,7 @@ static void update_dpb(struct hantro_ctx *ctx) + struct v4l2_h264_dpb_entry *cdpb; + + cdpb = &ctx->h264_dec.dpb[j]; +- if (cdpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE || +- !dpb_entry_match(cdpb, ndpb)) ++ if (!dpb_entry_match(cdpb, ndpb)) + continue; + + *cdpb = *ndpb; +@@ -314,7 +362,10 @@ dma_addr_t hantro_h264_get_ref_buf(struct hantro_ctx *ctx, + unsigned int dpb_idx) + { + struct v4l2_h264_dpb_entry *dpb = ctx->h264_dec.dpb; ++ const struct v4l2_ctrl_h264_decode_params *dec_param = ctx->h264_dec.ctrls.decode; + dma_addr_t dma_addr = 0; ++ s32 cur_poc; ++ u32 flags; + + if (dpb[dpb_idx].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE) + dma_addr = hantro_get_ref(ctx, dpb[dpb_idx].reference_ts); +@@ -332,7 +383,15 @@ dma_addr_t hantro_h264_get_ref_buf(struct hantro_ctx *ctx, + dma_addr = hantro_get_dec_buf_addr(ctx, buf); + } + +- return dma_addr; ++ cur_poc = dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD ? ++ dec_param->bottom_field_order_cnt : ++ dec_param->top_field_order_cnt; ++ flags = dpb[dpb_idx].flags & V4L2_H264_DPB_ENTRY_FLAG_FIELD ? 0x2 : 0; ++ flags |= abs(dpb[dpb_idx].top_field_order_cnt - cur_poc) < ++ abs(dpb[dpb_idx].bottom_field_order_cnt - cur_poc) ? ++ 0x1 : 0; ++ ++ return dma_addr | flags; + } + + int hantro_h264_dec_prepare_run(struct hantro_ctx *ctx) +diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h +index 219283a06f52..7e35140a4f22 100644 +--- a/drivers/staging/media/hantro/hantro_hw.h ++++ b/drivers/staging/media/hantro/hantro_hw.h +@@ -90,6 +90,8 @@ struct hantro_h264_dec_hw_ctx { + struct v4l2_h264_dpb_entry dpb[HANTRO_H264_DPB_SIZE]; + struct hantro_h264_dec_reflists reflists; + struct hantro_h264_dec_ctrls ctrls; ++ u32 dpb_longterm; ++ u32 dpb_valid; + }; + + /** + +From badc3bfbfabd4fd01837498a4dd6bc84420bea79 Mon Sep 17 00:00:00 2001 +From: Randy Li +Date: Sun, 6 Jan 2019 01:48:37 +0800 +Subject: [PATCH] soc: rockchip: power-domain: export idle request + +We need to put the power status of HEVC IP into IDLE unless +we can't reset that IP or the SoC would crash down. +rockchip_pmu_idle_request(dev, true)---> enter idle +rockchip_pmu_idle_request(dev, false)---> exit idle + +Signed-off-by: Caesar Wang +Signed-off-by: Jeffy Chen +Signed-off-by: Randy Li +--- + drivers/soc/rockchip/pm_domains.c | 23 +++++++++++++++++++++++ + include/linux/rockchip_pmu.h | 15 +++++++++++++++ + include/soc/rockchip/pm_domains.h | 18 ++++++++++++++++++ + 3 files changed, 56 insertions(+) + create mode 100644 include/linux/rockchip_pmu.h + create mode 100644 include/soc/rockchip/pm_domains.h + +diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c +index 54eb6cfc5d5b..727af107e6d3 100644 +--- a/drivers/soc/rockchip/pm_domains.c ++++ b/drivers/soc/rockchip/pm_domains.c +@@ -196,6 +196,29 @@ static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd, + return 0; + } + ++int rockchip_pmu_idle_request(struct device *dev, bool idle) ++{ ++ struct generic_pm_domain *genpd; ++ struct rockchip_pm_domain *pd; ++ int ret; ++ ++ if (IS_ERR_OR_NULL(dev)) ++ return -EINVAL; ++ ++ if (IS_ERR_OR_NULL(dev->pm_domain)) ++ return -EINVAL; ++ ++ genpd = pd_to_genpd(dev->pm_domain); ++ pd = to_rockchip_pd(genpd); ++ ++ mutex_lock(&pd->pmu->mutex); ++ ret = rockchip_pmu_set_idle_request(pd, idle); ++ mutex_unlock(&pd->pmu->mutex); ++ ++ return ret; ++} ++EXPORT_SYMBOL(rockchip_pmu_idle_request); ++ + static int rockchip_pmu_save_qos(struct rockchip_pm_domain *pd) + { + int i; +diff --git a/include/linux/rockchip_pmu.h b/include/linux/rockchip_pmu.h +new file mode 100644 +index 000000000000..720b3314e71a +--- /dev/null ++++ b/include/linux/rockchip_pmu.h +@@ -0,0 +1,15 @@ ++/* ++ * pm_domain.h - Definitions and headers related to device power domains. ++ * ++ * Copyright (C) 2017 Randy Li . ++ * ++ * This file is released under the GPLv2. ++ */ ++ ++#ifndef _LINUX_ROCKCHIP_PM_H ++#define _LINUX_ROCKCHIP_PM_H ++#include ++ ++int rockchip_pmu_idle_request(struct device *dev, bool idle); ++ ++#endif /* _LINUX_ROCKCHIP_PM_H */ +diff --git a/include/soc/rockchip/pm_domains.h b/include/soc/rockchip/pm_domains.h +new file mode 100644 +index 000000000000..690db6118636 +--- /dev/null ++++ b/include/soc/rockchip/pm_domains.h +@@ -0,0 +1,18 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++#ifndef __SOC_ROCKCHIP_PM_DOMAINS_H ++#define __SOC_ROCKCHIP_PM_DOMAINS_H ++ ++#include ++ ++struct device; ++ ++#ifdef CONFIG_ROCKCHIP_PM_DOMAINS ++int rockchip_pmu_idle_request(struct device *dev, bool idle); ++#else ++static inline int rockchip_pmu_idle_request(struct device *dev, bool idle) ++{ ++ return -ENOTSUPP; ++} ++#endif ++ ++#endif + +From 495e11bbb264dfb5f1d8b319ed647901fc91dc11 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Wed, 20 May 2020 17:04:47 +0200 +Subject: [PATCH] media: rkvdec: implement reset controls + +--- + .../bindings/media/rockchip,vdec.yaml | 19 ++++++ + drivers/staging/media/rkvdec/rkvdec-regs.h | 5 ++ + drivers/staging/media/rkvdec/rkvdec.c | 60 +++++++++++++++++++ + drivers/staging/media/rkvdec/rkvdec.h | 11 +++- + 4 files changed, 94 insertions(+), 1 deletion(-) + +diff --git a/Documentation/devicetree/bindings/media/rockchip,vdec.yaml b/Documentation/devicetree/bindings/media/rockchip,vdec.yaml +index 8d35c327018b..1e8cfd8e032b 100644 +--- a/Documentation/devicetree/bindings/media/rockchip,vdec.yaml ++++ b/Documentation/devicetree/bindings/media/rockchip,vdec.yaml +@@ -43,6 +43,18 @@ properties: + iommus: + maxItems: 1 + ++ resets: ++ maxItems: 6 ++ ++ reset-names: ++ items: ++ - const: video_h ++ - const: video_a ++ - const: video_core ++ - const: video_cabac ++ - const: niu_a ++ - const: niu_h ++ + required: + - compatible + - reg +@@ -50,6 +62,8 @@ required: + - clocks + - clock-names + - power-domains ++ - resets ++ - reset-names + + additionalProperties: false + +@@ -68,6 +82,11 @@ examples: + clock-names = "axi", "ahb", "cabac", "core"; + power-domains = <&power RK3399_PD_VDU>; + iommus = <&vdec_mmu>; ++ resets = <&cru SRST_H_VDU>, <&cru SRST_A_VDU>, ++ <&cru SRST_VDU_CORE>, <&cru SRST_VDU_CA>, ++ <&cru SRST_A_VDU_NOC>, <&cru SRST_H_VDU_NOC>; ++ reset-names = "video_h", "video_a", "video_core", "video_cabac", ++ "niu_a", "niu_h" + }; + + ... +diff --git a/drivers/staging/media/rkvdec/rkvdec-regs.h b/drivers/staging/media/rkvdec/rkvdec-regs.h +index 83bf790ed9b7..4addfaefdfb4 100644 +--- a/drivers/staging/media/rkvdec/rkvdec-regs.h ++++ b/drivers/staging/media/rkvdec/rkvdec-regs.h +@@ -28,6 +28,11 @@ + #define RKVDEC_SOFTRST_EN_P BIT(20) + #define RKVDEC_FORCE_SOFTRESET_VALID BIT(21) + #define RKVDEC_SOFTRESET_RDY BIT(22) ++#define RKVDEC_ERR_MASK (RKVDEC_BUS_STA \ ++ | RKVDEC_ERR_STA \ ++ | RKVDEC_TIMEOUT_STA \ ++ | RKVDEC_BUF_EMPTY_STA \ ++ | RKVDEC_COLMV_REF_ERR_STA ) + + #define RKVDEC_REG_SYSCTRL 0x008 + #define RKVDEC_IN_ENDIAN BIT(0) +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index 869275a411c8..74f566e65413 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -10,12 +10,15 @@ + */ + + #include ++#include + #include + #include + #include + #include + #include + #include ++#include ++#include + #include + #include + #include +@@ -871,6 +874,11 @@ static void rkvdec_job_finish(struct rkvdec_ctx *ctx, + + pm_runtime_mark_last_busy(rkvdec->dev); + pm_runtime_put_autosuspend(rkvdec->dev); ++ ++ if (result == VB2_BUF_STATE_ERROR && ++ rkvdec->reset_mask == RESET_NONE) ++ rkvdec->reset_mask |= RESET_SOFT; ++ + rkvdec_job_finish_no_pm(ctx, result); + } + +@@ -908,6 +916,40 @@ static void rkvdec_device_run(void *priv) + + if (WARN_ON(!desc)) + return; ++ if (rkvdec->reset_mask != RESET_NONE) { ++ ++ if (rkvdec->reset_mask & RESET_SOFT) { ++ writel(RKVDEC_SOFTRST_EN_P, ++ rkvdec->regs + RKVDEC_REG_INTERRUPT); ++ udelay(RKVDEC_RESET_DELAY); ++ if (readl(rkvdec->regs + RKVDEC_REG_INTERRUPT) ++ & RKVDEC_SOFTRESET_RDY) ++ dev_info_ratelimited(rkvdec->dev, ++ "softreset failed\n"); ++ else ++ dev_notice_ratelimited(rkvdec->dev, ++ "softreset done\n"); ++ } ++ ++ if (rkvdec->reset_mask & RESET_HARD) { ++ pm_runtime_suspend(rkvdec->dev); ++ rockchip_pmu_idle_request(rkvdec->dev, true); ++ ret = reset_control_assert(rkvdec->rstc); ++ if (!ret) { ++ udelay(RKVDEC_RESET_DELAY); ++ ret = reset_control_deassert(rkvdec->rstc); ++ } ++ rockchip_pmu_idle_request(rkvdec->dev, false); ++ if (ret) ++ dev_notice_ratelimited(rkvdec->dev, ++ "hardreset failed\n"); ++ else ++ dev_notice_ratelimited(rkvdec->dev, ++ "hardreset done\n"); ++ } ++ ++ rkvdec->reset_mask = RESET_NONE; ++ } + + ret = pm_runtime_get_sync(rkvdec->dev); + if (ret < 0) { +@@ -1175,6 +1217,11 @@ static irqreturn_t rkvdec_irq_handler(int irq, void *priv) + if (cancel_delayed_work(&rkvdec->watchdog_work)) { + struct rkvdec_ctx *ctx; + ++ if (state == VB2_BUF_STATE_ERROR) { ++ rkvdec->reset_mask |= (status & RKVDEC_ERR_MASK) ? ++ RESET_HARD : RESET_SOFT; ++ } ++ + ctx = v4l2_m2m_get_curr_priv(rkvdec->m2m_dev); + rkvdec_job_finish(ctx, state); + } +@@ -1192,6 +1239,7 @@ static void rkvdec_watchdog_func(struct work_struct *work) + ctx = v4l2_m2m_get_curr_priv(rkvdec->m2m_dev); + if (ctx) { + dev_err(rkvdec->dev, "Frame processing timed out!\n"); ++ rkvdec->reset_mask |= RESET_HARD; + writel(RKVDEC_CONFIG_DEC_CLK_GATE_E | RKVDEC_IRQ_DIS, + rkvdec->regs + RKVDEC_REG_INTERRUPT); + writel(0, rkvdec->regs + RKVDEC_REG_SYSCTRL); +@@ -1271,6 +1319,18 @@ static int rkvdec_probe(struct platform_device *pdev) + return ret; + } + ++ ++ rkvdec->rstc = devm_reset_control_array_get(&pdev->dev, false, true); ++ if (IS_ERR(rkvdec->rstc)) { ++ dev_err(&pdev->dev, ++ "get resets failed %ld\n", PTR_ERR(rkvdec->rstc)); ++ return PTR_ERR(rkvdec->rstc); ++ } else { ++ dev_dbg(&pdev->dev, ++ "requested %d resets\n", ++ reset_control_get_count(&pdev->dev)); ++ } ++ + pm_runtime_set_autosuspend_delay(&pdev->dev, 100); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_enable(&pdev->dev); +diff --git a/drivers/staging/media/rkvdec/rkvdec.h b/drivers/staging/media/rkvdec/rkvdec.h +index d5600c6a4c17..975fe4b5dd68 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.h ++++ b/drivers/staging/media/rkvdec/rkvdec.h +@@ -11,10 +11,11 @@ + #ifndef RKVDEC_H_ + #define RKVDEC_H_ + ++#include + #include ++#include + #include + #include +-#include + + #include + #include +@@ -22,6 +23,12 @@ + #include + #include + ++#define RESET_NONE 0 ++#define RESET_SOFT BIT(0) ++#define RESET_HARD BIT(1) ++ ++#define RKVDEC_RESET_DELAY 5 ++ + struct rkvdec_ctx; + + struct rkvdec_ctrl_desc { +@@ -95,6 +102,8 @@ struct rkvdec_dev { + void __iomem *regs; + struct mutex vdev_lock; /* serializes ioctls */ + struct delayed_work watchdog_work; ++ struct reset_control *rstc; ++ u8 reset_mask; + }; + + struct rkvdec_ctx { + +From 0f3ef2d452750f5688292c232b6c7d28ce2b0095 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Tue, 18 Aug 2020 11:38:04 +0200 +Subject: [PATCH] WIP: arm64: dts: add resets to vdec for RK3399 + +--- + arch/arm64/boot/dts/rockchip/rk3399.dtsi | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi +index 8973bf68d652..1efe2c916508 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi +@@ -1281,6 +1281,11 @@ vdec: video-codec@ff660000 { + clock-names = "axi", "ahb", "cabac", "core"; + iommus = <&vdec_mmu>; + power-domains = <&power RK3399_PD_VDU>; ++ resets = <&cru SRST_H_VDU>, <&cru SRST_A_VDU>, ++ <&cru SRST_VDU_CORE>, <&cru SRST_VDU_CA>, ++ <&cru SRST_A_VDU_NOC>, <&cru SRST_H_VDU_NOC>; ++ reset-names = "video_h", "video_a", "video_core", "video_cabac", ++ "niu_a", "niu_h" + }; + + vdec_mmu: iommu@ff660480 { + +From 98eac32dca51c74be1d223854976b834ac2d9587 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Fri, 24 Apr 2020 12:36:13 +0200 +Subject: [PATCH] media: hantro: add Rockchip RK3228 + +RK3228 has the same VPU IP-Block as RK3399 has and at the current state +the driver can be taken as is. +This adds just a new compatible string to bindings file if any future +ajustment for this SoC is necessary. +--- + Documentation/devicetree/bindings/media/rockchip-vpu.yaml | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml +index 2b629456d75f..4509891a0f0f 100644 +--- a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml ++++ b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml +@@ -16,6 +16,7 @@ description: + properties: + compatible: + enum: ++ - rockchip,rk3228-vpu + - rockchip,rk3288-vpu + - rockchip,rk3328-vpu + - rockchip,rk3399-vpu + +From e47b8ed20a45dcb324b997e5fa74586f71fc71cc Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Fri, 24 Apr 2020 12:38:24 +0200 +Subject: [PATCH] ARM: dts: rockchip: add vpu node for RK322x + +This adds VPU node to RK3228. While at it also add the required power-domain +controller and qos node to make the VPU work on this SoC. +--- + arch/arm/boot/dts/rk322x.dtsi | 35 +++++++++++++++++++++++++++++++++-- + 1 file changed, 33 insertions(+), 2 deletions(-) + +diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi +index b69b5be110c3..0586a89d24d3 100644 +--- a/arch/arm/boot/dts/rk322x.dtsi ++++ b/arch/arm/boot/dts/rk322x.dtsi +@@ -6,6 +6,7 @@ + #include + #include + #include ++#include + + / { + #address-cells = <1>; +@@ -208,6 +209,19 @@ io_domains: io-domains { + status = "disabled"; + }; + ++ power: power-controller { ++ compatible = "rockchip,rk3228-power-controller"; ++ #power-domain-cells = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ pd_vpu@RK3228_PD_VPU { ++ reg = ; ++ clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; ++ pm_qos = <&qos_vpu>; ++ }; ++ }; ++ + u2phy0: usb2-phy@760 { + compatible = "rockchip,rk3228-usb2phy"; + reg = <0x0760 0x0c>; +@@ -561,6 +575,18 @@ gpu: gpu@20000000 { + status = "disabled"; + }; + ++ vpu: video-codec@20020000 { ++ compatible = "rockchip,rk3228-vpu", "rockchip,rk3399-vpu"; ++ reg = <0x20020000 0x800>; ++ interrupts = , ++ ; ++ interrupt-names = "vepu", "vdpu"; ++ clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; ++ clock-names = "aclk", "hclk"; ++ iommus = <&vpu_mmu>; ++ power-domains = <&power RK3228_PD_VPU>; ++ }; ++ + vpu_mmu: iommu@20020800 { + compatible = "rockchip,iommu"; + reg = <0x20020800 0x100>; +@@ -568,8 +594,8 @@ vpu_mmu: iommu@20020800 { + interrupt-names = "vpu_mmu"; + clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; + clock-names = "aclk", "iface"; +- iommu-cells = <0>; +- status = "disabled"; ++ power-domains = <&power RK3228_PD_VPU>; ++ #iommu-cells = <0>; + }; + + vdec_mmu: iommu@20030480 { +@@ -807,6 +833,11 @@ gmac: ethernet@30200000 { + status = "disabled"; + }; + ++ qos_vpu: qos@31040000 { ++ compatible = "syscon"; ++ reg = <0x31040000 0x20>; ++ }; ++ + gic: interrupt-controller@32010000 { + compatible = "arm,gic-400"; + interrupt-controller; + +From 70feb241848426de731a1f8bc5ad0d9c45bf5bfa Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Tue, 26 May 2020 14:11:57 +0200 +Subject: [PATCH] media: hantro: add support for RK3188 + +RK3188s VPU IP-Block is the predecessor from what RK3288 has. + +While most of the registers match in the current state of the driver +there are some HW differences: + - supports resultion up to 1920x1088 only + - has one aclk and one hclk per vdpu/vepu + - doesn't have the 'G1_REG_SOFT_RESET' register + - ACLKs can be clocked up to 300 MHz only + - no MMU for VPU +These make it necessary to add another variant to the driver. + +This should be also reuseable for RK3066 but has not been tested, +so I'm not adding it here. +--- + .../bindings/media/rockchip-vpu.yaml | 7 +- + drivers/staging/media/hantro/hantro_drv.c | 1 + + drivers/staging/media/hantro/hantro_hw.h | 1 + + drivers/staging/media/hantro/rk3288_vpu_hw.c | 116 ++++++++++++++++++ + 4 files changed, 124 insertions(+), 1 deletion(-) + +diff --git a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml +index 4509891a0f0f..d95274bf3b0f 100644 +--- a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml ++++ b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml +@@ -16,6 +16,7 @@ description: + properties: + compatible: + enum: ++ - rockchip,rk3188-vpu + - rockchip,rk3228-vpu + - rockchip,rk3288-vpu + - rockchip,rk3328-vpu +@@ -36,12 +37,16 @@ properties: + - const: vdpu + + clocks: +- maxItems: 2 ++ maxItems: 4 + + clock-names: + items: + - const: aclk ++ - const: aclk_vdpu ++ - const: aclk_vepu + - const: hclk ++ - const: hclk_vdpu ++ - const: hclk_vepu + + power-domains: + maxItems: 1 +diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c +index 3cd00cc0a364..ecc0938b7f35 100644 +--- a/drivers/staging/media/hantro/hantro_drv.c ++++ b/drivers/staging/media/hantro/hantro_drv.c +@@ -475,6 +475,7 @@ static const struct of_device_id of_hantro_match[] = { + { .compatible = "rockchip,rk3399-vpu", .data = &rk3399_vpu_variant, }, + { .compatible = "rockchip,rk3328-vpu", .data = &rk3328_vpu_variant, }, + { .compatible = "rockchip,rk3288-vpu", .data = &rk3288_vpu_variant, }, ++ { .compatible = "rockchip,rk3188-vpu", .data = &rk3188_vpu_variant, }, + #endif + #ifdef CONFIG_VIDEO_HANTRO_IMX8M + { .compatible = "nxp,imx8mq-vpu", .data = &imx8mq_vpu_variant, }, +diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h +index 7e35140a4f22..22b0ed01f673 100644 +--- a/drivers/staging/media/hantro/hantro_hw.h ++++ b/drivers/staging/media/hantro/hantro_hw.h +@@ -152,6 +152,7 @@ enum hantro_enc_fmt { + RK3288_VPU_ENC_FMT_UYVY422 = 3, + }; + ++extern const struct hantro_variant rk3188_vpu_variant; + extern const struct hantro_variant rk3399_vpu_variant; + extern const struct hantro_variant rk3328_vpu_variant; + extern const struct hantro_variant rk3288_vpu_variant; +diff --git a/drivers/staging/media/hantro/rk3288_vpu_hw.c b/drivers/staging/media/hantro/rk3288_vpu_hw.c +index 7b299ee3e93d..1ac00695a864 100644 +--- a/drivers/staging/media/hantro/rk3288_vpu_hw.c ++++ b/drivers/staging/media/hantro/rk3288_vpu_hw.c +@@ -13,6 +13,7 @@ + #include "hantro_g1_regs.h" + #include "hantro_h1_regs.h" + ++#define RK3188_ACLK_MAX_FREQ (300 * 1000 * 1000) + #define RK3288_ACLK_MAX_FREQ (400 * 1000 * 1000) + + /* +@@ -63,6 +64,52 @@ static const struct hantro_fmt rk3288_vpu_postproc_fmts[] = { + }, + }; + ++static const struct hantro_fmt rk3188_vpu_dec_fmts[] = { ++ { ++ .fourcc = V4L2_PIX_FMT_NV12, ++ .codec_mode = HANTRO_MODE_NONE, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_H264_SLICE, ++ .codec_mode = HANTRO_MODE_H264_DEC, ++ .max_depth = 2, ++ .frmsize = { ++ .min_width = 48, ++ .max_width = 1920, ++ .step_width = MB_DIM, ++ .min_height = 48, ++ .max_height = 1088, ++ .step_height = MB_DIM, ++ }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_MPEG2_SLICE, ++ .codec_mode = HANTRO_MODE_MPEG2_DEC, ++ .max_depth = 2, ++ .frmsize = { ++ .min_width = 48, ++ .max_width = 1920, ++ .step_width = MB_DIM, ++ .min_height = 48, ++ .max_height = 1088, ++ .step_height = MB_DIM, ++ }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_VP8_FRAME, ++ .codec_mode = HANTRO_MODE_VP8_DEC, ++ .max_depth = 2, ++ .frmsize = { ++ .min_width = 48, ++ .max_width = 1920, ++ .step_width = MB_DIM, ++ .min_height = 48, ++ .max_height = 1088, ++ .step_height = MB_DIM, ++ }, ++ }, ++}; ++ + static const struct hantro_fmt rk3288_vpu_dec_fmts[] = { + { + .fourcc = V4L2_PIX_FMT_NV12, +@@ -145,6 +192,14 @@ static irqreturn_t rk3288_vdpu_irq(int irq, void *dev_id) + return IRQ_HANDLED; + } + ++static int rk3188_vpu_hw_init(struct hantro_dev *vpu) ++{ ++ /* Bump ACLKs to max. possible freq. to improve performance. */ ++ clk_set_rate(vpu->clocks[0].clk, RK3188_ACLK_MAX_FREQ); ++ clk_set_rate(vpu->clocks[2].clk, RK3188_ACLK_MAX_FREQ); ++ return 0; ++} ++ + static int rk3288_vpu_hw_init(struct hantro_dev *vpu) + { + /* Bump ACLK to max. possible freq. to improve performance. */ +@@ -161,6 +216,15 @@ static void rk3288_vpu_enc_reset(struct hantro_ctx *ctx) + vepu_write(vpu, 0, H1_REG_AXI_CTRL); + } + ++ ++static void rk3188_vpu_dec_reset(struct hantro_ctx *ctx) ++{ ++ struct hantro_dev *vpu = ctx->dev; ++ ++ vdpu_write(vpu, G1_REG_INTERRUPT_DEC_IRQ_DIS, G1_REG_INTERRUPT); ++ vdpu_write(vpu, G1_REG_CONFIG_DEC_CLK_GATE_E, G1_REG_CONFIG); ++} ++ + static void rk3288_vpu_dec_reset(struct hantro_ctx *ctx) + { + struct hantro_dev *vpu = ctx->dev; +@@ -174,6 +238,33 @@ static void rk3288_vpu_dec_reset(struct hantro_ctx *ctx) + * Supported codec ops. + */ + ++static const struct hantro_codec_ops rk3188_vpu_codec_ops[] = { ++ [HANTRO_MODE_JPEG_ENC] = { ++ .run = hantro_h1_jpeg_enc_run, ++ .reset = rk3288_vpu_enc_reset, ++ .init = hantro_jpeg_enc_init, ++ .exit = hantro_jpeg_enc_exit, ++ }, ++ [HANTRO_MODE_H264_DEC] = { ++ .run = hantro_g1_h264_dec_run, ++ .reset = rk3188_vpu_dec_reset, ++ .init = hantro_h264_dec_init, ++ .exit = hantro_h264_dec_exit, ++ }, ++ [HANTRO_MODE_MPEG2_DEC] = { ++ .run = hantro_g1_mpeg2_dec_run, ++ .reset = rk3188_vpu_dec_reset, ++ .init = hantro_mpeg2_dec_init, ++ .exit = hantro_mpeg2_dec_exit, ++ }, ++ [HANTRO_MODE_VP8_DEC] = { ++ .run = hantro_g1_vp8_dec_run, ++ .reset = rk3188_vpu_dec_reset, ++ .init = hantro_vp8_dec_init, ++ .exit = hantro_vp8_dec_exit, ++ }, ++}; ++ + static const struct hantro_codec_ops rk3288_vpu_codec_ops[] = { + [HANTRO_MODE_JPEG_ENC] = { + .run = hantro_h1_jpeg_enc_run, +@@ -211,10 +302,35 @@ static const struct hantro_irq rk3288_irqs[] = { + { "vdpu", rk3288_vdpu_irq }, + }; + ++static const char * const rk3188_clk_names[] = { ++ "aclk_vdpu", "hclk_vdpu", ++ "aclk_vepu", "hclk_vepu", ++}; ++ + static const char * const rk3288_clk_names[] = { + "aclk", "hclk" + }; + ++const struct hantro_variant rk3188_vpu_variant = { ++ .enc_offset = 0x0, ++ .enc_fmts = rk3288_vpu_enc_fmts, ++ .num_enc_fmts = ARRAY_SIZE(rk3288_vpu_enc_fmts), ++ .dec_offset = 0x400, ++ .dec_fmts = rk3188_vpu_dec_fmts, ++ .num_dec_fmts = ARRAY_SIZE(rk3188_vpu_dec_fmts), ++ .postproc_fmts = rk3288_vpu_postproc_fmts, ++ .num_postproc_fmts = ARRAY_SIZE(rk3288_vpu_postproc_fmts), ++ .postproc_regs = &hantro_g1_postproc_regs, ++ .codec = HANTRO_JPEG_ENCODER | HANTRO_MPEG2_DECODER | ++ HANTRO_VP8_DECODER | HANTRO_H264_DECODER, ++ .codec_ops = rk3188_vpu_codec_ops, ++ .irqs = rk3288_irqs, ++ .num_irqs = ARRAY_SIZE(rk3288_irqs), ++ .init = rk3188_vpu_hw_init, ++ .clk_names = rk3188_clk_names, ++ .num_clocks = ARRAY_SIZE(rk3188_clk_names) ++}; ++ + const struct hantro_variant rk3288_vpu_variant = { + .enc_offset = 0x0, + .enc_fmts = rk3288_vpu_enc_fmts, + +From 134592088d9c703169c9daff5793e0321ecc245d Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Tue, 26 May 2020 14:12:35 +0200 +Subject: [PATCH] ARM: dts: rockchip: add vpu node for RK3188 + +Add VPU node to RK3188s dtsi. +--- + arch/arm/boot/dts/rk3188.dtsi | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi +index 2298a8d840ba..b6c1699345d0 100644 +--- a/arch/arm/boot/dts/rk3188.dtsi ++++ b/arch/arm/boot/dts/rk3188.dtsi +@@ -112,6 +112,19 @@ smp-sram@0 { + }; + }; + ++ vpu: video-codec@10104000 { ++ compatible = "rockchip,rk3188-vpu"; ++ reg = <0x10104000 0x800>; ++ interrupts = , ++ ; ++ interrupt-names = "vepu", "vdpu"; ++ clocks = <&cru ACLK_VDPU>, <&cru HCLK_VDPU>, ++ <&cru ACLK_VEPU>, <&cru HCLK_VEPU>; ++ clock-names = "aclk_vdpu", "hclk_vdpu", ++ "aclk_vepu", "hclk_vepu"; ++ power-domains = <&power RK3188_PD_VIDEO>; ++ }; ++ + vop0: vop@1010c000 { + compatible = "rockchip,rk3188-vop"; + reg = <0x1010c000 0x1000>; + +From 573413b3e49d1ca7676c976aa3e7d6bb65e497ed Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Tue, 26 May 2020 17:24:12 +0200 +Subject: [PATCH] media: hantro: add support for Rockchip RK3036 + +RK3036 shares the hantro VPU IP Block with RK3288. +HW differences are: +- supports decoding up to 1920x1088 only +- ACLK can be clocked at max. 300MHz +This makes adding another variant to the driver necessary here also. + +However RK3036 TRM does not mention that it has an encoder also. I verfied +this on my devices and it worked for JPEG encoding. Since the identification +register share the id with RK3288 and the fact that it has an interrupt for +video encoding, makes me think that the encoding IP is the same. + +This variant could also be used for RK312x, but has not been tested. +--- + drivers/staging/media/hantro/hantro_drv.c | 1 + + drivers/staging/media/hantro/hantro_hw.h | 1 + + drivers/staging/media/hantro/rk3288_vpu_hw.c | 27 ++++++++++++++++++++ + 3 files changed, 29 insertions(+) + +diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c +index ecc0938b7f35..ee59fad9a2f3 100644 +--- a/drivers/staging/media/hantro/hantro_drv.c ++++ b/drivers/staging/media/hantro/hantro_drv.c +@@ -476,6 +476,7 @@ static const struct of_device_id of_hantro_match[] = { + { .compatible = "rockchip,rk3328-vpu", .data = &rk3328_vpu_variant, }, + { .compatible = "rockchip,rk3288-vpu", .data = &rk3288_vpu_variant, }, + { .compatible = "rockchip,rk3188-vpu", .data = &rk3188_vpu_variant, }, ++ { .compatible = "rockchip,rk3036-vpu", .data = &rk3036_vpu_variant, }, + #endif + #ifdef CONFIG_VIDEO_HANTRO_IMX8M + { .compatible = "nxp,imx8mq-vpu", .data = &imx8mq_vpu_variant, }, +diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h +index 22b0ed01f673..ede7acec5e9f 100644 +--- a/drivers/staging/media/hantro/hantro_hw.h ++++ b/drivers/staging/media/hantro/hantro_hw.h +@@ -152,6 +152,7 @@ enum hantro_enc_fmt { + RK3288_VPU_ENC_FMT_UYVY422 = 3, + }; + ++extern const struct hantro_variant rk3036_vpu_variant; + extern const struct hantro_variant rk3188_vpu_variant; + extern const struct hantro_variant rk3399_vpu_variant; + extern const struct hantro_variant rk3328_vpu_variant; +diff --git a/drivers/staging/media/hantro/rk3288_vpu_hw.c b/drivers/staging/media/hantro/rk3288_vpu_hw.c +index 1ac00695a864..b5887fdae250 100644 +--- a/drivers/staging/media/hantro/rk3288_vpu_hw.c ++++ b/drivers/staging/media/hantro/rk3288_vpu_hw.c +@@ -192,6 +192,13 @@ static irqreturn_t rk3288_vdpu_irq(int irq, void *dev_id) + return IRQ_HANDLED; + } + ++static int rk3036_vpu_hw_init(struct hantro_dev *vpu) ++{ ++ /* Bump ACLK to max. possible freq. to improve performance. */ ++ clk_set_rate(vpu->clocks[0].clk, RK3188_ACLK_MAX_FREQ); ++ return 0; ++} ++ + static int rk3188_vpu_hw_init(struct hantro_dev *vpu) + { + /* Bump ACLKs to max. possible freq. to improve performance. */ +@@ -311,6 +318,26 @@ static const char * const rk3288_clk_names[] = { + "aclk", "hclk" + }; + ++const struct hantro_variant rk3036_vpu_variant = { ++ .enc_offset = 0x0, ++ .enc_fmts = rk3288_vpu_enc_fmts, ++ .num_enc_fmts = ARRAY_SIZE(rk3288_vpu_enc_fmts), ++ .dec_offset = 0x400, ++ .dec_fmts = rk3188_vpu_dec_fmts, ++ .num_dec_fmts = ARRAY_SIZE(rk3188_vpu_dec_fmts), ++ .postproc_fmts = rk3288_vpu_postproc_fmts, ++ .num_postproc_fmts = ARRAY_SIZE(rk3288_vpu_postproc_fmts), ++ .postproc_regs = &hantro_g1_postproc_regs, ++ .codec = HANTRO_JPEG_ENCODER | HANTRO_MPEG2_DECODER | ++ HANTRO_VP8_DECODER | HANTRO_H264_DECODER, ++ .codec_ops = rk3288_vpu_codec_ops, ++ .irqs = rk3288_irqs, ++ .num_irqs = ARRAY_SIZE(rk3288_irqs), ++ .init = rk3036_vpu_hw_init, ++ .clk_names = rk3288_clk_names, ++ .num_clocks = ARRAY_SIZE(rk3288_clk_names) ++}; ++ + const struct hantro_variant rk3188_vpu_variant = { + .enc_offset = 0x0, + .enc_fmts = rk3288_vpu_enc_fmts, + +From 387d5e35e99f03bb0caed01163ef393e15b30362 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Tue, 26 May 2020 17:42:55 +0200 +Subject: [PATCH] ARM: dts: rockchip: add vpu node for RK3036 + +This adds VPU node to RK3036. While at it also add the required mmu, +power-domain controller and qos node to make the VPU work on this SoC. +--- + .../bindings/media/rockchip-vpu.yaml | 1 + + arch/arm/boot/dts/rk3036.dtsi | 44 +++++++++++++++++++ + 2 files changed, 45 insertions(+) + +diff --git a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml +index d95274bf3b0f..15aeae3d1daf 100644 +--- a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml ++++ b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml +@@ -16,6 +16,7 @@ description: + properties: + compatible: + enum: ++ - rockchip,rk3036-vpu + - rockchip,rk3188-vpu + - rockchip,rk3228-vpu + - rockchip,rk3288-vpu +diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi +index 6be6d9d134fe..10f15cdb932c 100644 +--- a/arch/arm/boot/dts/rk3036.dtsi ++++ b/arch/arm/boot/dts/rk3036.dtsi +@@ -6,6 +6,7 @@ + #include + #include + #include ++#include + + / { + #address-cells = <1>; +@@ -134,6 +135,29 @@ gpu: gpu@10090000 { + status = "disabled"; + }; + ++ vpu: video-codec@10108000 { ++ compatible = "rockchip,rk3036-vpu"; ++ reg = <0x10108000 0x800>; ++ interrupts = , ++ ; ++ interrupt-names = "vepu", "vdpu"; ++ clocks = <&cru ACLK_VCODEC>, <&cru HCLK_VCODEC>; ++ clock-names = "aclk", "hclk"; ++ iommus = <&vpu_mmu>; ++ power-domains = <&power RK3036_PD_VPU>; ++ }; ++ ++ vpu_mmu: iommu@10108800 { ++ compatible = "rockchip,iommu"; ++ reg = <0x10108800 0x100>; ++ interrupts = ; ++ interrupt-names = "vpu_mmu"; ++ clocks = <&cru ACLK_VCODEC>, <&cru HCLK_VCODEC>; ++ clock-names = "aclk", "iface"; ++ power-domains = <&power RK3036_PD_VPU>; ++ #iommu-cells = <0>; ++ }; ++ + vop: vop@10118000 { + compatible = "rockchip,rk3036-vop"; + reg = <0x10118000 0x19c>; +@@ -166,6 +190,11 @@ vop_mmu: iommu@10118300 { + status = "disabled"; + }; + ++ qos_vpu: qos@1012e000 { ++ compatible = "syscon"; ++ reg = <0x1012e000 0x20>; ++ }; ++ + gic: interrupt-controller@10139000 { + compatible = "arm,gic-400"; + interrupt-controller; +@@ -329,6 +358,21 @@ reboot-mode { + mode-bootloader = ; + mode-loader = ; + }; ++ ++ power: power-controller { ++ compatible = "rockchip,rk3036-power-controller"; ++ #power-domain-cells = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ pd_vpu@RK3036_PD_VPU { ++ reg = ; ++ clocks = <&cru ACLK_VCODEC>, ++ <&cru HCLK_VCODEC>; ++ pm_qos = <&qos_vpu>; ++ }; ++ ++ }; + }; + + acodec: acodec-ana@20030000 { + +From 871a3ef06a4100a3d7ecc75d2751acf67269a07c Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Tue, 26 May 2020 17:54:22 +0200 +Subject: [PATCH] media: hantro: adapt Kconfig help text + +Since help text line would get very long if all supported SoCs are mentioned +I shortend it to "Rockchip SoCs" +--- + drivers/staging/media/hantro/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/staging/media/hantro/Kconfig b/drivers/staging/media/hantro/Kconfig +index 5b6cf9f62b1a..d33f1ddbc9c9 100644 +--- a/drivers/staging/media/hantro/Kconfig ++++ b/drivers/staging/media/hantro/Kconfig +@@ -30,4 +30,4 @@ config VIDEO_HANTRO_ROCKCHIP + depends on ARCH_ROCKCHIP || COMPILE_TEST + default y + help +- Enable support for RK3288, RK3328, and RK3399 SoCs. ++ Enable support for Rockchip SoCs. + +From 83c9c3f037c52e8c4ada8b5b5f1269ccfa6f6f14 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sat, 23 May 2020 14:22:54 +0200 +Subject: [PATCH] ARM: dts: rockchip: add vdec node for RK322x + +RK322x has the same VDEC IP block as RK3399 has and the driver in its +current state can be used as is. +Other than RK3399 its SCLKs have also to set to a fixed value to make it +work correctly. Rather than doing this in the driver it is done via +"assigned-clocks" in the vdec node. +--- + arch/arm/boot/dts/rk322x.dtsi | 42 +++++++++++++++++++++++++++++++++-- + 1 file changed, 40 insertions(+), 2 deletions(-) + +diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi +index 0586a89d24d3..eec601fb4cd0 100644 +--- a/arch/arm/boot/dts/rk322x.dtsi ++++ b/arch/arm/boot/dts/rk322x.dtsi +@@ -220,6 +220,15 @@ pd_vpu@RK3228_PD_VPU { + clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; + pm_qos = <&qos_vpu>; + }; ++ ++ pd_rkvdec@RK3228_PD_RKVDEC { ++ reg = ; ++ clocks = <&cru ACLK_RKVDEC>, ++ <&cru HCLK_RKVDEC>, ++ <&cru SCLK_VDEC_CABAC>, ++ <&cru SCLK_VDEC_CORE>; ++ pm_qos = <&qos_rkvdec_r>, <&qos_rkvdec_w>; ++ }; + }; + + u2phy0: usb2-phy@760 { +@@ -598,6 +607,25 @@ vpu_mmu: iommu@20020800 { + #iommu-cells = <0>; + }; + ++ vdec: video-codec@20030000 { ++ compatible = "rockchip,rk322x-vdec", "rockchip,rk3399-vdec"; ++ reg = <0x20030000 0x400>; ++ interrupts = ; ++ clocks = <&cru ACLK_RKVDEC>, <&cru HCLK_RKVDEC>, ++ <&cru SCLK_VDEC_CABAC>, <&cru SCLK_VDEC_CORE>; ++ clock-names = "axi", "ahb", "cabac", "core"; ++ assigned-clocks = <&cru ACLK_RKVDEC>, <&cru SCLK_VDEC_CABAC>, ++ <&cru SCLK_VDEC_CORE>; ++ assigned-clock-rates = <500000000>, <300000000>, <300000000>; ++ power-domains = <&power RK3228_PD_RKVDEC>; ++ resets = <&cru SRST_RKVDEC_H>, <&cru SRST_RKVDEC_A>, ++ <&cru SRST_RKVDEC_CORE>, <&cru SRST_RKVDEC_CABAC>, ++ <&cru SRST_RKVDEC_NOC_A>, <&cru SRST_RKVDEC_NOC_H>; ++ reset-names = "video_h", "video_a", "video_core", "video_cabac", ++ "niu_a", "niu_h"; ++ iommus = <&vdec_mmu>; ++ }; ++ + vdec_mmu: iommu@20030480 { + compatible = "rockchip,iommu"; + reg = <0x20030480 0x40>, <0x200304c0 0x40>; +@@ -605,8 +633,8 @@ vdec_mmu: iommu@20030480 { + interrupt-names = "vdec_mmu"; + clocks = <&cru ACLK_RKVDEC>, <&cru HCLK_RKVDEC>; + clock-names = "aclk", "iface"; +- iommu-cells = <0>; +- status = "disabled"; ++ power-domains = <&power RK3228_PD_RKVDEC>; ++ #iommu-cells = <0>; + }; + + vop: vop@20050000 { +@@ -838,6 +866,16 @@ qos_vpu: qos@31040000 { + reg = <0x31040000 0x20>; + }; + ++ qos_rkvdec_r: qos@31070000 { ++ compatible = "syscon"; ++ reg = <0x31070000 0x20>; ++ }; ++ ++ qos_rkvdec_w: qos@31070080 { ++ compatible = "syscon"; ++ reg = <0x31070080 0x20>; ++ }; ++ + gic: interrupt-controller@32010000 { + compatible = "arm,gic-400"; + interrupt-controller; diff --git a/patch/kernel/rk322x-dev/01-linux-4000-rockchip-linux-wip.patch b/patch/kernel/rk322x-dev/01-linux-4000-rockchip-linux-wip.patch new file mode 100644 index 000000000..2c2489b47 --- /dev/null +++ b/patch/kernel/rk322x-dev/01-linux-4000-rockchip-linux-wip.patch @@ -0,0 +1,1692 @@ +From a49884fc5063fb0eb3db69568b45e3b8ef5ea094 Mon Sep 17 00:00:00 2001 +From: Finley Xiao +Date: Thu, 22 Jun 2017 20:22:25 +0800 +Subject: [PATCH] clk: rockchip: rk3228: fix some PLL_NUX_CLKs' gates + +Some PLL_NUX_CLKs' gates is actually behind muxs according to latest TRM, +so move the gates to composite clocks and amend their parent clocks. + +Change-Id: Ib6043caa61e9df0473f2d0bdc756850968bb2a55 +Signed-off-by: Finley Xiao +--- + drivers/clk/rockchip/clk-rk3228.c | 53 ++++++++----------------------- + 1 file changed, 14 insertions(+), 39 deletions(-) + +diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c +index dd414c8255e3..734126a2ad7e 100644 +--- a/drivers/clk/rockchip/clk-rk3228.c ++++ b/drivers/clk/rockchip/clk-rk3228.c +@@ -130,24 +130,22 @@ static const struct rockchip_cpuclk_reg_data rk3228_cpuclk_data = { + + PNAME(mux_pll_p) = { "clk_24m", "xin24m" }; + +-PNAME(mux_ddrphy_p) = { "dpll_ddr", "gpll_ddr", "apll_ddr" }; +-PNAME(mux_armclk_p) = { "apll_core", "gpll_core", "dpll_core" }; ++PNAME(mux_ddrphy_p) = { "dpll", "gpll", "apll" }; ++PNAME(mux_armclk_p) = { "apll", "gpll", "dpll" }; + PNAME(mux_usb480m_phy_p) = { "usb480m_phy0", "usb480m_phy1" }; + PNAME(mux_usb480m_p) = { "usb480m_phy", "xin24m" }; + PNAME(mux_hdmiphy_p) = { "hdmiphy_phy", "xin24m" }; +-PNAME(mux_aclk_cpu_src_p) = { "cpll_aclk_cpu", "gpll_aclk_cpu", "hdmiphy_aclk_cpu" }; + + PNAME(mux_pll_src_4plls_p) = { "cpll", "gpll", "hdmiphy" "usb480m" }; + PNAME(mux_pll_src_3plls_p) = { "cpll", "gpll", "hdmiphy" }; + PNAME(mux_pll_src_2plls_p) = { "cpll", "gpll" }; + PNAME(mux_sclk_hdmi_cec_p) = { "cpll", "gpll", "xin24m" }; +-PNAME(mux_aclk_peri_src_p) = { "cpll_peri", "gpll_peri", "hdmiphy_peri" }; + PNAME(mux_mmc_src_p) = { "cpll", "gpll", "xin24m", "usb480m" }; + PNAME(mux_pll_src_cpll_gpll_usb480m_p) = { "cpll", "gpll", "usb480m" }; + + PNAME(mux_sclk_rga_p) = { "gpll", "cpll", "sclk_rga_src" }; + +-PNAME(mux_sclk_vop_src_p) = { "gpll_vop", "cpll_vop" }; ++PNAME(mux_sclk_vop_src_p) = { "gpll", "cpll" }; + PNAME(mux_dclk_vop_p) = { "hdmiphy", "sclk_vop_pre" }; + + PNAME(mux_i2s0_p) = { "i2s0_src", "i2s0_frac", "ext_i2s", "xin12m" }; +@@ -216,27 +214,17 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + RK2928_CLKSEL_CON(4), 8, 5, DFLAGS), + + /* PD_DDR */ +- GATE(0, "apll_ddr", "apll", CLK_IGNORE_UNUSED, ++ COMPOSITE(0, "clk_ddrphy_src", mux_ddrphy_p, CLK_IGNORE_UNUSED, ++ RK2928_CLKSEL_CON(26), 8, 2, MFLAGS, 0, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, + RK2928_CLKGATE_CON(0), 2, GFLAGS), +- GATE(0, "dpll_ddr", "dpll", CLK_IGNORE_UNUSED, +- RK2928_CLKGATE_CON(0), 2, GFLAGS), +- GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED, +- RK2928_CLKGATE_CON(0), 2, GFLAGS), +- COMPOSITE(0, "ddrphy4x", mux_ddrphy_p, CLK_IGNORE_UNUSED, +- RK2928_CLKSEL_CON(26), 8, 2, MFLAGS, 0, 3, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, ++ GATE(0, "ddrphy4x", "clk_ddrphy_src", CLK_IGNORE_UNUSED, + RK2928_CLKGATE_CON(7), 1, GFLAGS), +- GATE(0, "ddrc", "ddrphy_pre", CLK_IGNORE_UNUSED, ++ FACTOR_GATE(0, "ddrc", "clk_ddrphy_src", CLK_IGNORE_UNUSED, 1, 4, + RK2928_CLKGATE_CON(8), 5, GFLAGS), +- FACTOR_GATE(0, "ddrphy", "ddrphy4x", CLK_IGNORE_UNUSED, 1, 4, ++ FACTOR_GATE(0, "ddrphy", "clk_ddrphy_src", CLK_IGNORE_UNUSED, 1, 4, + RK2928_CLKGATE_CON(7), 0, GFLAGS), + + /* PD_CORE */ +- GATE(0, "dpll_core", "dpll", CLK_IGNORE_UNUSED, +- RK2928_CLKGATE_CON(0), 6, GFLAGS), +- GATE(0, "apll_core", "apll", CLK_IGNORE_UNUSED, +- RK2928_CLKGATE_CON(0), 6, GFLAGS), +- GATE(0, "gpll_core", "gpll", CLK_IGNORE_UNUSED, +- RK2928_CLKGATE_CON(0), 6, GFLAGS), + COMPOSITE_NOMUX(0, "pclk_dbg", "armclk", CLK_IGNORE_UNUSED, + RK2928_CLKSEL_CON(1), 0, 4, DFLAGS | CLK_DIVIDER_READ_ONLY, + RK2928_CLKGATE_CON(4), 1, GFLAGS), +@@ -253,14 +241,9 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + RK2928_MISC_CON, 15, 1, MFLAGS), + + /* PD_BUS */ +- GATE(0, "hdmiphy_aclk_cpu", "hdmiphy", CLK_IGNORE_UNUSED, +- RK2928_CLKGATE_CON(0), 1, GFLAGS), +- GATE(0, "gpll_aclk_cpu", "gpll", CLK_IGNORE_UNUSED, +- RK2928_CLKGATE_CON(0), 1, GFLAGS), +- GATE(0, "cpll_aclk_cpu", "cpll", CLK_IGNORE_UNUSED, ++ COMPOSITE(0, "aclk_cpu_src", mux_pll_src_3plls_p, 0, ++ RK2928_CLKSEL_CON(0), 13, 2, MFLAGS, 8, 5, DFLAGS, + RK2928_CLKGATE_CON(0), 1, GFLAGS), +- COMPOSITE_NOGATE(0, "aclk_cpu_src", mux_aclk_cpu_src_p, 0, +- RK2928_CLKSEL_CON(0), 13, 2, MFLAGS, 8, 5, DFLAGS), + GATE(ACLK_CPU, "aclk_cpu", "aclk_cpu_src", 0, + RK2928_CLKGATE_CON(6), 0, GFLAGS), + COMPOSITE_NOMUX(HCLK_CPU, "hclk_cpu", "aclk_cpu_src", 0, +@@ -333,14 +316,9 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + RK2928_CLKGATE_CON(3), 8, GFLAGS), + + /* PD_PERI */ +- GATE(0, "cpll_peri", "cpll", CLK_IGNORE_UNUSED, ++ COMPOSITE(0, "aclk_peri_src", mux_pll_src_3plls_p, 0, ++ RK2928_CLKSEL_CON(10), 10, 2, MFLAGS, 0, 5, DFLAGS, + RK2928_CLKGATE_CON(2), 0, GFLAGS), +- GATE(0, "gpll_peri", "gpll", CLK_IGNORE_UNUSED, +- RK2928_CLKGATE_CON(2), 0, GFLAGS), +- GATE(0, "hdmiphy_peri", "hdmiphy", CLK_IGNORE_UNUSED, +- RK2928_CLKGATE_CON(2), 0, GFLAGS), +- COMPOSITE_NOGATE(0, "aclk_peri_src", mux_aclk_peri_src_p, 0, +- RK2928_CLKSEL_CON(10), 10, 2, MFLAGS, 0, 5, DFLAGS), + COMPOSITE_NOMUX(PCLK_PERI, "pclk_peri", "aclk_peri_src", 0, + RK2928_CLKSEL_CON(10), 12, 3, DFLAGS, + RK2928_CLKGATE_CON(5), 2, GFLAGS), +@@ -398,12 +376,9 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + * Clock-Architecture Diagram 2 + */ + +- GATE(0, "gpll_vop", "gpll", 0, +- RK2928_CLKGATE_CON(3), 1, GFLAGS), +- GATE(0, "cpll_vop", "cpll", 0, ++ COMPOSITE_NODIV(0, "sclk_vop_src", mux_sclk_vop_src_p, 0, ++ RK2928_CLKSEL_CON(27), 0, 1, MFLAGS, + RK2928_CLKGATE_CON(3), 1, GFLAGS), +- MUX(0, "sclk_vop_src", mux_sclk_vop_src_p, 0, +- RK2928_CLKSEL_CON(27), 0, 1, MFLAGS), + DIV(DCLK_HDMI_PHY, "dclk_hdmiphy", "sclk_vop_src", 0, + RK2928_CLKSEL_CON(29), 0, 3, DFLAGS), + DIV(0, "sclk_vop_pre", "sclk_vop_src", 0, + +From 368824e53d6be0914927df4281bbce6da58a03ff Mon Sep 17 00:00:00 2001 +From: Finley Xiao +Date: Sun, 18 Mar 2018 21:41:43 +0800 +Subject: [PATCH] clk: rockchip: rk3228: Fix sclk_wifi div_width + +Change-Id: I8e216249fbd588ce55660eba9911fc59aedc920d +Signed-off-by: Finley Xiao +--- + drivers/clk/rockchip/clk-rk3228.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c +index 734126a2ad7e..90e5638d4e7e 100644 +--- a/drivers/clk/rockchip/clk-rk3228.c ++++ b/drivers/clk/rockchip/clk-rk3228.c +@@ -353,7 +353,7 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + RK2928_CLKGATE_CON(10), 12, GFLAGS), + + COMPOSITE(SCLK_WIFI, "sclk_wifi", mux_pll_src_cpll_gpll_usb480m_p, 0, +- RK2928_CLKSEL_CON(23), 5, 2, MFLAGS, 0, 6, DFLAGS, ++ RK2928_CLKSEL_CON(23), 5, 2, MFLAGS, 0, 5, DFLAGS, + RK2928_CLKGATE_CON(2), 15, GFLAGS), + + COMPOSITE(SCLK_SDMMC, "sclk_sdmmc", mux_mmc_src_p, 0, + +From 06685aabce5c6147ca099bd1b1399f6a170f78e1 Mon Sep 17 00:00:00 2001 +From: Chen Lei +Date: Tue, 25 Dec 2018 18:29:04 +0800 +Subject: [PATCH] clk: rockchip: rk322x: fix wrong mmc phase shift for rk3228 + +mmc sample shift should be 1 for rk3228, or it will fail +if we enable mmc tuning for rk3228. + +Change-Id: I301c2a7d33de8d519d7c288aef03a82531016373 +Signed-off-by: Chen Lei +--- + drivers/clk/rockchip/clk-rk3228.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c +index 90e5638d4e7e..7fff74043766 100644 +--- a/drivers/clk/rockchip/clk-rk3228.c ++++ b/drivers/clk/rockchip/clk-rk3228.c +@@ -610,13 +610,13 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + + /* PD_MMC */ + MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "sclk_sdmmc", RK3228_SDMMC_CON0, 1), +- MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK3228_SDMMC_CON1, 0), ++ MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK3228_SDMMC_CON1, 1), + + MMC(SCLK_SDIO_DRV, "sdio_drv", "sclk_sdio", RK3228_SDIO_CON0, 1), +- MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "sclk_sdio", RK3228_SDIO_CON1, 0), ++ MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "sclk_sdio", RK3228_SDIO_CON1, 1), + + MMC(SCLK_EMMC_DRV, "emmc_drv", "sclk_emmc", RK3228_EMMC_CON0, 1), +- MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RK3228_EMMC_CON1, 0), ++ MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RK3228_EMMC_CON1, 1), + }; + + static const char *const rk3228_critical_clocks[] __initconst = { + +From a74448d0259e2fe4ad3d791d779ba7a85d31a08b Mon Sep 17 00:00:00 2001 +From: Finley Xiao +Date: Mon, 5 Feb 2018 10:04:15 +0800 +Subject: [PATCH] clk: rockchip: rk3228: Fix armclk parent + +Change-Id: I09830d96b37cca600f1782b9013b25e043467f97 +Signed-off-by: Finley Xiao +--- + drivers/clk/rockchip/clk-rk3228.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c +index 7fff74043766..00c5b8a1e295 100644 +--- a/drivers/clk/rockchip/clk-rk3228.c ++++ b/drivers/clk/rockchip/clk-rk3228.c +@@ -131,7 +131,7 @@ static const struct rockchip_cpuclk_reg_data rk3228_cpuclk_data = { + PNAME(mux_pll_p) = { "clk_24m", "xin24m" }; + + PNAME(mux_ddrphy_p) = { "dpll", "gpll", "apll" }; +-PNAME(mux_armclk_p) = { "apll", "gpll", "dpll" }; ++PNAME(mux_armclk_p) = { "apll_core", "gpll_core", "dpll_core" }; + PNAME(mux_usb480m_phy_p) = { "usb480m_phy0", "usb480m_phy1" }; + PNAME(mux_usb480m_p) = { "usb480m_phy", "xin24m" }; + PNAME(mux_hdmiphy_p) = { "hdmiphy_phy", "xin24m" }; +@@ -225,6 +225,12 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + RK2928_CLKGATE_CON(7), 0, GFLAGS), + + /* PD_CORE */ ++ GATE(0, "apll_core", "apll", CLK_IGNORE_UNUSED, ++ PX30_CLKGATE_CON(0), 6, GFLAGS), ++ GATE(0, "gpll_core", "gpll", CLK_IGNORE_UNUSED, ++ PX30_CLKGATE_CON(0), 6, GFLAGS), ++ GATE(0, "dpll_core", "dpll", CLK_IGNORE_UNUSED, ++ PX30_CLKGATE_CON(0), 6, GFLAGS), + COMPOSITE_NOMUX(0, "pclk_dbg", "armclk", CLK_IGNORE_UNUSED, + RK2928_CLKSEL_CON(1), 0, 4, DFLAGS | CLK_DIVIDER_READ_ONLY, + RK2928_CLKGATE_CON(4), 1, GFLAGS), + +From bdbce1840c0b73a5e5c01576fb394d1719736ee8 Mon Sep 17 00:00:00 2001 +From: Finley Xiao +Date: Sun, 18 Mar 2018 21:42:22 +0800 +Subject: [PATCH] clk: rockchip: rk3228: remove the flag ROCKCHIP_PLL_SYNC_RATE + for GPLL + +To slove the display shaking, when uboot logo display to kernel show. + +Change-Id: Ifc97f72df27b4e8dbcd34ab8ed65ac027fd424d1 +Signed-off-by: Finley Xiao +--- + drivers/clk/rockchip/clk-rk3228.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c +index 00c5b8a1e295..5e9c6986e541 100644 +--- a/drivers/clk/rockchip/clk-rk3228.c ++++ b/drivers/clk/rockchip/clk-rk3228.c +@@ -170,7 +170,7 @@ static struct rockchip_pll_clock rk3228_pll_clks[] __initdata = { + [cpll] = PLL(pll_rk3036, PLL_CPLL, "cpll", mux_pll_p, 0, RK2928_PLL_CON(6), + RK2928_MODE_CON, 8, 8, 0, NULL), + [gpll] = PLL(pll_rk3036, PLL_GPLL, "gpll", mux_pll_p, 0, RK2928_PLL_CON(9), +- RK2928_MODE_CON, 12, 9, ROCKCHIP_PLL_SYNC_RATE, rk3228_pll_rates), ++ RK2928_MODE_CON, 12, 9, 0, rk3228_pll_rates), + }; + + #define MFLAGS CLK_MUX_HIWORD_MASK + +From 0b7003eb4fe6803d6f6071758f069fd7a63f096a Mon Sep 17 00:00:00 2001 +From: Elaine Zhang +Date: Tue, 25 Dec 2018 14:58:30 +0800 +Subject: [PATCH] clk: rockchip: rk322x: fix up the gate con description error + +Change-Id: I439314c590a7144fab6e33d1fb4f325530669842 +Signed-off-by: Elaine Zhang +--- + drivers/clk/rockchip/clk-rk3228.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c +index 5e9c6986e541..448b202bf4f3 100644 +--- a/drivers/clk/rockchip/clk-rk3228.c ++++ b/drivers/clk/rockchip/clk-rk3228.c +@@ -226,11 +226,11 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + + /* PD_CORE */ + GATE(0, "apll_core", "apll", CLK_IGNORE_UNUSED, +- PX30_CLKGATE_CON(0), 6, GFLAGS), ++ RK2928_CLKGATE_CON(0), 6, GFLAGS), + GATE(0, "gpll_core", "gpll", CLK_IGNORE_UNUSED, +- PX30_CLKGATE_CON(0), 6, GFLAGS), ++ RK2928_CLKGATE_CON(0), 6, GFLAGS), + GATE(0, "dpll_core", "dpll", CLK_IGNORE_UNUSED, +- PX30_CLKGATE_CON(0), 6, GFLAGS), ++ RK2928_CLKGATE_CON(0), 6, GFLAGS), + COMPOSITE_NOMUX(0, "pclk_dbg", "armclk", CLK_IGNORE_UNUSED, + RK2928_CLKSEL_CON(1), 0, 4, DFLAGS | CLK_DIVIDER_READ_ONLY, + RK2928_CLKGATE_CON(4), 1, GFLAGS), + +From 8c78a060509051d135fceaaddd45aa8f3991298f Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sun, 16 Aug 2020 16:52:03 +0200 +Subject: [PATCH] clk: rockchip: add CLOCK_IGNORE_UNUSED to serval RK3228 clks + +Some clocks need the CLOCK_IGNORE_UNUSED flag in order to be prevented from being +disabled at boot time and to get respective devices working. +Has been taken from vendor kernel. +--- + drivers/clk/rockchip/clk-rk3228.c | 58 +++++++++++++++---------------- + 1 file changed, 29 insertions(+), 29 deletions(-) + +diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c +index 448b202bf4f3..e6654938d6bd 100644 +--- a/drivers/clk/rockchip/clk-rk3228.c ++++ b/drivers/clk/rockchip/clk-rk3228.c +@@ -510,12 +510,12 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + + /* PD_VOP */ + GATE(ACLK_RGA, "aclk_rga", "aclk_rga_pre", 0, RK2928_CLKGATE_CON(13), 0, GFLAGS), +- GATE(0, "aclk_rga_noc", "aclk_rga_pre", 0, RK2928_CLKGATE_CON(13), 11, GFLAGS), ++ GATE(0, "aclk_rga_noc", "aclk_rga_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(13), 11, GFLAGS), + GATE(ACLK_IEP, "aclk_iep", "aclk_iep_pre", 0, RK2928_CLKGATE_CON(13), 2, GFLAGS), +- GATE(0, "aclk_iep_noc", "aclk_iep_pre", 0, RK2928_CLKGATE_CON(13), 9, GFLAGS), ++ GATE(0, "aclk_iep_noc", "aclk_iep_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(13), 9, GFLAGS), + + GATE(ACLK_VOP, "aclk_vop", "aclk_vop_pre", 0, RK2928_CLKGATE_CON(13), 5, GFLAGS), +- GATE(0, "aclk_vop_noc", "aclk_vop_pre", 0, RK2928_CLKGATE_CON(13), 12, GFLAGS), ++ GATE(0, "aclk_vop_noc", "aclk_vop_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(13), 12, GFLAGS), + + GATE(ACLK_HDCP, "aclk_hdcp", "aclk_hdcp_pre", 0, RK2928_CLKGATE_CON(14), 10, GFLAGS), + GATE(0, "aclk_hdcp_noc", "aclk_hdcp_pre", 0, RK2928_CLKGATE_CON(13), 10, GFLAGS), +@@ -523,13 +523,13 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + GATE(HCLK_RGA, "hclk_rga", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 1, GFLAGS), + GATE(HCLK_IEP, "hclk_iep", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 3, GFLAGS), + GATE(HCLK_VOP, "hclk_vop", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 6, GFLAGS), +- GATE(0, "hclk_vio_ahb_arbi", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 7, GFLAGS), +- GATE(0, "hclk_vio_noc", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 8, GFLAGS), +- GATE(0, "hclk_vop_noc", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 13, GFLAGS), +- GATE(HCLK_VIO_H2P, "hclk_vio_h2p", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 7, GFLAGS), ++ GATE(0, "hclk_vio_ahb_arbi", "hclk_vio_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(13), 7, GFLAGS), ++ GATE(0, "hclk_vio_noc", "hclk_vio_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(13), 8, GFLAGS), ++ GATE(0, "hclk_vop_noc", "hclk_vio_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(13), 13, GFLAGS), ++ GATE(HCLK_VIO_H2P, "hclk_vio_h2p", "hclk_vio_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(14), 7, GFLAGS), + GATE(HCLK_HDCP_MMU, "hclk_hdcp_mmu", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 12, GFLAGS), + GATE(PCLK_HDMI_CTRL, "pclk_hdmi_ctrl", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 6, GFLAGS), +- GATE(PCLK_VIO_H2P, "pclk_vio_h2p", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 8, GFLAGS), ++ GATE(PCLK_VIO_H2P, "pclk_vio_h2p", "hclk_vio_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(14), 8, GFLAGS), + GATE(PCLK_HDCP, "pclk_hdcp", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 11, GFLAGS), + + /* PD_PERI */ +@@ -541,13 +541,13 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + GATE(HCLK_EMMC, "hclk_emmc", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 2, GFLAGS), + GATE(HCLK_NANDC, "hclk_nandc", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 3, GFLAGS), + GATE(HCLK_HOST0, "hclk_host0", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 6, GFLAGS), +- GATE(0, "hclk_host0_arb", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 7, GFLAGS), ++ GATE(0, "hclk_host0_arb", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(11), 7, GFLAGS), + GATE(HCLK_HOST1, "hclk_host1", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 8, GFLAGS), +- GATE(0, "hclk_host1_arb", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 9, GFLAGS), ++ GATE(0, "hclk_host1_arb", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(11), 9, GFLAGS), + GATE(HCLK_HOST2, "hclk_host2", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 10, GFLAGS), + GATE(HCLK_OTG, "hclk_otg", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 12, GFLAGS), +- GATE(0, "hclk_otg_pmu", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 13, GFLAGS), +- GATE(0, "hclk_host2_arb", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 14, GFLAGS), ++ GATE(0, "hclk_otg_pmu", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(11), 13, GFLAGS), ++ GATE(0, "hclk_host2_arb", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(11), 14, GFLAGS), + GATE(0, "hclk_peri_noc", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(12), 1, GFLAGS), + + GATE(PCLK_GMAC, "pclk_gmac", "pclk_peri", 0, RK2928_CLKGATE_CON(11), 5, GFLAGS), +@@ -555,15 +555,15 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + + /* PD_GPU */ + GATE(ACLK_GPU, "aclk_gpu", "aclk_gpu_pre", 0, RK2928_CLKGATE_CON(7), 14, GFLAGS), +- GATE(0, "aclk_gpu_noc", "aclk_gpu_pre", 0, RK2928_CLKGATE_CON(7), 15, GFLAGS), ++ GATE(0, "aclk_gpu_noc", "aclk_gpu_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(7), 15, GFLAGS), + + /* PD_BUS */ +- GATE(0, "sclk_initmem_mbist", "aclk_cpu", 0, RK2928_CLKGATE_CON(8), 1, GFLAGS), +- GATE(0, "aclk_initmem", "aclk_cpu", 0, RK2928_CLKGATE_CON(8), 0, GFLAGS), ++ GATE(0, "sclk_initmem_mbist", "aclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(8), 1, GFLAGS), ++ GATE(0, "aclk_initmem", "aclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(8), 0, GFLAGS), + GATE(ACLK_DMAC, "aclk_dmac_bus", "aclk_cpu", 0, RK2928_CLKGATE_CON(8), 2, GFLAGS), + GATE(0, "aclk_bus_noc", "aclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 1, GFLAGS), + +- GATE(0, "hclk_rom", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 3, GFLAGS), ++ GATE(0, "hclk_rom", "hclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(8), 3, GFLAGS), + GATE(HCLK_I2S0_8CH, "hclk_i2s0_8ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 7, GFLAGS), + GATE(HCLK_I2S1_8CH, "hclk_i2s1_8ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 8, GFLAGS), + GATE(HCLK_I2S2_2CH, "hclk_i2s2_2ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 9, GFLAGS), +@@ -572,9 +572,9 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + GATE(HCLK_M_CRYPTO, "hclk_crypto_mst", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 11, GFLAGS), + GATE(HCLK_S_CRYPTO, "hclk_crypto_slv", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 12, GFLAGS), + +- GATE(0, "pclk_ddrupctl", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(8), 4, GFLAGS), +- GATE(0, "pclk_ddrmon", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(8), 6, GFLAGS), +- GATE(0, "pclk_msch_noc", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(10), 2, GFLAGS), ++ GATE(0, "pclk_ddrupctl", "pclk_ddr_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(8), 4, GFLAGS), ++ GATE(0, "pclk_ddrmon", "pclk_ddr_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(8), 6, GFLAGS), ++ GATE(0, "pclk_msch_noc", "pclk_ddr_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 2, GFLAGS), + + GATE(PCLK_EFUSE_1024, "pclk_efuse_1024", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 13, GFLAGS), + GATE(PCLK_EFUSE_256, "pclk_efuse_256", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 14, GFLAGS), +@@ -583,7 +583,7 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + GATE(PCLK_I2C2, "pclk_i2c2", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 1, GFLAGS), + GATE(PCLK_I2C3, "pclk_i2c3", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 2, GFLAGS), + GATE(PCLK_TIMER, "pclk_timer0", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 4, GFLAGS), +- GATE(0, "pclk_stimer", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 5, GFLAGS), ++ GATE(0, "pclk_stimer", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 5, GFLAGS), + GATE(PCLK_SPI0, "pclk_spi0", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 6, GFLAGS), + GATE(PCLK_PWM, "pclk_rk_pwm", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 7, GFLAGS), + GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 8, GFLAGS), +@@ -597,22 +597,22 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + GATE(PCLK_GRF, "pclk_grf", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 0, GFLAGS), + GATE(0, "pclk_cru", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 1, GFLAGS), + GATE(0, "pclk_sgrf", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 2, GFLAGS), +- GATE(0, "pclk_sim", "pclk_cpu", 0, RK2928_CLKGATE_CON(10), 3, GFLAGS), ++ GATE(0, "pclk_sim", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 3, GFLAGS), + +- GATE(0, "pclk_ddrphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 3, GFLAGS), +- GATE(0, "pclk_acodecphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 5, GFLAGS), ++ GATE(0, "pclk_ddrphy", "pclk_phy_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 3, GFLAGS), ++ GATE(0, "pclk_acodecphy", "pclk_phy_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 5, GFLAGS), + GATE(PCLK_HDMI_PHY, "pclk_hdmiphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 7, GFLAGS), +- GATE(0, "pclk_vdacphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 8, GFLAGS), +- GATE(0, "pclk_phy_noc", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 9, GFLAGS), ++ GATE(0, "pclk_vdacphy", "pclk_phy_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 8, GFLAGS), ++ GATE(0, "pclk_phy_noc", "pclk_phy_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 9, GFLAGS), + + GATE(ACLK_VPU, "aclk_vpu", "aclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 0, GFLAGS), +- GATE(0, "aclk_vpu_noc", "aclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 4, GFLAGS), ++ GATE(0, "aclk_vpu_noc", "aclk_vpu_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(15), 4, GFLAGS), + GATE(ACLK_RKVDEC, "aclk_rkvdec", "aclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 2, GFLAGS), +- GATE(0, "aclk_rkvdec_noc", "aclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 6, GFLAGS), ++ GATE(0, "aclk_rkvdec_noc", "aclk_rkvdec_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(15), 6, GFLAGS), + GATE(HCLK_VPU, "hclk_vpu", "hclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 1, GFLAGS), +- GATE(0, "hclk_vpu_noc", "hclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 5, GFLAGS), ++ GATE(0, "hclk_vpu_noc", "hclk_vpu_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(15), 5, GFLAGS), + GATE(HCLK_RKVDEC, "hclk_rkvdec", "hclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 3, GFLAGS), +- GATE(0, "hclk_rkvdec_noc", "hclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 7, GFLAGS), ++ GATE(0, "hclk_rkvdec_noc", "hclk_rkvdec_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(15), 7, GFLAGS), + + /* PD_MMC */ + MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "sclk_sdmmc", RK3228_SDMMC_CON0, 1), + +From facbc2eed0bab25a67e65387c9ac05d504fb886e Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sun, 16 Aug 2020 17:07:35 +0200 +Subject: [PATCH] clk: rockchip add aclk_rkvdec and hclk_rkvdec to RK3228 + critical clocks + +To be prevented from being disabled at any time add aclk_rkvdec and hclk_rkvdec +to RK3228 critical clocks +--- + drivers/clk/rockchip/clk-rk3228.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c +index e6654938d6bd..595ad0301ca6 100644 +--- a/drivers/clk/rockchip/clk-rk3228.c ++++ b/drivers/clk/rockchip/clk-rk3228.c +@@ -656,8 +656,10 @@ static const char *const rk3228_critical_clocks[] __initconst = { + "pclk_phy_noc", + "aclk_vpu_noc", + "aclk_rkvdec_noc", ++ "aclk_rkvdec", + "hclk_vpu_noc", + "hclk_rkvdec_noc", ++ "hclk_rkvdec", + }; + + static void __init rk3228_clk_init(struct device_node *np) + +From 4a3f15e1bc2fb7cb7c093e2814dbc9f447e82bbc Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Fri, 24 Apr 2020 11:42:58 +0200 +Subject: [PATCH] soc: rockchip: Support powerdomains which don't need / + support to be switched on / off + +Taken from https://github.com/rockchip-linux/kernel/commit/5be2cb19cf8e678655b59ec70c6a5f66f08d9418 +--- + drivers/soc/rockchip/pm_domains.c | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c +index 727af107e6d3..3688e9e67872 100644 +--- a/drivers/soc/rockchip/pm_domains.c ++++ b/drivers/soc/rockchip/pm_domains.c +@@ -71,6 +71,7 @@ struct rockchip_pm_domain { + struct regmap **qos_regmap; + u32 *qos_save_regs[MAX_QOS_REGS_NUM]; + int num_clks; ++ bool is_ignore_pwr; + struct clk_bulk_data *clks; + }; + +@@ -353,6 +354,9 @@ static int rockchip_pd_power_on(struct generic_pm_domain *domain) + { + struct rockchip_pm_domain *pd = to_rockchip_pd(domain); + ++ if (pd->is_ignore_pwr) ++ return 0; ++ + return rockchip_pd_power(pd, true); + } + +@@ -360,6 +364,9 @@ static int rockchip_pd_power_off(struct generic_pm_domain *domain) + { + struct rockchip_pm_domain *pd = to_rockchip_pd(domain); + ++ if (pd->is_ignore_pwr) ++ return 0; ++ + return rockchip_pd_power(pd, false); + } + +@@ -439,6 +446,9 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, + pd->info = pd_info; + pd->pmu = pmu; + ++ if (!pd_info->pwr_mask) ++ pd->is_ignore_pwr = true; ++ + pd->num_clks = of_clk_get_parent_count(node); + if (pd->num_clks > 0) { + pd->clks = devm_kcalloc(pmu->dev, pd->num_clks, +@@ -589,6 +599,7 @@ static int rockchip_pm_add_subdomain(struct rockchip_pmu *pmu, + { + struct device_node *np; + struct generic_pm_domain *child_domain, *parent_domain; ++ struct rockchip_pm_domain *child_pd, *parent_pd; + int error; + + for_each_child_of_node(parent, np) { +@@ -629,6 +640,18 @@ static int rockchip_pm_add_subdomain(struct rockchip_pmu *pmu, + parent_domain->name, child_domain->name); + } + ++ /* ++ * If child_pd doesn't do idle request or power on/off, ++ * parent_pd may fail to do power on/off, so if parent_pd ++ * need to power on/off, child_pd can't ignore to do idle ++ * request and power on/off. ++ */ ++ child_pd = to_rockchip_pd(child_domain); ++ parent_pd = to_rockchip_pd(parent_domain); ++ if (!parent_pd->is_ignore_pwr) ++ child_pd->is_ignore_pwr = false; ++ ++ + rockchip_pm_add_subdomain(pmu, np); + } + + +From 02a2d327ebfce5e3b4ddd839c2cf3b9631c38b91 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Fri, 24 Apr 2020 13:01:07 +0200 +Subject: [PATCH] sound: soc: rockchip: use rouned rate for i2s + +--- + sound/soc/rockchip/rockchip_i2s.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c +index 61c984f10d8e..efca853eba6b 100644 +--- a/sound/soc/rockchip/rockchip_i2s.c ++++ b/sound/soc/rockchip/rockchip_i2s.c +@@ -279,10 +279,13 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, + if (i2s->is_master_mode) { + mclk_rate = clk_get_rate(i2s->mclk); + bclk_rate = 2 * 32 * params_rate(params); +- if (bclk_rate && mclk_rate % bclk_rate) ++ if (!bclk_rate) { ++ dev_err(i2s->dev, "invalid bclk_rate: %d\n", ++ bclk_rate); + return -EINVAL; ++ } + +- div_bclk = mclk_rate / bclk_rate; ++ div_bclk = DIV_ROUND_CLOSEST(mclk_rate, bclk_rate); + div_lrck = bclk_rate / params_rate(params); + regmap_update_bits(i2s->regmap, I2S_CKR, + I2S_CKR_MDIV_MASK, +@@ -312,6 +315,8 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, + val |= I2S_TXCR_VDW(32); + break; + default: ++ dev_err(i2s->dev, "invalid format: %d\n", ++ params_format(params)); + return -EINVAL; + } + + +From 824bce392cfdaaf0037f33637078e722a9f757b9 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Fri, 24 Apr 2020 09:08:44 +0200 +Subject: [PATCH] phy: rockchip: hdmi: readout hdmi phy flag for RK3228 HDMI + phys + +Some RK3228 HDMI phys only get a stable pll on frequencies higher 33,75 MHz. +This is defined in a flag in efuse of those devices. +--- + arch/arm/boot/dts/rk322x.dtsi | 6 +++ + drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 38 ++++++++++++++++++- + 2 files changed, 42 insertions(+), 2 deletions(-) + +diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi +index eec601fb4cd0..81dfdc8c864a 100644 +--- a/arch/arm/boot/dts/rk322x.dtsi ++++ b/arch/arm/boot/dts/rk322x.dtsi +@@ -340,6 +340,10 @@ efuse_id: id@7 { + cpu_leakage: cpu_leakage@17 { + reg = <0x17 0x1>; + }; ++ hdmi_phy_flag: hdmi-phy-flag@1d { ++ reg = <0x1d 0x1>; ++ bits = <1 1>; ++ }; + }; + + i2c0: i2c@11050000 { +@@ -559,6 +563,8 @@ hdmi_phy: hdmi-phy@12030000 { + clock-names = "sysclk", "refoclk", "refpclk"; + #clock-cells = <0>; + clock-output-names = "hdmiphy_phy"; ++ nvmem-cells = <&hdmi_phy_flag>; ++ nvmem-cell-names = "hdmi-phy-flag"; + #phy-cells = <0>; + status = "disabled"; + }; +diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c +index bb8bdf5e3301..0c7a97352714 100644 +--- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c +@@ -237,6 +237,9 @@ struct inno_hdmi_phy { + struct clk *refoclk; + struct clk *refpclk; + ++ /* phy_flag flag */ ++ bool phy_flag; ++ + /* platform data */ + const struct inno_hdmi_phy_drv_data *plat_data; + int chip_version; +@@ -347,6 +350,7 @@ static const struct pre_pll_config pre_pll_cfg_table[] = { + static const struct post_pll_config post_pll_cfg_table[] = { + {33750000, 1, 40, 8, 1}, + {33750000, 1, 80, 8, 2}, ++ {33750000, 1, 10, 2, 4}, + {74250000, 1, 40, 8, 1}, + {74250000, 18, 80, 8, 2}, + {148500000, 2, 40, 4, 3}, +@@ -497,8 +501,11 @@ static int inno_hdmi_phy_power_on(struct phy *phy) + return -EINVAL; + + for (; cfg->tmdsclock != 0; cfg++) +- if (tmdsclock <= cfg->tmdsclock && +- cfg->version & inno->chip_version) ++ if (((!inno->phy_flag || tmdsclock > 33750000) ++ && tmdsclock <= cfg->tmdsclock ++ && cfg->version & inno->chip_version) || ++ (inno->phy_flag && tmdsclock <= 33750000 ++ && cfg->version & 4)) + break; + + for (; phy_cfg->tmdsclock != 0; phy_cfg++) +@@ -909,6 +916,10 @@ static int inno_hdmi_phy_clk_register(struct inno_hdmi_phy *inno) + + static int inno_hdmi_phy_rk3228_init(struct inno_hdmi_phy *inno) + { ++ struct nvmem_cell *cell; ++ unsigned char *efuse_buf; ++ size_t len; ++ + /* + * Use phy internal register control + * rxsense/poweron/pllpd/pdataen signal. +@@ -923,7 +934,28 @@ static int inno_hdmi_phy_rk3228_init(struct inno_hdmi_phy *inno) + inno_update_bits(inno, 0xaa, RK3228_POST_PLL_CTRL_MANUAL, + RK3228_POST_PLL_CTRL_MANUAL); + ++ + inno->chip_version = 1; ++ inno->phy_flag = false; ++ ++ cell = nvmem_cell_get(inno->dev, "hdmi-phy-flag"); ++ if (IS_ERR(cell)) { ++ if (PTR_ERR(cell) == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ ++ return 0; ++ } ++ ++ efuse_buf = nvmem_cell_read(cell, &len); ++ nvmem_cell_put(cell); ++ ++ if (IS_ERR(efuse_buf)) ++ return 0; ++ if (len == 1) ++ inno->phy_flag = (efuse_buf[0] & BIT(1)) ? true : false; ++ kfree(efuse_buf); ++ ++ dev_info(inno->dev, "phy_flag is: %d\n", inno->phy_flag); + + return 0; + } +@@ -1023,6 +1055,8 @@ static int inno_hdmi_phy_rk3328_init(struct inno_hdmi_phy *inno) + + /* try to read the chip-version */ + inno->chip_version = 1; ++ inno->phy_flag = false; ++ + cell = nvmem_cell_get(inno->dev, "cpu-version"); + if (IS_ERR(cell)) { + if (PTR_ERR(cell) == -EPROBE_DEFER) + +From ac8834648e1e35703f6a0533b7c90b24d0d537da Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Tue, 26 May 2020 14:41:39 +0200 +Subject: [PATCH] usb: dwc2: QUIRKS: rockchip host only controller needs longer + msleep to initialize + +--- + drivers/usb/dwc2/core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c +index fec17a2d2447..eb55c64f63be 100644 +--- a/drivers/usb/dwc2/core.c ++++ b/drivers/usb/dwc2/core.c +@@ -663,7 +663,7 @@ void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg) + * platforms on their host-only dwc2. + */ + if (!dwc2_hw_is_otg(hsotg)) +- msleep(50); ++ msleep(200); + + break; + case USB_DR_MODE_PERIPHERAL: + +From 98c3cfe4ee409e64edcb9dff8341637588c9e166 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sun, 16 Aug 2020 17:35:43 +0200 +Subject: [PATCH] nvmem: rockchip-efuse: fix RK3188 efuse read + +In order to read from RK3188s efuse, the logic is slightly different from whats +done currently for RK3288 and also used for this SoC. +Logic, register mask and udelays have been taken from vendor kernel. +--- + drivers/nvmem/rockchip-efuse.c | 49 +++++++++++++++++++++++++++++++++- + 1 file changed, 48 insertions(+), 1 deletion(-) + +diff --git a/drivers/nvmem/rockchip-efuse.c b/drivers/nvmem/rockchip-efuse.c +index e4579de5d014..9afd71edf503 100644 +--- a/drivers/nvmem/rockchip-efuse.c ++++ b/drivers/nvmem/rockchip-efuse.c +@@ -17,6 +17,8 @@ + #include + #include + ++#define RK3188_A_MASK 0xff ++ + #define RK3288_A_SHIFT 6 + #define RK3288_A_MASK 0x3ff + #define RK3288_PGENB BIT(3) +@@ -52,6 +54,51 @@ struct rockchip_efuse_chip { + struct clk *clk; + }; + ++static int rockchip_rk3188_efuse_read(void *context, unsigned int offset, ++ void *val, size_t bytes) ++{ ++ struct rockchip_efuse_chip *efuse = context; ++ u8 *buf = val; ++ int ret; ++ ++ ret = clk_prepare_enable(efuse->clk); ++ if (ret < 0) { ++ dev_err(efuse->dev, "failed to prepare/enable efuse clk\n"); ++ return ret; ++ } ++ ++ writel(RK3288_CSB, efuse->base + REG_EFUSE_CTRL); ++ writel(RK3288_LOAD | RK3288_PGENB, efuse->base + REG_EFUSE_CTRL); ++ udelay(2); ++ ++ while (bytes--) { ++ writel(readl(efuse->base + REG_EFUSE_CTRL) & ++ (~(RK3188_A_MASK << RK3288_A_SHIFT)), ++ efuse->base + REG_EFUSE_CTRL); ++ writel(readl(efuse->base + REG_EFUSE_CTRL) | ++ ((offset++ & RK3188_A_MASK) << RK3288_A_SHIFT), ++ efuse->base + REG_EFUSE_CTRL); ++ udelay(2); ++ writel(readl(efuse->base + REG_EFUSE_CTRL) | ++ RK3288_STROBE, efuse->base + REG_EFUSE_CTRL); ++ udelay(2); ++ ++ *buf++ = readl(efuse->base + REG_EFUSE_DOUT); ++ writel(readl(efuse->base + REG_EFUSE_CTRL) & ++ (~RK3288_STROBE), efuse->base + REG_EFUSE_CTRL); ++ udelay(2); ++ } ++ ++ udelay(2); ++ /* Switch to standby mode */ ++ writel(RK3288_PGENB | RK3288_CSB, efuse->base + REG_EFUSE_CTRL); ++ udelay(1); ++ ++ clk_disable_unprepare(efuse->clk); ++ ++ return 0; ++} ++ + static int rockchip_rk3288_efuse_read(void *context, unsigned int offset, + void *val, size_t bytes) + { +@@ -222,7 +269,7 @@ static const struct of_device_id rockchip_efuse_match[] = { + }, + { + .compatible = "rockchip,rk3188-efuse", +- .data = (void *)&rockchip_rk3288_efuse_read, ++ .data = (void *)&rockchip_rk3188_efuse_read, + }, + { + .compatible = "rockchip,rk3228-efuse", + +From e95330563d2dfd9086ac3cadee0129b045c7a25d Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sun, 16 Aug 2020 17:43:08 +0200 +Subject: [PATCH] ARM: dts: rockchip: fix RK3188 efuse register width + +As with most Rockchip SoCs the RK3188s non-secure efuse contains 32 bytes of data. +This adapts the register width, so that we don't get repeated data when reading +out the values from it. +--- + arch/arm/boot/dts/rk3188.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi +index b6c1699345d0..9fab375231ec 100644 +--- a/arch/arm/boot/dts/rk3188.dtsi ++++ b/arch/arm/boot/dts/rk3188.dtsi +@@ -216,7 +216,7 @@ cru: clock-controller@20000000 { + + efuse: efuse@20010000 { + compatible = "rockchip,rk3188-efuse"; +- reg = <0x20010000 0x4000>; ++ reg = <0x20010000 0x20>; + #address-cells = <1>; + #size-cells = <1>; + clocks = <&cru PCLK_EFUSE>; + +From e12fc84e0782e332a2d309cc89f52119eee55de3 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sun, 16 Aug 2020 18:51:38 +0200 +Subject: [PATCH] ARM: dts: rockchip add operating-points, power-domain for + RK322Xs GPU + +This adds the operating-points table and the power-domain and the respective +qos registers for RK322xs GPU. +While at this it also adds the GPU to be a cooling cell. +--- + arch/arm/boot/dts/rk322x.dtsi | 39 ++++++++++++++++++++++++++++++++++- + 1 file changed, 38 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi +index 81dfdc8c864a..9e531d229ae1 100644 +--- a/arch/arm/boot/dts/rk322x.dtsi ++++ b/arch/arm/boot/dts/rk322x.dtsi +@@ -215,6 +215,12 @@ power: power-controller { + #address-cells = <1>; + #size-cells = <0>; + ++ pd_gpu@RK3228_PD_GPU { ++ reg = ; ++ clocks = <&cru ACLK_GPU>; ++ pm_qos = <&qos_gpu>; ++ }; ++ + pd_vpu@RK3228_PD_VPU { + reg = ; + clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; +@@ -533,6 +539,11 @@ map1 { + <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; ++ map2 { ++ trip = <&cpu_alert1>; ++ cooling-device = ++ <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; ++ }; + }; + }; + }; +@@ -587,7 +598,28 @@ gpu: gpu@20000000 { + clocks = <&cru ACLK_GPU>, <&cru ACLK_GPU>; + clock-names = "bus", "core"; + resets = <&cru SRST_GPU_A>; +- status = "disabled"; ++ operating-points-v2 = <&gpu_opp_table>; ++ power-domains = <&power RK3228_PD_GPU>; ++ #cooling-cells = <2>; /* min followed by max */ ++ }; ++ ++ gpu_opp_table: opp-table2 { ++ compatible = "operating-points-v2"; ++ ++ opp-200000000 { ++ opp-hz = /bits/ 64 <200000000>; ++ opp-microvolt = <1050000>; ++ }; ++ ++ opp-300000000 { ++ opp-hz = /bits/ 64 <300000000>; ++ opp-microvolt = <1050000>; ++ }; ++ ++ opp-500000000 { ++ opp-hz = /bits/ 64 <500000000>; ++ opp-microvolt = <1150000>; ++ }; + }; + + vpu: video-codec@20020000 { +@@ -872,6 +904,11 @@ qos_vpu: qos@31040000 { + reg = <0x31040000 0x20>; + }; + ++ qos_gpu: qos@31050000 { ++ compatible = "syscon"; ++ reg = <0x31050000 0x20>; ++ }; ++ + qos_rkvdec_r: qos@31070000 { + compatible = "syscon"; + reg = <0x31070000 0x20>; + +From 19b4b92aa56381148255f8d962649869f734b5f9 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sun, 16 Aug 2020 19:44:42 +0200 +Subject: [PATCH] ARM: dts: rockchip: add ethernet0 alias + +Add ethernet0 alias for gmac. This will, for example, be used +by u-boot to inject a "local-mac-address" in the devicetree. +--- + arch/arm/boot/dts/rk322x.dtsi | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi +index 9e531d229ae1..14eedffea4a3 100644 +--- a/arch/arm/boot/dts/rk322x.dtsi ++++ b/arch/arm/boot/dts/rk322x.dtsi +@@ -15,6 +15,7 @@ / { + interrupt-parent = <&gic>; + + aliases { ++ ethernet0 = &gmac; + serial0 = &uart0; + serial1 = &uart1; + serial2 = &uart2; + +From 7c1f6ab6b0c97b7aacaa39f842a9e8ef7bbea83e Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sun, 16 Aug 2020 20:00:01 +0200 +Subject: [PATCH] ARM: dts: rockchip: add hdmi simple-audio-card for RK322x + +Add "simple-audio-card" definition for hdmi-sound. While at +that also add the missing #sound-dai-cells for i2s, spdif and hdmi +nodes. +--- + arch/arm/boot/dts/rk322x.dtsi | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi +index 14eedffea4a3..7f15fc838c36 100644 +--- a/arch/arm/boot/dts/rk322x.dtsi ++++ b/arch/arm/boot/dts/rk322x.dtsi +@@ -124,6 +124,22 @@ arm-pmu { + interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>; + }; + ++ hdmi_sound: hdmi-sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,name = "hdmi-sound"; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,mclk-fs = <256>; ++ status = "disabled"; ++ ++ simple-audio-card,cpu { ++ sound-dai = <&i2s0>; ++ }; ++ ++ simple-audio-card,codec { ++ sound-dai = <&hdmi>; ++ }; ++ }; ++ + psci { + compatible = "arm,psci-1.0", "arm,psci-0.2"; + method = "smc"; +@@ -161,6 +177,7 @@ i2s1: i2s1@100b0000 { + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&i2s1_bus>; ++ #sound-dai-cells = <0>; + status = "disabled"; + }; + +@@ -172,6 +189,7 @@ i2s0: i2s0@100c0000 { + clocks = <&cru SCLK_I2S0>, <&cru HCLK_I2S0_8CH>; + dmas = <&pdma 11>, <&pdma 12>; + dma-names = "tx", "rx"; ++ #sound-dai-cells = <0>; + status = "disabled"; + }; + +@@ -185,6 +203,7 @@ spdif: spdif@100d0000 { + dma-names = "tx"; + pinctrl-names = "default"; + pinctrl-0 = <&spdif_tx>; ++ #sound-dai-cells = <0>; + status = "disabled"; + }; + +@@ -746,6 +765,7 @@ hdmi: hdmi@200a0000 { + phys = <&hdmi_phy>; + phy-names = "hdmi"; + rockchip,grf = <&grf>; ++ #sound-dai-cells = <0>; + status = "disabled"; + + ports { + +From 6fa1bf91b123f703a2fde726ad52af1539f365d0 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sun, 16 Aug 2020 21:16:11 +0200 +Subject: [PATCH] ARM: dts: rockchip: add uart1-1 pins for RK322x + +Add uart uart1-1 pins. +While at this also correct the uart2 default pinctrl, which is uart21_xfer. +--- + arch/arm/boot/dts/rk322x.dtsi | 19 ++++++++++++++++++- + 1 file changed, 18 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi +index 7f15fc838c36..693c6f18a889 100644 +--- a/arch/arm/boot/dts/rk322x.dtsi ++++ b/arch/arm/boot/dts/rk322x.dtsi +@@ -345,7 +345,7 @@ uart2: serial@11030000 { + clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>; + clock-names = "baudclk", "apb_pclk"; + pinctrl-names = "default"; +- pinctrl-0 = <&uart2_xfer>; ++ pinctrl-0 = <&uart21_xfer>; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; +@@ -1275,13 +1275,30 @@ uart1_xfer: uart1-xfer { + <1 RK_PB2 1 &pcfg_pull_none>; + }; + ++ uart11_xfer: uart11-xfer { ++ rockchip,pins = <3 RK_PB6 1 &pcfg_pull_up>, ++ <3 RK_PB5 1 &pcfg_pull_none>; ++ }; ++ + uart1_cts: uart1-cts { + rockchip,pins = <1 RK_PB0 1 &pcfg_pull_none>; + }; + ++ uart11_cts: uart11-cts { ++ rockchip,pins = <3 RK_PA7 1 &pcfg_pull_none>; ++ }; ++ + uart1_rts: uart1-rts { + rockchip,pins = <1 RK_PB3 1 &pcfg_pull_none>; + }; ++ ++ uart11_rts: uart11-rts { ++ rockchip,pins = <3 RK_PA6 1 &pcfg_pull_none>; ++ }; ++ ++ uart11_rts_gpio: uart11-rts-gpio { ++ rockchip,pins = <3 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; + }; + + uart2 { + +From 1c37c9a10362d2e049be1386bb1da7d4f488b1d8 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sun, 16 Aug 2020 21:58:56 +0200 +Subject: [PATCH] ARM: dts: rockchip: align mmc* node properties with driver + +Add resets, max-frequency and bus-width properties where required to emmc +,sdmmc and sdio nodes. While at that also add the sdmmc_pwr pinctrl which +is required to get the sd-card controller to work, if it was not/wrong +initialized by the bootloader (i.e. u-boot) +--- + arch/arm/boot/dts/rk322x.dtsi | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi +index 693c6f18a889..92e3eb1e7938 100644 +--- a/arch/arm/boot/dts/rk322x.dtsi ++++ b/arch/arm/boot/dts/rk322x.dtsi +@@ -787,9 +787,13 @@ sdmmc: mmc@30000000 { + clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>, + <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>; + clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; ++ bus-width = <4>; + fifo-depth = <0x100>; ++ max-frequency = <150000000>; + pinctrl-names = "default"; +- pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_bus4>; ++ pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_bus4 &sdmmc_pwr>; ++ resets = <&cru SRST_SDMMC>; ++ reset-names = "reset"; + status = "disabled"; + }; + +@@ -799,10 +803,14 @@ sdio: mmc@30010000 { + interrupts = ; + clocks = <&cru HCLK_SDIO>, <&cru SCLK_SDIO>, + <&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>; ++ bus-width = <4>; + clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; + fifo-depth = <0x100>; ++ max-frequency = <150000000>; + pinctrl-names = "default"; + pinctrl-0 = <&sdio_clk &sdio_cmd &sdio_bus4>; ++ resets = <&cru SRST_SDIO>; ++ reset-names = "reset"; + status = "disabled"; + }; + +@@ -810,14 +818,13 @@ emmc: mmc@30020000 { + compatible = "rockchip,rk3228-dw-mshc", "rockchip,rk3288-dw-mshc"; + reg = <0x30020000 0x4000>; + interrupts = ; +- clock-frequency = <37500000>; +- max-frequency = <37500000>; + clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>, + <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>; + clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; + bus-width = <8>; + rockchip,default-sample-phase = <158>; + fifo-depth = <0x100>; ++ max-frequency = <150000000>; + pinctrl-names = "default"; + pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; + resets = <&cru SRST_EMMC>; +@@ -1043,6 +1050,10 @@ sdmmc_bus4: sdmmc-bus4 { + <1 RK_PC4 1 &pcfg_pull_none_drv_12ma>, + <1 RK_PC5 1 &pcfg_pull_none_drv_12ma>; + }; ++ ++ sdmmc_pwr: sdmmc-pwr { ++ rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; + }; + + sdio { + +From 9a9db392c9d0fd23dd84c39f36290ab0bfbc2021 Mon Sep 17 00:00:00 2001 +From: Jeffy Chen +Date: Wed, 8 Jun 2016 14:05:42 +0800 +Subject: [PATCH] clk: rockchip: rk3036: add ACLK_VCODEC + +Change-Id: I36f6b23139345941656c127718cc4ff01c6d629f +Signed-off-by: Jeffy Chen +--- + drivers/clk/rockchip/clk-rk3036.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c +index 6a46f85ad837..3b285261ce39 100644 +--- a/drivers/clk/rockchip/clk-rk3036.c ++++ b/drivers/clk/rockchip/clk-rk3036.c +@@ -258,7 +258,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { + RK2928_CLKGATE_CON(1), 13, GFLAGS, + &rk3036_uart2_fracmux), + +- COMPOSITE(0, "aclk_vcodec", mux_pll_src_3plls_p, 0, ++ COMPOSITE(ACLK_VCODEC, "aclk_vcodec", mux_pll_src_3plls_p, 0, + RK2928_CLKSEL_CON(32), 14, 2, MFLAGS, 8, 5, DFLAGS, + RK2928_CLKGATE_CON(3), 11, GFLAGS), + FACTOR_GATE(HCLK_VCODEC, "hclk_vcodec", "aclk_vcodec", 0, 1, 4, + +From e1dd6aaa44b5ae46657f83bb066f50f5c9e0568a Mon Sep 17 00:00:00 2001 +From: Randy Li +Date: Fri, 20 Oct 2017 14:38:09 +0800 +Subject: [PATCH] clk: rockchip: rk3036: export the hevc core clock + +The clock hevc core will be used to drive the hevc decoder. + +Change-Id: Ic1298ce1edd07f86e5c243e3a2c9876481f4cba9 +Signed-off-by: Randy Li +--- + drivers/clk/rockchip/clk-rk3036.c | 2 +- + include/dt-bindings/clock/rk3036-cru.h | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c +index 3b285261ce39..a98ea978fc8a 100644 +--- a/drivers/clk/rockchip/clk-rk3036.c ++++ b/drivers/clk/rockchip/clk-rk3036.c +@@ -264,7 +264,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { + FACTOR_GATE(HCLK_VCODEC, "hclk_vcodec", "aclk_vcodec", 0, 1, 4, + RK2928_CLKGATE_CON(3), 12, GFLAGS), + +- COMPOSITE(0, "aclk_hvec", mux_pll_src_3plls_p, 0, ++ COMPOSITE(ACLK_HEVC, "aclk_hevc", mux_pll_src_3plls_p, 0, + RK2928_CLKSEL_CON(20), 0, 2, MFLAGS, 2, 5, DFLAGS, + RK2928_CLKGATE_CON(10), 6, GFLAGS), + +diff --git a/include/dt-bindings/clock/rk3036-cru.h b/include/dt-bindings/clock/rk3036-cru.h +index 35a5a01f9697..cd231f57278d 100644 +--- a/include/dt-bindings/clock/rk3036-cru.h ++++ b/include/dt-bindings/clock/rk3036-cru.h +@@ -55,6 +55,7 @@ + #define ACLK_VCODEC 208 + #define ACLK_CPU 209 + #define ACLK_PERI 210 ++#define ACLK_HEVC 211 + + /* pclk gates */ + #define PCLK_GPIO0 320 + +From e9752790e4c92f83924dc881cf1555977c512214 Mon Sep 17 00:00:00 2001 +From: Caesar Wang +Date: Mon, 13 Nov 2017 09:28:12 +0800 +Subject: [PATCH] clk: rockchip: export SCLK_I2S_PRE and SCLK_I2S_FRAC of i2s + on rk3036 + +Change-Id: I627c8c2582be2b27414e7b82e9d56dd560f68e64 +Signed-off-by: Caesar Wang +--- + drivers/clk/rockchip/clk-rk3036.c | 4 ++-- + include/dt-bindings/clock/rk3036-cru.h | 2 ++ + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c +index a98ea978fc8a..c67ee61ef0cd 100644 +--- a/drivers/clk/rockchip/clk-rk3036.c ++++ b/drivers/clk/rockchip/clk-rk3036.c +@@ -157,7 +157,7 @@ static struct rockchip_clk_branch rk3036_uart2_fracmux __initdata = + RK2928_CLKSEL_CON(15), 8, 2, MFLAGS); + + static struct rockchip_clk_branch rk3036_i2s_fracmux __initdata = +- MUX(0, "i2s_pre", mux_i2s_pre_p, CLK_SET_RATE_PARENT, ++ MUX(SCLK_I2S_PRE, "i2s_pre", mux_i2s_pre_p, CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(3), 8, 2, MFLAGS); + + static struct rockchip_clk_branch rk3036_spdif_fracmux __initdata = +@@ -306,7 +306,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { + COMPOSITE(0, "i2s_src", mux_pll_src_3plls_p, 0, + RK2928_CLKSEL_CON(3), 14, 2, MFLAGS, 0, 7, DFLAGS, + RK2928_CLKGATE_CON(0), 9, GFLAGS), +- COMPOSITE_FRACMUX(0, "i2s_frac", "i2s_src", CLK_SET_RATE_PARENT, ++ COMPOSITE_FRACMUX(SCLK_I2S_FRAC, "i2s_frac", "i2s_src", CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(7), 0, + RK2928_CLKGATE_CON(0), 10, GFLAGS, + &rk3036_i2s_fracmux), +diff --git a/include/dt-bindings/clock/rk3036-cru.h b/include/dt-bindings/clock/rk3036-cru.h +index cd231f57278d..4c7ff6141a67 100644 +--- a/include/dt-bindings/clock/rk3036-cru.h ++++ b/include/dt-bindings/clock/rk3036-cru.h +@@ -43,6 +43,8 @@ + #define SCLK_PVTM_CORE 123 + #define SCLK_PVTM_GPU 124 + #define SCLK_PVTM_VIDEO 125 ++#define SCLK_I2S_FRAC 126 ++#define SCLK_I2S_PRE 127 + #define SCLK_MAC 151 + #define SCLK_MACREF 152 + #define SCLK_MACPLL 153 + +From 1cfffef46d411629c71da2dea69c41b261355d5b Mon Sep 17 00:00:00 2001 +From: Caesar Wang +Date: Fri, 17 Nov 2017 14:49:16 +0800 +Subject: [PATCH] clk: rockchip: protect the armclk for rk3036 + +Some clocks may get disabled as a side effect of another clock +being disabled, because have no consumers. Says the dclk_hdmi's parent may +change from apll to gpll, but the apll's son clocks are very less. + +Change-Id: I4fb4e5fdf83a8f73979b50dbcf4f3e4543896fcf +Signed-off-by: Caesar Wang +--- + drivers/clk/rockchip/clk-rk3036.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c +index c67ee61ef0cd..ac5c1cfb3f54 100644 +--- a/drivers/clk/rockchip/clk-rk3036.c ++++ b/drivers/clk/rockchip/clk-rk3036.c +@@ -424,6 +424,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { + }; + + static const char *const rk3036_critical_clocks[] __initconst = { ++ "armclk", + "aclk_cpu", + "aclk_peri", + "hclk_peri", +@@ -467,14 +468,14 @@ static void __init rk3036_clk_init(struct device_node *np) + RK3036_GRF_SOC_STATUS0); + rockchip_clk_register_branches(ctx, rk3036_clk_branches, + ARRAY_SIZE(rk3036_clk_branches)); +- rockchip_clk_protect_critical(rk3036_critical_clocks, +- ARRAY_SIZE(rk3036_critical_clocks)); +- + rockchip_clk_register_armclk(ctx, ARMCLK, "armclk", + mux_armclk_p, ARRAY_SIZE(mux_armclk_p), + &rk3036_cpuclk_data, rk3036_cpuclk_rates, + ARRAY_SIZE(rk3036_cpuclk_rates)); + ++ rockchip_clk_protect_critical(rk3036_critical_clocks, ++ ARRAY_SIZE(rk3036_critical_clocks)); ++ + rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0), + ROCKCHIP_SOFTRST_HIWORD_MASK); + + +From 84f5c9e7a40b0e30b087aea7a618b18e2bb87fd5 Mon Sep 17 00:00:00 2001 +From: Finley Xiao +Date: Mon, 13 Nov 2017 15:32:25 +0800 +Subject: [PATCH] clk: rockchip: rk3036: leave apll for core, mac and lcdc only + +In order not to affect other clocks, remove the apll from the +parent list of other clocks and only core, mac and lcdc can +select apll as parent. + +Change-Id: I58b995f8ccf69c6564f74b5823f618a186030d70 +Signed-off-by: Finley Xiao +--- + drivers/clk/rockchip/clk-rk3036.c | 38 ++++++++++++++++--------------- + 1 file changed, 20 insertions(+), 18 deletions(-) + +diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c +index ac5c1cfb3f54..4ce2cf844123 100644 +--- a/drivers/clk/rockchip/clk-rk3036.c ++++ b/drivers/clk/rockchip/clk-rk3036.c +@@ -114,14 +114,16 @@ static const struct rockchip_cpuclk_reg_data rk3036_cpuclk_data = { + PNAME(mux_pll_p) = { "xin24m", "xin24m" }; + + PNAME(mux_armclk_p) = { "apll", "gpll_armclk" }; +-PNAME(mux_busclk_p) = { "apll", "dpll_cpu", "gpll_cpu" }; ++PNAME(mux_busclk_p) = { "dummy_apll", "dpll_cpu", "gpll_cpu" }; + PNAME(mux_ddrphy_p) = { "dpll_ddr", "gpll_ddr" }; +-PNAME(mux_pll_src_3plls_p) = { "apll", "dpll", "gpll" }; ++PNAME(mux_pll_src_apll_dpll_gpll_p) = { "apll", "dpll", "gpll" }; ++PNAME(mux_pll_src_dmyapll_dpll_gpll_p) = { "dummy_apll", "dpll", "gpll" }; ++ + PNAME(mux_timer_p) = { "xin24m", "pclk_peri_src" }; + +-PNAME(mux_pll_src_apll_dpll_gpll_usb480m_p) = { "apll", "dpll", "gpll", "usb480m" }; ++PNAME(mux_pll_src_dmyapll_dpll_gpll_usb480m_p) = { "dummy_apll", "dpll", "gpll", "usb480m" }; + +-PNAME(mux_mmc_src_p) = { "apll", "dpll", "gpll", "xin24m" }; ++PNAME(mux_mmc_src_p) = { "dummy_apll", "dpll", "gpll", "xin24m" }; + PNAME(mux_i2s_pre_p) = { "i2s_src", "i2s_frac", "ext_i2s", "xin12m" }; + PNAME(mux_i2s_clkout_p) = { "i2s_pre", "xin12m" }; + PNAME(mux_spdif_p) = { "spdif_src", "spdif_frac", "xin12m" }; +@@ -206,7 +208,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { + RK2928_CLKSEL_CON(1), 8, 2, DFLAGS | CLK_DIVIDER_READ_ONLY, + RK2928_CLKGATE_CON(0), 4, GFLAGS), + +- COMPOSITE(0, "aclk_peri_src", mux_pll_src_3plls_p, 0, ++ COMPOSITE(0, "aclk_peri_src", mux_pll_src_dmyapll_dpll_gpll_p, 0, + RK2928_CLKSEL_CON(10), 14, 2, MFLAGS, 0, 5, DFLAGS, + RK2928_CLKGATE_CON(2), 0, GFLAGS), + +@@ -234,7 +236,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { + RK2928_CLKSEL_CON(2), 7, 1, MFLAGS, + RK2928_CLKGATE_CON(2), 5, GFLAGS), + +- MUX(0, "uart_pll_clk", mux_pll_src_apll_dpll_gpll_usb480m_p, 0, ++ MUX(0, "uart_pll_clk", mux_pll_src_dmyapll_dpll_gpll_usb480m_p, 0, + RK2928_CLKSEL_CON(13), 10, 2, MFLAGS), + COMPOSITE_NOMUX(0, "uart0_src", "uart_pll_clk", 0, + RK2928_CLKSEL_CON(13), 0, 7, DFLAGS, +@@ -258,23 +260,23 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { + RK2928_CLKGATE_CON(1), 13, GFLAGS, + &rk3036_uart2_fracmux), + +- COMPOSITE(ACLK_VCODEC, "aclk_vcodec", mux_pll_src_3plls_p, 0, ++ COMPOSITE(ACLK_VCODEC, "aclk_vcodec", mux_pll_src_dmyapll_dpll_gpll_p, 0, + RK2928_CLKSEL_CON(32), 14, 2, MFLAGS, 8, 5, DFLAGS, + RK2928_CLKGATE_CON(3), 11, GFLAGS), + FACTOR_GATE(HCLK_VCODEC, "hclk_vcodec", "aclk_vcodec", 0, 1, 4, + RK2928_CLKGATE_CON(3), 12, GFLAGS), + +- COMPOSITE(ACLK_HEVC, "aclk_hevc", mux_pll_src_3plls_p, 0, ++ COMPOSITE(ACLK_HEVC, "aclk_hevc", mux_pll_src_dmyapll_dpll_gpll_p, 0, + RK2928_CLKSEL_CON(20), 0, 2, MFLAGS, 2, 5, DFLAGS, + RK2928_CLKGATE_CON(10), 6, GFLAGS), + +- COMPOSITE(0, "aclk_disp1_pre", mux_pll_src_3plls_p, 0, ++ COMPOSITE(0, "aclk_disp1_pre", mux_pll_src_dmyapll_dpll_gpll_p, 0, + RK2928_CLKSEL_CON(31), 14, 2, MFLAGS, 8, 5, DFLAGS, + RK2928_CLKGATE_CON(1), 4, GFLAGS), +- COMPOSITE(0, "hclk_disp_pre", mux_pll_src_3plls_p, 0, ++ COMPOSITE(0, "hclk_disp_pre", mux_pll_src_dmyapll_dpll_gpll_p, 0, + RK2928_CLKSEL_CON(30), 14, 2, MFLAGS, 8, 5, DFLAGS, + RK2928_CLKGATE_CON(0), 11, GFLAGS), +- COMPOSITE(SCLK_LCDC, "dclk_lcdc", mux_pll_src_3plls_p, 0, ++ COMPOSITE(SCLK_LCDC, "dclk_lcdc", mux_pll_src_apll_dpll_gpll_p, 0, + RK2928_CLKSEL_CON(28), 0, 2, MFLAGS, 8, 8, DFLAGS, + RK2928_CLKGATE_CON(3), 2, GFLAGS), + +@@ -303,7 +305,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { + MMC(SCLK_EMMC_DRV, "emmc_drv", "sclk_emmc", RK3036_EMMC_CON0, 1), + MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RK3036_EMMC_CON1, 0), + +- COMPOSITE(0, "i2s_src", mux_pll_src_3plls_p, 0, ++ COMPOSITE(0, "i2s_src", mux_pll_src_dmyapll_dpll_gpll_p, 0, + RK2928_CLKSEL_CON(3), 14, 2, MFLAGS, 0, 7, DFLAGS, + RK2928_CLKGATE_CON(0), 9, GFLAGS), + COMPOSITE_FRACMUX(SCLK_I2S_FRAC, "i2s_frac", "i2s_src", CLK_SET_RATE_PARENT, +@@ -316,7 +318,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { + GATE(SCLK_I2S, "sclk_i2s", "i2s_pre", CLK_SET_RATE_PARENT, + RK2928_CLKGATE_CON(0), 14, GFLAGS), + +- COMPOSITE(0, "spdif_src", mux_pll_src_3plls_p, 0, ++ COMPOSITE(0, "spdif_src", mux_pll_src_dmyapll_dpll_gpll_p, 0, + RK2928_CLKSEL_CON(5), 10, 2, MFLAGS, 0, 7, DFLAGS, + RK2928_CLKGATE_CON(2), 10, GFLAGS), + COMPOSITE_FRACMUX(0, "spdif_frac", "spdif_src", 0, +@@ -327,23 +329,23 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { + GATE(SCLK_OTGPHY0, "sclk_otgphy0", "xin12m", CLK_IGNORE_UNUSED, + RK2928_CLKGATE_CON(1), 5, GFLAGS), + +- COMPOSITE(SCLK_GPU, "sclk_gpu", mux_pll_src_3plls_p, 0, ++ COMPOSITE(SCLK_GPU, "sclk_gpu", mux_pll_src_dmyapll_dpll_gpll_p, 0, + RK2928_CLKSEL_CON(34), 8, 2, MFLAGS, 0, 5, DFLAGS, + RK2928_CLKGATE_CON(3), 13, GFLAGS), + +- COMPOSITE(SCLK_SPI, "sclk_spi", mux_pll_src_3plls_p, 0, ++ COMPOSITE(SCLK_SPI, "sclk_spi", mux_pll_src_dmyapll_dpll_gpll_p, 0, + RK2928_CLKSEL_CON(25), 8, 2, MFLAGS, 0, 7, DFLAGS, + RK2928_CLKGATE_CON(2), 9, GFLAGS), + +- COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_3plls_p, 0, ++ COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_dmyapll_dpll_gpll_p, 0, + RK2928_CLKSEL_CON(16), 8, 2, MFLAGS, 10, 5, DFLAGS, + RK2928_CLKGATE_CON(10), 4, GFLAGS), + +- COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_apll_dpll_gpll_usb480m_p, 0, ++ COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_dmyapll_dpll_gpll_usb480m_p, 0, + RK2928_CLKSEL_CON(16), 0, 2, MFLAGS, 2, 5, DFLAGS, + RK2928_CLKGATE_CON(10), 5, GFLAGS), + +- COMPOSITE_NOGATE(SCLK_MACPLL, "mac_pll_src", mux_pll_src_3plls_p, CLK_SET_RATE_NO_REPARENT, ++ COMPOSITE_NOGATE(SCLK_MACPLL, "mac_pll_src", mux_pll_src_apll_dpll_gpll_p, CLK_SET_RATE_NO_REPARENT, + RK2928_CLKSEL_CON(21), 0, 2, MFLAGS, 9, 5, DFLAGS), + MUX(SCLK_MACREF, "mac_clk_ref", mux_mac_p, CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(21), 3, 1, MFLAGS), + +From 30337bfc416283d487d91e82397c81f1cae745a9 Mon Sep 17 00:00:00 2001 +From: Randy Li +Date: Fri, 20 Apr 2018 10:43:46 +0800 +Subject: [PATCH] clk: rockchip: rk3036: export the sfc clocks + +The serial Flash controller on the rk3036 would request +two clock nodes. + +Change-Id: Iaa50c4a25602a68241b0b9b2f186e4c7e55bc3da +Signed-off-by: Randy Li +--- + drivers/clk/rockchip/clk-rk3036.c | 2 +- + include/dt-bindings/clock/rk3036-cru.h | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c +index 4ce2cf844123..0d1556ac185a 100644 +--- a/drivers/clk/rockchip/clk-rk3036.c ++++ b/drivers/clk/rockchip/clk-rk3036.c +@@ -404,7 +404,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { + GATE(HCLK_OTG0, "hclk_otg0", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 13, GFLAGS), + GATE(HCLK_OTG1, "hclk_otg1", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(7), 3, GFLAGS), + GATE(HCLK_I2S, "hclk_i2s", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 2, GFLAGS), +- GATE(0, "hclk_sfc", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(3), 14, GFLAGS), ++ GATE(HCLK_SFC, "hclk_sfc", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(3), 14, GFLAGS), + GATE(HCLK_MAC, "hclk_mac", "hclk_peri", 0, RK2928_CLKGATE_CON(3), 5, GFLAGS), + + /* pclk_peri gates */ +diff --git a/include/dt-bindings/clock/rk3036-cru.h b/include/dt-bindings/clock/rk3036-cru.h +index 4c7ff6141a67..72ba1952071d 100644 +--- a/include/dt-bindings/clock/rk3036-cru.h ++++ b/include/dt-bindings/clock/rk3036-cru.h +@@ -84,6 +84,7 @@ + #define HCLK_OTG0 449 + #define HCLK_OTG1 450 + #define HCLK_NANDC 453 ++#define HCLK_SFC 454 + #define HCLK_SDMMC 456 + #define HCLK_SDIO 457 + #define HCLK_EMMC 459 + +From 62768587c0db32f4180bd4cebbd9f8d8ad865901 Mon Sep 17 00:00:00 2001 +From: Elaine Zhang +Date: Mon, 1 Jun 2020 15:36:35 +0800 +Subject: [PATCH] clk: rockchip: rk3036: fix up the sclk_sfc parent error + +Change-Id: I0903161f34de8f309392bec6926348ffe37ba2f6 +Signed-off-by: Elaine Zhang +--- + drivers/clk/rockchip/clk-rk3036.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c +index 0d1556ac185a..693bee4009db 100644 +--- a/drivers/clk/rockchip/clk-rk3036.c ++++ b/drivers/clk/rockchip/clk-rk3036.c +@@ -122,6 +122,7 @@ PNAME(mux_pll_src_dmyapll_dpll_gpll_p) = { "dummy_apll", "dpll", "gpll" }; + PNAME(mux_timer_p) = { "xin24m", "pclk_peri_src" }; + + PNAME(mux_pll_src_dmyapll_dpll_gpll_usb480m_p) = { "dummy_apll", "dpll", "gpll", "usb480m" }; ++PNAME(mux_pll_src_dmyapll_dpll_gpll_xin24_p) = { "dummy_apll", "dpll", "gpll", "xin24m" }; + + PNAME(mux_mmc_src_p) = { "dummy_apll", "dpll", "gpll", "xin24m" }; + PNAME(mux_i2s_pre_p) = { "i2s_src", "i2s_frac", "ext_i2s", "xin12m" }; +@@ -341,7 +342,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { + RK2928_CLKSEL_CON(16), 8, 2, MFLAGS, 10, 5, DFLAGS, + RK2928_CLKGATE_CON(10), 4, GFLAGS), + +- COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_dmyapll_dpll_gpll_usb480m_p, 0, ++ COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_dmyapll_dpll_gpll_xin24_p, 0, + RK2928_CLKSEL_CON(16), 0, 2, MFLAGS, 2, 5, DFLAGS, + RK2928_CLKGATE_CON(10), 5, GFLAGS), + + +From cef2d7b595360c89a57fcf38d1dcf41759ceac95 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sun, 16 Aug 2020 22:41:29 +0200 +Subject: [PATCH] clk: rockchip: export PCLK_EFUSE for RK3036 + +Export PCLK_EFUSE for RK3036. +--- + drivers/clk/rockchip/clk-rk3036.c | 2 +- + include/dt-bindings/clock/rk3036-cru.h | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c +index 693bee4009db..06e92dd5ce25 100644 +--- a/drivers/clk/rockchip/clk-rk3036.c ++++ b/drivers/clk/rockchip/clk-rk3036.c +@@ -410,7 +410,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { + + /* pclk_peri gates */ + GATE(0, "pclk_peri_matrix", "pclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 1, GFLAGS), +- GATE(0, "pclk_efuse", "pclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 2, GFLAGS), ++ GATE(PCLK_EFUSE, "pclk_efuse", "pclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 2, GFLAGS), + GATE(PCLK_TIMER, "pclk_timer", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 7, GFLAGS), + GATE(PCLK_PWM, "pclk_pwm", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 10, GFLAGS), + GATE(PCLK_SPI, "pclk_spi", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 12, GFLAGS), +diff --git a/include/dt-bindings/clock/rk3036-cru.h b/include/dt-bindings/clock/rk3036-cru.h +index 72ba1952071d..febab04521a2 100644 +--- a/include/dt-bindings/clock/rk3036-cru.h ++++ b/include/dt-bindings/clock/rk3036-cru.h +@@ -79,6 +79,7 @@ + #define PCLK_DDRUPCTL 364 + #define PCLK_WDT 368 + #define PCLK_ACODEC 369 ++#define PCLK_EFUSE 370 + + /* hclk gates */ + #define HCLK_OTG0 449 + +From bf25b1441ad681e8b56ae6ec069165dc4fb6b445 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sun, 16 Aug 2020 22:43:41 +0200 +Subject: [PATCH] ARM: dts: rockchip: add RK3036 efuse node + +Add RK3036 efuse node to the devicetree and add the new compatible string +to bindings document. +--- + .../devicetree/bindings/nvmem/rockchip-efuse.yaml | 1 + + arch/arm/boot/dts/rk3036.dtsi | 7 +++++++ + 2 files changed, 8 insertions(+) + +diff --git a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.yaml b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.yaml +index 3ae00b0b23bc..c3fdabcb1e0a 100644 +--- a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.yaml ++++ b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.yaml +@@ -15,6 +15,7 @@ allOf: + properties: + compatible: + enum: ++ - rockchip,rk3036-efuse + - rockchip,rk3066a-efuse + - rockchip,rk3188-efuse + - rockchip,rk3228-efuse +diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi +index 10f15cdb932c..6700a17a6446 100644 +--- a/arch/arm/boot/dts/rk3036.dtsi ++++ b/arch/arm/boot/dts/rk3036.dtsi +@@ -873,4 +873,11 @@ spi_cs1:spi-cs1 { + }; + }; + }; ++ ++ efuse: efuse@20090000 { ++ compatible = "rockchip,rk3036-efuse", "rockchip,rk3288-efuse"; ++ reg = <0x20090000 0x20>; ++ clocks = <&cru PCLK_EFUSE>; ++ clock-names = "pclk_efuse"; ++ }; + }; + +From 490be97e9fdc5e4ea8afd5b41d2a9f2942f82b02 Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sun, 16 Aug 2020 23:02:00 +0200 +Subject: [PATCH] ARM: dts: add opp-table for RK3188s GPU + +Add opp-table for RK3188s mali400 MP4 GPU +--- + arch/arm/boot/dts/rk3188.dtsi | 30 ++++++++++++++++++++++++++++++ + 1 file changed, 30 insertions(+) + +diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi +index 9fab375231ec..894fe6259ef2 100644 +--- a/arch/arm/boot/dts/rk3188.dtsi ++++ b/arch/arm/boot/dts/rk3188.dtsi +@@ -112,6 +112,35 @@ smp-sram@0 { + }; + }; + ++ gpu_opp_table: opp-table2 { ++ compatible = "operating-points-v2"; ++ ++ opp-133000000 { ++ opp-hz = /bits/ 64 <133000000>; ++ opp-microvolt = <975000>; ++ }; ++ opp-200000000 { ++ opp-hz = /bits/ 64 <200000000>; ++ opp-microvolt = <1000000>; ++ }; ++ opp-266000000 { ++ opp-hz = /bits/ 64 <266000000>; ++ opp-microvolt = <1025000>; ++ }; ++ opp-300000000 { ++ opp-hz = /bits/ 64 <300000000>; ++ opp-microvolt = <1050000>; ++ }; ++ opp-400000000 { ++ opp-hz = /bits/ 64 <400000000>; ++ opp-microvolt = <1100000>; ++ }; ++ opp-600000000 { ++ opp-hz = /bits/ 64 <600000000>; ++ opp-microvolt = <1250000>; ++ }; ++ }; ++ + vpu: video-codec@10104000 { + compatible = "rockchip,rk3188-vpu"; + reg = <0x10104000 0x800>; +@@ -672,6 +701,7 @@ &gpu { + "ppmmu2", + "pp3", + "ppmmu3"; ++ operating-points-v2 = <&gpu_opp_table>; + power-domains = <&power RK3188_PD_GPU>; + }; + + +From 313b1d3730fc3a9076a783e9e296a13fdae599ce Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sun, 16 Aug 2020 23:12:25 +0200 +Subject: [PATCH] ARM: dts: rk322x: add crypto node + +In order to add support for RK322x's crypto HW, the node +has been added t its dts. + +Signed-off-by: Alex Bee +--- + arch/arm/boot/dts/rk322x.dtsi | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi +index 92e3eb1e7938..be46697e125e 100644 +--- a/arch/arm/boot/dts/rk322x.dtsi ++++ b/arch/arm/boot/dts/rk322x.dtsi +@@ -167,6 +167,17 @@ display_subsystem: display-subsystem { + ports = <&vop_out>; + }; + ++ crypto: cypto-controller@100a0000 { ++ compatible = "rockchip,rk3288-crypto"; ++ reg = <0x100a0000 0x4000>; ++ interrupts = ; ++ clocks = <&cru HCLK_M_CRYPTO>, <&cru HCLK_S_CRYPTO>, ++ <&cru SCLK_CRYPTO>, <&cru ACLK_DMAC>; ++ clock-names = "aclk", "hclk", "sclk", "apb_pclk"; ++ resets = <&cru SRST_CRYPTO>; ++ reset-names = "crypto-rst"; ++ }; ++ + i2s1: i2s1@100b0000 { + compatible = "rockchip,rk3228-i2s", "rockchip,rk3066-i2s"; + reg = <0x100b0000 0x4000>; diff --git a/patch/kernel/rk322x-dev/01-linux-9000-rockchip-linux-le-wip.patch b/patch/kernel/rk322x-dev/01-linux-9000-rockchip-linux-le-wip.patch new file mode 100644 index 000000000..dad10c696 --- /dev/null +++ b/patch/kernel/rk322x-dev/01-linux-9000-rockchip-linux-le-wip.patch @@ -0,0 +1,912 @@ +From 71fba6c19fa57e219657226d3d20528ebec86def Mon Sep 17 00:00:00 2001 +From: Alex Bee +Date: Sun, 16 Aug 2020 23:03:12 +0200 +Subject: [PATCH] WIP: ARM: dts: add RK322x box device trees + +--- + arch/arm/boot/dts/Makefile | 4 + + arch/arm/boot/dts/rk3228a-box-h96mini.dts | 115 +++++++++ + arch/arm/boot/dts/rk3228a-box.dts | 47 ++++ + arch/arm/boot/dts/rk3228a-box.dtsi | 12 + + arch/arm/boot/dts/rk3229-box-a95xr1.dts | 57 ++++ + arch/arm/boot/dts/rk3229-box.dts | 50 ++++ + arch/arm/boot/dts/rk3229-box.dtsi | 21 ++ + arch/arm/boot/dts/rk3229-cpu-opp.dtsi | 50 ++++ + arch/arm/boot/dts/rk322x-box-dcdc.dtsi | 164 ++++++++++++ + arch/arm/boot/dts/rk322x-box.dtsi | 301 ++++++++++++++++++++++ + 10 files changed, 821 insertions(+) + create mode 100644 arch/arm/boot/dts/rk3228a-box-h96mini.dts + create mode 100644 arch/arm/boot/dts/rk3228a-box.dts + create mode 100644 arch/arm/boot/dts/rk3228a-box.dtsi + create mode 100644 arch/arm/boot/dts/rk3229-box-a95xr1.dts + create mode 100644 arch/arm/boot/dts/rk3229-box.dts + create mode 100644 arch/arm/boot/dts/rk3229-box.dtsi + create mode 100644 arch/arm/boot/dts/rk3229-cpu-opp.dtsi + create mode 100644 arch/arm/boot/dts/rk322x-box-dcdc.dtsi + create mode 100644 arch/arm/boot/dts/rk322x-box.dtsi + +diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile +index e6a1cac0bfc7..1e633e4aa5a2 100644 +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -961,7 +961,11 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \ + rk3188-bqedison2qc.dtb \ + rk3188-px3-evb.dtb \ + rk3188-radxarock.dtb \ ++ rk3228a-box.dtb \ ++ rk3228a-box-h96mini.dtb \ + rk3228-evb.dtb \ ++ rk3229-box.dtb \ ++ rk3229-box-a95xr1.dtb \ + rk3229-evb.dtb \ + rk3229-xms6.dtb \ + rk3288-evb-act8846.dtb \ +diff --git a/arch/arm/boot/dts/rk3228a-box-h96mini.dts b/arch/arm/boot/dts/rk3228a-box-h96mini.dts +new file mode 100644 +index 000000000000..1041b6737d40 +--- /dev/null ++++ b/arch/arm/boot/dts/rk3228a-box-h96mini.dts +@@ -0,0 +1,115 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++/dts-v1/; ++#include ++#include ++#include "rk3228a-box.dtsi" ++ ++/ { ++ compatible = "eledvb,h96mini", "rockchip,rk3228a-box", "rockchip,rk3229"; ++ model = "Rockchip RK3228A Box H96 mini"; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led_green { ++ gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ }; ++ ++ led_red { ++ gpios = <&gpio0 RK_PB0 GPIO_ACTIVE_HIGH>; ++ default-state = "off"; ++ }; ++ }; ++ ++ openvfd { ++ compatible = "open,vfd"; ++ dev_name = "openvfd"; ++ openvfd_gpio_clk = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; ++ openvfd_gpio_dat = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>; ++ openvfd_display_type = <0x06000100>; ++ openvfd_dot_bits = [00 01 03 02 04 05 06]; ++ }; ++ ++}; ++ ++&emmc { ++ mmc-hs200-1_8v; ++ status = "okay"; ++}; ++ ++&gmac { ++ tx_delay = <0x26>; ++ rx_delay = <0x11>; ++}; ++ ++&ir_receiver { ++ status = "okay"; ++}; ++ ++&pinctrl { ++ wifi { ++ wifi_host_wake_l: wifi-host-wake-l { ++ rockchip,pins = <0 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ bt { ++ bt_host_wake_l: bt-host-wake-l { ++ rockchip,pins = <3 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ ++ bt_reg_on_h: bt-reg-on-h { ++ rockchip,pins = <2 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ ++ bt_wake_l: bt-wake-l { ++ rockchip,pins = <3 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++}; ++ ++&power_key { ++ status = "okay"; ++}; ++ ++&sdio { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ brcmf: wifi@1 { ++ compatible = "brcm,bcm4329-fmac"; ++ reg = <1>; ++ interrupt-parent = <&gpio0>; ++ interrupts = ; ++ interrupt-names = "host-wake"; ++ brcm,drive-strength = <5>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&wifi_host_wake_l>; ++ }; ++}; ++ ++&sdmmc { ++ disable-wp; ++ status = "okay"; ++}; ++ ++&uart1 { ++ status = "okay"; ++ ++ bluetooth { ++ compatible = "brcm,bcm4330-bt"; ++ host-wakeup-gpios = <&gpio3 RK_PD2 GPIO_ACTIVE_HIGH>; ++ device-wakeup-gpios = <&gpio3 RK_PD3 GPIO_ACTIVE_HIGH>; ++ shutdown-gpios = <&gpio2 RK_PD5 GPIO_ACTIVE_HIGH>; ++ max-speed = <4000000>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bt_reg_on_h &bt_host_wake_l &bt_wake_l>; ++ }; ++}; ++ ++&usb_otg { ++ dr_mode = "host"; ++}; +diff --git a/arch/arm/boot/dts/rk3228a-box.dts b/arch/arm/boot/dts/rk3228a-box.dts +new file mode 100644 +index 000000000000..e68ef44b95c9 +--- /dev/null ++++ b/arch/arm/boot/dts/rk3228a-box.dts +@@ -0,0 +1,47 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++/dts-v1/; ++#include "rk3228a-box.dtsi" ++ ++/ { ++ model = "Rockchip RK3228A Box"; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led_blue { ++ gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ }; ++ ++ led_red { ++ gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_HIGH>; ++ default-state = "off"; ++ }; ++ }; ++ ++}; ++ ++&emmc { ++ status = "okay"; ++}; ++ ++&ir_receiver { ++ status = "okay"; ++}; ++ ++&sdio { ++ status = "okay"; ++}; ++ ++&sdmmc { ++ status = "okay"; ++}; ++ ++&uart1 { ++ status = "okay"; ++}; ++ ++&usb_otg { ++ dr_mode = "host"; ++}; +diff --git a/arch/arm/boot/dts/rk3228a-box.dtsi b/arch/arm/boot/dts/rk3228a-box.dtsi +new file mode 100644 +index 000000000000..056945c6c9a7 +--- /dev/null ++++ b/arch/arm/boot/dts/rk3228a-box.dtsi +@@ -0,0 +1,12 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++/dts-v1/; ++ ++#include "rk322x-box-dcdc.dtsi" ++ ++/ { ++ ++ model = "Rockchip RK3228A Box"; ++ compatible = "rockchip,rk3228a-box", "rockchip,rk3229"; ++ ++}; +diff --git a/arch/arm/boot/dts/rk3229-box-a95xr1.dts b/arch/arm/boot/dts/rk3229-box-a95xr1.dts +new file mode 100644 +index 000000000000..b3695fb0b255 +--- /dev/null ++++ b/arch/arm/boot/dts/rk3229-box-a95xr1.dts +@@ -0,0 +1,57 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++/dts-v1/; ++#include ++#include ++#include "rk3229-box.dtsi" ++ ++/ { ++ model = "Rockchip RK3229 Box A95X-R1"; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led_blue { ++ gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ }; ++ ++ led_red { ++ gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_HIGH>; ++ default-state = "off"; ++ linux,default-trigger = "rc-feedback"; ++ }; ++ }; ++ ++}; ++ ++&emmc { ++ mmc-hs200-1_8v; ++ status = "okay"; ++}; ++ ++&gmac { ++ tx_delay = <0x26>; ++ rx_delay = <0x11>; ++}; ++ ++&ir_receiver { ++ status = "okay"; ++}; ++ ++&power_key { ++ status = "okay"; ++}; ++ ++&sdio { ++ status = "okay"; ++}; ++ ++&sdmmc { ++ disable-wp; ++ status = "okay"; ++}; ++ ++&usb_otg { ++ dr_mode = "host"; ++}; +diff --git a/arch/arm/boot/dts/rk3229-box.dts b/arch/arm/boot/dts/rk3229-box.dts +new file mode 100644 +index 000000000000..b63e61cda257 +--- /dev/null ++++ b/arch/arm/boot/dts/rk3229-box.dts +@@ -0,0 +1,50 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++/dts-v1/; ++#include "rk3229-box.dtsi" ++ ++/ { ++ model = "Rockchip RK3229 Box"; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led_green { ++ gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ }; ++ ++ led_red { ++ gpios = <&gpio0 RK_PB0 GPIO_ACTIVE_HIGH>; ++ default-state = "off"; ++ }; ++ }; ++}; ++ ++&emmc { ++ status = "okay"; ++}; ++ ++&ir_receiver { ++ status = "okay"; ++}; ++ ++&power_key { ++ status = "okay"; ++}; ++ ++&sdio { ++ status = "okay"; ++}; ++ ++&sdmmc { ++ status = "okay"; ++}; ++ ++&uart1 { ++ status = "okay"; ++}; ++ ++&usb_otg { ++ dr_mode = "host"; ++}; +diff --git a/arch/arm/boot/dts/rk3229-box.dtsi b/arch/arm/boot/dts/rk3229-box.dtsi +new file mode 100644 +index 000000000000..84f98fc53ebf +--- /dev/null ++++ b/arch/arm/boot/dts/rk3229-box.dtsi +@@ -0,0 +1,21 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++/dts-v1/; ++ ++#include "rk322x-box-dcdc.dtsi" ++#include "rk3229-cpu-opp.dtsi" ++ ++/ { ++ ++ model = "Rockchip RK3229 Box"; ++ compatible = "rockchip,rk3229-box", "rockchip,rk3229"; ++ ++}; ++ ++&cpu0_opp_table { ++ ++ opp-1464000000 { ++ status = "disabled"; ++ }; ++ ++}; +diff --git a/arch/arm/boot/dts/rk3229-cpu-opp.dtsi b/arch/arm/boot/dts/rk3229-cpu-opp.dtsi +new file mode 100644 +index 000000000000..c1c7613bab11 +--- /dev/null ++++ b/arch/arm/boot/dts/rk3229-cpu-opp.dtsi +@@ -0,0 +1,50 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd ++ */ ++ ++/ { ++ compatible = "rockchip,rk3229"; ++ ++ /delete-node/ opp-table0; ++ ++ cpu0_opp_table: opp_table0 { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ ++ opp-408000000 { ++ opp-hz = /bits/ 64 <408000000>; ++ opp-microvolt = <950000 950000 1400000>; ++ clock-latency-ns = <40000>; ++ opp-suspend; ++ }; ++ opp-600000000 { ++ opp-hz = /bits/ 64 <600000000>; ++ opp-microvolt = <975000 975000 1400000>; ++ }; ++ opp-816000000 { ++ opp-hz = /bits/ 64 <816000000>; ++ opp-microvolt = <1000000 1000000 1400000>; ++ }; ++ opp-1008000000 { ++ opp-hz = /bits/ 64 <1008000000>; ++ opp-microvolt = <1175000 1175000 1400000>; ++ }; ++ opp-1200000000 { ++ opp-hz = /bits/ 64 <1200000000>; ++ opp-microvolt = <1275000 1275000 1400000>; ++ }; ++ opp-1296000000 { ++ opp-hz = /bits/ 64 <1296000000>; ++ opp-microvolt = <1325000 1325000 1400000>; ++ }; ++ opp-1392000000 { ++ opp-hz = /bits/ 64 <1392000000>; ++ opp-microvolt = <1350000 1350000 1400000>; ++ }; ++ opp-1464000000 { ++ opp-hz = /bits/ 64 <1464000000>; ++ opp-microvolt = <1400000 1400000 1400000>; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/rk322x-box-dcdc.dtsi b/arch/arm/boot/dts/rk322x-box-dcdc.dtsi +new file mode 100644 +index 000000000000..b2e47c5b4693 +--- /dev/null ++++ b/arch/arm/boot/dts/rk322x-box-dcdc.dtsi +@@ -0,0 +1,164 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++/dts-v1/; ++ ++#include ++#include ++#include "rk322x-box.dtsi" ++ ++/ { ++ ++ vcc_host: vcc-host-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio3 RK_PC4 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&host_vbus_drv>; ++ regulator-name = "vcc_host"; ++ regulator-always-on; ++ regulator-boot-on; ++ vin-supply = <&vcc_sys>; ++ }; ++ ++ vccio_1v8: vccio-1v8-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vccio_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ vin-supply = <&vcc_sys>; ++ }; ++ ++ vccio_3v3: vccio-3v3-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vccio_3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ vin-supply = <&vcc_sys>; ++ }; ++ ++ ++ vcc_otg: vcc-otg-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio3 RK_PC6 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&otg_vbus_drv>; ++ regulator-name = "vcc_otg_vbus"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ regulator-always-on; ++ regulator-boot-on; ++ vin-supply = <&vcc_sys>; ++ }; ++ ++ vcc_phy: vcc-phy-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ regulator-name = "vcc_phy"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ vin-supply = <&vccio_1v8>; ++ }; ++ ++ vcc_sys: vcc-sys-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ }; ++ ++ vdd_arm: vdd-arm-regulator { ++ compatible = "pwm-regulator"; ++ pwms = <&pwm1 0 5000 1>; ++ pwm-supply = <&vcc_sys>; ++ regulator-name = "vdd_arm"; ++ regulator-min-microvolt = <950000>; ++ regulator-max-microvolt = <1400000>; ++ regulator-ramp-delay = <12500>; ++ regulator-settling-time-up-us = <250>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ vdd_log: vdd-log-regulator { ++ compatible = "pwm-regulator"; ++ pwms = <&pwm2 0 5000 1>; ++ pwm-supply = <&vcc_sys>; ++ regulator-name = "vdd_log"; ++ regulator-min-microvolt = <1000000>; ++ regulator-max-microvolt = <1300000>; ++ regulator-ramp-delay = <12500>; ++ regulator-settling-time-up-us = <250>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++}; ++ ++ ++&cpu0 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu1 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu2 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu3 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&io_domains { ++ vccio1-supply = <&vccio_3v3>; ++ vccio2-supply = <&vccio_1v8>; ++ vccio4-supply = <&vccio_3v3>; ++ status = "okay"; ++}; ++ ++&gmac { ++ phy-supply = <&vcc_phy>; ++}; ++ ++&gpu { ++ mali-supply = <&vdd_log>; ++}; ++ ++&pwm1 { ++ pinctrl-0 = <&pwm1_pin_pull_down>; ++ status = "okay"; ++}; ++ ++&pwm2 { ++ pinctrl-0 = <&pwm2_pin_pull_up>; ++ status = "okay"; ++}; ++ ++&u2phy0 { ++ u2phy0_host: host-port { ++ phy-supply = <&vcc_host>; ++ }; ++ ++ u2phy0_otg: otg-port { ++ phy-supply = <&vcc_otg>; ++ }; ++}; ++ ++&u2phy1 { ++ u2phy1_host: host-port { ++ phy-supply = <&vcc_host>; ++ }; ++ ++ u2phy1_otg: otg-port { ++ phy-supply = <&vcc_otg>; ++ }; ++}; +diff --git a/arch/arm/boot/dts/rk322x-box.dtsi b/arch/arm/boot/dts/rk322x-box.dtsi +new file mode 100644 +index 000000000000..02c9b3540f38 +--- /dev/null ++++ b/arch/arm/boot/dts/rk322x-box.dtsi +@@ -0,0 +1,299 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++/dts-v1/; ++ ++#include ++#include ++#include ++#include ++#include "rk322x.dtsi" ++ ++/ { ++ model = "Rockchip RK322x Box"; ++ compatible = "rockchip,rk3229"; ++ ++ chosen { ++ bootargs = "earlyprintk=uart8250,mmio32,0x11030000"; ++ }; ++ ++ gpio_keys { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ autorepeat; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwr_key>; ++ ++ power_key: power-key { ++ label = "GPIO Key Power"; ++ gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_LOW>; ++ linux,code = ; ++ debounce-interval = <100>; ++ wakeup-source; ++ status = "disabled"; ++ }; ++ }; ++ ++ ir_receiver: ir-receiver { ++ compatible = "gpio-ir-receiver"; ++ gpios = <&gpio1 RK_PB3 GPIO_ACTIVE_LOW>; ++ pinctrl-0 = <&ir_int>; ++ pinctrl-names = "default"; ++ status = "disabled"; ++ }; ++ ++ memory@60000000 { ++ device_type = "memory"; ++ reg = <0x60000000 0x40000000>; ++ }; ++ ++ reserved-memory { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ++ /* Not needed since u-boot 2020.07 ++ trust_reserved: trust@68400000 { ++ reg = <0x68400000 0xe00000>; ++ no-map; ++ };*/ ++ }; ++ ++ sdio_pwrseq: sdio-pwrseq { ++ compatible = "mmc-pwrseq-simple"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&wifi_enable_h>; ++ reset-gpios = <&gpio2 RK_PD2 GPIO_ACTIVE_LOW>; ++ }; ++ ++}; ++ ++&cpu_alert1 { ++ temperature = <105000>; ++}; ++ ++&cpu_crit { ++ temperature = <115000>; ++}; ++ ++&cpu_thermal { ++ cooling-maps { ++ /delete-node/ map0; ++ }; ++}; ++ ++&cpu0_opp_table { ++ ++ opp-408000000 { ++ opp-microvolt = <950000 950000 1275000>; ++ }; ++ ++ opp-600000000 { ++ opp-microvolt = <975000 975000 1275000>; ++ }; ++ ++ opp-816000000 { ++ opp-microvolt = <1000000 1000000 1275000>; ++ }; ++ ++ opp-1008000000 { ++ opp-microvolt = <1175000 1175000 1275000>; ++ }; ++ ++ opp-1200000000 { ++ opp-microvolt = <1275000 1275000 1275000>; ++ }; ++}; ++ ++&cru { ++ assigned-clocks = ++ <&cru PLL_GPLL>, <&cru ARMCLK>, ++ <&cru PLL_CPLL>, <&cru ACLK_PERI>, ++ <&cru HCLK_PERI>, <&cru PCLK_PERI>, ++ <&cru ACLK_CPU>, <&cru HCLK_CPU>, ++ <&cru PCLK_CPU>, <&cru ACLK_VOP>; ++ assigned-clock-rates = ++ <1200000000>, <816000000>, ++ <500000000>, <150000000>, ++ <150000000>, <75000000>, ++ <150000000>, <150000000>, ++ <75000000>, <400000000>; ++}; ++ ++&emmc { ++ cap-mmc-highspeed; ++ keep-power-in-suspend; ++ non-removable; ++}; ++ ++&gmac { ++ assigned-clocks = <&cru SCLK_MAC_SRC>; ++ assigned-clock-rates = <50000000>; ++ clock_in_out = "output"; ++ phy-handle = <&phy>; ++ phy-mode = "rmii"; ++ status = "okay"; ++ ++ mdio { ++ compatible = "snps,dwmac-mdio"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ phy: phy@0 { ++ compatible = "ethernet-phy-id1234.d400", ++ "ethernet-phy-ieee802.3-c22"; ++ reg = <0>; ++ clocks = <&cru SCLK_MAC_PHY>; ++ phy-is-integrated; ++ resets = <&cru SRST_MACPHY>; ++ }; ++ }; ++}; ++ ++&gpu { ++ assigned-clocks = <&cru ACLK_GPU>; ++ assigned-clock-rates = <300000000>; ++}; ++ ++&hdmi { ++ status = "okay"; ++}; ++ ++&hdmi_sound { ++ status = "okay"; ++}; ++ ++&hdmi_phy { ++ status = "okay"; ++}; ++ ++&i2s0 { ++ status = "okay"; ++}; ++ ++&pinctrl { ++ ++ ir { ++ ir_int: ir-int { ++ rockchip,pins = <1 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ keys { ++ pwr_key: pwr-key { ++ rockchip,pins = <3 RK_PC7 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ pwm1 { ++ pwm1_pin_pull_down: pwm1-pin-pull-down { ++ rockchip,pins = <0 RK_PD6 2 &pcfg_pull_down>; ++ }; ++ }; ++ ++ pwm2 { ++ pwm2_pin_pull_up: pwm2-pin-pull-up { ++ rockchip,pins = <1 RK_PB4 2 &pcfg_pull_up>; ++ }; ++ }; ++ ++ sdio-pwrseq { ++ wifi_enable_h: wifi-enable-h { ++ rockchip,pins = <2 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ usb { ++ host_vbus_drv: host-vbus-drv { ++ rockchip,pins = <3 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ ++ otg_vbus_drv: otg-vbus-drv { ++ rockchip,pins = <3 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++}; ++ ++&sdio { ++ mmc-pwrseq = <&sdio_pwrseq>; ++ cap-sd-highspeed; ++ cap-sdio-irq; ++ keep-power-in-suspend; ++ non-removable; ++ no-sd; ++}; ++ ++&sdmmc { ++ cap-sd-highspeed; ++ keep-power-in-suspend; ++ no-sdio; ++}; ++ ++&tsadc { ++ rockchip,grf = <&grf>; ++ rockchip,hw-tshut-mode = <0>; ++ rockchip,hw-tshut-polarity = <1>; ++ rockchip,hw-tshut-temp = <120000>; ++ status = "okay"; ++}; ++ ++&u2phy0 { ++ status = "okay"; ++}; ++ ++&u2phy1 { ++ status = "okay"; ++}; ++ ++&uart1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart11_xfer &uart11_rts &uart11_cts>; ++}; ++ ++&uart2 { ++ status = "okay"; ++}; ++ ++&usb_host0_ehci { ++ status = "okay"; ++}; ++ ++&usb_host0_ohci { ++ status = "okay"; ++}; ++ ++&usb_host1_ehci { ++ status = "okay"; ++}; ++ ++&usb_host1_ohci { ++ status = "okay"; ++}; ++ ++&usb_host2_ehci { ++ status = "okay"; ++}; ++ ++&usb_host2_ohci { ++ status = "okay"; ++}; ++ ++&usb_otg { ++ status = "okay"; ++}; ++ ++&vop { ++ assigned-clocks = <&cru DCLK_VOP>; ++ assigned-clock-parents = <&cru SCLK_HDMI_PHY>; ++ status = "okay"; ++}; ++ ++&vop_mmu { ++ status = "okay"; ++}; ++ ++&wdt { ++ status = "okay"; ++}; diff --git a/patch/kernel/rk322x-dev/02-linux-0004-dtsi-adjust-nand-pinctrls.patch b/patch/kernel/rk322x-dev/02-linux-0004-dtsi-adjust-nand-pinctrls.patch index db3e79e6c..a6ea7e3d4 100644 --- a/patch/kernel/rk322x-dev/02-linux-0004-dtsi-adjust-nand-pinctrls.patch +++ b/patch/kernel/rk322x-dev/02-linux-0004-dtsi-adjust-nand-pinctrls.patch @@ -1,91 +1,92 @@ diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi -index b2fcf0e75..25051c03f 100644 +index be46697e1..b2a0246fb 100644 --- a/arch/arm/boot/dts/rk322x.dtsi +++ b/arch/arm/boot/dts/rk322x.dtsi -@@ -1149,51 +1149,71 @@ +@@ -843,6 +843,22 @@ + status = "disabled"; + }; - flash_cs0: flash-cs0 { - rockchip,pins = -- <2 RK_PA6 1 &pcfg_pull_none>; -+ <2 RK_PA6 1 &pcfg_pull_up>; - }; - - flash_cs1: flash-cs1 { - rockchip,pins = -- <0 RK_PC7 1 &pcfg_pull_none>; -+ <0 RK_PC7 1 &pcfg_pull_up>; -+ }; ++ nfc: nand-controller@ff4b0000 { ++ compatible = "rockchip,rk3228_nfc"; ++ reg = <0x30030000 0x4000>; ++ interrupts = ; ++ clocks = <&cru SCLK_NANDC>, <&cru HCLK_NANDC>; ++ clock-names = "nfc", "ahb"; ++ assigned-clocks = <&cru SCLK_NANDC>; ++ assigned-clock-rates = <150000000>; + -+ flash_cs2: flash-cs2 { -+ rockchip,pins = -+ <1 RK_PC6 1 &pcfg_pull_up>; -+ }; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&flash_cs0 &flash_rdy &flash_ale &flash_cle ++ &flash_wrn &flash_rdn &flash_bus8>; ++ status = "disabled"; + -+ flash_cs3: flash-cs3 { -+ rockchip,pins = -+ <1 RK_PC7 1 &pcfg_pull_up>; - }; - - flash_rdy: flash-rdy { - rockchip,pins = -- <2 RK_PA4 1 &pcfg_pull_none>; -+ <2 RK_PA4 1 &pcfg_pull_up>; - }; - - flash_ale: flash-ale { - rockchip,pins = -- <2 RK_PA0 1 &pcfg_pull_none>; -+ <2 RK_PA0 1 &pcfg_pull_down>; - }; - - flash_cle: flash-cle { - rockchip,pins = -- <2 RK_PA1 1 &pcfg_pull_none>; -+ <2 RK_PA1 1 &pcfg_pull_down>; - }; - - flash_wrn: flash-wrn { -- rockchip,pins = -- <2 RK_PA2 1 &pcfg_pull_none>; -+ rockchip,pins = -+ <2 RK_PA2 1 &pcfg_pull_up>; - }; - - flash_rdn: flash-rdn { - rockchip,pins = -- <2 RK_PA3 1 &pcfg_pull_none>; -+ <2 RK_PA3 1 &pcfg_pull_up>; - }; - - flash_bus8: flash-bus8 { -- rockchip,pins = <1 RK_PD0 1 &pcfg_pull_none>, -- <1 RK_PD1 1 &pcfg_pull_none>, -- <1 RK_PD2 1 &pcfg_pull_none>, -- <1 RK_PD3 1 &pcfg_pull_none>, -- <1 RK_PD4 1 &pcfg_pull_none>, -- <1 RK_PD5 1 &pcfg_pull_none>, -- <1 RK_PD6 1 &pcfg_pull_none>, -- <1 RK_PD7 1 &pcfg_pull_none>; -+ rockchip,pins = <1 RK_PD0 1 &pcfg_pull_up>, -+ <1 RK_PD1 1 &pcfg_pull_up>, -+ <1 RK_PD2 1 &pcfg_pull_up>, -+ <1 RK_PD3 1 &pcfg_pull_up>, -+ <1 RK_PD4 1 &pcfg_pull_up>, -+ <1 RK_PD5 1 &pcfg_pull_up>, -+ <1 RK_PD6 1 &pcfg_pull_up>, -+ <1 RK_PD7 1 &pcfg_pull_up>; - }; -+ -+ flash_dqs: flash-dqs { -+ rockchip,pins = <2 RK_PA7 1 &pcfg_pull_up>; -+ }; -+ -+ flash_wp: flash-wp { -+ rockchip,pins = <2 RK_PA5 1 &pcfg_pull_down>; -+ }; ++ }; + + usb_otg: usb@30040000 { + compatible = "rockchip,rk3228-usb", "rockchip,rk3066-usb", + "snps,dwc2"; +@@ -1105,6 +1121,65 @@ + }; }; ++ flash { ++ ++ flash_cs0: flash-cs0 { ++ rockchip,pins = <2 RK_PA6 1 &pcfg_pull_up>; ++ }; ++ ++ flash_cs1: flash-cs1 { ++ rockchip,pins = <0 RK_PC7 1 &pcfg_pull_up>; ++ }; ++ ++ flash_cs2: flash-cs2 { ++ rockchip,pins = <1 RK_PC6 1 &pcfg_pull_up>; ++ }; ++ ++ flash_cs3: flash-cs3 { ++ rockchip,pins = <1 RK_PC7 1 &pcfg_pull_up>; ++ }; ++ ++ flash_rdy: flash-rdy { ++ rockchip,pins = <2 RK_PA4 1 &pcfg_pull_up>; ++ }; ++ ++ flash_ale: flash-ale { ++ rockchip,pins = <2 RK_PA0 1 &pcfg_pull_down>; ++ }; ++ ++ flash_cle: flash-cle { ++ rockchip,pins = <2 RK_PA1 1 &pcfg_pull_down>; ++ }; ++ ++ flash_wrn: flash-wrn { ++ rockchip,pins = <2 RK_PA2 1 &pcfg_pull_up>; ++ }; ++ ++ flash_rdn: flash-rdn { ++ rockchip,pins = <2 RK_PA3 1 &pcfg_pull_up>; ++ }; ++ ++ flash_bus8: flash-bus8 { ++ rockchip,pins = <1 RK_PD0 1 &pcfg_pull_up>, ++ <1 RK_PD1 1 &pcfg_pull_up>, ++ <1 RK_PD2 1 &pcfg_pull_up>, ++ <1 RK_PD3 1 &pcfg_pull_up>, ++ <1 RK_PD4 1 &pcfg_pull_up>, ++ <1 RK_PD5 1 &pcfg_pull_up>, ++ <1 RK_PD6 1 &pcfg_pull_up>, ++ <1 RK_PD7 1 &pcfg_pull_up>; ++ }; ++ ++ flash_dqs: flash-dqs { ++ rockchip,pins = <2 RK_PA7 1 &pcfg_pull_up>; ++ }; ++ ++ flash_wp: flash-wp { ++ rockchip,pins = <2 RK_PA5 1 &pcfg_pull_down>; ++ }; ++ ++ }; + gmac { rgmii_pins: rgmii-pins { diff --git a/patch/kernel/rk322x-dev/02-linux-0005-drm-plane-overlay.patch b/patch/kernel/rk322x-dev/02-linux-0005-drm-plane-overlay.patch new file mode 100644 index 000000000..15319a894 --- /dev/null +++ b/patch/kernel/rk322x-dev/02-linux-0005-drm-plane-overlay.patch @@ -0,0 +1,66 @@ +diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +index 73d24c6bbf05..d4ac6e161ef2 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c ++++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +@@ -614,6 +614,44 @@ static const struct vop_common rk3288_common = { + .dsp_background = VOP_REG(RK3288_DSP_BG, 0xffffffff, 0), + }; + ++static const struct vop_win_phy rk3228_win0_data = { ++ .scl = &rk3288_win_full_scl, ++ .data_formats = formats_win_full, ++ .nformats = ARRAY_SIZE(formats_win_full), ++ .enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0), ++ .format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1), ++ .rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12), ++ .act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0), ++ .dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0), ++ .dsp_st = VOP_REG(RK3288_WIN0_DSP_ST, 0x1fff1fff, 0), ++ .yrgb_mst = VOP_REG(RK3288_WIN0_YRGB_MST, 0xffffffff, 0), ++ .uv_mst = VOP_REG(RK3288_WIN0_CBR_MST, 0xffffffff, 0), ++ .yrgb_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 0), ++ .uv_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 16), ++ .src_alpha_ctl = VOP_REG(RK3288_WIN0_SRC_ALPHA_CTRL, 0xff, 0), ++ .dst_alpha_ctl = VOP_REG(RK3288_WIN0_DST_ALPHA_CTRL, 0xff, 0), ++ .channel = VOP_REG(RK3288_WIN0_CTRL2, 0xff, 0), ++}; ++ ++static const struct vop_win_phy rk3228_win1_data = { ++ .scl = &rk3288_win_full_scl, ++ .data_formats = formats_win_lite, ++ .nformats = ARRAY_SIZE(formats_win_lite), ++ .enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0), ++ .format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1), ++ .rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12), ++ .act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0), ++ .dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0), ++ .dsp_st = VOP_REG(RK3288_WIN0_DSP_ST, 0x1fff1fff, 0), ++ .yrgb_mst = VOP_REG(RK3288_WIN0_YRGB_MST, 0xffffffff, 0), ++ .uv_mst = VOP_REG(RK3288_WIN0_CBR_MST, 0xffffffff, 0), ++ .yrgb_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 0), ++ .uv_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 16), ++ .src_alpha_ctl = VOP_REG(RK3288_WIN0_SRC_ALPHA_CTRL, 0xff, 0), ++ .dst_alpha_ctl = VOP_REG(RK3288_WIN0_DST_ALPHA_CTRL, 0xff, 0), ++ .channel = VOP_REG(RK3288_WIN0_CTRL2, 0xff, 0), ++}; ++ + /* + * Note: rk3288 has a dedicated 'cursor' window, however, that window requires + * special support to get alpha blending working. For now, just use overlay +@@ -864,10 +902,10 @@ static const struct vop_data rk3399_vop_lit = { + }; + + static const struct vop_win_data rk3228_vop_win_data[] = { +- { .base = 0x00, .phy = &rk3288_win01_data, ++ { .base = 0x00, .phy = &rk3228_win0_data, + .type = DRM_PLANE_TYPE_PRIMARY }, +- { .base = 0x40, .phy = &rk3288_win01_data, +- .type = DRM_PLANE_TYPE_CURSOR }, ++ { .base = 0x40, .phy = &rk3228_win1_data, ++ .type = DRM_PLANE_TYPE_OVERLAY }, + }; + + static const struct vop_data rk3228_vop = { +-- +2.17.1 + diff --git a/patch/kernel/rk322x-dev/board-rk322x-box.patch b/patch/kernel/rk322x-dev/board-rk322x-box.patch index afec537f1..2b92f90c3 100644 --- a/patch/kernel/rk322x-dev/board-rk322x-box.patch +++ b/patch/kernel/rk322x-dev/board-rk322x-box.patch @@ -3,7 +3,7 @@ new file mode 100644 index 000000000..24590f864 --- /dev/null +++ b/arch/arm/boot/dts/rk322x-box.dts -@@ -0,0 +1,239 @@ +@@ -0,0 +1,235 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +/dts-v1/; @@ -53,10 +53,6 @@ index 000000000..24590f864 + rockchip,default-sample-phase = <180>; +}; + -+&nfc { -+ status = "okay"; -+}; -+ +&gmac { + tx_delay = <0x26>; + rx_delay = <0x11>; diff --git a/patch/kernel/rk322x-dev/wifi-4003-fix-sha256_state-clashes.patch b/patch/kernel/rk322x-dev/wifi-4003-fix-sha256_state-clashes.patch new file mode 100644 index 000000000..0dce511a1 --- /dev/null +++ b/patch/kernel/rk322x-dev/wifi-4003-fix-sha256_state-clashes.patch @@ -0,0 +1,248 @@ +diff --git a/drivers/net/wireless/rtl8189es/include/rtw_security.h b/drivers/net/wireless/rtl8189es/include/rtw_security.h +index 5820a55..3e8e428 100644 +--- a/drivers/net/wireless/rtl8189es/include/rtw_security.h ++++ b/drivers/net/wireless/rtl8189es/include/rtw_security.h +@@ -238,7 +238,7 @@ struct security_priv + #endif /* DBG_SW_SEC_CNT */ + }; + +-struct sha256_state { ++struct rtl_sha256_state { + u64 length; + u32 state[8], curlen; + u8 buf[64]; +diff --git a/drivers/net/wireless/rtl8189es/core/rtw_security.c b/drivers/net/wireless/rtl8189es/core/rtw_security.c +index 8dac771..9b3a1f9 100644 +--- a/drivers/net/wireless/rtl8189es/core/rtw_security.c ++++ b/drivers/net/wireless/rtl8189es/core/rtw_security.c +@@ -2281,7 +2281,7 @@ BIP_exit: + + #ifndef PLATFORM_FREEBSD + /* compress 512-bits */ +-static int sha256_compress(struct sha256_state *md, unsigned char *buf) ++static int sha256_compress(struct rtl_sha256_state *md, unsigned char *buf) + { + u32 S[8], W[64], t0, t1; + u32 t; +@@ -2323,7 +2323,7 @@ static int sha256_compress(struct sha256_state *md, unsigned char *buf) + } + + /* Initialize the hash state */ +-static void sha256_init(struct sha256_state *md) ++static void sha256_init(struct rtl_sha256_state *md) + { + md->curlen = 0; + md->length = 0; +@@ -2344,7 +2344,7 @@ static void sha256_init(struct sha256_state *md) + @param inlen The length of the data (octets) + @return CRYPT_OK if successful + */ +-static int sha256_process(struct sha256_state *md, unsigned char *in, ++static int sha256_process(struct rtl_sha256_state *md, unsigned char *in, + unsigned long inlen) + { + unsigned long n; +@@ -2385,7 +2385,7 @@ static int sha256_process(struct sha256_state *md, unsigned char *in, + @param out [out] The destination of the hash (32 bytes) + @return CRYPT_OK if successful + */ +-static int sha256_done(struct sha256_state *md, unsigned char *out) ++static int sha256_done(struct rtl_sha256_state *md, unsigned char *out) + { + int i; + +@@ -2437,7 +2437,7 @@ static int sha256_done(struct sha256_state *md, unsigned char *out) + static int sha256_vector(size_t num_elem, u8 *addr[], size_t *len, + u8 *mac) + { +- struct sha256_state ctx; ++ struct rtl_sha256_state ctx; + size_t i; + + sha256_init(&ctx); +diff --git a/drivers/net/wireless/rtl8811cu/include/rtw_security.h b/drivers/net/wireless/rtl8811cu/include/rtw_security.h +index ac8432e..5f74fb7 100755 +--- a/drivers/net/wireless/rtl8811cu/include/rtw_security.h ++++ b/drivers/net/wireless/rtl8811cu/include/rtw_security.h +@@ -249,7 +249,7 @@ struct security_priv { + #define SEC_IS_BIP_KEY_INSTALLED(sec) _FALSE + #endif + +-struct sha256_state { ++struct rtl_sha256_state { + u64 length; + u32 state[8], curlen; + u8 buf[64]; +diff --git a/drivers/net/wireless/rtl8811cu/core/rtw_security.c b/drivers/net/wireless/rtl8811cu/core/rtw_security.c +index b537a26..f8c42f4 100755 +--- a/drivers/net/wireless/rtl8811cu/core/rtw_security.c ++++ b/drivers/net/wireless/rtl8811cu/core/rtw_security.c +@@ -2133,7 +2133,7 @@ BIP_exit: + #ifndef PLATFORM_FREEBSD + #if defined(CONFIG_TDLS) + /* compress 512-bits */ +-static int sha256_compress(struct sha256_state *md, unsigned char *buf) ++static int sha256_compress(struct rtl_sha256_state *md, unsigned char *buf) + { + u32 S[8], W[64], t0, t1; + u32 t; +@@ -2181,7 +2181,7 @@ static int sha256_compress(struct sha256_state *md, unsigned char *buf) + } + + /* Initialize the hash state */ +-static void sha256_init(struct sha256_state *md) ++static void sha256_init(struct rtl_sha256_state *md) + { + md->curlen = 0; + md->length = 0; +@@ -2202,7 +2202,7 @@ static void sha256_init(struct sha256_state *md) + @param inlen The length of the data (octets) + @return CRYPT_OK if successful + */ +-static int sha256_process(struct sha256_state *md, unsigned char *in, ++static int sha256_process(struct rtl_sha256_state *md, unsigned char *in, + unsigned long inlen) + { + unsigned long n; +@@ -2243,7 +2243,7 @@ static int sha256_process(struct sha256_state *md, unsigned char *in, + @param out [out] The destination of the hash (32 bytes) + @return CRYPT_OK if successful + */ +-static int sha256_done(struct sha256_state *md, unsigned char *out) ++static int sha256_done(struct rtl_sha256_state *md, unsigned char *out) + { + int i; + +@@ -2293,7 +2293,7 @@ static int sha256_done(struct sha256_state *md, unsigned char *out) + static int sha256_vector(size_t num_elem, u8 *addr[], size_t *len, + u8 *mac) + { +- struct sha256_state ctx; ++ struct rtl_sha256_state ctx; + size_t i; + + sha256_init(&ctx); +diff --git a/drivers/net/wireless/rtl8188eu/include/rtw_security.h b/drivers/net/wireless/rtl8188eu/include/rtw_security.h +index 0adc700..2a9cf9d 100644 +--- a/drivers/net/wireless/rtl8188eu/include/rtw_security.h ++++ b/drivers/net/wireless/rtl8188eu/include/rtw_security.h +@@ -249,7 +249,7 @@ struct security_priv { + #define SEC_IS_BIP_KEY_INSTALLED(sec) _FALSE + #endif + +-struct sha256_state { ++struct rtl_sha256_state { + u64 length; + u32 state[8], curlen; + u8 buf[64]; +diff --git a/drivers/net/wireless/rtl8188eu/core/rtw_security.c b/drivers/net/wireless/rtl8188eu/core/rtw_security.c +index 5807521..0b3eed2 100644 +--- a/drivers/net/wireless/rtl8188eu/core/rtw_security.c ++++ b/drivers/net/wireless/rtl8188eu/core/rtw_security.c +@@ -2133,7 +2133,7 @@ BIP_exit: + #ifndef PLATFORM_FREEBSD + #if defined(CONFIG_TDLS) + /* compress 512-bits */ +-static int sha256_compress(struct sha256_state *md, unsigned char *buf) ++static int sha256_compress(struct rtl_sha256_state *md, unsigned char *buf) + { + u32 S[8], W[64], t0, t1; + u32 t; +@@ -2181,7 +2181,7 @@ static int sha256_compress(struct sha256_state *md, unsigned char *buf) + } + + /* Initialize the hash state */ +-static void sha256_init(struct sha256_state *md) ++static void sha256_init(struct rtl_sha256_state *md) + { + md->curlen = 0; + md->length = 0; +@@ -2202,7 +2202,7 @@ static void sha256_init(struct sha256_state *md) + @param inlen The length of the data (octets) + @return CRYPT_OK if successful + */ +-static int sha256_process(struct sha256_state *md, unsigned char *in, ++static int sha256_process(struct rtl_sha256_state *md, unsigned char *in, + unsigned long inlen) + { + unsigned long n; +@@ -2243,7 +2243,7 @@ static int sha256_process(struct sha256_state *md, unsigned char *in, + @param out [out] The destination of the hash (32 bytes) + @return CRYPT_OK if successful + */ +-static int sha256_done(struct sha256_state *md, unsigned char *out) ++static int sha256_done(struct rtl_sha256_state *md, unsigned char *out) + { + int i; + +@@ -2293,7 +2293,7 @@ static int sha256_done(struct sha256_state *md, unsigned char *out) + static int sha256_vector(size_t num_elem, u8 *addr[], size_t *len, + u8 *mac) + { +- struct sha256_state ctx; ++ struct rtl_sha256_state ctx; + size_t i; + + sha256_init(&ctx); +diff --git a/drivers/net/wireless/rtl88x2bu/include/rtw_security.h b/drivers/net/wireless/rtl88x2bu/include/rtw_security.h +index ac8432e..5f74fb7 100644 +--- a/drivers/net/wireless/rtl88x2bu/include/rtw_security.h ++++ b/drivers/net/wireless/rtl88x2bu/include/rtw_security.h +@@ -249,7 +249,7 @@ struct security_priv { + #define SEC_IS_BIP_KEY_INSTALLED(sec) _FALSE + #endif + +-struct sha256_state { ++struct rtl_sha256_state { + u64 length; + u32 state[8], curlen; + u8 buf[64]; +diff --git a/drivers/net/wireless/rtl88x2bu/core/rtw_security.c b/drivers/net/wireless/rtl88x2bu/core/rtw_security.c +index b537a26..f8c42f4 100644 +--- a/drivers/net/wireless/rtl88x2bu/core/rtw_security.c ++++ b/drivers/net/wireless/rtl88x2bu/core/rtw_security.c +@@ -2133,7 +2133,7 @@ BIP_exit: + #ifndef PLATFORM_FREEBSD + #if defined(CONFIG_TDLS) + /* compress 512-bits */ +-static int sha256_compress(struct sha256_state *md, unsigned char *buf) ++static int sha256_compress(struct rtl_sha256_state *md, unsigned char *buf) + { + u32 S[8], W[64], t0, t1; + u32 t; +@@ -2181,7 +2181,7 @@ static int sha256_compress(struct sha256_state *md, unsigned char *buf) + } + + /* Initialize the hash state */ +-static void sha256_init(struct sha256_state *md) ++static void sha256_init(struct rtl_sha256_state *md) + { + md->curlen = 0; + md->length = 0; +@@ -2202,7 +2202,7 @@ static void sha256_init(struct sha256_state *md) + @param inlen The length of the data (octets) + @return CRYPT_OK if successful + */ +-static int sha256_process(struct sha256_state *md, unsigned char *in, ++static int sha256_process(struct rtl_sha256_state *md, unsigned char *in, + unsigned long inlen) + { + unsigned long n; +@@ -2243,7 +2243,7 @@ static int sha256_process(struct sha256_state *md, unsigned char *in, + @param out [out] The destination of the hash (32 bytes) + @return CRYPT_OK if successful + */ +-static int sha256_done(struct sha256_state *md, unsigned char *out) ++static int sha256_done(struct rtl_sha256_state *md, unsigned char *out) + { + int i; + +@@ -2293,7 +2293,7 @@ static int sha256_done(struct sha256_state *md, unsigned char *out) + static int sha256_vector(size_t num_elem, u8 *addr[], size_t *len, + u8 *mac) + { +- struct sha256_state ctx; ++ struct rtl_sha256_state ctx; + size_t i; + + sha256_init(&ctx); diff --git a/patch/kernel/rk322x-dev/wifi-4004-fix-cfg80211-for-5.8.patch b/patch/kernel/rk322x-dev/wifi-4004-fix-cfg80211-for-5.8.patch new file mode 100644 index 000000000..587d60460 --- /dev/null +++ b/patch/kernel/rk322x-dev/wifi-4004-fix-cfg80211-for-5.8.patch @@ -0,0 +1,236 @@ +diff --git a/drivers/net/wireless/rtl8189es/os_dep/linux/ioctl_cfg80211.c b/drivers/net/wireless/rtl8189es/os_dep/linux/ioctl_cfg80211.c +index d77cc17..32cc240 100644 +--- a/drivers/net/wireless/rtl8189es/os_dep/linux/ioctl_cfg80211.c ++++ b/drivers/net/wireless/rtl8189es/os_dep/linux/ioctl_cfg80211.c +@@ -5567,6 +5567,33 @@ exit: + return ret; + } + ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)) ++ ++static void ++cfg80211_rtw_update_mgmt_frame_registrations(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ struct mgmt_frame_regs *upd) ++{ ++ struct net_device *ndev = wdev_to_ndev(wdev); ++ struct rtw_wdev_priv *pwdev_priv; ++ _adapter *adapter; ++ ++ if (ndev == NULL) ++ return; ++ ++ adapter = (_adapter *)rtw_netdev_priv(ndev); ++ pwdev_priv = adapter_wdev_data(adapter); ++ ++#ifdef CONFIG_DEBUG_CFG80211 ++ RTW_INFO(FUNC_ADPT_FMT" stypes:%x\n", FUNC_ADPT_ARG(adapter), ++ upd->interface_stypes); ++#endif ++ ++ /* not implemented, see bellow */ ++} ++ ++#else ++ + static void cfg80211_rtw_mgmt_frame_register(struct wiphy *wiphy, + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + struct wireless_dev *wdev, +@@ -5611,6 +5638,8 @@ exit: + return; + } + ++#endif ++ + #if defined(CONFIG_TDLS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0)) + static int cfg80211_rtw_tdls_mgmt(struct wiphy *wiphy, + struct net_device *ndev, +@@ -6505,7 +6534,11 @@ static struct cfg80211_ops rtw_cfg80211_ops = { + + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE) + .mgmt_tx = cfg80211_rtw_mgmt_tx, ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)) ++ .update_mgmt_frame_registrations = cfg80211_rtw_update_mgmt_frame_registrations, ++#else + .mgmt_frame_register = cfg80211_rtw_mgmt_frame_register, ++#endif + #elif (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,34) && LINUX_VERSION_CODE<=KERNEL_VERSION(2,6,35)) + .action = cfg80211_rtw_mgmt_tx, + #endif +diff --git a/drivers/net/wireless/rtl8811cu/os_dep/linux/ioctl_cfg80211.c b/drivers/net/wireless/rtl8811cu/os_dep/linux/ioctl_cfg80211.c +index c0df148..9bff924 100755 +--- a/drivers/net/wireless/rtl8811cu/os_dep/linux/ioctl_cfg80211.c ++++ b/drivers/net/wireless/rtl8811cu/os_dep/linux/ioctl_cfg80211.c +@@ -7143,6 +7143,33 @@ exit: + return ret; + } + ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)) ++ ++static void ++cfg80211_rtw_update_mgmt_frame_registrations(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ struct mgmt_frame_regs *upd) ++{ ++ struct net_device *ndev = wdev_to_ndev(wdev); ++ struct rtw_wdev_priv *pwdev_priv; ++ _adapter *adapter; ++ ++ if (ndev == NULL) ++ return; ++ ++ adapter = (_adapter *)rtw_netdev_priv(ndev); ++ pwdev_priv = adapter_wdev_data(adapter); ++ ++#ifdef CONFIG_DEBUG_CFG80211 ++ RTW_INFO(FUNC_ADPT_FMT" stypes:%x\n", FUNC_ADPT_ARG(adapter), ++ upd->interface_stypes); ++#endif ++ ++ /* not implemented, see bellow */ ++} ++ ++#else ++ + static void cfg80211_rtw_mgmt_frame_register(struct wiphy *wiphy, + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + struct wireless_dev *wdev, +@@ -7187,6 +7214,8 @@ exit: + return; + } + ++#endif ++ + #if defined(CONFIG_TDLS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)) + static int cfg80211_rtw_tdls_mgmt(struct wiphy *wiphy, + struct net_device *ndev, +@@ -9457,7 +9486,11 @@ static struct cfg80211_ops rtw_cfg80211_ops = { + + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE) + .mgmt_tx = cfg80211_rtw_mgmt_tx, ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)) ++ .update_mgmt_frame_registrations = cfg80211_rtw_update_mgmt_frame_registrations, ++#else + .mgmt_frame_register = cfg80211_rtw_mgmt_frame_register, ++#endif + #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) && LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) + .action = cfg80211_rtw_mgmt_tx, + #endif +diff --git a/drivers/net/wireless/rtl8188eu/os_dep/linux/ioctl_cfg80211.c b/drivers/net/wireless/rtl8188eu/os_dep/linux/ioctl_cfg80211.c +index 721723e..62fd530 100644 +--- a/drivers/net/wireless/rtl8188eu/os_dep/linux/ioctl_cfg80211.c ++++ b/drivers/net/wireless/rtl8188eu/os_dep/linux/ioctl_cfg80211.c +@@ -7470,6 +7470,33 @@ exit: + return ret; + } + ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)) ++ ++static void ++cfg80211_rtw_update_mgmt_frame_registrations(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ struct mgmt_frame_regs *upd) ++{ ++ struct net_device *ndev = wdev_to_ndev(wdev); ++ struct rtw_wdev_priv *pwdev_priv; ++ _adapter *adapter; ++ ++ if (ndev == NULL) ++ return; ++ ++ adapter = (_adapter *)rtw_netdev_priv(ndev); ++ pwdev_priv = adapter_wdev_data(adapter); ++ ++#ifdef CONFIG_DEBUG_CFG80211 ++ RTW_INFO(FUNC_ADPT_FMT" stypes:%x\n", FUNC_ADPT_ARG(adapter), ++ upd->interface_stypes); ++#endif ++ ++ /* not implemented, see bellow */ ++} ++ ++#else ++ + static void cfg80211_rtw_mgmt_frame_register(struct wiphy *wiphy, + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + struct wireless_dev *wdev, +@@ -7525,6 +7552,8 @@ exit: + return; + } + ++#endif ++ + #if defined(CONFIG_TDLS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)) + static int cfg80211_rtw_tdls_mgmt(struct wiphy *wiphy, + struct net_device *ndev, +@@ -9903,7 +9932,11 @@ static struct cfg80211_ops rtw_cfg80211_ops = { + + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE) + .mgmt_tx = cfg80211_rtw_mgmt_tx, ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)) ++ .update_mgmt_frame_registrations = cfg80211_rtw_update_mgmt_frame_registrations, ++#else + .mgmt_frame_register = cfg80211_rtw_mgmt_frame_register, ++#endif + #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) && LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) + .action = cfg80211_rtw_mgmt_tx, + #endif +diff --git a/drivers/net/wireless/rtl88x2bu/os_dep/linux/ioctl_cfg80211.c b/drivers/net/wireless/rtl88x2bu/os_dep/linux/ioctl_cfg80211.c +index 2fd4e28..b463e55 100755 +--- a/drivers/net/wireless/rtl88x2bu/os_dep/linux/ioctl_cfg80211.c ++++ b/drivers/net/wireless/rtl88x2bu/os_dep/linux/ioctl_cfg80211.c +@@ -7325,6 +7325,33 @@ exit: + return ret; + } + ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)) ++ ++static void ++cfg80211_rtw_update_mgmt_frame_registrations(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ struct mgmt_frame_regs *upd) ++{ ++ struct net_device *ndev = wdev_to_ndev(wdev); ++ struct rtw_wdev_priv *pwdev_priv; ++ _adapter *adapter; ++ ++ if (ndev == NULL) ++ return; ++ ++ adapter = (_adapter *)rtw_netdev_priv(ndev); ++ pwdev_priv = adapter_wdev_data(adapter); ++ ++#ifdef CONFIG_DEBUG_CFG80211 ++ RTW_INFO(FUNC_ADPT_FMT" stypes:%x\n", FUNC_ADPT_ARG(adapter), ++ upd->interface_stypes); ++#endif ++ ++ /* not implemented, see bellow */ ++} ++ ++#else ++ + static void cfg80211_rtw_mgmt_frame_register(struct wiphy *wiphy, + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + struct wireless_dev *wdev, +@@ -7369,6 +7396,8 @@ exit: + return; + } + ++#endif ++ + #if defined(CONFIG_TDLS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)) + static int cfg80211_rtw_tdls_mgmt(struct wiphy *wiphy, + struct net_device *ndev, +@@ -9652,7 +9681,11 @@ static struct cfg80211_ops rtw_cfg80211_ops = { + + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE) + .mgmt_tx = cfg80211_rtw_mgmt_tx, ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)) ++ .update_mgmt_frame_registrations = cfg80211_rtw_update_mgmt_frame_registrations, ++#else + .mgmt_frame_register = cfg80211_rtw_mgmt_frame_register, ++#endif + #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) && LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) + .action = cfg80211_rtw_mgmt_tx, + #endif diff --git a/patch/kernel/rk322x-legacy/01-linux-1002-rk322x-dts.patch b/patch/kernel/rk322x-legacy/01-linux-1002-rk322x-dts.patch index e546eadb8..81105648c 100644 --- a/patch/kernel/rk322x-legacy/01-linux-1002-rk322x-dts.patch +++ b/patch/kernel/rk322x-legacy/01-linux-1002-rk322x-dts.patch @@ -3,7 +3,7 @@ new file mode 100644 index 0000000..04330d3 --- /dev/null +++ b/arch/arm/boot/dts/rk322x-box.dtsi -@@ -0,0 +1,503 @@ +@@ -0,0 +1,504 @@ +/* + * Copyright (C) 2020 knaerzche + * @@ -36,14 +36,15 @@ index 0000000..04330d3 + #size-cells = <1>; + ranges; + -+ ramoops_mem: ramoops@62e00000 { ++ /*ramoops_mem: ramoops@62e00000 { + reg = <0x62e00000 0xf0000>; -+ }; ++ };*/ + ++ /* Not neeed for u-boot 2020.07 and up + trust_reserved: trust@68400000 { + reg = <0x68400000 0xe00000>; + no-map; -+ }; ++ };*/ + }; + + ramoops { diff --git a/patch/kernel/rk322x-legacy/03-001-wifi-esp8089-driver.patch b/patch/kernel/rk322x-legacy/03-001-wifi-esp8089-driver.patch index 7cca266fc..17fd43a3b 100644 --- a/patch/kernel/rk322x-legacy/03-001-wifi-esp8089-driver.patch +++ b/patch/kernel/rk322x-legacy/03-001-wifi-esp8089-driver.patch @@ -5324,8 +5324,8 @@ index 000000000..0f523fd20 + + /* ONLY station for now, support P2P soon... */ + hw->wiphy->interface_modes = -+ BIT(NL80211_IFTYPE_P2P_GO) | -+ BIT(NL80211_IFTYPE_P2P_CLIENT) | ++ //BIT(NL80211_IFTYPE_P2P_GO) | ++ //BIT(NL80211_IFTYPE_P2P_CLIENT) | + BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP); + + hw->wiphy->max_scan_ssids = 2; diff --git a/patch/kernel/rk322x-legacy/03-003-wifi-ssv6051-optimizations.patch b/patch/kernel/rk322x-legacy/03-003-wifi-ssv6051-optimizations.patch new file mode 100644 index 000000000..eafe28e9e --- /dev/null +++ b/patch/kernel/rk322x-legacy/03-003-wifi-ssv6051-optimizations.patch @@ -0,0 +1,36 @@ +diff --git a/drivers/net/wireless/rockchip_wlan/ssv6xxx/platform-config.mak b/drivers/net/wireless/rockchip_wlan/ssv6xxx/platform-config.mak +index 00d4792a0..373fc2bda 100644 +--- a/drivers/net/wireless/rockchip_wlan/ssv6xxx/platform-config.mak ++++ b/drivers/net/wireless/rockchip_wlan/ssv6xxx/platform-config.mak +@@ -9,7 +9,8 @@ ccflags-y += -Werror + + # Enable -g to help debug. Deassembly from .o to .S would help to track to + # the problomatic line from call stack dump. +-ccflags-y += -g ++#ccflags-y += -g ++ccflags += -Os + + ############################################################ + # If you change the settings, please change the file synchronization +@@ -71,7 +72,7 @@ ccflags-y += -DUSE_GENERIC_DECI_TBL + ccflags-y += -DUSE_LOCAL_CRYPTO + ccflags-y += -DUSE_LOCAL_WEP_CRYPTO + #ccflags-y += -DUSE_LOCAL_TKIP_CRYPTO +-ccflags-y += -DUSE_LOCAL_CCMP_CRYPTO ++#ccflags-y += -DUSE_LOCAL_CCMP_CRYPTO + ccflags-y += -DUSE_LOCAL_SMS4_CRYPTO + + ccflags-y += -DCONFIG_SSV_WAPI +diff --git a/drivers/net/wireless/rockchip_wlan/ssv6xxx/ssvdevice/ssvdevice.c b/drivers/net/wireless/rockchip_wlan/ssv6xxx/ssvdevice/ssvdevice.c +index 8718d8900..afce4ecef 100644 +--- a/drivers/net/wireless/rockchip_wlan/ssv6xxx/ssvdevice/ssvdevice.c ++++ b/drivers/net/wireless/rockchip_wlan/ssv6xxx/ssvdevice/ssvdevice.c +@@ -58,7 +58,7 @@ static char *ssv6xxx_cmd_buf; + char *ssv6xxx_result_buf; + extern struct ssv6xxx_cfg_cmd_table cfg_cmds[]; + extern struct ssv6xxx_cfg ssv_cfg; +-char DEFAULT_CFG_PATH[] = "/etc/firmware/ssv6051/ssv6051-wifi.cfg"; ++char DEFAULT_CFG_PATH[] = "/lib/firmware/ssv6051-wifi.cfg"; + static int ssv6xxx_dbg_open(struct inode *inode, struct file *filp) + { + filp->private_data = inode->i_private; diff --git a/patch/u-boot/u-boot-rk322x/u-boot-1000-rockchip.patch b/patch/u-boot/u-boot-rk322x/u-boot-1000-rockchip.patch index 4c2e4aa67..847ec67b9 100644 --- a/patch/u-boot/u-boot-rk322x/u-boot-1000-rockchip.patch +++ b/patch/u-boot/u-boot-rk322x/u-boot-1000-rockchip.patch @@ -268,31 +268,6 @@ index 866fc08215..b0d1b2f90a 100644 }; gic: interrupt-controller@ffc01000 { -diff --git a/arch/arm/dts/rk3328.dtsi b/arch/arm/dts/rk3328.dtsi -index 060c84e6c0..34c0b7de41 100644 ---- a/arch/arm/dts/rk3328.dtsi -+++ b/arch/arm/dts/rk3328.dtsi -@@ -337,6 +337,20 @@ - }; - }; - -+ efuse: efuse@ff260000 { -+ compatible = "rockchip,rk3328-efuse"; -+ reg = <0x0 0xff260000 0x0 0x80>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ clocks = <&cru SCLK_EFUSE>; -+ clock-names = "pclk_efuse"; -+ -+ /* Data cells */ -+ cpu_id: cpu-id@7 { -+ reg = <0x07 0x10>; -+ }; -+ }; -+ - saradc: saradc@ff280000 { - compatible = "rockchip,rk3328-saradc", "rockchip,saradc"; - reg = <0x0 0xff280000 0x0 0x100>; diff --git a/configs/evb-rk3328_defconfig b/configs/evb-rk3328_defconfig index 3db40a9a1a..edd1c41f09 100644 --- a/configs/evb-rk3328_defconfig @@ -314,19 +289,6 @@ index 3db40a9a1a..edd1c41f09 100644 CONFIG_MMC_DW=y CONFIG_MMC_DW_ROCKCHIP=y CONFIG_SF_DEFAULT_SPEED=20000000 -diff --git a/configs/evb-rk3399_defconfig b/configs/evb-rk3399_defconfig -index 8b8cdc5109..71c2daf8f5 100644 ---- a/configs/evb-rk3399_defconfig -+++ b/configs/evb-rk3399_defconfig -@@ -28,6 +28,8 @@ CONFIG_SYS_RELOC_GD_ENV_ADDR=y - CONFIG_NET_RANDOM_ETHADDR=y - CONFIG_ROCKCHIP_GPIO=y - CONFIG_SYS_I2C_ROCKCHIP=y -+CONFIG_MISC=y -+CONFIG_ROCKCHIP_EFUSE=y - CONFIG_MMC_DW=y - CONFIG_MMC_SDHCI=y - CONFIG_MMC_SDHCI_ROCKCHIP=y diff --git a/configs/miqi-rk3288_defconfig b/configs/miqi-rk3288_defconfig index cec8e42c5e..ac05d35392 100644 --- a/configs/miqi-rk3288_defconfig diff --git a/patch/u-boot/u-boot-rk322x/u-boot-1001-rockchip-rmii-integrated-phy.patch b/patch/u-boot/u-boot-rk322x/u-boot-1001-rockchip-rmii-integrated-phy.patch index b10a7950a..8777210de 100644 --- a/patch/u-boot/u-boot-rk322x/u-boot-1001-rockchip-rmii-integrated-phy.patch +++ b/patch/u-boot/u-boot-rk322x/u-boot-1001-rockchip-rmii-integrated-phy.patch @@ -63,27 +63,6 @@ index 4a8be5dabb..3c2861f271 100644 rockchip,grf = <&grf>; status = "disabled"; }; -diff --git a/arch/arm/dts/rk3328-evb.dts b/arch/arm/dts/rk3328-evb.dts -index a2ee838fcd..704712a05e 100644 ---- a/arch/arm/dts/rk3328-evb.dts -+++ b/arch/arm/dts/rk3328-evb.dts -@@ -100,6 +100,16 @@ - pinctrl-0 = <&rgmiim1_pins>; - tx_delay = <0x26>; - rx_delay = <0x11>; -+ status = "disabled"; -+}; -+ -+&gmac2phy { -+ phy-supply = <&vcc_phy>; -+ clock_in_out = "output"; -+ assigned-clocks = <&cru SCLK_MAC2PHY_SRC>; -+ assigned-clock-rate = <50000000>; -+ assigned-clocks = <&cru SCLK_MAC2PHY>; -+ assigned-clock-parents = <&cru SCLK_MAC2PHY_SRC>; - status = "okay"; - }; - diff --git a/arch/arm/dts/rk3328.dtsi b/arch/arm/dts/rk3328.dtsi index 060c84e6c0..c9419db07f 100644 --- a/arch/arm/dts/rk3328.dtsi @@ -388,11 +367,12 @@ index e152faf083..d3f6973043 100644 #include #include #include -@@ -23,6 +24,7 @@ +@@ -23,6 +24,8 @@ #include #include #include +#include ++#include #include #include "designware.h" diff --git a/patch/u-boot/u-boot-rk322x/u-boot-rk322x-with-spl.bin b/patch/u-boot/u-boot-rk322x/u-boot-rk322x-with-spl.bin new file mode 100644 index 000000000..e69de29bb